Merge Source/NSGradient.m Source/NSImage.m Source/NSImageRep.m

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/branches/gnustep_testplant_branch@38729 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Marcian Lytwyn 2015-06-30 23:04:56 +00:00
parent 1a6aa35155
commit d867a44374
3 changed files with 192 additions and 141 deletions

View file

@ -42,6 +42,12 @@
#define PI 3.1415926535897932384626434
#endif
@interface NSGradient (Private)
- (void) _drawInRect: (NSRect)rect angle: (CGFloat)angle;
- (void) _drawInRect: (NSRect)rect
relativeCenterPosition: (NSPoint)relativeCenterPoint;
@end
@implementation NSGradient
- (NSColorSpace *) colorSpace;
@ -79,7 +85,7 @@
[currentContext saveGraphicsState];
[path addClip];
[self drawInRect: [path bounds] angle: angle];
[self _drawInRect: [path bounds] angle: angle];
[currentContext restoreGraphicsState];
}
@ -90,102 +96,28 @@
[currentContext saveGraphicsState];
[path addClip];
[self drawInRect: [path bounds] relativeCenterPosition: relativeCenterPoint];
[self _drawInRect: [path bounds] relativeCenterPosition: relativeCenterPoint];
[currentContext restoreGraphicsState];
}
- (void) drawInRect: (NSRect)rect angle: (CGFloat)angle
{
NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
NSPoint startPoint;
NSPoint endPoint;
float rad;
float length;
// Normalize to 0.0 <= angle <= 360.0
while (angle < 0.0)
{
angle += 360.0;
}
while (angle > 360.0)
{
angle -= 360.0;
}
if (angle < 90.0)
{
startPoint = NSMakePoint(NSMinX(rect), NSMinY(rect));
}
else if (angle < 180.0)
{
startPoint = NSMakePoint(NSMaxX(rect), NSMinY(rect));
}
else if (angle < 270.0)
{
startPoint = NSMakePoint(NSMaxX(rect), NSMaxY(rect));
}
else
{
startPoint = NSMakePoint(NSMinX(rect), NSMaxY(rect));
}
rad = PI * angle / 180;
length = abs(NSWidth(rect) * cos(rad) + NSHeight(rect) * sin(rad));
endPoint = NSMakePoint(startPoint.x + length * cos(rad),
startPoint.y + length * sin(rad));
[currentContext saveGraphicsState];
[NSBezierPath clipRect: rect];
[self drawFromPoint: startPoint
toPoint: endPoint
options: 0];
[self _drawInRect: rect angle: angle];
[currentContext restoreGraphicsState];
}
static inline float sqr(float a)
{
return a * a;
}
static inline float euclidian_distance(NSPoint start, NSPoint end)
{
return sqrt(sqr(end.x - start.x) + sqr(end.y - start.y));
}
- (void) drawInRect: (NSRect)rect
relativeCenterPosition: (NSPoint)relativeCenterPoint
{
NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
NSPoint startCenter;
NSPoint endCenter;
CGFloat endRadius;
CGFloat distance;
NSAssert(relativeCenterPoint.x >= 0.0 && relativeCenterPoint.x <= 1.0, @"NSGradient invalid relative center point");
NSAssert(relativeCenterPoint.y >= 0.0 && relativeCenterPoint.y <= 1.0, @"NSGradient invalid relative center point");
startCenter = NSMakePoint(NSMidX(rect), NSMidY(rect));
endCenter = NSMakePoint(startCenter.x + rect.size.width * relativeCenterPoint.x,
startCenter.y + rect.size.height * relativeCenterPoint.y);
endRadius = 0.0;
distance = euclidian_distance(endCenter, NSMakePoint(NSMinX(rect), NSMinY(rect)));
if (endRadius < distance)
endRadius = distance;
distance = euclidian_distance(endCenter, NSMakePoint(NSMaxX(rect), NSMinY(rect)));
if (endRadius < distance)
endRadius = distance;
distance = euclidian_distance(endCenter, NSMakePoint(NSMinX(rect), NSMaxY(rect)));
if (endRadius < distance)
endRadius = distance;
distance = euclidian_distance(endCenter, NSMakePoint(NSMaxX(rect), NSMaxY(rect)));
if (endRadius < distance)
endRadius = distance;
[currentContext saveGraphicsState];
[NSBezierPath clipRect: rect];
[self drawFromCenter: startCenter
radius: 0.0
toCenter: endCenter
radius: endRadius
options: 0];
[self _drawInRect: rect relativeCenterPosition: relativeCenterPoint];
[currentContext restoreGraphicsState];
}
@ -365,3 +297,93 @@ relativeCenterPosition: (NSPoint)relativeCenterPoint
}
@end
@implementation NSGradient (Private)
- (void) _drawInRect: (NSRect)rect angle: (CGFloat)angle
{
NSPoint startPoint;
NSPoint endPoint;
float rad;
float length;
// Normalize to 0.0 <= angle <= 360.0
while (angle < 0.0)
{
angle += 360.0;
}
while (angle > 360.0)
{
angle -= 360.0;
}
if (angle < 90.0)
{
startPoint = NSMakePoint(NSMinX(rect), NSMinY(rect));
}
else if (angle < 180.0)
{
startPoint = NSMakePoint(NSMaxX(rect), NSMinY(rect));
}
else if (angle < 270.0)
{
startPoint = NSMakePoint(NSMaxX(rect), NSMaxY(rect));
}
else
{
startPoint = NSMakePoint(NSMinX(rect), NSMaxY(rect));
}
rad = PI * angle / 180;
length = fabs(NSWidth(rect) * cos(rad) + NSHeight(rect) * sin(rad));
endPoint = NSMakePoint(startPoint.x + length * cos(rad),
startPoint.y + length * sin(rad));
[self drawFromPoint: startPoint
toPoint: endPoint
options: 0];
}
static inline float sqr(float a)
{
return a * a;
}
static inline float euclidian_distance(NSPoint start, NSPoint end)
{
return sqrt(sqr(end.x - start.x) + sqr(end.y - start.y));
}
- (void) _drawInRect: (NSRect)rect
relativeCenterPosition: (NSPoint)relativeCenterPoint
{
NSPoint startCenter;
NSPoint endCenter;
CGFloat endRadius;
CGFloat distance;
NSAssert(relativeCenterPoint.x >= 0.0 && relativeCenterPoint.x <= 1.0, @"NSGradient invalid relative center point");
NSAssert(relativeCenterPoint.y >= 0.0 && relativeCenterPoint.y <= 1.0, @"NSGradient invalid relative center point");
startCenter = NSMakePoint(NSMidX(rect), NSMidY(rect));
endCenter = NSMakePoint(startCenter.x + rect.size.width * relativeCenterPoint.x,
startCenter.y + rect.size.height * relativeCenterPoint.y);
endRadius = 0.0;
distance = euclidian_distance(endCenter, NSMakePoint(NSMinX(rect), NSMinY(rect)));
if (endRadius < distance)
endRadius = distance;
distance = euclidian_distance(endCenter, NSMakePoint(NSMaxX(rect), NSMinY(rect)));
if (endRadius < distance)
endRadius = distance;
distance = euclidian_distance(endCenter, NSMakePoint(NSMinX(rect), NSMaxY(rect)));
if (endRadius < distance)
endRadius = distance;
distance = euclidian_distance(endCenter, NSMakePoint(NSMaxX(rect), NSMaxY(rect)));
if (endRadius < distance)
endRadius = distance;
[self drawFromCenter: startCenter
radius: 0.0
toCenter: endCenter
radius: endRadius
options: 0];
}
@end

View file

@ -96,6 +96,10 @@ NSString *const NSImageNameNetwork = @"NSNetwork";
// OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
NSString *const NSImageNameFolder = @"NSFolder";
@interface NSView (Private)
- (void) _lockFocusInContext: (NSGraphicsContext *)ctxt inRect: (NSRect)rect;
@end
@implementation NSBundle (NSImageAdditions)
- (NSString*) pathForImageResource: (NSString*)name
@ -499,6 +503,16 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
return NO;
}
- (NSString*) description
{
return [NSString stringWithFormat: @"<%@ %p Name=%@ Size=%@ Reps=%@>",
[self class],
self,
[self name],
NSStringFromSize([self size]),
[self representations]];
}
/* This methd sets the name of an image, updating the global name dictionary
* to point to the image (or removing an image from the dictionary if the
* new name is nil).
@ -788,7 +802,7 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
// Set the CTM to the identity matrix with the current translation
// and the user space scale factor
{
NSAffineTransform *backup = [ctxt GSCurrentCTM];
NSAffineTransform *backup = [[ctxt GSCurrentCTM] retain];
NSAffineTransform *newTransform = [NSAffineTransform transform];
NSPoint translation = [backup transformPoint: aPoint];
[newTransform translateXBy: translation.x
@ -803,6 +817,8 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
fraction: delta];
[ctxt GSSetCTM: backup];
[backup release];
}
}
@ -963,10 +979,13 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
{
GSRepData *repd;
repd = [GSRepData new];
repd->rep = RETAIN(imageRep);
[_reps addObject: repd];
RELEASE(repd);
if (imageRep != nil)
{
repd = [GSRepData new];
repd->rep = RETAIN(imageRep);
[_reps addObject: repd];
RELEASE(repd);
}
}
- (void) addRepresentations: (NSArray *)imageRepArray
@ -1035,9 +1054,14 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
window = [(NSCachedImageRep *)imageRep window];
_lockedView = [window contentView];
if (_lockedView == nil)
[NSException raise: NSImageCacheException
format: @"Cannot lock focus on nil rep"];
[_lockedView lockFocus];
{
[NSException raise: NSImageCacheException
format: @"Cannot lock focus on nil rep"];
}
// FIXME: This is needed to get image caching working while printing. A better solution
// needs to remove the viewIsPrinting variable from NSView.
[_lockedView _lockFocusInContext: [window graphicsContext] inRect: [_lockedView bounds]];
if (repd->bg == nil)
{
NSRect fillrect = NSMakeRect(0, 0, _size.width, _size.height);
@ -2394,61 +2418,65 @@ iterate_reps_for_types(NSArray* imageReps, SEL method)
}
// We end here, when no representation are there or no match is found.
{
NSImageRep *cacheRep = nil;
GSRepData *repd;
NSSize imageSize = [self size];
NSSize repSize;
NSInteger pixelsWide, pixelsHigh;
if (rep != nil)
{
repSize = [rep size];
if (repSize.width <= 0 || repSize.height <= 0)
repSize = imageSize;
pixelsWide = [rep pixelsWide];
pixelsHigh = [rep pixelsHigh];
if (pixelsWide == NSImageRepMatchesDevice ||
pixelsHigh == NSImageRepMatchesDevice)
{
// FIXME: Since the cached rep must be a bitmap,
// we must rasterize vector reps at a particular DPI.
// Here we hardcode 72, but we should choose the DPI more intelligently.
pixelsWide = repSize.width;
pixelsHigh = repSize.height;
}
}
else // e.g. when there are no representations at all
{
repSize = imageSize;
// FIXME: assumes 72 DPI. Also truncates, not sure if that is a problem.
pixelsWide = imageSize.width;
pixelsHigh = imageSize.height;
}
if (repSize.width <= 0 || repSize.height <= 0 ||
pixelsWide <= 0 || pixelsHigh <= 0)
{
NSImageRep *cacheRep = nil;
GSRepData *repd;
NSSize imageSize = [self size];
NSSize repSize;
NSInteger pixelsWide, pixelsHigh;
if (rep != nil)
{
repSize = [rep size];
if (repSize.width <= 0 || repSize.height <= 0)
repSize = imageSize;
pixelsWide = [rep pixelsWide];
pixelsHigh = [rep pixelsHigh];
if (pixelsWide == NSImageRepMatchesDevice ||
pixelsHigh == NSImageRepMatchesDevice)
{
// FIXME: Since the cached rep must be a bitmap,
// we must rasterize vector reps at a particular DPI.
// Here we hardcode 72, but we should choose the DPI more intelligently.
pixelsWide = repSize.width;
pixelsHigh = repSize.height;
}
}
else // e.g. when there are no representations at all
{
repSize = imageSize;
// FIXME: assumes 72 DPI. Also truncates, not sure if that is a problem.
pixelsWide = imageSize.width;
pixelsHigh = imageSize.height;
}
if (repSize.width <= 0 || repSize.height <= 0 ||
pixelsWide <= 0 || pixelsHigh <= 0)
return nil;
// Create a new cached image rep without any contents.
cacheRep = [[cachedClass alloc] initWithSize: repSize
pixelsWide: pixelsWide
pixelsHigh: pixelsHigh
depth: [[NSScreen mainScreen] depth]
separate: _flags.cacheSeparately
alpha: [rep hasAlpha]];
if (cacheRep == nil)
{
return nil;
// Create a new cached image rep without any contents.
cacheRep = [[cachedClass alloc]
initWithSize: repSize
pixelsWide: pixelsWide
pixelsHigh: pixelsHigh
depth: [[NSScreen mainScreen] depth]
separate: _flags.cacheSeparately
alpha: [rep hasAlpha]];
repd = [GSRepData new];
repd->rep = cacheRep;
repd->original = rep; // may be nil!
[_reps addObject: repd];
RELEASE(repd); /* Retained in _reps array. */
return repd;
}
}
repd = [GSRepData new];
repd->rep = cacheRep;
repd->original = rep; // may be nil!
[_reps addObject: repd];
RELEASE(repd); /* Retained in _reps array. */
return repd;
}
}
}

View file

@ -849,7 +849,7 @@ Fallback for backends other than Cairo. */
{
NSAffineTransform *newXform;
backup = [ctx GSCurrentCTM];
backup = [[ctx GSCurrentCTM] retain];
newXform = [backup copy];
[newXform translateXBy: dstRect.origin.x yBy: dstRect.origin.y + dstRect.size.height];
@ -876,6 +876,7 @@ Fallback for backends other than Cairo. */
if (compensateForFlip)
{
[ctx GSSetCTM: backup];
[backup release];
}
return YES;