Small bugfix and performance optimisation.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@27735 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2009-01-30 16:27:36 +00:00
parent 49383abd25
commit 4ac3bb0344
4 changed files with 303 additions and 182 deletions

View file

@ -1,3 +1,16 @@
2009-01-30 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSThemeTools.m: Add checks to prevent problems in the case
where the control being drawn is actually smaller than the tiles used.
* Headers/AppKit/NSScreen.h:
* Source/NSScreen.m: Cache device description dictionary ... when
debugging the problem with theme tools (which caused a loop to
repeatedly composite the tile image instead of doing it once), I
noticed that almost every time I stopped the app in gdb, it was in
the process of creating a device description, strongly suggesting
that this is actually quite a time consuming part of drawing
images.
2009-01-30 Richard Frith-Macdonald <rfm@gnu.org> 2009-01-30 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSApplication.m: Try to get behavior to match MacOS-X * Source/NSApplication.m: Try to get behavior to match MacOS-X

View file

@ -47,7 +47,8 @@
NSWindowDepth _depth; NSWindowDepth _depth;
NSRect _frame; NSRect _frame;
int _screenNumber; int _screenNumber;
NSWindowDepth *_supportedWindowDepths; NSWindowDepth *_supportedWindowDepths;
void *_reserved;
} }
/* /*
@ -56,7 +57,7 @@
+ (NSScreen*) mainScreen; + (NSScreen*) mainScreen;
+ (NSScreen*) deepestScreen; + (NSScreen*) deepestScreen;
+ (NSArray*) screens; + (NSArray*) screens;
+ (void)resetScreens; + (void) resetScreens;
/* /*
* Reading Screen Information * Reading Screen Information

View file

@ -476,6 +476,28 @@
unsigned count; unsigned count;
float y; float y;
if (rect.size.width <= 0.0)
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] rect width is not positive",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
if (rect.size.height <= 0.0)
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] rect height is not positive",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
if (source.size.width <= 0.0)
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] source width is not positive",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
if (source.size.height <= 0.0)
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] source height is not positive",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
if (image == nil)
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] image is nil",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
ctxt = GSCurrentContext();
DPSgsave (ctxt); DPSgsave (ctxt);
path = [NSBezierPath bezierPathWithRect: rect]; path = [NSBezierPath bezierPathWithRect: rect];
[path addClip]; [path addClip];
@ -500,7 +522,7 @@ withRepeatedImage: (NSImage*)image
fromRect: (NSRect)source fromRect: (NSRect)source
center: (BOOL)center center: (BOOL)center
{ {
NSGraphicsContext *ctxt = GSCurrentContext (); NSGraphicsContext *ctxt;
NSBezierPath *path; NSBezierPath *path;
NSSize size; NSSize size;
unsigned xrepetitions; unsigned xrepetitions;
@ -508,6 +530,28 @@ withRepeatedImage: (NSImage*)image
unsigned x; unsigned x;
unsigned y; unsigned y;
if (rect.size.width <= 0.0)
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] rect width is not positive",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
if (rect.size.height <= 0.0)
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] rect height is not positive",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
if (source.size.width <= 0.0)
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] source width is not positive",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
if (source.size.height <= 0.0)
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] source height is not positive",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
if (image == nil)
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] image is nil",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
ctxt = GSCurrentContext ();
DPSgsave (ctxt); DPSgsave (ctxt);
path = [NSBezierPath bezierPathWithRect: rect]; path = [NSBezierPath bezierPathWithRect: rect];
[path addClip]; [path addClip];
@ -545,9 +589,23 @@ withRepeatedImage: (NSImage*)image
NSSize bls = tiles->rects[TileBL].size; NSSize bls = tiles->rects[TileBL].size;
NSSize bms = tiles->rects[TileBM].size; NSSize bms = tiles->rects[TileBM].size;
NSSize brs = tiles->rects[TileBR].size; NSSize brs = tiles->rects[TileBR].size;
NSSize tsz;
NSRect inFill; NSRect inFill;
BOOL flipped = [[ctxt focusView] isFlipped]; BOOL flipped = [[ctxt focusView] isFlipped];
if (rect.size.width <= 0.0)
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] rect width is not positive",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
if (rect.size.height <= 0.0)
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] rect height is not positive",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
if (tiles == nil)
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] tiles is nil",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
if (color == nil) if (color == nil)
{ {
[[NSColor redColor] set]; [[NSColor redColor] set];
@ -558,6 +616,19 @@ withRepeatedImage: (NSImage*)image
} }
NSRectFill(rect); NSRectFill(rect);
tsz.width = tiles->rects[TileTL].size.width
+ tiles->rects[TileTR].size.width;
if (tiles->images[TileTM] == nil)
{
tsz.width += tiles->rects[TileTM].size.width;
}
tsz.height = tiles->rects[TileTL].size.height
+ tiles->rects[TileBL].size.height;
if (tiles->images[TileCL] == nil)
{
tsz.height += tiles->rects[TileCL].size.height;
}
if (style == GSThemeFillStyleMatrix) if (style == GSThemeFillStyleMatrix)
{ {
NSRect grid; NSRect grid;
@ -569,31 +640,21 @@ withRepeatedImage: (NSImage*)image
inFill = NSZeroRect; inFill = NSZeroRect;
if (tiles->images[TileTM] == nil) if (tiles->images[TileTM] == nil)
{ {
grid.size.width = (tiles->rects[TileTL].size.width grid.size.width = tsz.width + space * 3.0;
+ tiles->rects[TileTR].size.width
+ space * 3.0);
} }
else else
{ {
grid.size.width = (tiles->rects[TileTL].size.width grid.size.width = tsz.width + space * 4.0;
+ tiles->rects[TileTM].size.width
+ tiles->rects[TileTR].size.width
+ space * 4.0);
} }
scale = floor(rect.size.width / grid.size.width); scale = floor(rect.size.width / grid.size.width);
if (tiles->images[TileCL] == nil) if (tiles->images[TileCL] == nil)
{ {
grid.size.height = (tiles->rects[TileTL].size.height grid.size.height = tsz.height + space * 3.0;
+ tiles->rects[TileBL].size.height
+ space * 3.0);
} }
else else
{ {
grid.size.height = (tiles->rects[TileTL].size.height grid.size.height = tsz.height + space * 4.0;
+ tiles->rects[TileCL].size.height
+ tiles->rects[TileBL].size.height
+ space * 4.0);
} }
if ((rect.size.height / grid.size.height) < scale) if ((rect.size.height / grid.size.height) < scale)
{ {
@ -717,64 +778,71 @@ withRepeatedImage: (NSImage*)image
} }
else if (flipped) else if (flipped)
{ {
[self fillHorizontalRect: if (tsz.width <= rect.size.width && tsz.height <= rect.size.height)
NSMakeRect (rect.origin.x + bls.width, {
rect.origin.y + rect.size.height - bms.height, [self fillHorizontalRect:
rect.size.width - bls.width - brs.width, NSMakeRect (rect.origin.x + bls.width,
bms.height) rect.origin.y + rect.size.height - bms.height,
withImage: tiles->images[TileBM] rect.size.width - bls.width - brs.width,
fromRect: tiles->rects[TileBM] bms.height)
flipped: YES]; withImage: tiles->images[TileBM]
[self fillHorizontalRect: fromRect: tiles->rects[TileBM]
NSMakeRect (rect.origin.x + tls.width, flipped: YES];
rect.origin.y, [self fillHorizontalRect:
rect.size.width - tls.width - trs.width, NSMakeRect (rect.origin.x + tls.width,
tms.height) rect.origin.y,
withImage: tiles->images[TileTM] rect.size.width - tls.width - trs.width,
fromRect: tiles->rects[TileTM] tms.height)
flipped: YES]; withImage: tiles->images[TileTM]
[self fillVerticalRect: fromRect: tiles->rects[TileTM]
NSMakeRect (rect.origin.x, flipped: YES];
rect.origin.y + bls.height, [self fillVerticalRect:
cls.width, NSMakeRect (rect.origin.x,
rect.size.height - bls.height - tls.height) rect.origin.y + bls.height,
withImage: tiles->images[TileCL] cls.width,
fromRect: tiles->rects[TileCL] rect.size.height - bls.height - tls.height)
flipped: NO]; withImage: tiles->images[TileCL]
[self fillVerticalRect: fromRect: tiles->rects[TileCL]
NSMakeRect (rect.origin.x + rect.size.width - crs.width, flipped: NO];
rect.origin.y + brs.height, [self fillVerticalRect:
crs.width, NSMakeRect (rect.origin.x + rect.size.width - crs.width,
rect.size.height - brs.height - trs.height) rect.origin.y + brs.height,
withImage: tiles->images[TileCR] crs.width,
fromRect: tiles->rects[TileCR] rect.size.height - brs.height - trs.height)
flipped: NO]; withImage: tiles->images[TileCR]
fromRect: tiles->rects[TileCR]
flipped: NO];
[tiles->images[TileTL] compositeToPoint: [tiles->images[TileTL] compositeToPoint:
NSMakePoint (rect.origin.x, NSMakePoint (rect.origin.x,
rect.origin.y) rect.origin.y)
fromRect: tiles->rects[TileTL] fromRect: tiles->rects[TileTL]
operation: NSCompositeSourceOver]; operation: NSCompositeSourceOver];
[tiles->images[TileTR] compositeToPoint: [tiles->images[TileTR] compositeToPoint:
NSMakePoint (rect.origin.x + rect.size.width - tls.width, NSMakePoint (rect.origin.x + rect.size.width - tls.width,
rect.origin.y) rect.origin.y)
fromRect: tiles->rects[TileTR] fromRect: tiles->rects[TileTR]
operation: NSCompositeSourceOver]; operation: NSCompositeSourceOver];
[tiles->images[TileBL] compositeToPoint: [tiles->images[TileBL] compositeToPoint:
NSMakePoint (rect.origin.x, NSMakePoint (rect.origin.x,
rect.origin.y + rect.size.height - tls.height) rect.origin.y + rect.size.height - tls.height)
fromRect: tiles->rects[TileBL] fromRect: tiles->rects[TileBL]
operation: NSCompositeSourceOver]; operation: NSCompositeSourceOver];
[tiles->images[TileBR] compositeToPoint: [tiles->images[TileBR] compositeToPoint:
NSMakePoint (rect.origin.x + rect.size.width - brs.width, NSMakePoint (rect.origin.x + rect.size.width - brs.width,
rect.origin.y + rect.size.height - tls.height) rect.origin.y + rect.size.height - tls.height)
fromRect: tiles->rects[TileBR] fromRect: tiles->rects[TileBR]
operation: NSCompositeSourceOver]; operation: NSCompositeSourceOver];
inFill = NSMakeRect (rect.origin.x + cls.width, inFill = NSMakeRect (rect.origin.x + cls.width,
rect.origin.y + bms.height, rect.origin.y + bms.height,
rect.size.width - cls.width - crs.width, rect.size.width - cls.width - crs.width,
rect.size.height - bms.height - tms.height); rect.size.height - bms.height - tms.height);
}
else
{
inFill = rect;
}
if (style == GSThemeFillStyleCenter) if (style == GSThemeFillStyleCenter)
{ {
NSRect r = tiles->rects[TileCM]; NSRect r = tiles->rects[TileCM];
@ -794,6 +862,8 @@ withRepeatedImage: (NSImage*)image
withRepeatedImage: tiles->images[TileCM] withRepeatedImage: tiles->images[TileCM]
fromRect: tiles->rects[TileCM] fromRect: tiles->rects[TileCM]
center: NO]; center: NO];
NSLog(@"rect %@ too small fire tiles %@",
NSStringFromSize(rect.size), NSStringFromSize(tsz));
} }
else if (style == GSThemeFillStyleScale) else if (style == GSThemeFillStyleScale)
{ {
@ -822,73 +892,81 @@ withRepeatedImage: (NSImage*)image
} }
else else
{ {
[self fillHorizontalRect: if (tsz.width <= rect.size.width && tsz.height <= rect.size.height)
NSMakeRect( {
rect.origin.x + tls.width, [self fillHorizontalRect:
rect.origin.y + rect.size.height - tms.height, NSMakeRect(
rect.size.width - bls.width - brs.width, rect.origin.x + tls.width,
tms.height) rect.origin.y + rect.size.height - tms.height,
withImage: tiles->images[TileTM] rect.size.width - bls.width - brs.width,
fromRect: tiles->rects[TileTM] tms.height)
flipped: NO]; withImage: tiles->images[TileTM]
[self fillHorizontalRect: fromRect: tiles->rects[TileTM]
NSMakeRect( flipped: NO];
rect.origin.x + bls.width, [self fillHorizontalRect:
rect.origin.y, NSMakeRect(
rect.size.width - bls.width - brs.width, rect.origin.x + bls.width,
bms.height) rect.origin.y,
withImage: tiles->images[TileBM] rect.size.width - bls.width - brs.width,
fromRect: tiles->rects[TileBM] bms.height)
flipped: NO]; withImage: tiles->images[TileBM]
[self fillVerticalRect: fromRect: tiles->rects[TileBM]
NSMakeRect( flipped: NO];
rect.origin.x, [self fillVerticalRect:
rect.origin.y + bls.height, NSMakeRect(
cls.width, rect.origin.x,
rect.size.height - tls.height - bls.height) rect.origin.y + bls.height,
withImage: tiles->images[TileCL] cls.width,
fromRect: tiles->rects[TileCL] rect.size.height - tls.height - bls.height)
flipped: NO]; withImage: tiles->images[TileCL]
[self fillVerticalRect: fromRect: tiles->rects[TileCL]
NSMakeRect( flipped: NO];
rect.origin.x + rect.size.width - crs.width, [self fillVerticalRect:
rect.origin.y + brs.height, NSMakeRect(
crs.width, rect.origin.x + rect.size.width - crs.width,
rect.size.height - trs.height - brs.height) rect.origin.y + brs.height,
withImage: tiles->images[TileCR] crs.width,
fromRect: tiles->rects[TileCR] rect.size.height - trs.height - brs.height)
flipped: NO]; withImage: tiles->images[TileCR]
fromRect: tiles->rects[TileCR]
flipped: NO];
[tiles->images[TileTL] compositeToPoint: [tiles->images[TileTL] compositeToPoint:
NSMakePoint ( NSMakePoint (
rect.origin.x, rect.origin.x,
rect.origin.y + rect.size.height - tls.height) rect.origin.y + rect.size.height - tls.height)
fromRect: tiles->rects[TileTL] fromRect: tiles->rects[TileTL]
operation: NSCompositeSourceOver]; operation: NSCompositeSourceOver];
[tiles->images[TileTR] compositeToPoint: [tiles->images[TileTR] compositeToPoint:
NSMakePoint( NSMakePoint(
rect.origin.x + rect.size.width - trs.width, rect.origin.x + rect.size.width - trs.width,
rect.origin.y + rect.size.height - trs.height) rect.origin.y + rect.size.height - trs.height)
fromRect: tiles->rects[TileTR] fromRect: tiles->rects[TileTR]
operation: NSCompositeSourceOver]; operation: NSCompositeSourceOver];
[tiles->images[TileBL] compositeToPoint: [tiles->images[TileBL] compositeToPoint:
NSMakePoint( NSMakePoint(
rect.origin.x, rect.origin.x,
rect.origin.y) rect.origin.y)
fromRect: tiles->rects[TileBL] fromRect: tiles->rects[TileBL]
operation: NSCompositeSourceOver]; operation: NSCompositeSourceOver];
[tiles->images[TileBR] compositeToPoint: [tiles->images[TileBR] compositeToPoint:
NSMakePoint( NSMakePoint(
rect.origin.x + rect.size.width - brs.width, rect.origin.x + rect.size.width - brs.width,
rect.origin.y) rect.origin.y)
fromRect: tiles->rects[TileBR] fromRect: tiles->rects[TileBR]
operation: NSCompositeSourceOver]; operation: NSCompositeSourceOver];
inFill = NSMakeRect (rect.origin.x +cls.width,
rect.origin.y + bms.height,
rect.size.width - cls.width - crs.width,
rect.size.height - bms.height - tms.height);
inFill = NSMakeRect (rect.origin.x +cls.width,
rect.origin.y + bms.height,
rect.size.width - cls.width - crs.width,
rect.size.height - bms.height - tms.height);
}
else
{
inFill = rect;
NSLog(@"rect %@ too small fire tiles %@",
NSStringFromSize(rect.size), NSStringFromSize(tsz));
}
if (style == GSThemeFillStyleCenter) if (style == GSThemeFillStyleCenter)
{ {
NSRect r = tiles->rects[TileCM]; NSRect r = tiles->rects[TileCM];
@ -941,12 +1019,33 @@ withRepeatedImage: (NSImage*)image
fromRect: (NSRect)source fromRect: (NSRect)source
flipped: (BOOL)flipped flipped: (BOOL)flipped
{ {
NSGraphicsContext *ctxt = GSCurrentContext(); NSGraphicsContext *ctxt;
NSBezierPath *path; NSBezierPath *path;
unsigned repetitions; unsigned repetitions;
unsigned count; unsigned count;
NSPoint p; NSPoint p;
if (rect.size.width <= 0.0)
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] rect width is not positive",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
if (rect.size.height <= 0.0)
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] rect height is not positive",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
if (source.size.width <= 0.0)
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] source width is not positive",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
if (source.size.height <= 0.0)
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] source height is not positive",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
if (image == nil)
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] image is nil",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
ctxt = GSCurrentContext();
DPSgsave (ctxt); DPSgsave (ctxt);
path = [NSBezierPath bezierPathWithRect: rect]; path = [NSBezierPath bezierPathWithRect: rect];
[path addClip]; [path addClip];

View file

@ -72,7 +72,7 @@ static NSMutableArray *screenArray = nil;
+ (void) resetScreens + (void) resetScreens
{ {
screenArray = nil; DESTROY(screenArray);
} }
/** /**
@ -260,49 +260,54 @@ static NSMutableArray *screenArray = nil;
*/ */
- (NSDictionary*) deviceDescription - (NSDictionary*) deviceDescription
{ {
NSMutableDictionary *devDesc; if (_reserved == 0)
int bps = 0;
NSSize screenResolution;
NSString *colorSpaceName = nil;
GSDisplayServer *srv;
/*
* This method generates a dictionary from the
* information we have gathered from the screen.
*/
// Set the screen number in the current object.
devDesc = [NSMutableDictionary dictionary];
[devDesc setObject: [NSNumber numberWithInt: _screenNumber]
forKey: @"NSScreenNumber"];
// This is assumed since we are in NSScreen.
[devDesc setObject: @"YES" forKey: NSDeviceIsScreen];
// Add the NSDeviceSize dictionary item
[devDesc setObject: [NSValue valueWithSize: _frame.size]
forKey: NSDeviceSize];
// Add the NSDeviceResolution dictionary item
srv = GSCurrentServer();
if (srv != nil)
{ {
screenResolution = [srv resolutionForScreen: _screenNumber]; NSMutableDictionary *devDesc;
[devDesc setObject: [NSValue valueWithSize: screenResolution] int bps = 0;
forKey: NSDeviceResolution]; NSSize screenResolution;
NSString *colorSpaceName = nil;
GSDisplayServer *srv;
/*
* This method generates a dictionary from the
* information we have gathered from the screen.
*/
// Set the screen number in the current object.
devDesc = [[NSMutableDictionary alloc] initWithCapacity: 8];
[devDesc setObject: [NSNumber numberWithInt: _screenNumber]
forKey: @"NSScreenNumber"];
// This is assumed since we are in NSScreen.
[devDesc setObject: @"YES" forKey: NSDeviceIsScreen];
// Add the NSDeviceSize dictionary item
[devDesc setObject: [NSValue valueWithSize: _frame.size]
forKey: NSDeviceSize];
// Add the NSDeviceResolution dictionary item
srv = GSCurrentServer();
if (srv != nil)
{
screenResolution = [srv resolutionForScreen: _screenNumber];
[devDesc setObject: [NSValue valueWithSize: screenResolution]
forKey: NSDeviceResolution];
}
// Add the bits per sample entry
bps = NSBitsPerSampleFromDepth(_depth);
[devDesc setObject: [NSNumber numberWithInt: bps]
forKey: NSDeviceBitsPerSample];
// Add the color space entry.
colorSpaceName = NSColorSpaceFromDepth(_depth);
[devDesc setObject: colorSpaceName
forKey: NSDeviceColorSpaceName];
_reserved = (void*)[devDesc copy];
RELEASE(devDesc);
} }
return (NSDictionary*)_reserved;
// Add the bits per sample entry
bps = NSBitsPerSampleFromDepth(_depth);
[devDesc setObject: [NSNumber numberWithInt: bps]
forKey: NSDeviceBitsPerSample];
// Add the color space entry.
colorSpaceName = NSColorSpaceFromDepth(_depth);
[devDesc setObject: colorSpaceName
forKey: NSDeviceColorSpaceName];
return [NSDictionary dictionaryWithDictionary: devDesc];
} }
// Mac OS X methods // Mac OS X methods
@ -393,7 +398,10 @@ static NSMutableArray *screenArray = nil;
{ {
NSZoneFree(NSDefaultMallocZone(), _supportedWindowDepths); NSZoneFree(NSDefaultMallocZone(), _supportedWindowDepths);
} }
if (_reserved != 0)
{
[(id)_reserved release];
}
[super dealloc]; [super dealloc];
} }