PageRenderTime 21ms CodeModel.GetById 12ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

/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
 25@import <Foundation/CPObject.j>
 26
 27@import "CPGraphicsContext.j"
 28
 29
 30// Class defaults
 31
 32var DefaultLineWidth = 1.0;
 33
 34
 35/*!
 36    @ingroup appkit
 37    @class CPBezierPath
 38
 39    A CPBezierPath allows you to create paths for drawing to the screen using a simpler API than CoreGraphics.
 40    Paths can form any shape, including regular polygons like squares and triangles; circles, arcs; or complex
 41    line segments.
 42
 43    A path can be stroked and filled using the relevant method. The currently active fill and stroke color will
 44    be used, which can be set by calling setFill: and setStroke: on any CPColor object (or set: for both).
 45*/
 46
 47@implementation CPBezierPath : CPObject
 48{
 49    CGPath  _path;
 50    float   _lineWidth;
 51    CPArray _lineDashes;
 52    float   _lineDashesPhase;
 53}
 54
 55/*!
 56    Create a new CPBezierPath object.
 57*/
 58+ (CPBezierPath)bezierPath
 59{
 60    return [[self alloc] init];
 61}
 62
 63/*!
 64    Create a new CPBezierPath object initialized with an oval path drawn within a rectangular path.
 65*/
 66+ (CPBezierPath)bezierPathWithOvalInRect:(CGRect)aRect
 67{
 68    var path = [self bezierPath];
 69
 70    [path appendBezierPathWithOvalInRect:aRect];
 71
 72    return path;
 73}
 74
 75/*!
 76    Create a new CPBezierPath object initialized with a rectangular path.
 77*/
 78+ (CPBezierPath)bezierPathWithRect:(CGRect)aRect
 79{
 80    var path = [self bezierPath];
 81
 82    [path appendBezierPathWithRect:aRect];
 83
 84    return path;
 85}
 86
 87+ (CPBezierPath)bezierPathWithRoundedRect:(CGRect)aRect xRadius:(float)xRadius yRadius:(float)yRadius
 88{
 89    var path = [self bezierPath];
 90
 91    [path appendBezierPathWithRoundedRect:aRect xRadius:xRadius yRadius:yRadius];
 92
 93    return path;
 94}
 95
 96/*!
 97    Get default line width.
 98*/
 99+ (float)defaultLineWidth
100{
101    return DefaultLineWidth;
102}
103
104/*!
105    Set default line width.
106*/
107+ (void)setDefaultLineWidth:(float)width
108{
109    DefaultLineWidth = width;
110}
111
112/*!
113    Fill rectangular path with current fill color.
114*/
115+ (void)fillRect:(CGRect)aRect
116{
117    [[self bezierPathWithRect:aRect] fill];
118}
119
120/*!
121    Using the current stroke color and default drawing attributes, strokes a counterclockwise path beginning at the rectangle's origin.
122*/
123+ (void)strokeRect:(CGRect)aRect
124{
125    [[self bezierPathWithRect:aRect] stroke];
126}
127
128/*!
129    Using the current stroke color and default drawing attributes, strokes a line between two points.
130*/
131+ (void)strokeLineFromPoint:(CGPoint)point1 toPoint:(CGPoint)point2
132{
133    var path = [self bezierPath];
134
135    [path moveToPoint:point1];
136    [path lineToPoint:point2];
137
138    [path stroke];
139}
140
141/*!
142    Create a new CPBezierPath object using the default line width.
143*/
144- (id)init
145{
146    if (self = [super init])
147    {
148        _path = CGPathCreateMutable();
149        _lineWidth = [[self class] defaultLineWidth];
150        _lineDashesPhase = 0;
151        _lineDashes = [];
152    }
153
154    return self;
155}
156
157/*!
158    Moves the current point to another location.
159*/
160- (void)moveToPoint:(CGPoint)point
161{
162    CGPathMoveToPoint(_path, nil, point.x, point.y);
163}
164
165/*!
166    Append a straight line to the path.
167*/
168- (void)lineToPoint:(CGPoint)point
169{
170    CGPathAddLineToPoint(_path, nil, point.x, point.y);
171}
172
173/*!
174    Add a cubic Bezier curve to the path.
175*/
176- (void)curveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2
177{
178    CGPathAddCurveToPoint(_path, nil, controlPoint1.x, controlPoint1.y, controlPoint2.x, controlPoint2.y, endPoint.x, endPoint.y);
179}
180
181- (CGRect)bounds
182{
183    // TODO: this should return this. The controlPointBounds is not a tight fit.
184    // return CGPathGetBoundingBox(_path);
185
186    return [self controlPointBounds];
187}
188
189- (CGRect)controlPointBounds
190{
191    return CGPathGetBoundingBox(_path);
192}
193
194/*!
195    Create a line segment between the first and last points in the subpath, closing it.
196*/
197- (void)closePath
198{
199    CGPathCloseSubpath(_path);
200}
201
202/*!
203    Draw a line along the path with the current stroke color and default drawing attributes.
204*/
205- (void)stroke
206{
207    var ctx = [[CPGraphicsContext currentContext] graphicsPort];
208
209    CGContextBeginPath(ctx);
210    CGContextAddPath(ctx, _path);
211    CGContextSetLineWidth(ctx, [self lineWidth]);
212    CGContextSetLineDash(ctx, _lineDashesPhase, _lineDashes);
213    CGContextStrokePath(ctx);
214}
215
216/*!
217    Fill the path with the current fill color.
218*/
219- (void)fill
220{
221    var ctx = [[CPGraphicsContext currentContext] graphicsPort];
222
223    CGContextBeginPath(ctx);
224    CGContextAddPath(ctx, _path);
225    CGContextSetLineWidth(ctx, [self lineWidth]);
226    CGContextSetLineDash(ctx, _lineDashesPhase, _lineDashes);
227    CGContextClosePath(ctx);
228    CGContextFillPath(ctx);
229}
230
231/*!
232    Cocoa compatibility.
233*/
234- (void)getLineDash:(CPArrayRef)patternRef count:(NSInteger)count phase:(CGFloatRef)phaseRef
235{
236    return [self getLineDash:patternRef phase:phaseRef];
237}
238
239/*!
240    Retrieve the line dash pattern and phase and write them into the provided references.
241*/
242- (void)getLineDash:(CPArrayRef)patternRef phase:(CGFloatRef)phaseRef
243{
244    if (patternRef)
245        @deref(patternRef) = [_lineDashes copy];
246    if (phaseRef)
247        @deref(phaseRef) = _lineDashesPhase;
248}
249
250/*!
251    Cocoa compatibility.
252*/
253- (void)setLineDash:(CPArray)aPattern count:(NSInteger)count phase:(CGFloat)aPhase
254{
255    [self setLineDash:aPattern phase:aPhase];
256}
257
258/*!
259    Set stroke line dash pattern.
260
261    @param aPattern an array of stroke-skip lengths such as [2, 2, 4, 4]
262    @param aPhase amount of shift for the starting position of the first stroke
263*/
264- (void)setLineDash:(CPArray)aPattern phase:(CGFloat)aPhase
265{
266    _lineDashes = aPattern;
267    _lineDashesPhase = aPhase;
268}
269
270/*!
271    Get the line width.
272*/
273- (float)lineWidth
274{
275    return _lineWidth;
276}
277
278/*!
279    Set the line width.
280*/
281- (void)setLineWidth:(float)lineWidth
282{
283    _lineWidth = lineWidth;
284}
285
286/*!
287    Get the total number of elements.
288*/
289- (unsigned)elementCount
290{
291    return _path.count;
292}
293
294/*!
295    Check if receiver is empty, returns appropriate Boolean value.
296*/
297- (BOOL)isEmpty
298{
299    return CGPathIsEmpty(_path);
300}
301
302/*!
303    Get the current point.
304*/
305- (CGPoint)currentPoint
306{
307    return CGPathGetCurrentPoint(_path);
308}
309
310/*!
311    Append a series of line segments.
312*/
313- (void)appendBezierPathWithPoints:(CPArray)points count:(unsigned)count
314{
315    CGPathAddLines(_path, nil, points, count);
316}
317
318/*!
319    Append a rectangular path.
320*/
321- (void)appendBezierPathWithRect:(CGRect)rect
322{
323    CGPathAddRect(_path, nil, rect);
324}
325
326/*!
327    Append an oval path; oval is drawn within the rectangular path.
328*/
329- (void)appendBezierPathWithOvalInRect:(CGRect)rect
330{
331    CGPathAddPath(_path, nil, CGPathWithEllipseInRect(rect));
332}
333
334/*!
335    Append a rounded rectangular path.
336*/
337- (void)appendBezierPathWithRoundedRect:(CGRect)rect xRadius:(float)xRadius yRadius:(float)yRadius
338{
339    CGPathAddPath(_path, nil, CGPathWithRoundedRectangleInRect(rect, xRadius, yRadius, YES, YES, YES, YES));
340}
341
342- (void)appendBezierPathWithArcFromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint radius:(float)radius
343{
344    CGPathAddArcToPoint(_path, null, fromPoint.x, fromPoint.y, toPoint.x, toPoint.y, radius);
345}
346
347/*!
348    Append the contents of a CPBezierPath object.
349*/
350- (void)appendBezierPath:(CPBezierPath)other
351{
352    CGPathAddPath(_path, nil, other._path);
353}
354
355/*!
356    Remove all path elements; clears path.
357*/
358- (void)removeAllPoints
359{
360    _path = CGPathCreateMutable();
361}
362
363- (void)addClip
364{
365    var ctx = [[CPGraphicsContext currentContext] graphicsPort];
366
367    CGContextAddPath(ctx, _path);
368    CGContextClip(ctx);
369}
370
371- (void)setClip
372{
373    var ctx = [[CPGraphicsContext currentContext] graphicsPort];
374
375    CGContextBeginPath(ctx);
376    CGContextAddPath(ctx, _path);
377    CGContextClip(ctx);
378}
379
380@end