1from Quartz import * 2import Quartz 3 4import Utilities 5 6import sys 7 8def drawQuartzRomanText(context): 9 text = "Quartz" 10 textlen = len(text) 11 fontSize = 60 12 13 opaqueBlack = [0.0, 0.0, 0.0, 1.0] 14 opaqueRed = [0.663, 0.0, 0.031, 1.0] 15 16 # Set the fill color space. This sets the 17 # fill painting color to opaque black. 18 CGContextSetFillColorSpace(context, 19 Utilities.getTheCalibratedRGBColorSpace()) 20 21 # The Cocoa framework calls the draw method with an undefined 22 # value of the text matrix. It's best to set it to what is needed by 23 # this code: the identity transform. 24 CGContextSetTextMatrix(context, CGAffineTransformIdentity) 25 26 # Set the font with the PostScript name "Times-Roman", at 27 # fontSize points, with the MacRoman encoding. 28 CGContextSelectFont(context, "Times-Roman", fontSize, kCGEncodingMacRoman) 29 30 # The default text drawing mode is fill. Draw the text at (70, 400). 31 CGContextShowTextAtPoint(context, 70, 400, text, textlen) 32 33 # Set the fill color to red. 34 CGContextSetFillColor(context, opaqueRed) 35 36 # Draw the next piece of text where the previous one left off. 37 CGContextShowText(context, text, textlen) 38 39 for i in range(3): 40 # Get the current text pen position. 41 p = CGContextGetTextPosition(context) 42 # Translate to the current text pen position. 43 CGContextTranslateCTM(context, p.x, p.y) 44 45 # Rotate clockwise by 90 degrees for the next 46 # piece of text. 47 CGContextRotateCTM(context, Utilities.DEGREES_TO_RADIANS(-90)) 48 # Draw the next piece of text in blac at the origin. 49 CGContextSetFillColor(context, opaqueBlack) 50 CGContextShowTextAtPoint(context, 0, 0, text, textlen) 51 # Draw the next piece of text where the previous piece 52 # left off and paint it with red. 53 CGContextSetFillColor(context, opaqueRed) 54 CGContextShowText(context, text, textlen) 55 56 57def myCGContextStrokeLineSegments(context, s, count): 58 # CGContextStrokeLineSegments is available only on Tiger and later 59 # so if it isn't available, use an emulation of 60 # CGContextStrokeLineSegments. It is better to use the 61 # built-in CGContextStrokeLineSegments since it has significant 62 # performance optimizations on some hardware. 63 if hasattr(Quartz, 'CGContextStrokeLineSegments'): 64 CGContextStrokeLineSegments(context, s, count) 65 else: 66 CGContextBeginPath(context) 67 for k in xrange(0, count, 2): 68 CGContextMoveToPoint(context, s[k].x, s[k].y) 69 CGContextAddLineToPoint(context, s[k+1].x, s[k+1].y) 70 CGContextStrokePath(context) 71 72_gridLines = [] 73def drawGridLines(context): 74 numlines = 60 75 76 if not _gridLines: 77 stepsize = 4.0 78 val = 0 79 for i in xrange(0, 2*numlines, 2): 80 _gridLines.append(CGPointMake(val, -60)) 81 _gridLines.append(CGPointMake(val, 200)) 82 val += stepsize 83 84 val = -20 85 for i in xrange(2*numlines, 4*numlines, 2): 86 _gridLines.append(CGPointMake(0, val)) 87 _gridLines.append(CGPointMake(400, val)) 88 val += stepsize 89 90 myCGContextStrokeLineSegments(context, _gridLines, len(_gridLines)) 91 92def drawQuartzTextWithTextModes(context): 93 fillText = "Fill " 94 strokeText = "Stroke " 95 fillAndStrokeText = "FillStroke " 96 invisibleText = "Invisible " 97 clipText = "ClipText " 98 fillStrokeClipText = "FillStrokeClip " 99 fontSize = 40.0 100 extraLeading = 5.0 101 dash = (1,1) 102 opaqueRed = (1.0, 0.0, 0.0, 1.0) 103 104 # Set the fill and stroke color space. This sets the 105 # fill and stroke painting color to opaque black. 106 CGContextSetFillColorSpace(context, 107 Utilities.getTheCalibratedRGBColorSpace()) 108 CGContextSetStrokeColorSpace(context, 109 Utilities.getTheCalibratedRGBColorSpace()) 110 111 # The Cocoa framework calls the draw method with an undefined 112 # value of the text matrix. It's best to set it to what is needed by 113 # this code: the identity transform. 114 CGContextSetTextMatrix(context, CGAffineTransformIdentity) 115 116 # Set the font with the PostScript name "Times-Roman", at 117 # fontSize points, with the MacRoman encoding. 118 CGContextSelectFont(context, "Times-Roman", fontSize, kCGEncodingMacRoman) 119 120 # ---- Text Line 1 ---- 121 122 # Default text drawing mode is fill. Draw the text at (10, 400). 123 CGContextShowTextAtPoint(context, 10, 400, fillText, len(fillText)) 124 125 # Set the fill color to red. 126 CGContextSetFillColor(context, opaqueRed) 127 128 CGContextSetTextPosition(context, 180, 400) 129 CGContextShowText(context, fillText, len(fillText)) 130 131 # Translate down for the next line of text. 132 CGContextTranslateCTM(context, 0, -(fontSize + extraLeading)) 133 134 # ---- Text Line 2 ---- 135 136 # Now stroke the text by setting the text drawing mode 137 # to kCGTextStroke. When stroking text, Quartz uses the stroke 138 # color in the graphics state. 139 CGContextSetTextDrawingMode(context, kCGTextStroke) 140 CGContextShowTextAtPoint(context, 10, 400, strokeText, len(strokeText)) 141 142 # When stroking text, the line width and other gstate parameters 143 # that affect stroking affect text stroking as well. 144 CGContextSetLineWidth(context, 2) 145 CGContextSetLineDash(context, 0, dash, 2) 146 147 CGContextSetTextPosition(context, 180, 400) 148 CGContextShowText(context, strokeText, len(strokeText)) 149 150 # Reset the line dash and line width to their defaults. 151 CGContextSetLineDash(context, 0, None, 0) 152 CGContextSetLineWidth(context, 1) 153 154 # Translate down for the next line of text. 155 CGContextTranslateCTM(context, 0, -(fontSize + extraLeading)) 156 157 # ---- Text Line 3 ---- 158 159 # Set the text drawing mode so that text is both filled and 160 # stroked. This produces text that is filled with the fill 161 # color and stroked with the stroke color. 162 CGContextSetTextDrawingMode(context, kCGTextFillStroke) 163 CGContextShowTextAtPoint(context, 10, 400, 164 fillAndStrokeText, len(fillAndStrokeText)) 165 166 # Now draw again with a thicker stroke width. 167 CGContextSetLineWidth(context, 2) 168 CGContextSetTextPosition(context, 180, 400) 169 CGContextShowText(context, fillAndStrokeText, len(fillAndStrokeText)) 170 171 CGContextSetLineWidth(context, 1) 172 CGContextTranslateCTM(context, 0, -(fontSize + extraLeading)) 173 174 # ---- Text Line 4 ---- 175 176 # Set the text drawing mode to invisible so that the next piece of 177 # text does not appear. Quartz updates the text position as 178 # if it had been drawn. 179 CGContextSetTextDrawingMode(context, kCGTextInvisible) 180 CGContextShowTextAtPoint(context, 10, 400, 181 invisibleText, len(invisibleText)) 182 183 CGContextSetTextDrawingMode(context, kCGTextFill) 184 185 CGContextSetTextPosition(context, 180, 400) 186 CGContextShowText(context, fillText, len(fillText)) 187 188 CGContextTranslateCTM(context, 0, -(fontSize + extraLeading)) 189 190 # ---- Text Line 5 ---- 191 CGContextSaveGState(context) 192 if 1: 193 # Use the text as a clipping path. 194 CGContextSetTextDrawingMode(context, kCGTextClip) 195 CGContextShowTextAtPoint(context, 10, 400, clipText, len(clipText)) 196 197 # Position and draw a grid of lines. 198 CGContextTranslateCTM(context, 10, 400) 199 drawGridLines(context) 200 CGContextRestoreGState(context) 201 202 CGContextSaveGState(context) 203 if 1: 204 # The current text position is that after the last piece 205 # of text has been drawn. Since CGContextSaveGState/ 206 # CGContextRestoreGState do not affect the text position or 207 # the text matrix, the text position is that after the last 208 # text was "drawn", that drawn with the kCGTextClip mode 209 # above. This is where the next text drawn will go if it 210 # isn't explicitly positioned. 211 nextTextPosition = CGContextGetTextPosition(context) 212 213 # Draw so that the text is filled, stroked, and then used 214 # the clip subsequent drawing. 215 CGContextSetTextDrawingMode(context, kCGTextFillStrokeClip) 216 217 # Explicitly set the text position. 218 CGContextSetTextPosition(context, 180, 400) 219 nextTextPosition = CGContextGetTextPosition(context) 220 221 CGContextShowText(context, fillStrokeClipText, len(fillStrokeClipText)) 222 # Adjust the location of the grid lines so that they overlap the 223 # text just drawn. 224 CGContextTranslateCTM(context, nextTextPosition.x, nextTextPosition.y) 225 # Draw the grid lines clipped by the text. 226 drawGridLines(context) 227 CGContextRestoreGState(context) 228 229# showFlippedTextAtPoint is a cover routine for CGContextShowText 230# that is useful for drawing text in a coordinate system where the y axis 231# is flipped relative to the default Quartz coordinate system. 232# 233# This code assumes that the text matrix is only used to 234# flip the text, not to perform scaling or any other 235# possible use of the text matrix. 236# 237# This function preserves the a, b, c, and d components of 238# the text matrix across its execution but updates the 239# tx, ty components (the text position) to reflect the 240# text just drawn. If all the text you draw is flipped, it 241# isn't necessary to continually set the text matrix. Instead 242# you could simply call CGContextSetTextMatrix once with 243# the flipped matrix each time your drawing 244# code is called. 245def showFlippedTextAtPoint(c, x, y, text, textLen): 246 t = CGAffineTransform(1.0, 0.0, 0.0, -1.0, 0.0, 0.0) 247 # Get the existing text matrix. 248 s = CGContextGetTextMatrix(c) 249 # Set the text matrix to the one that flips in y. 250 CGContextSetTextMatrix(c, t) 251 # Draw the text at the point. 252 CGContextShowTextAtPoint(c, x, y, text, textLen) 253 # Get the updated text position. 254 p = CGContextGetTextPosition(c) 255 # Update the saved text matrix to reflect the updated 256 # text position. 257 s.tx = p.x ; s.ty = p.y 258 # Reset to the text matrix in effect when this 259 # routine was called but with the text position updated. 260 CGContextSetTextMatrix(c, s) 261 262 263def drawQuartzTextWithTextMatrix(context): 264 fontSize = 60.0 265 extraLeading = 10.0 266 text = "Quartz " 267 textlen = len(text) 268 269 # The Cocoa framework calls the draw method with an undefined 270 # value of the text matrix. It's best to set it to what is needed by 271 # this code. Initially that is the identity transform. 272 CGContextSetTextMatrix(context, CGAffineTransformIdentity) 273 274 # Set the font with the PostScript name "Times-Roman", at 275 # fontSize points, with the MacRoman encoding. 276 CGContextSelectFont(context, "Times-Roman", fontSize, kCGEncodingMacRoman) 277 278 # ---- Text Line 1 ---- 279 280 # Draw the text at (10, 600). 281 CGContextShowTextAtPoint(context, 10, 600, text, textlen) 282 283 # Get the current text position. The text pen is at the trailing 284 # point from the text just drawn. 285 textPosition = CGContextGetTextPosition(context) 286 287 # Set the text matrix to one that flips text in y and sets 288 # the text position to the user space coordinate (0,0). 289 t = CGAffineTransformMake(1, 0, 0, -1, 0, 0) 290 CGContextSetTextMatrix(context, t) 291 292 # Set the text position to the point where the previous text ended. 293 CGContextSetTextPosition(context, textPosition.x, textPosition.y) 294 295 # Draw the text at the current text position. It will be drawn 296 # flipped in y, relative to the text drawn previously. 297 CGContextShowText(context, text, textlen) 298 299 # ---- Text Line 2 ---- 300 301 # Translate down for the next piece of text. 302 CGContextTranslateCTM(context, 0, -(3*fontSize + extraLeading)) 303 304 CGContextSaveGState(context) 305 if 1: 306 # Change the text matrix to {1, 0, 0, 3, 0, 0}, which 307 # scales text by a factor of 1 in x and 3 in y. 308 # This scaling doesn't affect any drawing other than text 309 # drawing since only text drawing is transformed by 310 # the text matrix. 311 t = CGAffineTransformMake(1, 0, 0, 3, 0, 0) 312 CGContextSetTextMatrix(context, t) 313 314 # This text is scaled relative to the previous text 315 # because of the text matrix scaling. 316 CGContextShowTextAtPoint(context, 10, 600, text, textlen) 317 318 # This restores the graphics state to what it was at the time 319 # of the last CGContextSaveGState, but since the text matrix 320 # isn't part of the Quartz graphics state, it isn't affected. 321 CGContextRestoreGState(context) 322 323 # The text matrix isn't affected by CGContextSaveGState and 324 # CGContextRestoreGState. You can see this by observing that 325 # the next text piece appears immediately after the first piece 326 # and with the same text scaling as that text drawn with the 327 # text matrix established before we did CGContextRestoreGState. 328 CGContextShowText(context, text, textlen) 329 330 # ---- Text Line 3 ---- 331 # Translate down for the next piece of text. 332 CGContextTranslateCTM(context, 0, -(fontSize + extraLeading)) 333 334 # Reset the text matrix to the identity matrix. 335 CGContextSetTextMatrix(context, CGAffineTransformIdentity) 336 337 # Now draw text in a flipped coordinate system. 338 CGContextSaveGState(context) 339 if 1: 340 # Flip the coordinate system to mimic a coordinate system with the origin 341 # at the top-left corner of a window. The new origin is at 600 units in 342 # +y from the old origin and the y axis now increases with positive y 343 # going down the window. 344 CGContextConcatCTM(context, CGAffineTransformMake(1, 0, 0, -1, 0, 600)) 345 # This text will be flipped along with the CTM. 346 CGContextShowTextAtPoint(context, 10, 10, text, textlen) 347 # Obtain the user space coordinates of the current text position. 348 textPosition = CGContextGetTextPosition(context) 349 # Draw text at that point but flipped in y. 350 showFlippedTextAtPoint(context, textPosition.x, textPosition.y, text, textlen) 351 CGContextRestoreGState(context) 352