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