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