/AppKit/CPBezierPath.j

http://github.com/cacaodev/cappuccino · Unknown · 380 lines · 318 code · 62 blank · 0 comment · 0 complexity · ba6a824944e731188c11618c2dff2f6e MD5 · raw file

  1. /*
  2. * CPBezierPath.j
  3. *
  4. * Created by Ross Boucher.
  5. * Copyright 2009, 280 North, Inc.
  6. *
  7. * Adapted from Kevin Wojniak, portions Copyright 2009 Kevin Wojniak.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 2.1 of the License, or (at your option) any later version.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. * Copyright 2009 280 North, Inc.
  23. */
  24. @import <Foundation/CPObject.j>
  25. @import "CPGraphicsContext.j"
  26. // Class defaults
  27. var DefaultLineWidth = 1.0;
  28. /*!
  29. @ingroup appkit
  30. @class CPBezierPath
  31. A CPBezierPath allows you to create paths for drawing to the screen using a simpler API than CoreGraphics.
  32. Paths can form any shape, including regular polygons like squares and triangles; circles, arcs; or complex
  33. line segments.
  34. A path can be stroked and filled using the relevant method. The currently active fill and stroke color will
  35. be used, which can be set by calling setFill: and setStroke: on any CPColor object (or set: for both).
  36. */
  37. @implementation CPBezierPath : CPObject
  38. {
  39. CGPath _path;
  40. float _lineWidth;
  41. CPArray _lineDashes;
  42. float _lineDashesPhase;
  43. }
  44. /*!
  45. Create a new CPBezierPath object.
  46. */
  47. + (CPBezierPath)bezierPath
  48. {
  49. return [[self alloc] init];
  50. }
  51. /*!
  52. Create a new CPBezierPath object initialized with an oval path drawn within a rectangular path.
  53. */
  54. + (CPBezierPath)bezierPathWithOvalInRect:(CGRect)aRect
  55. {
  56. var path = [self bezierPath];
  57. [path appendBezierPathWithOvalInRect:aRect];
  58. return path;
  59. }
  60. /*!
  61. Create a new CPBezierPath object initialized with a rectangular path.
  62. */
  63. + (CPBezierPath)bezierPathWithRect:(CGRect)aRect
  64. {
  65. var path = [self bezierPath];
  66. [path appendBezierPathWithRect:aRect];
  67. return path;
  68. }
  69. + (CPBezierPath)bezierPathWithRoundedRect:(CGRect)aRect xRadius:(float)xRadius yRadius:(float)yRadius
  70. {
  71. var path = [self bezierPath];
  72. [path appendBezierPathWithRoundedRect:aRect xRadius:xRadius yRadius:yRadius];
  73. return path;
  74. }
  75. /*!
  76. Get default line width.
  77. */
  78. + (float)defaultLineWidth
  79. {
  80. return DefaultLineWidth;
  81. }
  82. /*!
  83. Set default line width.
  84. */
  85. + (void)setDefaultLineWidth:(float)width
  86. {
  87. DefaultLineWidth = width;
  88. }
  89. /*!
  90. Fill rectangular path with current fill color.
  91. */
  92. + (void)fillRect:(CGRect)aRect
  93. {
  94. [[self bezierPathWithRect:aRect] fill];
  95. }
  96. /*!
  97. Using the current stroke color and default drawing attributes, strokes a counterclockwise path beginning at the rectangle's origin.
  98. */
  99. + (void)strokeRect:(CGRect)aRect
  100. {
  101. [[self bezierPathWithRect:aRect] stroke];
  102. }
  103. /*!
  104. Using the current stroke color and default drawing attributes, strokes a line between two points.
  105. */
  106. + (void)strokeLineFromPoint:(CGPoint)point1 toPoint:(CGPoint)point2
  107. {
  108. var path = [self bezierPath];
  109. [path moveToPoint:point1];
  110. [path lineToPoint:point2];
  111. [path stroke];
  112. }
  113. /*!
  114. Create a new CPBezierPath object using the default line width.
  115. */
  116. - (id)init
  117. {
  118. if (self = [super init])
  119. {
  120. _path = CGPathCreateMutable();
  121. _lineWidth = [[self class] defaultLineWidth];
  122. _lineDashesPhase = 0;
  123. _lineDashes = [];
  124. }
  125. return self;
  126. }
  127. /*!
  128. Moves the current point to another location.
  129. */
  130. - (void)moveToPoint:(CGPoint)point
  131. {
  132. CGPathMoveToPoint(_path, nil, point.x, point.y);
  133. }
  134. /*!
  135. Append a straight line to the path.
  136. */
  137. - (void)lineToPoint:(CGPoint)point
  138. {
  139. CGPathAddLineToPoint(_path, nil, point.x, point.y);
  140. }
  141. /*!
  142. Add a cubic Bezier curve to the path.
  143. */
  144. - (void)curveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2
  145. {
  146. CGPathAddCurveToPoint(_path, nil, controlPoint1.x, controlPoint1.y, controlPoint2.x, controlPoint2.y, endPoint.x, endPoint.y);
  147. }
  148. - (CGRect)bounds
  149. {
  150. // TODO: this should return this. The controlPointBounds is not a tight fit.
  151. // return CGPathGetBoundingBox(_path);
  152. return [self controlPointBounds];
  153. }
  154. - (CGRect)controlPointBounds
  155. {
  156. return CGPathGetBoundingBox(_path);
  157. }
  158. /*!
  159. Create a line segment between the first and last points in the subpath, closing it.
  160. */
  161. - (void)closePath
  162. {
  163. CGPathCloseSubpath(_path);
  164. }
  165. /*!
  166. Draw a line along the path with the current stroke color and default drawing attributes.
  167. */
  168. - (void)stroke
  169. {
  170. var ctx = [[CPGraphicsContext currentContext] graphicsPort];
  171. CGContextBeginPath(ctx);
  172. CGContextAddPath(ctx, _path);
  173. CGContextSetLineWidth(ctx, [self lineWidth]);
  174. CGContextSetLineDash(ctx, _lineDashesPhase, _lineDashes);
  175. CGContextStrokePath(ctx);
  176. }
  177. /*!
  178. Fill the path with the current fill color.
  179. */
  180. - (void)fill
  181. {
  182. var ctx = [[CPGraphicsContext currentContext] graphicsPort];
  183. CGContextBeginPath(ctx);
  184. CGContextAddPath(ctx, _path);
  185. CGContextSetLineWidth(ctx, [self lineWidth]);
  186. CGContextSetLineDash(ctx, _lineDashesPhase, _lineDashes);
  187. CGContextClosePath(ctx);
  188. CGContextFillPath(ctx);
  189. }
  190. /*!
  191. Cocoa compatibility.
  192. */
  193. - (void)getLineDash:(CPArrayRef)patternRef count:(NSInteger)count phase:(CGFloatRef)phaseRef
  194. {
  195. return [self getLineDash:patternRef phase:phaseRef];
  196. }
  197. /*!
  198. Retrieve the line dash pattern and phase and write them into the provided references.
  199. */
  200. - (void)getLineDash:(CPArrayRef)patternRef phase:(CGFloatRef)phaseRef
  201. {
  202. if (patternRef)
  203. @deref(patternRef) = [_lineDashes copy];
  204. if (phaseRef)
  205. @deref(phaseRef) = _lineDashesPhase;
  206. }
  207. /*!
  208. Cocoa compatibility.
  209. */
  210. - (void)setLineDash:(CPArray)aPattern count:(NSInteger)count phase:(CGFloat)aPhase
  211. {
  212. [self setLineDash:aPattern phase:aPhase];
  213. }
  214. /*!
  215. Set stroke line dash pattern.
  216. @param aPattern an array of stroke-skip lengths such as [2, 2, 4, 4]
  217. @param aPhase amount of shift for the starting position of the first stroke
  218. */
  219. - (void)setLineDash:(CPArray)aPattern phase:(CGFloat)aPhase
  220. {
  221. _lineDashes = aPattern;
  222. _lineDashesPhase = aPhase;
  223. }
  224. /*!
  225. Get the line width.
  226. */
  227. - (float)lineWidth
  228. {
  229. return _lineWidth;
  230. }
  231. /*!
  232. Set the line width.
  233. */
  234. - (void)setLineWidth:(float)lineWidth
  235. {
  236. _lineWidth = lineWidth;
  237. }
  238. /*!
  239. Get the total number of elements.
  240. */
  241. - (unsigned)elementCount
  242. {
  243. return _path.count;
  244. }
  245. /*!
  246. Check if receiver is empty, returns appropriate Boolean value.
  247. */
  248. - (BOOL)isEmpty
  249. {
  250. return CGPathIsEmpty(_path);
  251. }
  252. /*!
  253. Get the current point.
  254. */
  255. - (CGPoint)currentPoint
  256. {
  257. return CGPathGetCurrentPoint(_path);
  258. }
  259. /*!
  260. Append a series of line segments.
  261. */
  262. - (void)appendBezierPathWithPoints:(CPArray)points count:(unsigned)count
  263. {
  264. CGPathAddLines(_path, nil, points, count);
  265. }
  266. /*!
  267. Append a rectangular path.
  268. */
  269. - (void)appendBezierPathWithRect:(CGRect)rect
  270. {
  271. CGPathAddRect(_path, nil, rect);
  272. }
  273. /*!
  274. Append an oval path; oval is drawn within the rectangular path.
  275. */
  276. - (void)appendBezierPathWithOvalInRect:(CGRect)rect
  277. {
  278. CGPathAddPath(_path, nil, CGPathWithEllipseInRect(rect));
  279. }
  280. /*!
  281. Append a rounded rectangular path.
  282. */
  283. - (void)appendBezierPathWithRoundedRect:(CGRect)rect xRadius:(float)xRadius yRadius:(float)yRadius
  284. {
  285. CGPathAddPath(_path, nil, CGPathWithRoundedRectangleInRect(rect, xRadius, yRadius, YES, YES, YES, YES));
  286. }
  287. - (void)appendBezierPathWithArcFromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint radius:(float)radius
  288. {
  289. CGPathAddArcToPoint(_path, null, fromPoint.x, fromPoint.y, toPoint.x, toPoint.y, radius);
  290. }
  291. /*!
  292. Append the contents of a CPBezierPath object.
  293. */
  294. - (void)appendBezierPath:(CPBezierPath)other
  295. {
  296. CGPathAddPath(_path, nil, other._path);
  297. }
  298. /*!
  299. Remove all path elements; clears path.
  300. */
  301. - (void)removeAllPoints
  302. {
  303. _path = CGPathCreateMutable();
  304. }
  305. - (void)addClip
  306. {
  307. var ctx = [[CPGraphicsContext currentContext] graphicsPort];
  308. CGContextAddPath(ctx, _path);
  309. CGContextClip(ctx);
  310. }
  311. - (void)setClip
  312. {
  313. var ctx = [[CPGraphicsContext currentContext] graphicsPort];
  314. CGContextBeginPath(ctx);
  315. CGContextAddPath(ctx, _path);
  316. CGContextClip(ctx);
  317. }
  318. @end