I strongly encourage non-Macintosh programmers to pick up this book and find out for themselves what a truly great development platform we have in the Macintosh. Programmers and software managers at Windows, Linux, and Unix shops should seriously consider the Macintosh as an addition to (or replacement for!) their current stable of platforms. In particular, movie studios, animation houses, and special-effects facilities would do well to consider that with Macintosh, a single platform can provide every- thing they need…. —from the foreword by Philip J. Schneider R&D Engineer, Industrial Light + Magic
Finally, the book I’ve wanted for years is here! As a graphics pro- grammer, I appreciate the clear explanations of how Quartz has packaged the state of the art for mere mortals. As a Cocoa pro- grammer, I appreciate the clear explanation of which [Quartz] facilities…Cocoa is already leveraging. This will become a well- thumbed resource for all graphics programmers on Mac OS X, whether or not they’re using Cocoa, Carbon, or porting code from another platform. —Dr. Michael B. Johnson Pixar Animation Studios
I’ve been using Quartz since the first release of Mac OS X, and this book covers it all! Great advice, good sample code—it’s the book to have if you want to learn everything about Quartz. —Stephane Marcouiller SDE, Microsoft Corporation
Not only do the authors of Programming with Quartz have a superb understanding of their subject matter, but they have conveyed their knowledge in a clear, concise, and readable manner. Program- ming with Quartz has saved me quite a bit of time on my first major Quartz project, and its more general lessons on graphics programming techniques and concepts will prove valuable when using any modern graphics API. —Josh Aas Software Engineer, Mozilla Corporation
Even after implementing several features using Quartz, I still learned things from this book that I did not know. For example, the chapter on handling PDF images is very thorough in its descriptions and the issues it raises. I wish I had this chapter when I implemented this feature. The book is very well written and covers many complex topics in 2D graphics clearly and at a level appropriate for all programmers. Programming with Quartz contin- ues Apple's tradition of producing excellent documentation for its developers. —Ron Ullmann Macintosh Business Unit, Microsoft Corporation
Programming with Quartz 2D and PDF Graphics in Mac OS X
David Gelphman Bunny Laden
Senior Editor Tim Cox Publishing Services Manager Simon Crump Project Manager Elisabeth Beller Assistant Editor Rick Camp Editorial Assistant Jessica Evans Cover Design Laurie Anderson Cover Image © Digital Vision/Getty Images (photographer, Chris Knapton) Text Design Rebecca Evans Composition Nancy Logan Technical Illustration Dartmouth Publishing, Inc.; Apple Copyeditor Yonie Overton Proofreader Jennifer McClain Indexer Steve Rath Interior and Cover Printer Transcontinental Interglobe © 2006 by Apple Computer, Inc. All rights reserved. Apple, the Apple logo, AppleScript, Aqua, Carbon, Cocoa, ColorSync, LaserWriter, Mac, Mac OS, Macintosh, Panther, PowerBook, Quartz, QuickDraw, QuickTime, and Xcode are trademarks of Apple Computer, Inc., registered in the United States and other coun- tries, used by Morgan Kaufmann with permission. Apple Remote Desktop, Finder, Gadget, and Tiger are trademarks of Apple Computer, Inc. used by Morgan Kaufmann with permission. Designations used by companies to distinguish their products are often claimed as trade- marks or registered trademarks. In all instances in which Morgan Kaufmann Publishers is aware of a claim, the product names appear in initial capital or all capital letters. Readers, however, should contact the appropriate companies for more complete information regarding trademarks and registration. Morgan Kaufmann Publishers is an imprint of Elsevier. 500 Sansome Street, Suite 400, San Francisco, CA 94111 No part of this publication may be reproduced, stored in a retrieval system, or transmit- ted in any form or by any means—electronic, mechanical, photocopying, scanning, or otherwise—without prior written permission of the publisher. Permissions may be sought directly from Elsevier’s Science & Technology Rights Depart- ment in Oxford, UK: phone: (+44) 1865 843830, fax: (+44) 1865 853333, e-mail: [email protected]. You may also complete your request on-line via the Elsevier homepage (http://elsevier.com) by selecting “Customer Support” and then “Obtaining Per- missions.” Library of Congress Cataloging-in-Publication Data Application submitted. ISBN 13: 978-0-12-369473-7 ISBN 10: 0-12-369473-6 For information on all Morgan Kaufmann publications, visit our website at www.mkp.com or www.books.elsevier.com. Printed in Canada 05 06 07 08 09 5 4 3 2 1
Working together to grow libraries in developing countries www.elsevier.com | www.bookaid.org | www.sabre.org
To my friend, colleague, and manager of many years, who fosters a great working environment, inspires me with his creativity and hard work, and provides top- notch technical assistance and advice.
To Mac developers, who will bring Quartz alive in innovative ways.
Contents
Foreward xv Preface xix Our Objective xix Outline xx Conventions and Assumptions xxii Source Code xxiii Header Files xxiv Quartz Technologies xxv See Also xxvi Acknowledgments xxviii Chapter 1 Introducing Quartz 2D 1 A Bit of History 1 Quartz 2D Overview 8 What Software Can Use Quartz 2D? 10 Summary 12 See Also 12 Chapter 2 Quartz 2D Drawing Basics 15 Quartz Graphics Contexts 15 Filling a Rectangle 16 Stroking a Rectangle 18 The Order of Fill and Stroke Operations 20 Transforming the Coordinate System 23 Constructing Quartz Paths 25 Painting with Alpha 30 Making Dashed Lines 32 Clipping a Drawing 36 Drawing PDF Content 38 More About Graphics Contexts 41 Summary 42 See Also 43
vii
viii Contents
Chapter 3 Using Quartz 2D in Cocoa 45 Xcode Overview 46 Creating a Cocoa Xcode Project in Tiger 46 Creating a View in Interface Builder 49 Connecting the Interface to the Code 53 Obtaining a Graphics Context in Cocoa 55 Writing the Drawing Code 56 Examining the Drawing Output 58 Cocoa Framework Drawing and Quartz 59 Summary 62 See Also 62 Chapter 4 Using Quartz 2D in Carbon 65 Creating a Carbon Xcode Project 66 Setting Up a Carbon Window 68 Creating an Event Handler 73 Examining the Drawing Output 76 Using QDBeginCGContext 79 Summary 81 See Also 82 Chapter 5 The Quartz Coordinate System and Coordinate Transformations 83 User Space and Device Space 83 Coordinate Transformations 86 The Current Transformation Matrix 87 The Mathematics of Affine Transforms 88 Saving and Restoring a Coordinate System 91 Affine Transform Convenience Functions 94 Creating a Skewed Coordinate System 98 Summary 100 See Also 101 Chapter 6 Drawing with Paths 103 Properties of Paths 104 Path Construction Primitives 105 Cubic Bézier Curves 106
Contents ix
Quadratic Bézier Curves 109 Closing Subpaths 110 Path Construction Convenience Functions 111 Additional Path Convenience Functions (Tiger) 116 Stroking Paths 119 Line Width 120 Line Joins 121 Line Caps 123 Line Dash 125 Filling Paths 126 Clipping with Paths 129 CGPath Objects (Jaguar) 131 Anti-aliasing 134 Path Utility Functions 137 Aligning User Space Coordinates on Pixel Boundaries (Tiger) 139 Summary 144 See Also 144 Chapter 7 Color, Alpha Transparency, and the Quartz Graphics State 147 Color and Color Spaces 148 A General Approach to Setting Color 150 CGColor Objects (Panther) 152 Calibrated Color Spaces 155 Device Color Spaces 160 Special Color Spaces 161 Creating Color Spaces by Name (Jaguar) 164 Rendering Intents 165 Alpha Transparency 166 Blend Modes (Tiger) 170 Graphics State Parameters 173 Summary 181 See Also 182 Chapter 8 Data Providers and Data Consumers 185 Data Providers 186 CGDataProviderCreateWithURL 187 CGDataProviderCreateWithData 188 CGDataProviderCreate 190 CGDataProviderCreateDirectAccess 194
x Contents
CGDataProviderCreateWithCFData (Tiger) 196 Guidelines for Using Data Providers 198 Data Consumers 198 Summary 202 See Also 202 Chapter 9 Drawing Images 203 Creating CGImage Objects 204 Specialized Functions for JPEG and PNG 204 Drawing Images into a Flipped Coordinate System 210 A General Function for Uncompressed Data 211 Alpha Information 212 Pixel Formats 214 Decode Array 215 Interpolation 217 Drawing Uncompressed, Raw Image Data 219 Drawing a Synthetic Image from Data in Memory 222 Drawing a Synthetic Image by Accessing Data Directly 223 Bitmap Images and Universal Binaries (Tiger) 225 Generalized Functions for Compressed Image Data (Tiger) 226 Importing Image Data with QuickTime 238 Guidelines for Image Creation 240 Best Practices for Working with Images 241 Image Utility Functions 244 Getting Image Dimensions 244 Getting the Pixel Format 244 Creating an Image from a Bitmap Context 245 Working with Color Spaces 245 Creating Subimages 249 Writing Image Data Using CGImageDestination (Tiger) 255 Exporting to JPEG Using a QuickTime Exporter 258 Summary 259 See Also 260 Chapter 10 Image Masking 263 Creating an Image Mask 264 Drawing and Inverting a 1-Bit Image Mask 266 Drawing an 8-Bit-Deep Mask 272 Masking an Image (Tiger) 273 Masking an Image with an Image Mask 274 Masking an Image with an Image 277 Masking Guidelines 279
Contents xi
Using Color as a Mask (Tiger) 279 Clipping to a Mask (Tiger) 282 Summary 287 See Also 287 Chapter 11 Text 289 Text Drawing Parameters 290 Font and Font Size 290 Text Matrix and Text Position 291 Text Drawing Modes 292 Font Smoothing (Jaguar) 295 Character Spacing 296 Drawing Text Using Quartz 296 Drawing with Characters 297 Drawing with Glyphs 305 Drawing Text Using Cocoa 306 Using NSString 308 Using NSLayoutManager 313 Subclassing to Get Additional Control 315 Drawing Text Using Carbon 324 Using HIThemeDrawTextBox (Panther) 325 Using Multilingual Text Engine 329 Using Apple Type Services for Unicode Imaging 330 Drawing Text in a Flipped Coordinate System 338 Summary 341 See Also 341 Chapter 12 Creating Bits 345 Bitmap Graphics Context 346 Supported Pixel Formats 346 Creating a Bitmap Graphics Context 349 Bitmap Contexts and Universal Binaries (Tiger) 355 Getting Information About a Bitmap Context 356 Using the Bitmap Data from a Bitmap Context 357 CGLayers (Tiger) 371 Creating a CGLayer Object 373 Drawing to a CGLayer 374 Drawing the Contents of a CGLayer 375 Using a CGLayer to Draw a Checkerboard 376 Caching Drawing Offscreen 379 Drawing Repeatedly Without Caching 381 xii Contents
Drawing Repeatedly with Bitmap Context Caching 384 Drawing Repeatedly with CGLayer Caching 386 Display Profile Issues 389 Replacing CopyBits 391 Summary 393 See Also 393 Chapter 13 Opening and Drawing PDF Documents 397 PDF Document Properties 398 Opening a PDF Document 400 Using PDF as a Graphical Interchange 401 Creating PDF Data from a Pasteboard: Cocoa 403 Creating PDF from a Pasteboard: Carbon 404 Drawing PDF Pages 406 Drawing with CGContextDrawPDFDocument 406 Drawing PDF Documents in a Flipped Coordinate System 408 Using CGPDFPage Objects (Panther) 412 Drawing with PDF Rotation on Jaguar and Earlier Versions 416 Handling Protected PDF Documents (Jaguar) 424 PDF Document Utility Functions 429 Summary 431 See Also 431 Chapter 14 Creating and Examining PDF Documents 435 Creating New PDF Documents 435 Using CGPDFContextCreateWithURL 436 Using the Auxiliary Information Dictionary 439 Copying PDF Content to a Pasteboard 443 Adding Content to Existing PDF Documents 447 Adding Links to PDF Documents (Tiger) 455 Creating a Link to a URL 456 Creating a Link to Another Page in the Document 458 Creating Encrypted PDF Output (Tiger) 462 PDF Document Generation Issues 466 Examining PDF Document Content (Panther, Tiger) 467 Quartz PDF Introspection 468 Scanning the PDF Content Stream (Tiger) 469 Summary 478 See Also 478 Contents xiii
Chapter 15 Advanced Drawing Features 481 Drawing with Patterns 481 Creating Patterns 483 Creating and Drawing Colored Patterns 485 Base Space, the Pattern Matrix, and Transforming Patterns 493 Pattern Phase 497 Creating and Drawing Stencil Patterns 499 Drawing Complex Patterns 505 Pattern Issues 510 Drawing with Shadows (Panther) 512 Shadow Attributes 512 Creating and Drawing with Shadows 513 Shadow Offset and Quartz Base Space 517 Shadows and Grouped Objects 520 Shadows and PDF Documents 521 Drawing with Transparency Layers (Panther) 522 Using Transparency Layers 523 Alpha Compositing and Transparency Layers 526 Transparency Layers and PDF Documents 528 Transparency Layers Compared to CGLayers 531 Drawing with Shadings (Jaguar) 531 Shading Concepts and the CGFunction 533 Axial Shadings 537 Radial Shadings 545 Radial Shading Geometries 550 Transforming Shadings 558 Summary 562 See Also 563 Chapter 16 Supporting PostScript and EPS Data 565 Overview of the Conversion Process 566 Quartz Conversion Functions and Callbacks (Panther) 567 Creating a PDF Data File from PostScript Data 569 Using Converted PostScript Data in Your Application 575 PSConverter Advanced Issues 580 Printing Source EPS Data 582 Guidelines for Supporting EPS Data in Your Application 589 Summary 590 See Also 591 xiv Contents
Chapter 17 Performance and Debugging 593 Optimizing Performance 593 The Quartz Compositor 594 Quartz Object and Memory Model 599 Improving Performance 602 Measuring Performance 606 Debugging Your Drawing 613 Examining the Coordinate System 613 Checking the Clipping Area 617 Drawing a Debugging Rectangle 617 Looking for Console Messages 618 Checking for Data Provider Integrity 619 Checking for Immutability Violations 620 Checking for Improperly Initialized Contexts 620 Checking for Out-of-Sync Color Setting 620 Drawing Images to a PDF Context 621 Releasing a CGPDFContext Object 621 Checking Pattern Color Space Usage 622 Using PDF Generation as a Debugging Aid 622 Summary 626 See Also 627 Chapter 18 Creating Quartz Tools and Python Scripts 631 Python Scripting with Quartz (Panther) 632 Getting Started 632 Creating Bits with Python 634 Using Quartz in UNIX Tools 637 Security Issues 638 The PDF Workflow in Printing (Jaguar) 639 Summary 646 See Also 646 Index 647
Foreword
The typical day-to-day experience of most programmers consists of what is euphemistically known as “maintenance” (that is, fixing mistakes in existing code) or, if their karma is particularly good, the occasional opportunity to add new features to an existing library or application. While these activities (particu- larly the latter) can be rewarding in their own ways, the programmer is always constrained in some fashion by the requirement of compatibility with the exist- ing code base, with other existing libraries and applications, or with old file for- mats. While civilians (i.e., nonprogrammers) often fantasize about winning the lottery, the equivalent for many programmers is the rare opportunity to create a new library from scratch, without the constraints that often frustrate their desires to extend and improve an existing library. The advent of Mac OS X provided engineers at Apple with the opportunity (and challenge) to start afresh. Apple wisely chose to bring forward those parts of the original “toolbox” (APIs, in non-Apple speak) in the form of the Carbon inter- face—this allowed the existing application base to be ported to Mac OS X in a relatively painless fashion. However, Apple also recognized the tremendous opportunity afforded them by the fact that new Mac OS X APIs needn’t be backward compatible; they could start from scratch without being so con- strained and could take advantage of new technologies, hardware capabilities, and the lessons learned over many years of providing libraries and services to application developers. With Quartz 2D, Apple’s engineers have gone far beyond merely meeting that challenge and have produced an API that is simply spectacular. Here’s a thought experiment: close your eyes and imagine you’ve been given the opportunity to write a modern 2D graphics API from the ground up—what would be on your wish list? Certainly you’d want it to be device- and resolution-independent. You’d want sophisticated color management—the ability to use a variety of color spaces, including calibrated color—and you’d certainly want to support transpar- ency and blending. You’d want sophisticated handling of text: layout, fonts, and Unicode support. You’d want to be able to take advantage of widely used file for- mats and libraries (such as QuickTime, JPEG, PostScript, EPS, and PDF) but be independent of these as much as possible. You’d want it to be easy to do easy things, like draw a circle or a box, and you’d want it to be as easy as possible to do very complex things (for example, by providing a manageable interface to
xv
xvi Foreword
inherently complex functionality such as with color management or bitmap file formats). You’d want the API to be clean, consistent, elegant, and orthogonal so programmers could create more of the incredible applications the Macintosh is justifiably known for. You’d also want it to be blazingly fast to give users the best possible experience. Quartz 2D fulfills all those wishes and much more. The best API in the world isn’t going to go very far without adequate documen- tation. At the very least one needs a reference manual, and Apple’s have histori- cally been quite good. Reference manuals are not intended to teach program- mers the how and why of using an API, and so one can find for almost any API a number (often a large number) of books that purport to be tutorial in nature. I don’t need to offer more than the observation that such books tend to be highly variable in their value, to put it as diplomatically as possible. This is lamentable but understandable; the task of describing a rich and powerful API is certainly one of the most difficult in technical writing. The authors of the book you now hold in your hands have met the challenge of describing Quartz 2D in a simply spectacular fashion: this is unquestionably one of the best API books I’ve ever encountered. The Quartz 2D API’s elegance, clar- ity, and power is mirrored beautifully by the authors’ presentation: easy things are easy to understand, while complex functionality is explained in as straight- forward a fashion as possible. Many API how-to books fall down most dramati- cally in their use of code examples—either they are much too shallow or much too arcane or, worst of all, they will attempt to guide the reader through the entire development cycle of a contrived application. Not so with this book— indeed, the examples here are, well, exemplary; they’re chosen to guide the reader from complete naiveté to mastery and are explained in such a way that the application programmer understands why and not just how. This book has two other great strengths. First, as with many APIs, Quartz 2D provides several ways of accessing the library’s functionality, and the authors go to great effort to explain the often subtle differences in the approaches and provide clear guide- lines to the programmer for choosing the right approach. Second, the authors have provided a liberal dose of advice on best practices: tidbits of information regarding how to use the API correctly, which may not necessarily be obvious even to experienced programmers. The authors, in the preface that follows, have nicely described the goals and organization of the book and have provided a broad overview of some of Quartz 2D’s functionality (that is, what makes it such a great API), so I won’t belabor that here. Read the book! They also describe the intended audience, but since I have an opinion here and the imprimatur to state it, I will belabor that aspect. The Macintosh is so widely regarded for its “ease of use” that this phrase has almost become a cliché. The Macintosh has been wildly successful in the artistic, musical, and publishing communities. Both of these phenomena have led to the
Foreword xvii view among many non-Macintosh programmers that the Macintosh is not a seri- ous machine for business or science, much less an appealing platform for hard- core programming. I love the Macintosh for its ease of use, its “it just works” nature, the beauty and elegance of its user interface, and the awesome applica- tions available for it, but, even with all of this, I believe the Macintosh’s greatest strength lies in its APIs—they are simply the best in the business. The Macintosh is inarguably the best platform for users, but it is also the best platform for developers as well. By using Quartz 2D in the Carbon or Cocoa framework, developers can create the sorts of interactive applications for which the Mac is famous, and with much greater ease than on other platforms. But since Quartz 2D is not by its nature tied to either of these frameworks, program- mers can take advantage of the tremendous power of the API in command-line applications written in C and C++. Quartz 2D also has Python bindings for the great majority of its functionality, allowing programmers to simultaneously take advantage of Python and Quartz 2D. The authors don’t specifically mention it, but it would be possible to write an interactive application with a GUI in either X11 or Python and use most of the functionality of Quartz 2D. In light of all this, I strongly encourage non-Macintosh programmers to pick up this book and find out for themselves what a truly great development platform we have in the Macintosh. Programmers and software managers at Windows, Linux, and Unix shops should seriously consider the Macintosh as an addition to (or replacement for!) their current stable of platforms. In particular, movie stu- dios, animation houses, and special-effects facilities would do well to consider that with Macintosh, a single platform can provide everything they need: 3D applications (e.g., Maya and LightWave 3D), 2D applications (e.g., Adobe Pho- toshop), compositing (Shake), digital video editing (Final Cut Pro), and so on, as well as the best platform for developing in-house 3D and 2D applications. Let Quartz 2D and this wonderful book show you the possibilities. Philip J. Schneider R&D Engineer Industrial Light + Magic October 2005
Preface
This book describes the Quartz 2D graphics and imaging system in Mac OS X and explains how to use the Quartz 2D application programming interface (API). With the Portable Document Format (PDF) at the core of its imaging model, Quartz 2D is a breakthrough technology for two-dimensional (2D) graphics on personal computers. Quartz 2D provides the support you’d expect for graphics primitives like lines, curves, rectangles, arbitrary paths, and images. It also supports features such as translucency, layers, shadows, and a host of other sophisticated effects. Not only can you create PDF documents, but you can draw and dissect existing ones. The Quartz 2D implementation is fast and easy to use. In addition to 2D- drawing and PDF support, Quartz 2D reads, displays, and writes a wide variety of bitmap image formats. Color management is built into Quartz. Quartz 2D works behind the scenes with ColorSync technology to make sure ICC color profiles are respected. Appli- cations can use calibrated color spaces as well as device color spaces. Quartz 2D drawing can be sent to a printer, captured to a PDF file, or rendered to an offscreen bitmap just as easily as it can be drawn to the display. That’s because drawing destinations are treated as abstractions. Applications can focus on the drawing and let the system handle the process of rendering the content to a specific destination.
Our Objective
This book is intended to familiarize developers with the capabilities of Quartz 2D and to get them programming Quartz graphics in their applications. The book describes how best to use Quartz 2D and gives numerous code examples to show how to accomplish many of the drawing tasks possible with Quartz 2D. Any of the following will benefit from reading this book: