1from __future__ import with_statement
2
3from PyObjCTools.TestSupport import *
4from Quartz.CoreGraphics import *
5import os
6
7
8class TestCGContext (TestCase):
9    def testTypes(self):
10        self.failUnlessIsCFType(CGContextRef)
11
12    def testConstants(self):
13        self.failUnlessEqual(kCGLineJoinMiter, 0)
14        self.failUnlessEqual(kCGLineJoinRound, 1)
15        self.failUnlessEqual(kCGLineJoinBevel, 2)
16
17        self.failUnlessEqual(kCGLineCapButt, 0)
18        self.failUnlessEqual(kCGLineCapRound, 1)
19        self.failUnlessEqual(kCGLineCapSquare, 2)
20
21        self.failUnlessEqual(kCGPathFill, 0)
22        self.failUnlessEqual(kCGPathEOFill, 1)
23        self.failUnlessEqual(kCGPathStroke, 2)
24        self.failUnlessEqual(kCGPathFillStroke, 3)
25        self.failUnlessEqual(kCGPathEOFillStroke, 4)
26
27        self.failUnlessEqual(kCGTextFill, 0)
28        self.failUnlessEqual(kCGTextStroke, 1)
29        self.failUnlessEqual(kCGTextFillStroke, 2)
30        self.failUnlessEqual(kCGTextInvisible, 3)
31        self.failUnlessEqual(kCGTextFillClip, 4)
32        self.failUnlessEqual(kCGTextStrokeClip, 5)
33        self.failUnlessEqual(kCGTextFillStrokeClip, 6)
34        self.failUnlessEqual(kCGTextClip, 7)
35
36        self.failUnlessEqual(kCGEncodingFontSpecific, 0)
37        self.failUnlessEqual(kCGEncodingMacRoman, 1)
38
39        self.failUnlessEqual(kCGInterpolationDefault, 0)
40        self.failUnlessEqual(kCGInterpolationNone, 1)
41        self.failUnlessEqual(kCGInterpolationLow, 2)
42        self.failUnlessEqual(kCGInterpolationHigh, 3)
43
44        self.failUnlessEqual(kCGBlendModeNormal, 0)
45        self.failUnlessEqual(kCGBlendModeMultiply, 1)
46        self.failUnlessEqual(kCGBlendModeScreen, 2)
47        self.failUnlessEqual(kCGBlendModeOverlay, 3)
48        self.failUnlessEqual(kCGBlendModeDarken, 4)
49        self.failUnlessEqual(kCGBlendModeLighten, 5)
50        self.failUnlessEqual(kCGBlendModeColorDodge, 6)
51        self.failUnlessEqual(kCGBlendModeColorBurn, 7)
52        self.failUnlessEqual(kCGBlendModeSoftLight, 8)
53        self.failUnlessEqual(kCGBlendModeHardLight, 9)
54        self.failUnlessEqual(kCGBlendModeDifference, 10)
55        self.failUnlessEqual(kCGBlendModeExclusion, 11)
56        self.failUnlessEqual(kCGBlendModeHue, 12)
57        self.failUnlessEqual(kCGBlendModeSaturation, 13)
58        self.failUnlessEqual(kCGBlendModeColor, 14)
59        self.failUnlessEqual(kCGBlendModeLuminosity, 15)
60        self.failUnlessEqual(kCGBlendModeClear, 16)
61        self.failUnlessEqual(kCGBlendModeCopy, 17)
62        self.failUnlessEqual(kCGBlendModeSourceIn, 18)
63        self.failUnlessEqual(kCGBlendModeSourceOut, 19)
64        self.failUnlessEqual(kCGBlendModeSourceAtop, 20)
65        self.failUnlessEqual(kCGBlendModeDestinationOver, 21)
66        self.failUnlessEqual(kCGBlendModeDestinationIn, 22)
67        self.failUnlessEqual(kCGBlendModeDestinationOut, 23)
68        self.failUnlessEqual(kCGBlendModeDestinationAtop, 24)
69        self.failUnlessEqual(kCGBlendModeXOR, 25)
70        self.failUnlessEqual(kCGBlendModePlusDarker, 26)
71        self.failUnlessEqual(kCGBlendModePlusLighter, 27)
72
73    def testFunctions(self):
74        self.failUnlessIsInstance(CGContextGetTypeID(), (int, long))
75
76        url = CFURLCreateWithFileSystemPath(None,
77                "/tmp/pyobjc.test.pdf", kCFURLPOSIXPathStyle, False)
78        self.failUnlessIsInstance(url, CFURLRef)
79        context = CGPDFContextCreateWithURL(url,
80                ((0, 0), (1000, 1000)), None)
81        self.failUnlessIsInstance(context, CGContextRef)
82        CGContextBeginPage(context, objc.NULL)
83
84        self.failUnless(CGContextIsPathEmpty(context) is True)
85        try:
86            CGContextBeginPath(context)
87            CGContextAddEllipseInRect(context, ((0, 10), (50, 30)))
88            CGContextDrawPath(context, kCGPathStroke)
89
90            CGContextSaveGState(context)
91            CGContextRestoreGState(context)
92
93            CGContextScaleCTM(context, 5.5, 9.5)
94            CGContextTranslateCTM(context, 4.5, 3.5)
95            CGContextRotateCTM(context, 0.79)
96            CGContextConcatCTM(context, CGAffineTransformIdentity)
97
98            tf = CGContextGetCTM(context)
99            self.failUnlessIsInstance(tf, CGAffineTransform)
100
101            CGContextSetLineWidth(context, 2.5)
102            CGContextSetLineCap(context, kCGLineCapRound)
103            CGContextSetLineJoin(context, kCGLineJoinMiter)
104            CGContextSetMiterLimit(context, 9.5)
105
106            CGContextSetLineDash(context, 0.5, [0.4, 0.2, 0.8, 0.1], 4)
107
108            self.assertRaises(ValueError, CGContextSetLineDash,
109                    context, 0.5, [0.4, 0.2, 0.8, 0.1], 8)
110
111            CGContextSetFlatness(context, 0.8)
112            CGContextSetAlpha(context, 0.5)
113            CGContextSetBlendMode(context, kCGBlendModeLighten)
114
115
116            CGContextMoveToPoint(context, 10.5, 50.8)
117            CGContextAddLineToPoint(context, 0.5, 0.7)
118            CGContextAddCurveToPoint(context, 7.5, 8.7, 9.10, 9.10, 99.5, 80.5)
119            CGContextAddQuadCurveToPoint(context, 50.5, 50.5, 75.9, 78.4)
120            CGContextClosePath(context)
121
122            CGContextAddRect(context, CGRect(CGPoint(10, 10), CGSize(50, 50)))
123            CGContextAddRects(context, [
124                ( (8, 8), (7, 7) ),
125                ( (90, 80), (6, 6) ),
126                ( (50, 80), (60, 6) ),
127            ], 3)
128            self.assertRaises(ValueError,
129                CGContextAddRects, context, [
130                    ( (8, 8), (7, 7) ),
131                    ( (90, 80), (6, 6) ),
132                    ( (50, 80), (60, 6) ),
133                ], 8)
134
135
136            CGContextAddLines(context, [ (0, 10), (50, 7), (50, 90), (90.5, 8)],
137                    4)
138            self.assertRaises(ValueError,
139                CGContextAddLines, context, [ (0, 10), (50, 7), (50, 90), (90.5, 8)],
140                    7)
141
142            CGContextAddEllipseInRect(context, ((0, 10), (50, 30)))
143
144            CGContextAddArc(context, 50, 50, 70.5, 0.5, 1.3, 0)
145
146            CGContextAddArcToPoint(context, 20, 30, 70, 20, 55)
147
148            path = CGPathCreateMutable()
149            CGPathAddEllipseInRect(path, None, ((10, 50), (33, 33)))
150            self.failUnlessIsInstance(path, CGPathRef)
151            CGContextAddPath(context, path)
152
153            self.failUnlessResultHasType(CGContextIsPathEmpty, objc._C_BOOL)
154            self.failUnless(CGContextIsPathEmpty(context) is False)
155
156            pt = CGContextGetPathCurrentPoint(context)
157            self.failUnlessIsInstance(pt, CGPoint)
158
159            box = CGContextGetPathBoundingBox(context)
160            self.failUnlessIsInstance(box, CGRect)
161
162            self.failUnlessResultHasType(CGContextPathContainsPoint, objc._C_BOOL)
163            self.failUnlessIsInstance(CGContextPathContainsPoint(context, pt, kCGPathStroke), bool)
164
165            CGContextFillPath(context)
166            CGContextEOFillPath(context)
167            CGContextStrokePath(context)
168            CGContextFillRect(context, ((10, 10), (50, 30)))
169
170            CGContextFillRects(context, [
171                ((10, 10), (50, 30)),
172                ((90, 10), (50, 30)),
173                ((30, 50), (50, 30))], 3)
174            self.assertRaises(ValueError, CGContextFillRects, context, [
175                ((10, 10), (50, 30)),
176                ((90, 10), (50, 30)),
177                ((30, 50), (50, 30))], 6)
178
179            CGContextStrokeRect(context, ((10, 10), (50, 30)))
180            CGContextStrokeRectWithWidth(context, ((10, 10), (50, 30)), 8.0)
181            CGContextClearRect(context, ((10, 10), (50, 30)))
182
183            CGContextFillEllipseInRect(context, ((10, 10), (50, 30)))
184            CGContextStrokeEllipseInRect(context, ((10, 10), (50, 30)))
185
186            CGContextStrokeLineSegments(context,
187                    [ (0, 0), (10, 15), (15, 10) ], 3)
188            self.assertRaises(ValueError, CGContextStrokeLineSegments, context,
189                    [ (0, 0), (10, 15), (15, 10) ], 4)
190
191            CGContextAddRect(context, CGRect(CGPoint(10, 10), CGSize(50, 50)))
192            CGContextClip(context)
193
194            CGContextAddRect(context, CGRect(CGPoint(10, 10), CGSize(50, 50)))
195            CGContextEOClip(context)
196
197            box = CGContextGetClipBoundingBox(context)
198            self.failUnlessIsInstance(box, CGRect)
199
200            CGContextClipToRect(context, ((0, 0), (40, 50)))
201            CGContextClipToRects(context,
202                    [ ((0, 0), (40, 50)), ((60, 50), (90, 100))], 2)
203            self.assertRaises(ValueError, CGContextClipToRects, context,
204                    [ ((0, 0), (40, 50)), ((60, 50), (90, 100))], 3)
205
206            color = CGColorCreateGenericRGB(1.0, 0.5, 0.5, 1.0)
207            self.failUnlessIsInstance(color, CGColorRef)
208            CGContextSetFillColorWithColor(context, color)
209            CGContextSetStrokeColorWithColor(context, color)
210
211            CGContextSetFillColorSpace(context, CGColorSpaceCreateDeviceGray())
212            CGContextSetStrokeColorSpace(context, CGColorSpaceCreateDeviceGray())
213
214            CGContextSetFillColor(context, [0.5, 1.0])
215            CGContextSetStrokeColor(context, [0.5, 1.0])
216
217            CGContextSetPatternPhase(context, CGSize(10.0, 50.0))
218
219            CGContextSetGrayFillColor(context, 0.8, 1.0)
220            CGContextSetGrayStrokeColor(context, 0.8, 1.0)
221
222            CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0)
223            CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0)
224
225            CGContextSetCMYKFillColor(context, 1.0, 1.0, 1.0, 0.5, 0.8)
226            CGContextSetCMYKStrokeColor(context, 1.0, 1.0, 1.0, 0.5, 0.8)
227
228            CGContextSetRenderingIntent(context, kCGRenderingIntentPerceptual)
229
230            v = CGContextGetInterpolationQuality(context)
231            self.failUnlessIsInstance(v, (int, long))
232
233            CGContextSetInterpolationQuality(context, kCGInterpolationHigh)
234
235            CGContextSetShadowWithColor(context, (2, 3), 0.5, color)
236            CGContextSetShadow(context, (5, 6), 0.6)
237
238            gradient = CGGradientCreateWithColorComponents(
239                    CGColorSpaceCreateDeviceGray(),
240                    (0.25, 0.8), (0.95, 0.99), 2)
241            self.failUnlessIsInstance(gradient, CGGradientRef)
242
243            CGContextDrawLinearGradient(context, gradient, (0, 10), (50, 60),
244                    kCGGradientDrawsAfterEndLocation)
245
246            CGContextSetCharacterSpacing(context, 0.1)
247            CGContextSetTextPosition(context, 10, 50)
248            p = CGContextGetTextPosition(context)
249            self.failUnlessIsInstance(pt, CGPoint)
250
251            CGContextSetTextMatrix(context, CGAffineTransformIdentity)
252
253            tr = CGContextGetTextMatrix(context)
254            self.failUnlessIsInstance(tr, CGAffineTransform)
255
256            CGContextSetTextDrawingMode(context, kCGTextStroke)
257
258            font =  CGFontCreateWithFontName("Helvetica")
259            self.failUnlessIsInstance(font, CGFontRef)
260            CGContextSetFont(context, font)
261
262            CGContextSetFontSize(context, 11.5)
263
264            CGContextSelectFont(context, "Helvetica", 10.5, kCGEncodingMacRoman)
265
266            CGContextShowText(context, "value", 5)
267            CGContextShowTextAtPoint(context, 50, 60, "value", 5)
268
269
270            v = CGContextRetain(context)
271            self.failUnless(v is context)
272            CGContextRelease(context)
273
274            CGContextFlush(context)
275            CGContextSynchronize(context)
276
277            self.failUnlessArgHasType(CGContextSetShouldAntialias, 1, objc._C_BOOL)
278            CGContextSetShouldAntialias(context, True)
279
280            self.failUnlessArgHasType(CGContextSetAllowsAntialiasing, 1, objc._C_BOOL)
281            CGContextSetAllowsAntialiasing(context, True)
282
283            self.failUnlessArgHasType(CGContextSetShouldSmoothFonts, 1, objc._C_BOOL)
284            CGContextSetShouldSmoothFonts(context, True)
285
286
287            CGContextBeginTransparencyLayer(context, None)
288            CGContextEndTransparencyLayer(context)
289
290            CGContextBeginTransparencyLayerWithRect(context,
291                    ((10, 10), (500, 100)), None)
292            CGContextEndTransparencyLayer(context)
293
294            tf = CGContextGetUserSpaceToDeviceSpaceTransform(context)
295            self.failUnlessIsInstance(tf, CGAffineTransform)
296
297            pt = CGContextConvertPointToDeviceSpace(context, (10.5, 11.9))
298            self.failUnlessIsInstance(pt, CGPoint)
299
300            pt = CGContextConvertPointToUserSpace(context, (10.5, 11.9))
301            self.failUnlessIsInstance(pt, CGPoint)
302
303            sz = CGContextConvertSizeToDeviceSpace(context, (10.5, 11.9))
304            self.failUnlessIsInstance(sz, CGSize)
305
306            sz = CGContextConvertSizeToUserSpace(context, (10.5, 11.9))
307            self.failUnlessIsInstance(sz, CGSize)
308
309            box = CGContextConvertRectToDeviceSpace(context,
310                    ((10.5, 11.9), (55.6, 39.3)))
311            self.failUnlessIsInstance(box, CGRect)
312            box = CGContextConvertRectToUserSpace(context,
313                    ((10.5, 11.9), (55.6, 39.3)))
314            self.failUnlessIsInstance(box, CGRect)
315
316            myInfo = object()
317            def drawPattern(info, context):
318                pass
319
320            pattern = CGPatternCreate(myInfo, CGRectMake(0, 0, 10, 10), CGAffineTransformIdentity, 10.0, 10.0,
321                            kCGPatternTilingConstantSpacing, True, drawPattern)
322            self.failUnlessIsInstance(pattern, CGPatternRef)
323
324            CGContextSetFillColorSpace(context, CGColorSpaceCreatePattern(None))
325            CGContextSetStrokeColorSpace(context, CGColorSpaceCreatePattern(None))
326            CGContextSetFillPattern(context, pattern, (1.0,1.0,1.0,1.0))
327            CGContextSetStrokePattern(context, pattern, (1.0,1.0,1.0,1.0))
328
329            provider = CGDataProviderCreateWithCFData(buffer(
330                            open('/System/Library/CoreServices/DefaultDesktop.jpg', 'rb').read()))
331            image = CGImageCreateWithJPEGDataProvider(provider, None, True, kCGRenderingIntentDefault)
332            self.failUnlessIsInstance(image, CGImageRef)
333
334            CGContextDrawImage(context, ((0, 0), (70, 50)), image)
335            CGContextDrawTiledImage(context, ((0, 0), (10, 10)), image)
336
337            provider = CGDataProviderCreateWithCFData(buffer("1" * 4 * 20 * 10))
338            mask = CGImageMaskCreate(20, 10, 8, 32, 80, provider, None, True)
339            self.failUnlessIsInstance(mask, CGImageRef)
340
341            CGContextClipToMask(context, CGRectMake(0, 0, 50, 90), mask)
342
343        finally:
344            CGContextEndPage(context)
345            CGPDFContextClose(context)
346            if os.path.exists("/tmp/pyobjc.test.pdf"):
347                os.unlink("/tmp/pyobjc.test.pdf")
348
349    def testMissing(self):
350        self.fail("CGContextShowGlyphsAtPositions")
351        self.fail("CGContextShowGlyphs")
352        self.fail("CGContextShowGlyphsAtPoint")
353        self.fail("CGContextShowGlyphsWithAdvances")
354        self.fail("CGContextDrawPDFPage")
355        self.fail("CGContextDrawPDFDocument")
356
357
358    def testContextManager(self):
359        """
360        Tests for some additional functionality
361        """
362        url = CFURLCreateWithFileSystemPath(None,
363                "/tmp/pyobjc.test.pdf", kCFURLPOSIXPathStyle, False)
364        self.failUnlessIsInstance(url, CFURLRef)
365        context = CGPDFContextCreateWithURL(url,
366                ((0, 0), (1000, 1000)), None)
367        self.failUnlessIsInstance(context, CGContextRef)
368        try:
369            CGContextBeginPage(context, objc.NULL)
370            transform = CGContextGetCTM(context)
371            newTransform = CGAffineTransformMake(1.5, 2.5, 3.5, 4.5, 5.5, 6.5)
372
373            with CGSavedGState(context):
374                CGContextConcatCTM(context, newTransform)
375                tf = CGContextGetCTM(context)
376                self.failIfEqual(tf, transform)
377
378
379            tf = CGContextGetCTM(context)
380            self.failUnlessEqual(tf, transform)
381
382
383            # XXX: This need actual tests, this at least tests that
384            # the contextmanagers can be used
385            with CGTransparencyLayer(context, None):
386                pass
387
388            with CGTransparencyLayer(context, None, ((10, 10), (200, 200))):
389                pass
390
391
392            CGContextEndPage(context)
393            with CGContextPage(context):
394                pass
395
396            with CGContextPage(context, CGRectMake(0, 0, 500, 500)):
397                pass
398
399            CGContextBeginPage(context, None)
400
401
402
403        finally:
404            CGContextEndPage(context)
405            CGPDFContextClose(context)
406            if os.path.exists("/tmp/pyobjc.test.pdf"):
407                os.unlink("/tmp/pyobjc.test.pdf")
408
409if __name__ == "__main__":
410    main()
411