1from Quartz import * 2 3import Utilities 4 5 6def scaleShadowOffset(offset): 7 shadowScaling = Utilities.getScalingFactor() 8 # Adjust the shadow offset if scaling to export as bits. This is 9 # equivalent to scaling base space by the scaling factor. 10 if shadowScaling != 1.0: 11 offset = CGSizeApplyAffineTransform(offset, 12 CGAffineTransformMakeScale(shadowScaling, shadowScaling)) 13 return offset 14 15 16def createTrianglePath(context): 17 CGContextBeginPath(context) 18 CGContextMoveToPoint(context, 0, 0) 19 CGContextAddLineToPoint(context, 50, 0) 20 CGContextAddLineToPoint(context, 25, 50) 21 CGContextClosePath(context) 22 23def drawSimpleShadow(context): 24 r = CGRectMake(20, 20, 100, 200) 25 26 CGContextTranslateCTM(context, 20, 300) 27 28 # A blur of 0 is a hard edge blur. 29 blur = 0 30 # An offset where both components are negative casts a shadow to the 31 # left and down from the object. The coordinate system for the offset 32 # is base space, not current user space. 33 offset = CGSize(-7, -7) 34 offset = scaleShadowOffset(offset) 35 36 # Set the shadow in the context. 37 CGContextSetShadow(context, offset, blur) 38 39 # Object 1. 40 # Paint a rectangle. 41 CGContextFillRect(context, r) 42 43 # Object 2. 44 CGContextTranslateCTM(context, 150, 0) 45 # A blur of 3 is a soft blur more 46 # appropriate for a shadow effect. 47 blur = 3 48 CGContextSetShadow(context, offset, blur) 49 50 # Fill an ellipse to the right of the rect. 51 CGContextBeginPath(context) 52 Utilities.myCGContextAddEllipseInRect(context, r) 53 CGContextFillPath(context) 54 55 # Object 3. 56 CGContextTranslateCTM(context, -130, -140) 57 # Scale the coordinate system but the shadow is not affected. The offset 58 # is in the base space of the context. Typically it looks best if the shapes 59 # have a uniform shadow regardless of how the shapes were created, scaled, 60 # rotated, or otherwise transformed. 61 CGContextScaleCTM(context, 2, 2) 62 createTrianglePath(context) 63 CGContextSetStrokeColorWithColor(context, Utilities.getRGBOpaqueRedColor()) 64 65 CGContextSetLineWidth(context, 5) 66 # Stroking produces a shadow as well. 67 CGContextStrokePath(context) 68 69 # Object 4. 70 CGContextTranslateCTM(context, 75, 0) 71 createTrianglePath(context) 72 # Cast the shadow to the left and up from 73 # the shape painted. 74 offset.width = -5 75 offset.height = +7 76 offset = scaleShadowOffset(offset) 77 78 # The shadow can be colored. Create a CGColorRef 79 # that represents a red color with opacity of 0.3333... 80 shadowColor = CGColorCreateCopyWithAlpha(Utilities.getRGBOpaqueRedColor(), 1.0/3.0) 81 82 CGContextSetShadowWithColor(context, offset, blur, shadowColor) 83 CGContextStrokePath(context) 84 85 # Object 5. Three stroked circles. 86 CGContextTranslateCTM(context, -75, -65) 87 # Set a black shadow offset at -7,-7. 88 offset.width = -7 89 offset.height = -7 90 91 offset = scaleShadowOffset(offset) 92 93 CGContextSetShadow(context, offset, blur) 94 # Draw a set of three circles side by side. 95 CGContextBeginPath(context) 96 CGContextSetLineWidth(context, 3) 97 r = CGRectMake(30, 20, 20, 20) 98 Utilities.myCGContextAddEllipseInRect(context, r) 99 r = CGRectOffset(r, 20, 0) 100 Utilities.myCGContextAddEllipseInRect(context, r) 101 r = CGRectOffset(r, 20, 0) 102 Utilities.myCGContextAddEllipseInRect(context, r) 103 CGContextStrokePath(context) 104 105 106def doShadowScaling(context): 107 offset = CGSize(-7, -7) 108 blur = 3 109 110 CGContextTranslateCTM(context, 20, 220) 111 CGContextSetShadow(context, scaleShadowOffset(offset), blur) 112 113 # Object 1 114 # Draw a triangle filled with black and shadowed with black. 115 createTrianglePath(context) 116 CGContextFillPath(context) 117 118 # Object 2 119 # Scaling without changing the shadow doesn't impact 120 # the shadow offset or blur. 121 t = CGAffineTransformMakeScale(2, 2) 122 CGContextConcatCTM(context, t) 123 CGContextTranslateCTM(context, 40, 0) 124 createTrianglePath(context) 125 CGContextFillPath(context) 126 127 # Object 3 128 # By transforming the offset you can transform the shadow. 129 # This may be desirable if you are drawing a zoomed view. 130 offset = CGSizeApplyAffineTransform(offset, t) 131 CGContextSetShadow(context, scaleShadowOffset(offset), blur) 132 CGContextTranslateCTM(context, 70, 0) 133 createTrianglePath(context) 134 CGContextFillPath(context) 135 136 137def drawFillAndStrokeWithShadow(context): 138 r = CGRectMake(60, 60, 100, 100) 139 offset = CGSize(-7, -7) 140 blur = 3 141 142 # Set the shadow. 143 CGContextSetShadow(context, scaleShadowOffset(offset), blur) 144 145 CGContextSetFillColorWithColor(context, Utilities.getRGBOpaqueOrangeColor()) 146 147 # Draw the graphic on the left. 148 CGContextBeginPath(context) 149 Utilities.myCGContextAddEllipseInRect(context, r) 150 CGContextDrawPath(context, kCGPathFillStroke) 151 152 # Draw the graphic on the right. 153 r = CGRectOffset(r, 125, 0) 154 # Begin the transparency layer. 155 CGContextBeginTransparencyLayer(context, None) 156 if 1: 157 Utilities.myCGContextAddEllipseInRect(context, r) 158 CGContextDrawPath(context, kCGPathFillStroke) 159 # End the transparency layer. 160 CGContextEndTransparencyLayer(context) 161 162def drawColoredLogo(context): 163 r = CGRectMake(0, 0, 100, 100) 164 CGContextSaveGState(context) 165 if 1: 166 # Position the center of the rectangle on the left. 167 CGContextTranslateCTM(context, 140, 140) 168 # Rotate so that the rectangles are rotated 45 degrees 169 # about the current coordinate origin. 170 CGContextRotateCTM(context, Utilities.DEGREES_TO_RADIANS(45)) 171 # Translate so that the center of the rect is at the previous origin. 172 CGContextTranslateCTM(context, 173 -r.size.width/2, -r.size.height/2) 174 # Set the fill color to a purple color. 175 CGContextSetFillColorWithColor(context, 176 Utilities.getRGBOpaquePurpleColor()) 177 # Fill the first rectangle. 178 CGContextFillRect(context, r) 179 # Position to draw the right-most rectangle. 180 CGContextTranslateCTM(context, 60, -60) 181 # Set the fill color to a yellow color. 182 CGContextSetFillColorWithColor(context, 183 Utilities.getRGBOpaqueYellowColor()) 184 CGContextFillRect(context, r) 185 186 # Position for the center rectangle. 187 CGContextTranslateCTM(context, -30, +30) 188 # Set the stroke color to an orange color. 189 CGContextSetStrokeColorWithColor(context, 190 Utilities.getRGBOpaqueOrangeColor()) 191 # Stroke the rectangle with a linewidth of 12. 192 CGContextStrokeRectWithWidth(context, r, 12) 193 CGContextRestoreGState(context) 194 195def showComplexShadowIssues(context): 196 offset = CGSize(-6, -6) 197 blur = 3 198 199 # Set the shadow. 200 CGContextSetShadow(context, scaleShadowOffset(offset), blur) 201 # Draw the colored logo. 202 drawColoredLogo(context) 203 204def showComplexShadow(context): 205 offset = CGSize(-6, -6) 206 blur = 3 207 208 # Set the shadow. 209 CGContextSetShadow(context, scaleShadowOffset(offset), blur) 210 211 # Begin a transparency layer. A snapshot is made of the graphics state and 212 # the shadow parameter is temporarily reset to no shadow, the blend mode 213 # is set to Normal, and the global alpha parameter is set to 1.0. 214 # 215 # All drawing that occurs after CGContextBeginTransparencyLayer but before 216 # CGContextEndTransparencyLayer is collected together and when 217 # CGContextEndTransparencyLayer is called, Quartz composites the collected 218 # drawing to the context, using the global alpha, blend mode, and shadow 219 # that was in effect when CGContextBeginTransparencyLayer was called. 220 221 CGContextBeginTransparencyLayer(context, None) 222 # Draw the colored logo. 223 drawColoredLogo(context) 224 225 # Ending the transparency layer causes all drawing in the transparency 226 # layer to be composited with the global alpha, blend mode, and shadow 227 # in effect at the time CGContextBeginTransparencyLayer was called. The 228 # graphics state is restored to that in effect when 229 # CGContextBeginTransparencyLayer was called. 230 231 # This restores the graphics state to that in effect 232 # at the last call to CGContextBeginTransparencyLayer. 233 CGContextEndTransparencyLayer(context) 234 235def doLayerCompositing(context): 236 r = CGRectMake(40, 50, 142, 180) 237 # Object 1. 238 CGContextTranslateCTM(context, 20, 20) 239 CGContextSetFillColorWithColor(context, Utilities.getRGBOpaqueGreenColor()) 240 # Draw a green background. 241 CGContextFillRect(context, r) 242 # Draw the colored logo. 243 drawColoredLogo(context) 244 245 # Object 2. 246 CGContextTranslateCTM(context, 300, 0) 247 CGContextSetFillColorWithColor(context, Utilities.getRGBOpaqueGreenColor()) 248 # Draw a green background. 249 CGContextFillRect(context, r) 250 251 # Draw the rectangles with opacity 0.75. 252 CGContextSetAlpha(context, 0.75) 253 254 drawColoredLogo(context) 255 256 # Object 3. 257 CGContextTranslateCTM(context, 300, 0) 258 # Set the alpha to 1.0 for drawing the background. 259 CGContextSetAlpha(context, 1.0) 260 CGContextSetFillColorWithColor(context, Utilities.getRGBOpaqueGreenColor()) 261 CGContextFillRect(context, r) 262 # Draw the rectangles with opacity 0.75. 263 CGContextSetAlpha(context, 0.75) 264 # Begin a transparency layer. Drawing collected in 265 # this transparency layer will be composited with an 266 # alpha value of 0.75 when the transparency layer is ended. 267 CGContextBeginTransparencyLayer(context, None) 268 if 1: 269 # Draw the colored logo into the transparency layer. 270 drawColoredLogo(context) 271 272 # Ending the transparency layer causes the drawing 273 # to then be composited with the global alpha value 274 # in effect when CGContextBeginTransparencyLayer was called. 275 CGContextEndTransparencyLayer(context) 276 277def shadowPDFDocument(context, url): 278 pdfDoc = CGPDFDocumentCreateWithURL(url) 279 offset = CGSize(-7, -7) 280 281 if pdfDoc is None: 282 print >>sys.stderr, "Couldn't create PDF document reference!" 283 return 284 285 r = CGPDFDocumentGetMediaBox(pdfDoc, 1) 286 r.origin.x = 20 287 r.origin.y = 20 288 289 # Set the shadow. 290 CGContextSetShadow(context, scaleShadowOffset(offset), 3) 291 292 # On Tiger and later, there is no need to use 293 # a transparency layer to draw a PDF document as 294 # a grouped object. On Panther, you can do so 295 # by using a transparency layer. Drawing collected in 296 # this transparency layer is drawn with the shadow 297 # when the layer is ended. 298 CGContextBeginTransparencyLayer(context, None) 299 if 1: 300 CGContextDrawPDFDocument(context, r, pdfDoc, 1) 301 302 CGContextEndTransparencyLayer(context) 303