def doRotatedEllipses(context): totreps = 144 tint = 1.0 tintIncrement = 1.0 / totreps # Create a new transform consisting of a 45 degrees rotation. theTransform = Quartz.CGAffineTransformMakeRotation(math.pi / 4) # Apply a scale to the transform just created. theTransform = Quartz.CGAffineTransformScale(theTransform, 1, 2) # Place the first ellipse at a good location. Quartz.CGContextTranslateCTM(context, 100.0, 100.0) for _ in range(totreps): # Make a snapshot the coordinate system. Quartz.CGContextSaveGState(context) # Set up the coordinate system for the rotated ellipse. Quartz.CGContextConcatCTM(context, theTransform) Quartz.CGContextBeginPath(context) Quartz.CGContextAddArc(context, 0.0, 0.0, 45.0, 0.0, 2 * math.pi, 0) # Set the fill color for this instance of the ellipse. Quartz.CGContextSetRGBFillColor(context, tint, 0.0, 0.0, 1.0) Quartz.CGContextDrawPath(context, Quartz.kCGPathFill) # Restore the coordinate system to that of the snapshot. Quartz.CGContextRestoreGState(context) # Compute the next tint color. tint -= tintIncrement # Move over by 1 unit in x for the next ellipse. Quartz.CGContextTranslateCTM(context, 1.0, 0.0)
def doRotatedEllipsesWithCGPath(context): totreps = 144 tint = 1.0 tintIncrement = 1.0 / totreps # Create a new transform consisting of a 45 degree rotation. theTransform = Quartz.CGAffineTransformMakeRotation(math.pi / 4) # Apply a scaling transformation to the transform just created. theTransform = Quartz.CGAffineTransformScale(theTransform, 1, 2) # Create a mutable CGPath object. path = Quartz.CGPathCreateMutable() if path is None: print("Couldn't create path!") return # Add a circular arc to the CGPath object, transformed # by an affine transform. Quartz.CGPathAddArc(path, theTransform, 0.0, 0.0, 45.0, 0.0, 2 * math.pi, False) # Close the CGPath object. Quartz.CGPathCloseSubpath(path) # Place the first ellipse at a good location. Quartz.CGContextTranslateCTM(context, 100, 100) for _ in range(totreps): Quartz.CGContextBeginPath(context) # Add the CGPath object to the current path in the context. Quartz.CGContextAddPath(context, path) # Set the fill color for this instance of the ellipse. Quartz.CGContextSetRGBFillColor(context, tint, 0.0, 0.0, 1.0) # Filling the path implicitly closes it. Quartz.CGContextFillPath(context) # Compute the next tint color. tint -= tintIncrement # Move over for the next ellipse. Quartz.CGContextTranslateCTM(context, 1, 0.0)
def testFunctions(self): tf = Quartz.CGAffineTransformMake(1.5, 2.5, 3.5, 4.5, 5.5, 6.5) self.assertIsInstance(tf, Quartz.CGAffineTransform) self.assertEqual(tf.a, 1.5) self.assertEqual(tf.b, 2.5) self.assertEqual(tf.c, 3.5) self.assertEqual(tf.d, 4.5) self.assertEqual(tf.tx, 5.5) self.assertEqual(tf.ty, 6.5) tf = Quartz.CGAffineTransformMakeTranslation(2.5, 3.5) self.assertIsInstance(tf, Quartz.CGAffineTransform) self.assertEqual(tf.a, 1.0) self.assertEqual(tf.b, 0.0) self.assertEqual(tf.c, 0.0) self.assertEqual(tf.d, 1.0) self.assertEqual(tf.tx, 2.5) self.assertEqual(tf.ty, 3.5) tf = Quartz.CGAffineTransformMakeScale(2.5, 3.5) self.assertIsInstance(tf, Quartz.CGAffineTransform) self.assertEqual(tf.a, 2.5) self.assertEqual(tf.b, 0.0) self.assertEqual(tf.c, 0.0) self.assertEqual(tf.d, 3.5) self.assertEqual(tf.tx, 0.0) self.assertEqual(tf.ty, 0.0) tf = Quartz.CGAffineTransformMakeRotation(3.4) self.assertIsInstance(tf, Quartz.CGAffineTransform) self.assertResultHasType(Quartz.CGAffineTransformIsIdentity, objc._C_BOOL) self.assertTrue(Quartz.CGAffineTransformIsIdentity(tf) is False) self.assertTrue( Quartz.CGAffineTransformIsIdentity(Quartz.CGAffineTransformIdentity) is True ) tf = Quartz.CGAffineTransformTranslate(tf, 2.5, 3.5) self.assertIsInstance(tf, Quartz.CGAffineTransform) tf = Quartz.CGAffineTransformScale(tf, 5.5, 9.5) self.assertIsInstance(tf, Quartz.CGAffineTransform) tf = Quartz.CGAffineTransformRotate(tf, 0.8) self.assertIsInstance(tf, Quartz.CGAffineTransform) tf = Quartz.CGAffineTransformInvert(tf) self.assertIsInstance(tf, Quartz.CGAffineTransform) tf2 = Quartz.CGAffineTransformConcat( tf, Quartz.CGAffineTransformMake(1.0, 1.0, 1.0, 1.0, 1.0, 1.0) ) self.assertIsInstance(tf2, Quartz.CGAffineTransform) self.assertResultHasType(Quartz.CGAffineTransformEqualToTransform, objc._C_BOOL) self.assertTrue(Quartz.CGAffineTransformEqualToTransform(tf, tf2) is False) self.assertTrue(Quartz.CGAffineTransformEqualToTransform(tf2, tf2) is True) pt = Quartz.CGPointApplyAffineTransform((2.5, 3.5), tf) self.assertIsInstance(pt, Quartz.CGPoint) sz = Quartz.CGSizeApplyAffineTransform((2.5, 3.5), tf) self.assertIsInstance(sz, Quartz.CGSize) rct = Quartz.CGRectApplyAffineTransform(((2.5, 3.5), (4.5, 5.5)), tf) self.assertIsInstance(rct, Quartz.CGRect)
def doEllipseShading(context): black = [0, 0, 0] red = [1, 0, 0] # This function describes a color ramp where the starting color # is red, the ending color is black. redBlackFunction = createFunctionWithStartEndColorRamp(red, black) if redBlackFunction is None: print("Couldn't create the red-black function!") return Quartz.CGContextTranslateCTM(context, 100, 300) # Shading 1. # To obtain an elliptical shading requires that user space # at the time the shading is painted is transformed so that # the circles which define the radial shading geometry are # rotated and elliptical. User space will be rotated # by 45 degrees, then scaled by 1 in x and 2 in y to produce # the ellipses. # Compute the transform needed to create the rotated ellipses. t = Quartz.CGAffineTransformMakeRotation(Utilities.DEGREES_TO_RADIANS(45)) t = Quartz.CGAffineTransformScale(t, 1, 2) circleACenter = Quartz.CGPoint(x=0, y=0) circleBCenter = Quartz.CGPoint(x=circleACenter.x + 144, y=circleACenter.y) circleARadius = 45 circleBRadius = 45 # Don't extend this shading. extendStart = extendEnd = False shading = Quartz.CGShadingCreateRadial( Utilities.getTheCalibratedRGBColorSpace(), circleACenter, circleARadius, circleBCenter, circleBRadius, redBlackFunction, extendStart, extendEnd) if shading is None: # Couldn't create the shading so release # the function before returning. print("Couldn't create the shading!") return Quartz.CGContextSaveGState(context) if 1: # Transform coordinates for the drawing of the shading. # This transform produces the rotated elliptical shading. # This produces the left shading in the figure, the # one where both the ellipses and the shading are # rotated relative to default user space. Quartz.CGContextConcatCTM(context, t) Quartz.CGContextDrawShading(context, shading) del shading Quartz.CGContextRestoreGState(context) Quartz.CGContextTranslateCTM(context, 300, 10) # Shading 2. # Now draw the shading where the shading ellipses are # rotated but the axis between the origins of # the ellipses lies parallel to the x axis in default # user space. This is similar to the shading drawn # manually in Chapter 5. # # To compute the correct origins for the shading, # the code needs to compute the points that, # transformed by the matrix t used to paint the shading, # produce the desired coordinates. We want coordinates # that are transformed as follows: # # P' = P x t # # where P' is the point in untransformed user space that # we want as the origin, P is the point in transformed # user space that will be transformed by t, the matrix # which transforms the circles into rotated ellipses. # # So we want to calculate P such that P' = P x t . # # Notice that if P = P' x Inverse(t) then: # # P' = P' x Inverse(t) x t = P' x Identity = P'. # # This means that we can calculate the point P # by computing P' x Inverse(t). inverseT = Quartz.CGAffineTransformInvert(t) # Now the code can transform the coordinates through the # inverse transform to compute the new coordinates. These # coordinates, when transformed with the transform t, # produce the original coordinate. circleACenter = Quartz.CGPointApplyAffineTransform(circleACenter, inverseT) circleBCenter = Quartz.CGPointApplyAffineTransform(circleBCenter, inverseT) shading = Quartz.CGShadingCreateRadial( Utilities.getTheCalibratedRGBColorSpace(), circleACenter, circleARadius, circleBCenter, circleBRadius, redBlackFunction, extendStart, extendEnd) # The code is finished with the function so release it. del redBlackFunction if shading is None: print("Couldn't create the shading!") return # Transform coordinates for the drawing of the shading. # This transform produces the rotated elliptical shading. Quartz.CGContextConcatCTM(context, t) Quartz.CGContextDrawShading(context, shading)