mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-05-30 16:00:37 +00:00
Update image caching for printing
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@15666 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
cda830aed6
commit
2eb03143c3
3 changed files with 209 additions and 38 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
||||||
|
2003-01-20 Adam Fedor <fedor@gnu.org>
|
||||||
|
|
||||||
|
* Headers/gnustep/gui/NSImage.m (NSImageCacheMore): New enum and ivar.
|
||||||
|
* Source/NSImage.m (-setCacheMode:): New method.
|
||||||
|
(-cacheMode): Idem.
|
||||||
|
(-compositeToPoint:fromRect:operation:): If printing, composite from
|
||||||
|
source image, not cache.
|
||||||
|
(-dissolveToPoint:fromRect:fraction:): Idem.
|
||||||
|
(-drawRepresentation:inRect:): Correct background rectfill for
|
||||||
|
flipped views.
|
||||||
|
(-bestRepresentationForDevice:): Rewrite. Close to being correct.
|
||||||
|
|
||||||
Tue Jan 21 00:39:52 2003 Serg Stoyan <stoyan@on.com.ua>
|
Tue Jan 21 00:39:52 2003 Serg Stoyan <stoyan@on.com.ua>
|
||||||
|
|
||||||
* Source/NSMenu.m ([-performKeyEquivalent:]): Only perform the
|
* Source/NSMenu.m ([-performKeyEquivalent:]): Only perform the
|
||||||
|
|
|
@ -43,6 +43,14 @@
|
||||||
@class NSColor;
|
@class NSColor;
|
||||||
@class NSView;
|
@class NSView;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NSImageCacheDefault,
|
||||||
|
NSImageCacheAlways,
|
||||||
|
NSImageCacheBySize,
|
||||||
|
NSImageCacheNever
|
||||||
|
} NSImageCacheMode;
|
||||||
|
|
||||||
|
|
||||||
@interface NSImage : NSObject <NSCoding, NSCopying>
|
@interface NSImage : NSObject <NSCoding, NSCopying>
|
||||||
{
|
{
|
||||||
// Attributes
|
// Attributes
|
||||||
|
@ -64,8 +72,9 @@
|
||||||
} _flags;
|
} _flags;
|
||||||
NSMutableArray *_reps;
|
NSMutableArray *_reps;
|
||||||
NSColor *_color;
|
NSColor *_color;
|
||||||
NSView *_lockedView;
|
NSView *_lockedView;
|
||||||
id _delegate;
|
id _delegate;
|
||||||
|
NSImageCacheMode _cacheMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -155,6 +164,8 @@
|
||||||
- (BOOL) isDataRetained;
|
- (BOOL) isDataRetained;
|
||||||
- (void) setCacheDepthMatchesImageDepth: (BOOL)flag;
|
- (void) setCacheDepthMatchesImageDepth: (BOOL)flag;
|
||||||
- (BOOL) cacheDepthMatchesImageDepth;
|
- (BOOL) cacheDepthMatchesImageDepth;
|
||||||
|
- (void) setCacheMode: (NSImageCacheMode)mode;
|
||||||
|
- (NSImageCacheMode) cacheMode;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Drawing
|
// Drawing
|
||||||
|
|
220
Source/NSImage.m
220
Source/NSImage.m
|
@ -44,9 +44,10 @@
|
||||||
#include <AppKit/NSScreen.h>
|
#include <AppKit/NSScreen.h>
|
||||||
#include <AppKit/NSColor.h>
|
#include <AppKit/NSColor.h>
|
||||||
#include <AppKit/NSPasteboard.h>
|
#include <AppKit/NSPasteboard.h>
|
||||||
|
#include <AppKit/NSPrintOperation.h>
|
||||||
#include <AppKit/PSOperators.h>
|
#include <AppKit/PSOperators.h>
|
||||||
|
#include <AppKit/GSDisplayServer.h>
|
||||||
|
|
||||||
BOOL NSImageDoesCaching = YES; /* enable caching */
|
|
||||||
BOOL NSImageForceCaching = NO; /* use on missmatch */
|
BOOL NSImageForceCaching = NO; /* use on missmatch */
|
||||||
|
|
||||||
@implementation NSBundle (NSImageAdditions)
|
@implementation NSBundle (NSImageAdditions)
|
||||||
|
@ -329,6 +330,7 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
//_flags.syncLoad = NO;
|
//_flags.syncLoad = NO;
|
||||||
_reps = [[NSMutableArray alloc] initWithCapacity: 2];
|
_reps = [[NSMutableArray alloc] initWithCapacity: 2];
|
||||||
ASSIGN(_color, clearColor);
|
ASSIGN(_color, clearColor);
|
||||||
|
_cacheMode = NSImageCacheDefault;
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -610,6 +612,17 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
return _flags.unboundedCacheDepth;
|
return _flags.unboundedCacheDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) setCacheMode: (NSImageCacheMode)mode
|
||||||
|
{
|
||||||
|
_cacheMode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSImageCacheMode) cacheMode
|
||||||
|
{
|
||||||
|
return _cacheMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Determining How the Image is Drawn
|
// Determining How the Image is Drawn
|
||||||
- (BOOL) isValid
|
- (BOOL) isValid
|
||||||
{
|
{
|
||||||
|
@ -691,17 +704,20 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
fromRect: (NSRect)aRect
|
fromRect: (NSRect)aRect
|
||||||
operation: (NSCompositingOperation)op
|
operation: (NSCompositingOperation)op
|
||||||
{
|
{
|
||||||
NSImageRep *rep;
|
NSImageRep *rep = nil;
|
||||||
|
|
||||||
NS_DURING
|
NS_DURING
|
||||||
{
|
{
|
||||||
rep = [self _doImageCache];
|
if ([GSCurrentContext() isDrawingToScreen] == YES)
|
||||||
|
rep = [self _doImageCache];
|
||||||
if (NSImageDoesCaching == YES && [rep isKindOfClass: cachedClass])
|
if (rep
|
||||||
|
&&_cacheMode != NSImageCacheNever
|
||||||
|
&& [rep isKindOfClass: cachedClass])
|
||||||
{
|
{
|
||||||
NSRect rect = [(NSCachedImageRep *)rep rect];
|
NSRect rect;
|
||||||
float y = aPoint.y;
|
float y = aPoint.y;
|
||||||
|
|
||||||
|
rect = [(NSCachedImageRep *)rep rect];
|
||||||
NSDebugLLog(@"NSImage", @"composite rect %@ in %@",
|
NSDebugLLog(@"NSImage", @"composite rect %@ in %@",
|
||||||
NSStringFromRect(rect), NSStringFromRect(aRect));
|
NSStringFromRect(rect), NSStringFromRect(aRect));
|
||||||
// Move the drawing rectangle to the origin of the image rep
|
// Move the drawing rectangle to the origin of the image rep
|
||||||
|
@ -716,14 +732,14 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSRect rect;
|
NSRect rect;
|
||||||
|
rep = [self bestRepresentationForDevice: nil];
|
||||||
rect = NSMakeRect(aPoint.x, aPoint.y, _size.width, _size.height);
|
rect = NSMakeRect(aPoint.x, aPoint.y, _size.width, _size.height);
|
||||||
[self drawRepresentation: rep inRect: rect];
|
[self drawRepresentation: rep inRect: rect];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NS_HANDLER
|
NS_HANDLER
|
||||||
{
|
{
|
||||||
NSLog(@"NSImage: composite failed due to %@: %@",
|
NSLog(@"NSImage: compositeToPoint:fromRect:operation: failed due to %@: %@",
|
||||||
[localException name], [localException reason]);
|
[localException name], [localException reason]);
|
||||||
if ([_delegate respondsToSelector: @selector(imageDidNotDraw:inRect:)])
|
if ([_delegate respondsToSelector: @selector(imageDidNotDraw:inRect:)])
|
||||||
{
|
{
|
||||||
|
@ -775,13 +791,16 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
|
|
||||||
NS_DURING
|
NS_DURING
|
||||||
{
|
{
|
||||||
rep = [self _doImageCache];
|
if ([GSCurrentContext() isDrawingToScreen] == YES)
|
||||||
|
rep = [self _doImageCache];
|
||||||
if (NSImageDoesCaching == YES && [rep isKindOfClass: cachedClass])
|
if (rep
|
||||||
|
&&_cacheMode != NSImageCacheNever
|
||||||
|
&& [rep isKindOfClass: cachedClass])
|
||||||
{
|
{
|
||||||
NSRect rect = [(NSCachedImageRep *)rep rect];
|
NSRect rect;
|
||||||
float y = aPoint.y;
|
float y = aPoint.y;
|
||||||
|
|
||||||
|
rect = [(NSCachedImageRep *)rep rect];
|
||||||
// Move the drawing rectangle to the origin of the image rep
|
// Move the drawing rectangle to the origin of the image rep
|
||||||
// and intersect the two rects.
|
// and intersect the two rects.
|
||||||
aRect.origin.x += rect.origin.x;
|
aRect.origin.x += rect.origin.x;
|
||||||
|
@ -794,6 +813,9 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
{
|
{
|
||||||
NSRect rect;
|
NSRect rect;
|
||||||
|
|
||||||
|
/* FIXME: Here we are supposed to composite directly from the source
|
||||||
|
but how do you do that? */
|
||||||
|
rep = [self bestRepresentationForDevice: nil];
|
||||||
rect = NSMakeRect(aPoint.x, aPoint.y, _size.width, _size.height);
|
rect = NSMakeRect(aPoint.x, aPoint.y, _size.width, _size.height);
|
||||||
[self drawRepresentation: rep inRect: rect];
|
[self drawRepresentation: rep inRect: rect];
|
||||||
}
|
}
|
||||||
|
@ -819,8 +841,16 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
{
|
{
|
||||||
if (_color != nil)
|
if (_color != nil)
|
||||||
{
|
{
|
||||||
|
NSRect fillrect = aRect;
|
||||||
[_color set];
|
[_color set];
|
||||||
NSRectFill(aRect);
|
if ([[NSView focusView] isFlipped])
|
||||||
|
fillrect.origin.y -= _size.height;
|
||||||
|
NSRectFill(fillrect);
|
||||||
|
if ([GSCurrentContext() isDrawingToScreen] == NO)
|
||||||
|
{
|
||||||
|
/* Reset alpha for image drawing. */
|
||||||
|
[[NSColor whiteColor] set];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_flags.scalable)
|
if (!_flags.scalable)
|
||||||
|
@ -896,7 +926,7 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
|
|
||||||
- (void) lockFocusOnRepresentation: (NSImageRep *)imageRep
|
- (void) lockFocusOnRepresentation: (NSImageRep *)imageRep
|
||||||
{
|
{
|
||||||
if (NSImageDoesCaching == YES)
|
if (_cacheMode != NSImageCacheNever)
|
||||||
{
|
{
|
||||||
NSWindow *window;
|
NSWindow *window;
|
||||||
GSRepData *repd;
|
GSRepData *repd;
|
||||||
|
@ -946,30 +976,102 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSImageRep*) bestRepresentationForDevice: (NSDictionary*)deviceDescription
|
/* Determine if the device is color or gray scale and find the reps of
|
||||||
|
the same type
|
||||||
|
*/
|
||||||
|
- (NSMutableArray *) _bestRep: (NSArray *)reps
|
||||||
|
withColorMatch: (NSDictionary*)deviceDescription
|
||||||
{
|
{
|
||||||
NSArray *reps = [self representations];
|
int colors = 3;
|
||||||
|
NSImageRep* rep;
|
||||||
|
NSMutableArray *breps;
|
||||||
NSEnumerator *enumerator = [reps objectEnumerator];
|
NSEnumerator *enumerator = [reps objectEnumerator];
|
||||||
NSImageRep *rep = nil;
|
NSString *colorSpace = [deviceDescription objectForKey: NSDeviceColorSpaceName];
|
||||||
NSImageRep *best = nil;
|
|
||||||
|
if (colorSpace != nil)
|
||||||
|
colors = NSNumberOfColorComponents(colorSpace);
|
||||||
|
|
||||||
|
breps = [NSMutableArray array];
|
||||||
while ((rep = [enumerator nextObject]) != nil)
|
while ((rep = [enumerator nextObject]) != nil)
|
||||||
{
|
{
|
||||||
/*
|
if ([rep colorSpaceName] || abs(NSNumberOfColorComponents([rep colorSpaceName]) - colors) <= 1)
|
||||||
* What's the best representation?
|
[breps addObject: rep];
|
||||||
* FIXME: At the moment we take the last bitmap we find.
|
|
||||||
* If we can't find a bitmap, we take whatever we can.
|
|
||||||
* NSCursor will only handle returned NSBitmapImageReps!
|
|
||||||
*/
|
|
||||||
if ([rep isKindOfClass: bitmapClass])
|
|
||||||
best = rep;
|
|
||||||
else if (best == nil)
|
|
||||||
best = rep;
|
|
||||||
}
|
}
|
||||||
return best;
|
|
||||||
|
/* If there are no matches, pass all the reps */
|
||||||
|
if ([breps count] == 0)
|
||||||
|
return (NSMutableArray *)reps;
|
||||||
|
return breps;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray *) representations
|
/* Find reps that match the resolution of the device or return the rep
|
||||||
|
that has the highest resolution */
|
||||||
|
- (NSMutableArray *) _bestRep: (NSArray *)reps
|
||||||
|
withResolutionMatch: (NSDictionary*)deviceDescription
|
||||||
|
{
|
||||||
|
NSImageRep* rep;
|
||||||
|
NSMutableArray *breps;
|
||||||
|
NSSize dres;
|
||||||
|
NSEnumerator *enumerator = [reps objectEnumerator];
|
||||||
|
NSValue *resolution = [deviceDescription objectForKey: NSDeviceResolution];
|
||||||
|
|
||||||
|
if (resolution)
|
||||||
|
dres = [resolution sizeValue];
|
||||||
|
else
|
||||||
|
dres = NSMakeSize(0, 0);
|
||||||
|
|
||||||
|
breps = [NSMutableArray array];
|
||||||
|
while ((rep = [enumerator nextObject]) != nil)
|
||||||
|
{
|
||||||
|
/* FIXME: Not sure about checking resolution */
|
||||||
|
[breps addObject: rep];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If there are no matches, pass all the reps */
|
||||||
|
if ([breps count] == 0)
|
||||||
|
return (NSMutableArray *)reps;
|
||||||
|
return breps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find reps that match the bps of the device or return the rep that
|
||||||
|
has the highest bps */
|
||||||
|
- (NSMutableArray *) _bestRep: (NSArray *)reps
|
||||||
|
withBpsMatch: (NSDictionary*)deviceDescription
|
||||||
|
{
|
||||||
|
NSImageRep* rep, *max_rep;
|
||||||
|
NSMutableArray *breps;
|
||||||
|
NSEnumerator *enumerator = [reps objectEnumerator];
|
||||||
|
int bps = [[deviceDescription objectForKey: NSDeviceBitsPerSample] intValue];
|
||||||
|
int max_bps;
|
||||||
|
|
||||||
|
breps = [NSMutableArray array];
|
||||||
|
max_bps = 0;
|
||||||
|
max_rep = nil;
|
||||||
|
while ((rep = [enumerator nextObject]) != nil)
|
||||||
|
{
|
||||||
|
int rep_bps;
|
||||||
|
if ([rep respondsToSelector: @selector(bitsPerPixel)])
|
||||||
|
rep_bps = [(NSBitmapImageRep *)rep bitsPerPixel];
|
||||||
|
if (rep_bps > max_bps)
|
||||||
|
{
|
||||||
|
max_bps = rep_bps;
|
||||||
|
max_rep = rep;
|
||||||
|
}
|
||||||
|
if (rep_bps == bps)
|
||||||
|
[breps addObject: rep];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ([breps count] == 0 && max_rep != nil)
|
||||||
|
[breps addObject: max_rep];
|
||||||
|
|
||||||
|
/* If there are no matches, pass all the reps */
|
||||||
|
if ([breps count] == 0)
|
||||||
|
return (NSMutableArray *)reps;
|
||||||
|
return breps;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSMutableArray *) _representationsWithCachedImages: (BOOL)flag
|
||||||
{
|
{
|
||||||
unsigned count;
|
unsigned count;
|
||||||
|
|
||||||
|
@ -989,17 +1091,63 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
id repList[count];
|
id repList[count];
|
||||||
unsigned i;
|
unsigned i, j;
|
||||||
|
|
||||||
[_reps getObjects: repList];
|
[_reps getObjects: repList];
|
||||||
|
j = 0;
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
repList[i] = ((GSRepData*)repList[i])->rep;
|
if (flag || ((GSRepData*)repList[i])->original == nil)
|
||||||
|
{
|
||||||
|
repList[j] = ((GSRepData*)repList[i])->rep;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return [NSArray arrayWithObjects: repList count: count];
|
return [NSArray arrayWithObjects: repList count: j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSImageRep*) bestRepresentationForDevice: (NSDictionary*)deviceDescription
|
||||||
|
{
|
||||||
|
NSMutableArray *reps = [self _representationsWithCachedImages: NO];
|
||||||
|
|
||||||
|
if (deviceDescription == nil)
|
||||||
|
{
|
||||||
|
if ([GSCurrentContext() isDrawingToScreen] == YES)
|
||||||
|
{
|
||||||
|
int screen = [[[GSCurrentServer() attributes]
|
||||||
|
objectForKey: GSScreenNumber] intValue];
|
||||||
|
deviceDescription = [[[NSScreen screens] objectAtIndex: screen]
|
||||||
|
deviceDescription];
|
||||||
|
}
|
||||||
|
else if ([NSPrintOperation currentOperation])
|
||||||
|
{
|
||||||
|
/* FIXME: We could try to use the current printer,
|
||||||
|
but there are many cases where might
|
||||||
|
not be printing (EPS, PDF, etc) to a specific device */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_flags.colorMatchPreferred == YES)
|
||||||
|
{
|
||||||
|
reps = [self _bestRep: reps withColorMatch: deviceDescription];
|
||||||
|
reps = [self _bestRep: reps withResolutionMatch: deviceDescription];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reps = [self _bestRep: reps withResolutionMatch: deviceDescription];
|
||||||
|
reps = [self _bestRep: reps withColorMatch: deviceDescription];
|
||||||
|
}
|
||||||
|
reps = [self _bestRep: reps withBpsMatch: deviceDescription];
|
||||||
|
/* Pick an arbitrary representation if there is more than one */
|
||||||
|
return [reps lastObject];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *) representations
|
||||||
|
{
|
||||||
|
return [self _representationsWithCachedImages: YES];
|
||||||
|
}
|
||||||
|
|
||||||
- (void) setDelegate: anObject
|
- (void) setDelegate: anObject
|
||||||
{
|
{
|
||||||
_delegate = anObject;
|
_delegate = anObject;
|
||||||
|
@ -1294,7 +1442,7 @@ iterate_reps_for_types(NSArray* imageReps, SEL method)
|
||||||
{
|
{
|
||||||
NSImageRep *rep = [self bestRepresentationForDevice: nil];
|
NSImageRep *rep = [self bestRepresentationForDevice: nil];
|
||||||
|
|
||||||
if (NSImageDoesCaching == YES)
|
if (_cacheMode != NSImageCacheNever)
|
||||||
{
|
{
|
||||||
GSRepData *repd;
|
GSRepData *repd;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue