• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /macosx-10.9.5/pyobjc-42/pyobjc/pyobjc-framework-Quartz/Examples/Programming with Quartz/BasicDrawing/
1from Quartz import *
2import math
3
4def doEgg(context):
5    p0 = CGPoint(0, 0)
6    p1 = CGPoint(0, 200)
7    c1 = CGPoint(140, 5)
8    c2 = CGPoint(80, 198)
9
10    CGContextTranslateCTM(context, 100, 5)
11    CGContextBeginPath(context)
12
13    CGContextMoveToPoint(context, p0.x, p0.y)
14    # Create the Bezier path segment for the right side of the egg.
15    CGContextAddCurveToPoint(context, c1.x, c1.y, c2.x, c2.y, p1.x, p1.y)
16    # Create the Bezier path segment for the left side of the egg.
17    CGContextAddCurveToPoint(context, -c2.x, c2.y, -c1.x, c1.y, p0.x, p0.y)
18    CGContextClosePath(context)
19    CGContextSetLineWidth(context, 2)
20    CGContextDrawPath(context, kCGPathStroke)
21
22def addRoundedRectToPath(context, rect, ovalWidth, ovalHeight):
23    # If either ovalWidth or ovalHeight is 0, draw a regular rectangle.
24    if ovalWidth == 0 or ovalHeight == 0:
25        CGContextAddRect(context, rect)
26    else:
27        CGContextSaveGState(context)
28        if 1:
29            # Translate to lower-left corner of rectangle.
30            CGContextTranslateCTM(context,
31                    CGRectGetMinX(rect), CGRectGetMinY(rect))
32            # Scale by the oval width and height so that
33            # each rounded corner is 0.5 units in radius.
34            CGContextScaleCTM(context, ovalWidth, ovalHeight)
35            # Unscale the rectangle width by the amount of the X scaling.
36            fw = CGRectGetWidth(rect) / ovalWidth
37            # Unscale the rectangle height by the amount of the Y scaling.
38            fh = CGRectGetHeight(rect) / ovalHeight
39            # Start at the right edge of the rect, at the midpoint in Y.
40            CGContextMoveToPoint(context, fw, fh/2)
41            # Segment 1
42            CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 0.5)
43            # Segment 2
44            CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 0.5)
45            # Segment 3
46            CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 0.5)
47            # Segment 4
48            CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 0.5)
49            # Closing the path adds the last segment.
50            CGContextClosePath(context)
51        CGContextRestoreGState(context)
52
53def doRoundedRects(context):
54    rect = CGRectMake(10, 10, 210, 150)
55    ovalWidth = 100
56    ovalHeight = 100
57    CGContextSetLineWidth(context, 2.)
58    CGContextBeginPath(context)
59    addRoundedRectToPath(context, rect, ovalWidth, ovalHeight)
60    CGContextSetRGBStrokeColor(context, 1, 0, 0, 1)
61    CGContextDrawPath(context, kCGPathStroke)
62
63def doStrokeWithCTM(context):
64    CGContextTranslateCTM(context, 150., 180.)
65    CGContextSetLineWidth(context, 10)
66    # Draw ellipse 1 with a uniform stroke.
67    CGContextSaveGState(context)
68    if 1:
69        # Scale the CTM so the circular arc will be elliptical.
70        CGContextScaleCTM(context, 2, 1)
71        CGContextBeginPath(context)
72        # Create an arc that is a circle.
73        CGContextAddArc(context, 0., 0., 45., 0., 2*math.pi, 0)
74	# Restore the context parameters prior to stroking the path.
75	# CGContextRestoreGState does not affect the path in the context.
76    CGContextRestoreGState(context)
77    CGContextStrokePath(context)
78
79    # *** was 0, -120
80    CGContextTranslateCTM(context, 220., 0.)
81    # Draw ellipse 2 with non-uniform stroke.
82    CGContextSaveGState(context)
83    if 1:
84        # Scale the CTM so the circular arc will be elliptical.
85        CGContextScaleCTM(context, 2, 1)
86        CGContextBeginPath(context)
87        # Create an arc that is a circle.
88        CGContextAddArc(context, 0., 0., 45., 0., 2*math.pi, 0)
89        # Stroke the path with the scaled coordinate system in effect.
90        CGContextStrokePath(context)
91    CGContextRestoreGState(context)
92
93def doRotatedEllipsesWithCGPath(context):
94    totreps = 144
95    tint = 1.0
96    tintIncrement = 1.0/totreps
97
98    # Create a new transform consisting of a 45 degree rotation.
99    theTransform = CGAffineTransformMakeRotation(math.pi/4)
100    # Apply a scaling transformation to the transform just created.
101    theTransform = CGAffineTransformScale(theTransform, 1, 2)
102    # Create a mutable CGPath object.
103    path = CGPathCreateMutable()
104    if path is None:
105        print >>sys.stderr, "Couldn't create path!"
106        return
107
108    # Add a circular arc to the CGPath object, transformed
109    # by an affine transform.
110    CGPathAddArc(path, theTransform, 0., 0., 45., 0., 2*math.pi, False);
111    # Close the CGPath object.
112    CGPathCloseSubpath(path)
113
114    # Place the first ellipse at a good location.
115    CGContextTranslateCTM(context, 100, 100)
116    for i in range(totreps):
117        CGContextBeginPath(context)
118        # Add the CGPath object to the current path in the context.
119        CGContextAddPath(context, path)
120
121        # Set the fill color for this instance of the ellipse.
122        CGContextSetRGBFillColor(context, tint, 0., 0., 1.)
123        # Filling the path implicitly closes it.
124        CGContextFillPath(context)
125        # Compute the next tint color.
126        tint -= tintIncrement
127        # Move over for the next ellipse.
128        CGContextTranslateCTM(context, 1, 0.)
129
130def alignPointToUserSpace(context, p):
131    # Compute the coordinates of the point in device space.
132    p = CGContextConvertPointToDeviceSpace(context, p)
133    # Ensure that coordinates are at exactly the corner
134    # of a device pixel.
135    p.x = math.floor(p.x)
136    p.y = math.floor(p.y)
137    # Convert the device aligned coordinate back to user space.
138    return CGContextConvertPointToUserSpace(context, p)
139
140def alignSizeToUserSpace(context, s):
141    # Compute the size in device space.
142    s = CGContextConvertSizeToDeviceSpace(context, s)
143    # Ensure that size is an integer multiple of device pixels.
144    s.width = math.floor(s.width)
145    s.height = math.floor(s.height)
146    # Convert back to user space.
147    return CGContextConvertSizeToUserSpace(context, s)
148
149def alignRectToUserSpace(context, r):
150    # Compute the coordinates of the rectangle in device space.
151    r = CGContextConvertRectToDeviceSpace(context, r)
152    # Ensure that the x and y coordinates are at a pixel corner.
153    r.origin.x = math.floor(r.origin.x)
154    r.origin.y = math.floor(r.origin.y)
155    # Ensure that the width and height are an integer number of
156    # device pixels. Note that this produces a width and height
157    # that is less than or equal to the original width. Another
158    # approach is to use ceil to ensure that the new rectangle
159    # encloses the original one.
160    r.size.width = math.floor(r.size.width)
161    r.size.height = math.floor(r.size.height)
162
163    # Convert back to user space.
164    return CGContextConvertRectToUserSpace(context, r)
165
166def doPixelAlignedFillAndStroke(context):
167    p1 = CGPointMake(16.7, 17.8)
168    p2 = CGPointMake(116.7, 17.8)
169    r = CGRectMake(16.7, 20.8, 100.6, 100.6)
170
171    CGContextSetLineWidth(context, 2)
172    CGContextSetRGBFillColor(context, 1., 0., 0., 1.)
173    CGContextSetRGBStrokeColor(context, 1., 0., 0., 1.)
174
175    # Unaligned drawing.
176    CGContextBeginPath(context)
177    CGContextMoveToPoint(context, p1.x, p1.y)
178    CGContextAddLineToPoint(context, p2.x, p2.y)
179    CGContextStrokePath(context)
180    CGContextFillRect(context, r)
181
182    # Translate to the right before drawing along
183    # aligned coordinates.
184    CGContextTranslateCTM(context, 106, 0)
185
186    # Aligned drawing.
187
188    # Compute the length of the line in user space.
189    s = CGSizeMake(p2.x - p1.x, p2.y - p1.y)
190
191    CGContextBeginPath(context)
192    # Align the starting point to a device
193    # pixel boundary.
194    p1 = alignPointToUserSpace(context, p1)
195    # Establish the starting point of the line.
196    CGContextMoveToPoint(context, p1.x, p1.y)
197    # Compute the line length as an integer
198    # number of device pixels.
199    s = alignSizeToUserSpace(context, s)
200    CGContextAddLineToPoint(context,
201				p1.x + s.width,
202				p1.y + s.height)
203    CGContextStrokePath(context)
204    # Compute a rect that is aligned to device
205    # space with a width that is an integer
206    # number of device pixels.
207    r = alignRectToUserSpace(context, r)
208    CGContextFillRect(context, r)
209