mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-22 19:01:15 +00:00
* Source/NSBezierPath.m: Implement keyed coding and complete
keyed decoding. Patch by Christopher Armstrong <carmstrong@fastmail.com.au> * Source/NSBezierPath.m: Rewrote -elementAtIndex:associatedPoints: to return a point for NSClosePathBezierPathElement. And adjust all callers to make use of that point. Complete non-keyed coding and decoding. * Tests/gui/NSBezierPath/basic.m: Add basic tests for NSBezierPath. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@36267 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
6bb67c5e40
commit
2f6cc73444
3 changed files with 316 additions and 36 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,4 +1,16 @@
|
|||
2013-03-04 Fred Kiefer <FredKiefer@gmx.de>
|
||||
|
||||
* Source/NSBezierPath.m: Implement keyed coding and complete keyed
|
||||
decoding.
|
||||
Patch by Christopher Armstrong <carmstrong@fastmail.com.au>
|
||||
* Source/NSBezierPath.m: Rewrote -elementAtIndex:associatedPoints:
|
||||
to return a point for NSClosePathBezierPathElement. And adjust all
|
||||
callers to make use of that point. Complete non-keyed coding and
|
||||
decoding.
|
||||
* Tests/gui/NSBezierPath/basic.m: Add basic tests for NSBezierPath.
|
||||
|
||||
2013-03-02 Sebastian Reitenbach <sebastia@l00-bugdead-prods.de>
|
||||
|
||||
* Source/NSMenuItemCell.m
|
||||
* Headers/AppKit/NSMenuItemCell.h
|
||||
float -> CGFloat transitions
|
||||
|
|
|
@ -98,6 +98,10 @@ static CGFloat default_miter_limit = 10.0;
|
|||
|
||||
+ (void)initialize
|
||||
{
|
||||
if (self == [NSBezierPath class])
|
||||
{
|
||||
[self setVersion: 2];
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -664,7 +668,7 @@ static CGFloat default_miter_limit = 10.0;
|
|||
NSBezierPathElement type, last_type;
|
||||
NSPoint pts[3];
|
||||
NSPoint p, cp1, cp2;
|
||||
NSInteger i, j, count;
|
||||
NSInteger i, count;
|
||||
BOOL closed = NO;
|
||||
|
||||
/* Silence compiler warnings. */
|
||||
|
@ -689,17 +693,7 @@ static CGFloat default_miter_limit = 10.0;
|
|||
p = pts[2];
|
||||
break;
|
||||
case NSClosePathBezierPathElement:
|
||||
// find the first point of segment
|
||||
for (j = i - 1; j >= 0; j--)
|
||||
{
|
||||
type = [self elementAtIndex: i associatedPoints: pts];
|
||||
if (type == NSMoveToBezierPathElement)
|
||||
{
|
||||
p = pts[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
// FIXME: What to do if we don't find a move element?
|
||||
p = pts[0];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -793,7 +787,7 @@ static CGFloat default_miter_limit = 10.0;
|
|||
{
|
||||
NSBezierPathElement type;
|
||||
NSPoint points[3];
|
||||
NSInteger i, count;
|
||||
NSInteger count;
|
||||
|
||||
count = [self elementCount];
|
||||
if (!count)
|
||||
|
@ -811,13 +805,7 @@ static CGFloat default_miter_limit = 10.0;
|
|||
return points[2];
|
||||
break;
|
||||
case NSClosePathBezierPathElement:
|
||||
// We have to find the last move element and take its point
|
||||
for (i = count - 2; i >= 0; i--)
|
||||
{
|
||||
type = [self elementAtIndex: i associatedPoints: points];
|
||||
if (type == NSMoveToBezierPathElement)
|
||||
return points[0];
|
||||
}
|
||||
return points[0];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -853,19 +841,38 @@ static CGFloat default_miter_limit = 10.0;
|
|||
{
|
||||
PathElement elm = GSIArrayItemAtIndex(_pathElements, index).ext;
|
||||
NSBezierPathElement type = elm.type;
|
||||
NSInteger i;
|
||||
|
||||
if (points != NULL)
|
||||
{
|
||||
if (type == NSMoveToBezierPathElement || type == NSLineToBezierPathElement)
|
||||
switch(type)
|
||||
{
|
||||
case NSMoveToBezierPathElement:
|
||||
case NSLineToBezierPathElement:
|
||||
points[0] = elm.points[0];
|
||||
}
|
||||
else if (type == NSCurveToBezierPathElement)
|
||||
{
|
||||
break;
|
||||
case NSCurveToBezierPathElement:
|
||||
points[0] = elm.points[0];
|
||||
points[1] = elm.points[1];
|
||||
points[2] = elm.points[2];
|
||||
}
|
||||
break;
|
||||
case NSClosePathBezierPathElement:
|
||||
// We have to find the last move element and take its point
|
||||
for (i = index - 1; i >= 0; i--)
|
||||
{
|
||||
elm = GSIArrayItemAtIndex(_pathElements, i).ext;
|
||||
type = elm.type;
|
||||
if (type == NSMoveToBezierPathElement)
|
||||
{
|
||||
points[0] = elm.points[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
// FIXME: What to do if we don't find a move element?
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
|
@ -1686,8 +1693,102 @@ static int winding_curve(double_point from, double_point to, double_point c1,
|
|||
|
||||
if ([aCoder allowsKeyedCoding])
|
||||
{
|
||||
[aCoder encodeFloat: (float)_flatness forKey: @"NSFlatness"];
|
||||
// FIXME
|
||||
NSUInteger count, i;
|
||||
NSMutableData *d;
|
||||
float x,y;
|
||||
char ctype;
|
||||
|
||||
[aCoder encodeFloat: [self flatness] forKey: @"NSFlatness"];
|
||||
[aCoder encodeFloat: [self lineWidth] forKey: @"NSLineWidth"];
|
||||
[aCoder encodeInt: [self lineCapStyle] forKey: @"NSLineCapStyle"];
|
||||
[aCoder encodeInt: [self lineJoinStyle] forKey: @"NSLineJoinStyle"];
|
||||
[aCoder encodeInt: [self windingRule] forKey: @"NSWindingRule"];
|
||||
[aCoder encodeFloat: [self miterLimit] forKey: @"NSMiterLimit"];
|
||||
|
||||
count = [self elementCount];
|
||||
d = [[NSMutableData alloc] init];
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
type = [self elementAtIndex: i associatedPoints: pts];
|
||||
ctype = type;
|
||||
[d serializeDataAt: &ctype
|
||||
ofObjCType: "c"
|
||||
context: nil];
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case NSMoveToBezierPathElement:
|
||||
case NSLineToBezierPathElement:
|
||||
x = pts[0].x;
|
||||
y = pts[0].y;
|
||||
[d serializeDataAt: &x
|
||||
ofObjCType: "f"
|
||||
context: nil];
|
||||
[d serializeDataAt: &y
|
||||
ofObjCType: "f"
|
||||
context: nil];
|
||||
break;
|
||||
case NSCurveToBezierPathElement:
|
||||
x = pts[0].x;
|
||||
y = pts[0].y;
|
||||
[d serializeDataAt: &x
|
||||
ofObjCType: "f"
|
||||
context: nil];
|
||||
[d serializeDataAt: &y
|
||||
ofObjCType: "f"
|
||||
context: nil];
|
||||
[d serializeDataAt: &ctype
|
||||
ofObjCType: "c"
|
||||
context: nil];
|
||||
x = pts[1].x;
|
||||
y = pts[1].y;
|
||||
[d serializeDataAt: &x
|
||||
ofObjCType: "f"
|
||||
context: nil];
|
||||
[d serializeDataAt: &y
|
||||
ofObjCType: "f"
|
||||
context: nil];
|
||||
[d serializeDataAt: &ctype
|
||||
ofObjCType: "c"
|
||||
context: nil];
|
||||
x = pts[2].x;
|
||||
y = pts[2].y;
|
||||
[d serializeDataAt: &x
|
||||
ofObjCType: "f"
|
||||
context: nil];
|
||||
[d serializeDataAt: &y
|
||||
ofObjCType: "f"
|
||||
context: nil];
|
||||
break;
|
||||
case NSClosePathBezierPathElement:
|
||||
x = pts[0].x;
|
||||
y = pts[0].y;
|
||||
[d serializeDataAt: &x
|
||||
ofObjCType: "f"
|
||||
context: nil];
|
||||
[d serializeDataAt: &y
|
||||
ofObjCType: "f"
|
||||
context: nil];
|
||||
[d serializeDataAt: &ctype
|
||||
ofObjCType: "c"
|
||||
context: nil];
|
||||
x = pts[0].x;
|
||||
y = pts[0].y;
|
||||
[d serializeDataAt: &x
|
||||
ofObjCType: "f"
|
||||
context: nil];
|
||||
[d serializeDataAt: &y
|
||||
ofObjCType: "f"
|
||||
context: nil];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
[aCoder encodeBytes: [d bytes]
|
||||
length: [d length]
|
||||
forKey: @"NSSegments"];
|
||||
RELEASE(d);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1703,6 +1804,12 @@ static int winding_curve(double_point from, double_point to, double_point c1,
|
|||
i = [self windingRule];
|
||||
[aCoder encodeValueOfObjCType: @encode(int) at: &i];
|
||||
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &_cachesBezierPath];
|
||||
|
||||
// version 2
|
||||
f = [self flatness];
|
||||
[aCoder encodeValueOfObjCType: @encode(float) at: &f];
|
||||
f = [self miterLimit];
|
||||
[aCoder encodeValueOfObjCType: @encode(float) at: &f];
|
||||
|
||||
count = [self elementCount];
|
||||
[aCoder encodeValueOfObjCType: @encode(int) at: &count];
|
||||
|
@ -1741,6 +1848,7 @@ static int winding_curve(double_point from, double_point to, double_point c1,
|
|||
if ([aCoder allowsKeyedCoding])
|
||||
{
|
||||
float f;
|
||||
int i;
|
||||
|
||||
if ([aCoder containsValueForKey: @"NSFlatness"])
|
||||
{
|
||||
|
@ -1752,6 +1860,27 @@ static int winding_curve(double_point from, double_point to, double_point c1,
|
|||
f = [aCoder decodeFloatForKey: @"NSLineWidth"];
|
||||
[self setLineWidth: f];
|
||||
}
|
||||
if ([aCoder containsValueForKey: @"NSLineCapStyle"])
|
||||
{
|
||||
i = [aCoder decodeIntForKey: @"NSLineCapStyle"];
|
||||
[self setLineCapStyle: i];
|
||||
}
|
||||
if ([aCoder containsValueForKey: @"NSLineJoinStyle"])
|
||||
{
|
||||
i = [aCoder decodeIntForKey: @"NSLineJoinStyle"];
|
||||
[self setLineJoinStyle: i];
|
||||
}
|
||||
if ([aCoder containsValueForKey: @"NSWindingRule"])
|
||||
{
|
||||
i = [aCoder decodeIntForKey: @"NSWindingRule"];
|
||||
[self setWindingRule: i];
|
||||
}
|
||||
if ([aCoder containsValueForKey: @"NSMiterLimit"])
|
||||
{
|
||||
f = [aCoder decodeFloatForKey: @"NSMiterLimit"];
|
||||
[self setMiterLimit: f];
|
||||
}
|
||||
|
||||
if ([aCoder containsValueForKey: @"NSSegments"])
|
||||
{
|
||||
NSUInteger length;
|
||||
|
@ -1870,6 +1999,7 @@ static int winding_curve(double_point from, double_point to, double_point c1,
|
|||
[self closePath];
|
||||
break;
|
||||
default:
|
||||
//NSLog(@"Unable to decode unknown bezier path element type %d", c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1881,6 +2011,7 @@ static int winding_curve(double_point from, double_point to, double_point c1,
|
|||
NSPoint pts[3];
|
||||
int i, count;
|
||||
float f;
|
||||
int version = [aCoder versionForClassName: @"NSBezierPath"];
|
||||
|
||||
[aCoder decodeValueOfObjCType: @encode(float) at: &f];
|
||||
[self setLineWidth: f];
|
||||
|
@ -1892,6 +2023,14 @@ static int winding_curve(double_point from, double_point to, double_point c1,
|
|||
[self setWindingRule: i];
|
||||
[aCoder decodeValueOfObjCType: @encode(BOOL) at: &_cachesBezierPath];
|
||||
|
||||
if (version >= 2)
|
||||
{
|
||||
[aCoder decodeValueOfObjCType: @encode(float) at: &f];
|
||||
[self setFlatness: f];
|
||||
[aCoder decodeValueOfObjCType: @encode(float) at: &f];
|
||||
[self setMiterLimit: f];
|
||||
}
|
||||
|
||||
[aCoder decodeValueOfObjCType: @encode(int) at: &count];
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
|
@ -1975,12 +2114,9 @@ static NSPoint point_on_curve(double t, NSPoint a, NSPoint b, NSPoint c,
|
|||
{
|
||||
NSBezierPathElement type;
|
||||
NSPoint p; /* Current point. */
|
||||
NSPoint last_move;
|
||||
NSPoint pts[3];
|
||||
|
||||
NSPoint min, max; /* Path bounding box. */
|
||||
NSPoint cmin, cmax; /* Control-point bounding box. */
|
||||
|
||||
int i, count, num_curves;
|
||||
|
||||
count = [self elementCount];
|
||||
|
@ -1992,7 +2128,7 @@ static NSPoint point_on_curve(double t, NSPoint a, NSPoint b, NSPoint c,
|
|||
return;
|
||||
}
|
||||
|
||||
last_move = p = min = max = cmin = cmax = NSMakePoint(0, 0);
|
||||
p = min = max = cmin = cmax = NSMakePoint(0, 0);
|
||||
|
||||
#define CHECK_MAX(max, p) \
|
||||
if (p.x > max.x) max.x = p.x; \
|
||||
|
@ -2006,20 +2142,18 @@ static NSPoint point_on_curve(double t, NSPoint a, NSPoint b, NSPoint c,
|
|||
{
|
||||
type = [self elementAtIndex: i associatedPoints: pts];
|
||||
|
||||
if (!i)
|
||||
if (i == 0)
|
||||
{
|
||||
cmin = cmax = min = max = p = last_move = pts[0];
|
||||
cmin = cmax = min = max = p = pts[0];
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case NSClosePathBezierPathElement:
|
||||
p = last_move;
|
||||
p = pts[0];
|
||||
continue;
|
||||
|
||||
case NSMoveToBezierPathElement:
|
||||
last_move = pts[0];
|
||||
/* Fall-through. */
|
||||
case NSLineToBezierPathElement:
|
||||
CHECK_MAX(max, pts[0])
|
||||
CHECK_MIN(min, pts[0])
|
||||
|
|
134
Tests/gui/NSBezierPath/basic.m
Normal file
134
Tests/gui/NSBezierPath/basic.m
Normal file
|
@ -0,0 +1,134 @@
|
|||
#import "ObjectTesting.h"
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSAutoreleasePool.h>
|
||||
#import <AppKit/NSBezierPath.h>
|
||||
#include <math.h>
|
||||
|
||||
static BOOL eq(double d1, double d2)
|
||||
{
|
||||
if (abs(d1 - d2) < 0.000001)
|
||||
return YES;
|
||||
return NO;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
NSAutoreleasePool *arp = [NSAutoreleasePool new];
|
||||
id testObject;
|
||||
id testObject1;
|
||||
id testObject2;
|
||||
NSArray *testObjects;
|
||||
|
||||
testObject = [NSBezierPath new];
|
||||
testObject1 = [NSBezierPath bezierPathWithRoundedRect: NSMakeRect(0, 0, 20, 30)
|
||||
xRadius: 2.0
|
||||
yRadius: 3.0];
|
||||
testObject2 = [NSBezierPath new];
|
||||
[testObject2 setLineWidth: 12.4];
|
||||
[testObject2 setFlatness: 13.4];
|
||||
[testObject2 setLineCapStyle: NSSquareLineCapStyle];
|
||||
[testObject2 setLineJoinStyle: NSRoundLineJoinStyle];
|
||||
[testObject2 setMiterLimit: 14.4];
|
||||
[testObject2 setWindingRule: NSEvenOddWindingRule];
|
||||
testObjects = [NSArray arrayWithObjects: testObject, testObject1, testObject2, nil];
|
||||
RELEASE(testObject);
|
||||
RELEASE(testObject2);
|
||||
|
||||
test_alloc(@"NSBezierPath");
|
||||
test_NSObject(@"NSBezierPath", testObjects);
|
||||
test_NSCoding(testObjects);
|
||||
test_keyed_NSCoding(testObjects);
|
||||
test_NSCopying(@"NSBezierPath",
|
||||
@"NSBezierPath",
|
||||
testObjects, NO, NO);
|
||||
|
||||
[arp release];
|
||||
return 0;
|
||||
}
|
||||
|
||||
@implementation NSBezierPath (Testing)
|
||||
|
||||
- (BOOL) isEqual: (id)anObject
|
||||
{
|
||||
NSInteger i;
|
||||
NSBezierPathElement type1;
|
||||
NSPoint pts1[3];
|
||||
NSBezierPathElement type2;
|
||||
NSPoint pts2[3];
|
||||
|
||||
if (self == anObject)
|
||||
return YES;
|
||||
if (![anObject isKindOfClass: [NSBezierPath class]])
|
||||
return NO;
|
||||
if (!eq([self lineWidth], [anObject lineWidth]))
|
||||
{
|
||||
NSLog(@"different lineWidth %g %g", (float)[self lineWidth], (float)[anObject lineWidth]);
|
||||
return NO;
|
||||
}
|
||||
if (!eq([self flatness], [anObject flatness]))
|
||||
{
|
||||
NSLog(@"different flatness %g %g", (float)[self flatness], (float)[anObject flatness]);
|
||||
return NO;
|
||||
}
|
||||
if (!eq([self miterLimit], [anObject miterLimit]))
|
||||
{
|
||||
NSLog(@"different miterLimit %g %g", (float)[self miterLimit], (float)[anObject miterLimit]);
|
||||
return NO;
|
||||
}
|
||||
if ([self lineCapStyle] != [anObject lineCapStyle])
|
||||
{
|
||||
NSLog(@"different lineCapStyle %d %d", [self lineCapStyle], [anObject lineCapStyle]);
|
||||
return NO;
|
||||
}
|
||||
if ([self lineJoinStyle] != [anObject lineJoinStyle])
|
||||
{
|
||||
NSLog(@"different lineJoinStyle %d %d", [self lineJoinStyle], [anObject lineJoinStyle]);
|
||||
return NO;
|
||||
}
|
||||
if ([self windingRule] != [anObject windingRule])
|
||||
{
|
||||
NSLog(@"different winding rule %d %d", [self windingRule], [anObject windingRule]);
|
||||
return NO;
|
||||
}
|
||||
|
||||
if ([self elementCount] != [anObject elementCount])
|
||||
{
|
||||
NSLog(@"different element count %d %d", [self elementCount], [anObject elementCount]);
|
||||
return NO;
|
||||
}
|
||||
|
||||
for (i = 0; i < [self elementCount]; i++)
|
||||
{
|
||||
type1 = [self elementAtIndex: i associatedPoints: pts1];
|
||||
type2 = [anObject elementAtIndex: i associatedPoints: pts2];
|
||||
if (type1 != type2)
|
||||
{
|
||||
NSLog(@"different type count %d %d", type1, type2);
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (!eq(pts1[0].x, pts2[0].x) || !eq(pts1[0].y, pts2[0].y))
|
||||
{
|
||||
NSLog(@"different point %@ %@", NSStringFromPoint(pts1[0]), NSStringFromPoint(pts2[0]));
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (type1 == NSCurveToBezierPathElement)
|
||||
{
|
||||
if (!eq(pts1[1].x, pts2[1].x) || !eq(pts1[1].y, pts2[1].y))
|
||||
{
|
||||
NSLog(@"different point %@ %@", NSStringFromPoint(pts1[1]), NSStringFromPoint(pts2[1]));
|
||||
return NO;
|
||||
}
|
||||
if (!eq(pts1[2].x, pts2[2].x) || !eq(pts1[2].y, pts2[2].y))
|
||||
{
|
||||
NSLog(@"different point %@ %@", NSStringFromPoint(pts1[2]), NSStringFromPoint(pts2[2]));
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
Loading…
Reference in a new issue