00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "CGGeometry.h"
00024 #include "CGAffineTransform.h"
00025
00026 @import "CGGeometry.j"
00027 @import "CGAffineTransform.j"
00028
00029
00030 kCGPathElementMoveToPoint = 0;
00031 kCGPathElementAddLineToPoint = 1;
00032 kCGPathElementAddQuadCurveToPoint = 2;
00033 kCGPathElementAddCurveToPoint = 3;
00034 kCGPathElementCloseSubpath = 4;
00035
00036 kCGPathElementAddArc = 5;
00037 kCGPathElementAddArcToPoint = 6;
00038
00039 function CGPathCreateMutable()
00040 {
00041 return { count:0, start:NULL, current:NULL, elements:[] };
00042 }
00043
00044 function CGPathCreateMutableCopy(aPath)
00045 {
00046 var path = CGPathCreateMutable();
00047
00048 CGPathAddPath(path, aPath);
00049
00050 return path;
00051 }
00052
00053 function CGPathCreateCopy(aPath)
00054 {
00055 return CGPathCreateMutableCopy(aPath);
00056 }
00057
00058 function CGPathRelease(aPath)
00059 {
00060 }
00061
00062 function CGPathRetain(aPath)
00063 {
00064 return aPath;
00065 }
00066
00067 function CGPathAddArc(aPath, aTransform, x, y, aRadius, aStartAngle, anEndAngle, isClockwise)
00068 {
00069 if (aTransform && !_CGAffineTransformIsIdentity(aTransform))
00070 {
00071 var center = _CGPointMake(x, y),
00072 end = _CGPointMake(COS(anEndAngle), SIN(anEndAngle)),
00073 start = _CGPointMake(COS(aStartAngle), SIN(aStartAngle));
00074
00075 end = _CGPointApplyAffineTransform(end, aTransform);
00076 start = _CGPointApplyAffineTransform(start, aTransform);
00077 center = _CGPointApplyAffineTransform(center, aTransform);
00078
00079 x = center.x;
00080 y = center.y;
00081
00082 var oldEndAngle = anEndAngle,
00083 oldStartAngle = aStartAngle;
00084
00085 anEndAngle = ATAN2(end.y - aTransform.ty, end.x - aTransform.tx);
00086 aStartAngle = ATAN2(start.y - aTransform.ty, start.x - aTransform.tx);
00087
00088
00089
00090
00091 if (anEndAngle == aStartAngle && oldEndAngle != oldStartAngle)
00092 if (oldStartAngle > oldEndAngle)
00093 anEndAngle = anEndAngle - PI2;
00094 else
00095 aStartAngle = aStartAngle - PI2;
00096
00097 aRadius = _CGSizeMake(aRadius, 0);
00098 aRadius = _CGSizeApplyAffineTransform(aRadius, aTransform);
00099 aRadius = SQRT(aRadius.width * aRadius.width + aRadius.height * aRadius.height);
00100 }
00101
00102 aPath.current = _CGPointMake(x + aRadius * COS(anEndAngle), y + aRadius * SIN(anEndAngle));
00103 aPath.elements[aPath.count++] = { type:kCGPathElementAddArc, x:x, y:y, radius:aRadius, startAngle:aStartAngle, endAngle:anEndAngle };
00104 }
00105
00106 function CGPathAddArcToPoint(aPath, aTransform, x1, y1, x2, y2, aRadius)
00107 {
00108 }
00109
00110 function CGPathAddCurveToPoint(aPath, aTransform, cp1x, cp1y, cp2x, cp2y, x, y)
00111 {
00112 var cp1 = _CGPointMake(cp1x, cp1y),
00113 cp2 = _CGPointMake(cp2x, cp2y),
00114 end = _CGPointMake(x, y);
00115
00116 if (aTransform)
00117 {
00118 cp1 = _CGPointApplyAffineTransform(cp1, aTransform);
00119 cp2 = _CGPointApplyAffineTransform(cp2, aTransform);
00120 end = _CGPointApplyAffineTransform(end, aTransform);
00121 }
00122
00123 aPath.current = end;
00124 aPath.elements[aPath.count++] = { type:kCGPathElementAddCurveToPoint, cp1x:cp1.x, cp1y:cp1.y, cp2x:cp2.x, cp2y:cp2.y, x:end.x, y:end.y };
00125 }
00126
00127 function CGPathAddLines(aPath, aTransform, points, count)
00128 {
00129 var i = 1;
00130
00131 if (arguments["count"] == NULL)
00132 var count = points.length;
00133
00134 if (!aPath || count < 2)
00135 return;
00136
00137 CGPathMoveToPoint(aPath, aTransform, points[0].x, points[0].y);
00138
00139 for (; i < count; ++i)
00140 CGPathAddLineToPoint(aPath, aTransform, points[i].x, points[i].y);
00141 }
00142
00143 function CGPathAddLineToPoint(aPath, aTransform, x, y)
00144 {
00145 var point = _CGPointMake(x, y);
00146
00147 if (aTransform != NULL)
00148 point = _CGPointApplyAffineTransform(point, aTransform);
00149
00150 aPath.elements[aPath.count++] = { type: kCGPathElementAddLineToPoint, x:point.x, y:point.y };
00151 aPath.current = point;
00152 }
00153
00154 function CGPathAddPath(aPath, aTransform, anotherPath)
00155 {
00156 var i = 0,
00157 count = anotherPath.count;
00158
00159 for (; i < count; ++i)
00160 {
00161 var element = anotherPath[i];
00162
00163 aPath.elements[aPath.count++] = { type:element.type, points:element.point.slice() };
00164
00165 if (element.type == kCGPathElementAddArc || element.type == kCGPathElementAddArcToPoint)
00166 aPath.elements[aPath.count - 1].radius = element.radius;
00167 }
00168
00169 aPath.current = anotherPath.current;
00170 }
00171
00172 function CGPathAddQuadCurveToPoint(aPath, aTransform, cpx, cpy, x, y)
00173 {
00174 var cp = _CGPointMake(cpx, cpy),
00175 end = _CGPointMake(x, y);
00176
00177 if (aTransform)
00178 {
00179 cp = _CGPointApplyAffineTransform(control, aTransform);
00180 end = _CGPointApplyAffineTransform(end, aTransform);
00181 }
00182
00183 aPath.elements[aPath.count++] = { type:kCGPathElementAddQuadCurveToPoint, cpx:cp.x, cpy:cp.y, x:end.x, y:end.y }
00184 aPath.current = end;
00185 }
00186
00187 function CGPathAddRect(aPath, aTransform, aRect)
00188 {
00189 CGPathAddRects(aPath, aTransform, [aRect], 1);
00190 }
00191
00192 function CGPathAddRects(aPath, aTransform, rects, count)
00193 {
00194 var i = 0;
00195
00196 if (arguments["count"] == NULL)
00197 var count = rects.length;
00198
00199 for (; i < count; ++i)
00200 {
00201 var rect = rects[i];
00202
00203 CGPathMoveToPoint(aPath, aTransform, _CGRectGetMinX(rect), _CGRectGetMinY(rect));
00204 CGPathAddLineToPoint(aPath, aTransform, _CGRectGetMaxX(rect), _CGRectGetMinY(rect));
00205 CGPathAddLineToPoint(aPath, aTransform, _CGRectGetMaxX(rect), _CGRectGetMaxY(rect));
00206 CGPathAddLineToPoint(aPath, aTransform, _CGRectGetMinX(rect), _CGRectGetMaxY(rect));
00207
00208 CGPathCloseSubpath(aPath);
00209 }
00210 }
00211
00212 function CGPathMoveToPoint(aPath, aTransform, x, y)
00213 {
00214 var point = _CGPointMake(x, y),
00215 count = aPath.count;
00216
00217 if (aTransform != NULL)
00218 point = _CGPointApplyAffineTransform(point, aTransform);
00219
00220 aPath.start = point;
00221 aPath.current = point;
00222
00223 var previous = aPath.elements[count - 1];
00224
00225 if (count != 0 && previous.type == kCGPathElementMoveToPoint)
00226 {
00227 previous.x = point.x;
00228 previous.y = point.y;
00229 }
00230 else
00231 aPath.elements[aPath.count++] = { type:kCGPathElementMoveToPoint, x:point.x, y:point.y };
00232 }
00233
00234 function CGPathCloseSubpath(aPath)
00235 {
00236 var count = aPath.count;
00237
00238
00239 if (count == 0 || aPath.elements[count - 1].type == kCGPathElementCloseSubpath)
00240 return;
00241
00242 aPath.elements[aPath.count++] = { type:kCGPathElementCloseSubpath, points:[aPath.start] };
00243 }
00244
00245 function CGPathEqualToPath(aPath, anotherPath)
00246 {
00247 if (aPath == anotherPath)
00248 return YES;
00249
00250 if (aPath.count != anotherPath.count || !_CGPointEqualToPoint(aPath.start, anotherPath.start) || !_CGPointEqualToPoint(aPath.current, anotherPath.current))
00251 return NO;
00252
00253 var i = 0,
00254 count = aPath.count;
00255
00256 for (; i < count; ++i)
00257 {
00258 var element = aPath[i],
00259 anotherElement = anotherPath[i];
00260
00261 if (element.type != anotherElement.type)
00262 return NO;
00263
00264 if ((element.type == kCGPathElementAddArc || element.type == kCGPathElementAddArcToPoint) &&
00265 element.radius != anotherElement.radius)
00266 return NO;
00267
00268 var j = element.points.length;
00269
00270 while (j--)
00271 if (!_CGPointEqualToPoint(element.points[j], anotherElement.points[j]))
00272 return NO;
00273 }
00274
00275 return YES;
00276 }
00277
00278 function CGPathGetCurrentPoint(aPath)
00279 {
00280 return _CGPointCreateCopy(aPath.current);
00281 }
00282
00283 function CGPathIsEmpty(aPath)
00284 {
00285 return !aPath || aPath.count == 0;
00286 }