Quartz 2d Programming Guide Download
Quartz 2d Programming Guide Download
https://ebookbell.com/product/quartz-2d-programming-guide-2463152
https://ebookbell.com/product/programming-with-quartz-2d-and-pdf-
graphics-in-mac-os-x-1st-edition-david-gelphman-2382698
https://ebookbell.com/product/quartz-2d-graphics-for-mac-os-x-
developers-r-scott-thompson-983430
Quartz Mountain The Lost Realm Book 1 The Lost Realm Series Audrey
Lynn
https://ebookbell.com/product/quartz-mountain-the-lost-realm-
book-1-the-lost-realm-series-audrey-lynn-55442972
Quartz Deposits Mineralogy And Analytics 1st Edition Jens Gtze Auth
https://ebookbell.com/product/quartz-deposits-mineralogy-and-
analytics-1st-edition-jens-gtze-auth-4399110
Quartz Job Scheduling Framework Building Open Source Enterprise
Applications 1st Edition Chuck Cavaness
https://ebookbell.com/product/quartz-job-scheduling-framework-
building-open-source-enterprise-applications-1st-edition-chuck-
cavaness-919256
https://ebookbell.com/product/the-quartz-crystal-microbalance-in-soft-
matter-research-fundamentals-and-modeling-1st-edition-diethelm-
johannsmann-auth-4931394
Cool How The Brains Hidden Quest For Cool Drives Our Economy And
Shapes Our World Steven Quartz
https://ebookbell.com/product/cool-how-the-brains-hidden-quest-for-
cool-drives-our-economy-and-shapes-our-world-steven-quartz-5026410
https://ebookbell.com/product/learning-quartz-composer-a-handson-
guide-to-creating-motion-graphics-with-quartz-composer-graham-
robinson-10303858
https://ebookbell.com/product/understanding-quartz-crystals-and-
oscillators-ramn-m-cerda-10566446
Quartz 2D Programming Guide
Graphics & Animation: 2D Drawing
2010-11-19
Even though Apple has reviewed this document,
APPLE MAKES NO WARRANTY OR REPRESENTATION,
Apple Inc. EITHER EXPRESS OR IMPLIED, WITH RESPECT TO
© 2001, 2010 Apple Inc. THIS DOCUMENT, ITS QUALITY, ACCURACY,
MERCHANTABILITY, OR FITNESS FOR A PARTICULAR
All rights reserved. PURPOSE. AS A RESULT, THIS DOCUMENT IS
PROVIDED “AS IS,” AND YOU, THE READER, ARE
ASSUMING THE ENTIRE RISK AS TO ITS QUALITY
No part of this publication may be reproduced, AND ACCURACY.
stored in a retrieval system, or transmitted, in IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT,
any form or by any means, mechanical, INDIRECT, SPECIAL, INCIDENTAL, OR
electronic, photocopying, recording, or CONSEQUENTIAL DAMAGES RESULTING FROM ANY
DEFECT OR INACCURACY IN THIS DOCUMENT, even
otherwise, without prior written permission of if advised of the possibility of such damages.
Apple Inc., with the following exceptions: Any THE WARRANTY AND REMEDIES SET FORTH ABOVE
person is hereby authorized to store ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL
documentation on a single computer for OR WRITTEN, EXPRESS OR IMPLIED. No Apple
dealer, agent, or employee is authorized to make
personal use only and to print copies of any modification, extension, or addition to this
documentation for personal use provided that warranty.
the documentation contains Apple’s copyright Some states do not allow the exclusion or limitation
of implied warranties or liability for incidental or
notice. consequential damages, so the above limitation or
exclusion may not apply to you. This warranty gives
The Apple logo is a trademark of Apple Inc. you specific legal rights, and you may also have
other rights which vary from state to state.
No licenses, express or implied, are granted
with respect to any of the technology described
in this document. Apple retains all intellectual
property rights associated with the technology
described in this document. This document is
intended to assist application developers to
develop applications only for Apple-labeled
computers.
Apple Inc.
1 Infinite Loop
Cupertino, CA 95014
408-996-1010
Introduction Introduction 15
The Page 19
Drawing Destinations: The Graphics Context 20
Quartz 2D Opaque Data Types 22
Graphics States 23
Quartz 2D Coordinate Systems 24
Memory Management: Object Ownership 26
Chapter 3 Paths 43
3
2010-11-19 | © 2001, 2010 Apple Inc. All Rights Reserved.
CONTENTS
Clipping to a Path 64
Chapter 5 Transforms 75
Chapter 6 Patterns 85
4
2010-11-19 | © 2001, 2010 Apple Inc. All Rights Reserved.
CONTENTS
5
2010-11-19 | © 2001, 2010 Apple Inc. All Rights Reserved.
CONTENTS
6
2010-11-19 | © 2001, 2010 Apple Inc. All Rights Reserved.
CONTENTS
Glossary 201
7
2010-11-19 | © 2001, 2010 Apple Inc. All Rights Reserved.
CONTENTS
8
2010-11-19 | © 2001, 2010 Apple Inc. All Rights Reserved.
Figures, Tables, and Listings
Figure 2-1 A view in the Cocoa framework that contains Quartz drawing 30
Figure 2-2 A PDF created by using CGPDFContextCreateWithURL 32
Figure 2-3 An image created from a bitmap graphics context and drawn to a window graphics
context 39
Figure 2-4 A comparison of aliased and anti-aliasing drawing 41
Table 2-1 Pixel formats supported for bitmap graphics contexts 39
Listing 2-1 Drawing to a window graphics context 30
Listing 2-2 Calling CGPDFContextCreateWithURL to create a PDF graphics context 32
Listing 2-3 Calling CGPDFContextCreate to create a PDF graphics context 33
Listing 2-4 Drawing to a PDF graphics context 34
Listing 2-5 Creating a bitmap graphics context 37
Listing 2-6 Drawing to a bitmap graphics context 38
Chapter 3 Paths 43
9
2010-11-19 | © 2001, 2010 Apple Inc. All Rights Reserved.
FIGURES, TABLES, AND LISTINGS
Figure 4-1 Applying a BGR and an RGB color profile to the same image 68
Figure 4-2 A comparison of large rectangles painted using various alpha values 68
Figure 4-3 A comparison of global alpha values 69
Figure 4-4 A CMYK fill color and an RGB stroke color 72
Table 4-1 Color values in different color spaces 67
Table 4-2 Color-setting functions 72
Chapter 5 Transforms 75
10
2010-11-19 | © 2001, 2010 Apple Inc. All Rights Reserved.
FIGURES, TABLES, AND LISTINGS
Chapter 6 Patterns 85
11
2010-11-19 | © 2001, 2010 Apple Inc. All Rights Reserved.
FIGURES, TABLES, AND LISTINGS
12
2010-11-19 | © 2001, 2010 Apple Inc. All Rights Reserved.
FIGURES, TABLES, AND LISTINGS
Figure 11-17 Background drawing (left) and foreground image (right) 152
Figure 11-18 Drawing an image over a background using normal blend mode 152
Figure 11-19 Drawing an image over a background using multiply blend mode 153
Figure 11-20 Drawing an image over a background using screen blend mode 154
Figure 11-21 Drawing an image over a background using overlay blend mode 154
Figure 11-22 Drawing an image over a background using darken blend mode 155
Figure 11-23 Drawing an image over a background using lighten blend mode 156
Figure 11-24 Drawing an image over a background using color dodge blend mode 156
Figure 11-25 Drawing an image over a background using color burn blend mode 157
Figure 11-26 Drawing an image over a background using soft light blend mode 158
Figure 11-27 Drawing an image over a background using hard light blend mode 158
Figure 11-28 Drawing an image over a background using difference blend mode 159
Figure 11-29 Drawing an image over a background using exclusion blend mode 160
Figure 11-30 Drawing an image over a background using hue blend mode 160
Figure 11-31 Drawing an image over a background using saturation blend mode 161
Figure 11-32 Drawing an image over a background using color blend mode 161
Figure 11-33 Drawing an image over a background using luminosity blend mode 162
Table 11-1 Functions for creating images 140
Listing 11-1 Code that creates a subimage and draws it enlarged 141
Listing 11-2 The prototype for the function CGImageMaskCreate 143
Listing 11-3 Masking light to mid-range brown colors in an image 147
Listing 11-4 Masking shades of brown to black 148
Listing 11-5 Masking a range of colors and setting a fill color and 149
13
2010-11-19 | © 2001, 2010 Apple Inc. All Rights Reserved.
FIGURES, TABLES, AND LISTINGS
14
2010-11-19 | © 2001, 2010 Apple Inc. All Rights Reserved.
INTRODUCTION
Introduction
Quartz 2D is an advanced, two-dimensional drawing engine available for iOS application development and
to all Mac OS X application environments outside of the kernel. Quartz 2D provides low-level, lightweight
2D rendering with unmatched output fidelity regardless of display or printing device. Quartz 2D is resolution-
and device-independent; you don’t need to think about the final destination when you use the Quartz 2D
application programming interface (API) for drawing.
The Quartz 2D API is easy to use and provides access to powerful features such as transparency layers,
path-based drawing, offscreen rendering, advanced color management, anti-aliased rendering, and PDF
document creation, display, and parsing.
The Quartz 2D API is part of the Core Graphics framework, so you may see Quartz referred to as Core Graphics
or, simply, CG.
This document is intended for iOS and Mac OS X developers who need to perform any of the following tasks:
● Draw graphics
● “Overview of Quartz 2D” (page 19) describes the page, drawing destinations, Quartz opaque data types,
graphics states, coordinates, and memory management, and it takes a look at how Quartz works “under
the hood.”
● “Graphics Contexts” (page 29) describes the kinds of drawing destinations and provides step-by-step
instructions for creating all flavors of graphics contexts.
● “Paths” (page 43) discusses the basic elements that make up paths, shows how to create and paint them,
shows how to set up a clipping area, and explains how blend modes affect painting.
● “Color and Color Spaces” (page 67) discusses color values and using alpha values for transparency, and
it describes how to create a color space, set colors, create color objects, and set rendering intent.
● “Transforms” (page 75) describes the current transformation matrix and explains how to modify it, shows
how to set up affine transforms, shows how to convert between user and device space, and provides
background information on the mathematical operations that Quartz performs.
● “Patterns” (page 85) defines what a pattern and its parts are, tells how Quartz renders them, and shows
how to create colored and stenciled patterns.
● “Shadows” (page 101) describes what shadows are, explains how they work, and shows how to paint
with them.
● “Gradients” (page 105) discusses axial and radial gradients and shows how to create and use CGShading
and CGGradient objects.
● “Transparency Layers” (page 125) gives examples of what transparency layers look like, discusses how
they work, and provides step-by-step instructions for implementing them.
● “Data Management in Quartz 2D” (page 129) discusses how to move data into and out of Quartz.
● “Bitmap Images and Image Masks” (page 135) describes what makes up a bitmap image definition and
shows how to use a bitmap image as a Quartz drawing primitive. It also describes masking techniques
you can use on images and shows the various effects you can achieve by using blend modes when
drawing images.
● “Core Graphics Layer Drawing” (page 163) describes how to create and use drawing layers to achieve
high-performance patterned drawing or to draw offscreen.
● “PDF Document Creation, Viewing, and Transforming” (page 173) shows how to open and view PDF
documents, apply transforms to them, create a PDF file, access PDF metadata, add links, and add security
features (such as password protection).
● “PDF Document Parsing” (page 181) describes how to use CGPDFScanner and CGPDFContentStream
objects to parse and inspect PDF documents.
● “PostScript Conversion” (page 189) gives an overview of the functions you can use in Mac OS X to convert
a PostScript file to a PDF document. These functions are not available in iOS.
● “Text” (page 193) describes Quartz 2D low-level support for text and glyphs, and alternatives that provide
higher-level and Unicode text support. It also discusses how to copy font variations.
See Also
These items are essential reading for anyone using Quartz 2D:
● Quartz 2D Reference Collection, organized by header file, provides a complete reference for the Quartz
2D application programming interface.
● Color Management Overview is a brief introduction to the principles of color perception, color spaces,
and color management systems.
● Mailing lists. Join the quartz-dev mailing list to discuss problems using Quartz 2D.
16 See Also
2010-11-19 | © 2001, 2010 Apple Inc. All Rights Reserved.
INTRODUCTION
Introduction
● Programming With Quartz: 2D and PDF Graphics in Mac OS X provides in-depth information on using
Quartz. This book is current through Mac OS X v10.4 and was written prior to the introduction of iOS.
The book includes examples that show how to support earlier versions of Mac OS X as well as how to
use the features introduced in v10.4. The sample code associated with this book is available from the
publisher.
See Also 17
2010-11-19 | © 2001, 2010 Apple Inc. All Rights Reserved.
INTRODUCTION
Introduction
18 See Also
2010-11-19 | © 2001, 2010 Apple Inc. All Rights Reserved.
CHAPTER 1
Overview of Quartz 2D
Quartz 2D is a two-dimensional drawing engine accessible in the iOS environment and from all Mac OS X
application environments outside of the kernel. You can use the Quartz 2D application programming interface
(API) to gain access to features such as path-based drawing, painting with transparency, shading, drawing
shadows, transparency layers, color management, anti-aliased rendering, PDF document generation, and
PDF metadata access. Whenever possible, Quartz 2D leverages the power of the graphics hardware.
In Mac OS X, Quartz 2D can work with all other graphics and imaging technologies—Core Image, Core Video,
OpenGL, and QuickTime. It’s possible to create an image in Quartz from a QuickTime graphics importer, using
the QuickTime function GraphicsImportCreateCGImage. See QuickTime Framework Reference for details.
“Moving Data Between Quartz 2D and Core Image in Mac OS X” (page 132) describes how you can provide
images to Core Image, which is a framework that supports image processing.
Similarly, in iOS, Quartz 2D works with all available graphics and animation technologies, such as Core
Animation, OpenGL ES, and the UIKit classes.
The Page
Quartz 2D uses the painter’s model for its imaging. In the painter’s model, each successive drawing operation
applies a layer of “paint” to an output “canvas,” often called a page. The paint on the page can be modified
by overlaying more paint through additional drawing operations. An object drawn on the page cannot be
modified except by overlaying more paint. This model allows you to construct extremely sophisticated images
from a small number of powerful primitives.
Figure 1-1 shows how the painter’s model works. To get the image in the top part of the figure, the shape
on the left was drawn first followed by the solid shape. The solid shape overlays the first shape, obscuring
all but the perimeter of the first shape. The shapes are drawn in the opposite order in the bottom of the
figure, with the solid shape drawn first. As you can see, in the painter’s model the drawing order is important.
The Page 19
2010-11-19 | © 2001, 2010 Apple Inc. All Rights Reserved.
CHAPTER 1
Overview of Quartz 2D
Result
Drawing order
The page may be a real sheet of paper (if the output device is a printer); it may be a virtual sheet of paper (if
the output device is a PDF file); it may even be a bitmap image. The exact nature of the page depends on
the particular graphics context you use.
A graphics context is an opaque data type (CGContextRef) that encapsulates the information Quartz uses
to draw images to an output device, such as a PDF file, a bitmap, or a window on a display. The information
inside a graphics context includes graphics drawing parameters and a device-specific representation of the
paint on the page. All objects in Quartz are drawn to, or contained by, a graphics context.
You can think of a graphics context as a drawing destination, as shown in Figure 1-2. When you draw with
Quartz, all device-specific characteristics are contained within the specific type of graphics context you use.
In other words, you can draw the same image to a different device simply by providing a different graphics
context to the same sequence of Quartz drawing routines. You do not need to perform any device-specific
calculations; Quartz does it for you.
Window
Printer Layer
Drawing
PDF Bitmap
● A bitmap graphics context allows you to paint RGB colors, CMYK colors, or grayscale into a bitmap. A
bitmap is a rectangular array (or raster) of pixels, each pixel representing a point in an image. Bitmap
images are also called sampled images. See “Creating a Bitmap Graphics Context” (page 35).
● A PDF graphics context allows you to create a PDF file. In a PDF file, your drawing is preserved as a
sequence of commands. There are some significant differences between PDF files and bitmaps:
● PDF files, unlike bitmaps, may contain more than one page.
● When you draw a page from a PDF file on a different device, the resulting image is optimized for
the display characteristics of that device.
● PDF files are resolution independent by nature—the size at which they are drawn can be increased
or decreased infinitely without sacrificing image detail. The user-perceived quality of a bitmap image
is tied to the resolution at which the bitmap is intended to be viewed.
● A window graphics context is a graphics context that you can use to draw into a window. Note that
because Quartz 2D is a graphics engine and not a window management system, you use one of the
application frameworks to obtain a graphics context for a window. See “Creating a Window Graphics
Context in Mac OS X” (page 29) for details.
● A layer context (CGLayerRef) is an offscreen drawing destination associated with another graphics
context. It is designed for optimal performance when drawing the layer to the graphics context that
created it. A layer context can be a much better choice for offscreen drawing than a bitmap graphics
context. See “Core Graphics Layer Drawing” (page 163).
● When you want to print in Mac OS X, you send your content to a PostScript graphics context that is
managed by the printing framework. See “Obtaining a Graphics Context for Printing” (page 41) for more
information.
The Quartz 2D API defines a variety of opaque data types in addition to graphics contexts. Because the API
is part of the Core Graphics framework, the data types and the routines that operate on them use the CG
prefix.
Quartz 2D creates objects from opaque data types that your application operates on to achieve a particular
drawing output. Figure 1-3 shows the sorts of results you can achieve when you apply drawing operations
to three of the objects provided by Quartz 2D. For example:
● You can rotate and display a PDF page by creating a PDF page object, applying a rotation operation to
the graphics context, and asking Quartz 2D to draw the page to a graphics context.
● You can draw a pattern by creating a pattern object, defining the shape that makes up the pattern, and
setting up Quartz 2D to use the pattern as paint when it draws to a graphics context.
● You can fill an area with an axial or radial shading by creating a shading object, providing a function
that determines the color at each point in the shading, and then asking Quartz 2D to use the shading
as a fill color.
Figure 1-3 Opaque data types are the basis of drawing primitives in Quartz 2D
● CGPathRef, used for vector graphics to create paths that you fill or stroke. See “Paths” (page 43).
● CGImageRef, used to represent bitmap images and bitmap image masks based on sample data that
you supply. See “Bitmap Images and Image Masks” (page 135).
● CGLayerRef, used to represent a drawing layer that can be used for repeated drawing (such as for
backgrounds or patterns) and for offscreen drawing. See “Core Graphics Layer Drawing” (page 163)
● CGShadingRef and CGGradientRef, used to paint gradients. See “Gradients” (page 105).
● CGFunctionRef, used to define callback functions that take an arbitrary number of floating-point
arguments. You use this data type when you create gradients for a shading. See “Gradients” (page 105).
● CGColorRef and CGColorSpaceRef, used to inform Quartz how to interpret color. See “Color and
Color Spaces” (page 67).
● CGImageSourceRef and CGImageDestinationRef, which you use to move data into and out of
Quartz. See “Data Management in Quartz 2D” (page 129) and Image I/O Programming Guide.
● CGPDFScannerRef and CGPDFContentStreamRef, which parse PDF metadata. See “PDF Document
Parsing” (page 181).
● CGPSConverterRef, used to convert PostScript to PDF. It is not available in iOS. See “PostScript
Conversion” (page 189).
Graphics States
Quartz modifies the results of drawing operations according to the parameters in the current graphics state.
The graphics state contains parameters that would otherwise be taken as arguments to drawing routines.
Routines that draw to a graphics context consult the graphics state to determine how to render their results.
For example, when you call a function to set the fill color, you are modifying a value stored in the current
graphics state. Other commonly used elements of the current graphics state include the line width, the
current position, and the text font size.
The graphics context contains a stack of graphics states. When Quartz creates a graphics context, the stack
is empty. When you save the graphics state, Quartz pushes a copy of the current graphics state onto the
stack. When you restore the graphics state, Quartz pops the graphics state off the top of the stack. The popped
state becomes the current graphics state.
To save the current graphics state, use the function CGContextSaveGState to push a copy of the current
graphics state onto the stack. To restore a previously saved graphics state, use the function
CGContextRestoreGState to replace the current graphics state with the graphics state that’s on top of
the stack.
Note that not all aspects of the current drawing environment are elements of the graphics state. For example,
the current path is not considered part of the graphics state and is therefore not saved when you call the
function CGContextSaveGState. The graphics state parameters that are saved when you call this function
are listed in Table 1-1.
Graphics States 23
2010-11-19 | © 2001, 2010 Apple Inc. All Rights Reserved.
CHAPTER 1
Overview of Quartz 2D
Table 1-1 Parameters that are associated with the graphics state
Line: width, join, cap, dash, miter limit “Paths” (page 43)
Color: fill and stroke settings “Color and Color Spaces” (page 67)
Color space: fill and stroke settings “Color and Color Spaces” (page 67)
Text: font, font size, character spacing, text drawing “Text” (page 193)
mode
Blend mode “Paths” (page 43) and “Bitmap Images and Image
Masks” (page 135)
A coordinate system, shown in Figure 1-4, defines the range of locations used to express the location and
sizes of objects to be drawn on the page. You specify the location and size of graphics in the user-space
coordinate system, or, more simply, the user space. Coordinates are defined as floating-point values.
y-axis
(0,0) x-axis
Because different devices have different underlying imaging capabilities, the locations and sizes of graphics
must be defined in a device-independent manner. For example, a screen display device might be capable
of displaying no more than 96 pixels per inch, while a printer might be capable of displaying 300 pixels per
inch. If you define the coordinate system at the device level (in this example, either 96 pixels or 300 pixels),
objects drawn in that space cannot be reproduced on other devices without visible distortion. They will
appear too large or too small.
The current transformation matrix has a secondary purpose: It allows you to transform how objects are drawn.
For example, to draw a box rotated by 45 degrees, you rotate the coordinate system of the page (the CTM)
before you draw the box. Quartz draws to the output device using the rotated coordinate system.
A point in user space is represented by a coordinate pair (x,y), where x represents the location along the
horizontal axis (left and right) and y represents the vertical axis (up and down). The origin of the user
coordinate space is the point (0,0). The origin is located at the lower-left corner of the page, as shown in
Figure 1-4 (page 24). In the default coordinate system for Quartz, the x-axis increases as it moves from the
left toward the right of the page. The y-axis increases in value as it moves from the bottom toward the top
of the page.
Some technologies set up their graphics contexts using a different default coordinate system than the one
used by Quartz. Relative to Quartz, such a coordinate system is a modified coordinate system and must be
compensated for when performing some Quartz drawing operations. The most common modified coordinate
system places the origin in the upper-right corner of the context and changes the y-axis to point towards
the bottom of the page. A few places where you might see this specific coordinate system used are the
following:
● In Mac OS X, a subclass of NSView that overrides its isFlipped method to return YES.
The reason UIKit returns Quartz drawing contexts with modified coordinate systems is that UIKit uses a
different default coordinate convention; it applies the transform to Quartz contexts it creates so that they
match its conventions. If your application wants to use the same drawing routines to draw to both a UIView
object and a PDF graphics context (which is created by Quartz and uses the default coordinate system), you
need to apply a transform so that the PDF graphics context receives the same modified coordinate system.
To do this, apply a transform that translates the origin to the upper-left corner of the PDF context and scales
the y-coordinate by -1.
Using a scaling transform to negate the y-coordinate alters some conventions in Quartz drawing. For example,
if you call CGContextDrawImage to draw an image into the context, the image is modified by the transform
when it is drawn into the destination. Similarly, path drawing routines accept parameters that specify whether
an arc is drawn in a clockwise or counterclockwise direction in the default coordinate system. If a coordinate
system is modified, the result is also modified, as if the image were reflected in a mirror. In Figure 1-5, passing
the same parameters into Quartz results in a clockwise arc in the default coordinate system and a
counterclockwise arc after the y-coordinate is negated by the transform.
y (0,0)
x
(0,0)
x
y
Default Coordinates Modified Coordinates
flipped_coordinates.eps
Cocoa Drawing
Apple Computer, Inc.
February 9, 2006
It is up to your application to adjust any Quartz calls it makes to a context that has a transform applied to it.
For example, if you want an image or PDF to draw correctly into a graphics context, your application may
need to temporarily adjust the CTM of the graphics context. In iOS, if you use a UIImage object to wrap a
CGImage object you create, you do not need to modify the CTM. The UIImage object automatically
compensates for the modified coordinate system applied by UIKit.
Important: The above discussion is essential to understand if you plan to write applications that directly
target Quartz on iOS, but it is not sufficient. On iOS 3.2 and later, when UIKit creates a drawing context for
your application, it also makes additional changes to the context to match the default UIKIt conventions. In
particular, patterns and shadows, which are not affected by the CTM, are adjusted separately so that their
conventions match UIKit’s coordinate system. In this case, there is no equivalent mechanism to the CTM that
your application can use to change a context created by Quartz to match the behavior for a context provided
by UIKit; your application must recognize the what kind of context it is drawing into and adjust its behavior
to match the expectations of the context.
Quartz uses the Core Foundation memory management model, in which objects are reference counted.
When created, Core Foundation objects start out with a reference count of 1. You can increment the reference
count by calling a function to retain the object, and decrement the reference count by calling a function to
release the object. When the reference count is decremented to 0, the object is freed. This model allows
objects to safely share references to other objects.
● If you create or copy an object, you own it, and therefore you must release it. That is, in general, if you
obtain an object from a function with the words “Create” or “Copy” in its name, you must release the
object when you’re done with it. Otherwise, a memory leak results.
● If you obtain an object from a function that does not contain the words “Create” or “Copy” in its name,
you do not own a reference to the object, and you must not release it. The object will be released by its
owner at some point in the future.
● If you do not own an object and you need to keep it around, you must retain it and release it when
you’re done with it. You use the Quartz 2D functions specific to an object to retain and release that
object. For example, if you create a CGColorspace object, you use the functions CGColorSpaceRetain
and CGColorSpaceRelease to retain and release the object as needed. You can also use the Core
Foundation functions CFRetain and CFRelease, but you must be careful not to pass NULL to these
functions.
Graphics Contexts
A graphics context represents a drawing destination. It contains drawing parameters and all device-specific
information that the drawing system needs to perform any subsequent drawing commands. A graphics
context defines basic drawing attributes such as the colors to use when drawing, the clipping area, line width
and style information, font information, compositing options, and several others.
You can obtain a graphics context by using Quartz context creation functions or by using higher-level functions
provided by one of the Mac OS X frameworks or the UIKit framework in iOS. Quartz provides functions for
various flavors of Quartz graphics contexts including bitmap and PDF, which you can use to create custom
content.
This chapter shows you how to create a graphics context for a variety of drawing destinations. A graphics
context is represented in your code by the data type CGContextRef, which is an opaque data type. After
you obtain a graphics context, you can use Quartz 2D functions to draw to the context, perform operations
(such as translations) on the context, and change graphics state parameters, such as line width and fill color.
To draw to the screen in an iOS application, you set up a UIView object and implement its drawRect:
method to perform drawing. The view’s drawRect: method is called when the view is visible onscreen and
its contents need updating. Before calling your custom drawRect: method, the view object automatically
configures its drawing environment so that your code can start drawing immediately. As part of this
configuration, the UIView object creates a graphics context (a CGContextRef opaque type) for the current
drawing environment. You obtain this graphics context in your drawRect: method by calling the UIKit
function UIGraphicsGetCurrentContext.
The default coordinate system used throughout UIKit is different from the coordinate system used by Quartz.
In UIKit, the origin is in the upper-left corner, with the positive-y value pointing downward. The UIView
object modifies the CTM of the Quartz graphics context to match the UIKit conventions by translating the
origin to the upper left corner of the view and inverting the y-axis by multiplying it by -1. For more information
on modified-coordinate systems and the implications in your own drawing code, see “Quartz 2D
Coordinates” (page 24).
UIView objects are described in detail in View Programming Guide for iOS.
When drawing in Mac OS X, you need to create a window graphics context that’s appropriate for the framework
you are using. The Quartz 2D API itself provides no functions to obtain a windows graphics context. Instead,
you use the Cocoa framework to obtain a context for a window created in Cocoa.
You obtain a Quartz graphics context from within the drawRect: routine of a Cocoa application using the
following line of code:
The method currentContext returns the NSGraphicsContext instance of the current thread. The method
graphicsPort returns the low-level, platform-specific graphics context represented by the receiver, which
is a Quartz graphics context. (Don’t get confused by the method names; they are historical.) For more
information see NSGraphicsContext Class Reference.
After you obtain the graphics context, you can call any of the Quartz 2D drawing functions in your Cocoa
application. You can also mix Quartz 2D calls with Cocoa drawing calls. You can see an example of Quartz
2D drawing to a Cocoa view by looking at Figure 2-1. The drawing consists of two overlapping rectangles,
an opaque red one and a partially transparent blue one. You’ll learn more about transparency in “Color and
Color Spaces” (page 67). The ability to control how much you can “see through” colors is one of the hallmark
features of Quartz 2D.
Figure 2-1 A view in the Cocoa framework that contains Quartz drawing
To create the drawing in Figure 2-1, you first create a Cocoa application Xcode project. In Interface Builder,
drag a Custom View to the window and subclass it. Then write an implementation for the subclassed view,
similar to what Listing 2-1 shows. For this example, the subclassed view is named MyQuartzView. The
drawRect: method for the view contains all the Quartz drawing code. A detailed explanation for each
numbered line of code appears following the listing.
Note: The drawRect: method of the NSView class is invoked automatically each time the view needs to be
drawn. To find out more about overriding the drawRect: method, see NSView Class Reference.
- (id)initWithFrame:(NSRect)frameRect
{
- (void)drawRect:(NSRect)rect
{
CGContextRef myContext = [[NSGraphicsContext // 1
currentContext] graphicsPort];
// ********** Your drawing code here ********** // 2
CGContextSetRGBFillColor (myContext, 1, 0, 0, 1); // 3
CGContextFillRect (myContext, CGRectMake (0, 0, 200, 100 )); // 4
CGContextSetRGBFillColor (myContext, 0, 0, 1, .5); // 5
CGContextFillRect (myContext, CGRectMake (0, 0, 100, 200)); // 6
}
@end
2. This is where you insert your drawing code. The four lines of code that follow are examples of using
Quartz 2D functions.
3. Sets a red fill color that’s fully opaque. For information on colors and alpha (which sets opacity), see
“Color and Color Spaces” (page 67).
4. Fills a rectangle whose origin is (0,0) and whose width is 200 and height is 100. For information on
drawing rectangles, see “Paths” (page 43).
6. Fills a rectangle whose origin is (0,0) and whose width is 100 and height is 200.
When you create a PDF graphics context and draw to that context, Quartz records your drawing as a series
of PDF drawing commands written to a file. You supply a location for the PDF output and a default media
box—a rectangle that specifies bounds of the page. Figure 2-2 shows the result of drawing to a PDF graphics
context and then opening the resulting PDF in Preview.
The Quartz 2D API provides two functions that create a PDF graphics context:
● CGPDFContextCreateWithURL, which you use when you want to specify the location for the PDF
output as a Core Foundation URL. Listing 2-2 (page 32) shows how to use this function to create a PDF
graphics context.
● CGPDFContextCreate, which you use when you want the PDF output sent to a data consumer. (For
more information see “Data Management in Quartz 2D” (page 129).) Listing 2-3 (page 33) shows how to
use this function to create a PDF graphics context.
A detailed explanation for each numbered line of code follows each listing.
iOS Note: A PDF graphics context in iOS uses the default coordinate system provided by Quartz, without
applying a transform to match the UIKit coordinate system. If your application plans on sharing drawing
code between your PDF graphics context and the graphics context provided by UIView object, your application
should modify the CTM of the PDF graphics context to modify the coordinate system. See “Quartz 2D
Coordinates” (page 24).
1. Calls the Core Foundation function to create a CFURL object from the CFString object supplied to the
MyPDFContextCreate function. You pass NULL as the first parameter to use the default allocator. You
also need to specify a path style, which for this example is a POSIX-style pathname.
2. Calls the Quartz 2D function to create a PDF graphics context using the PDF location just created (as a
CFURL object) and a rectangle that specifies the bounds of the PDF. The rectangle (CGRect) was passed
to the MyPDFContextCreate function and is the default page media bounding box for the PDF.
4. Returns the PDF graphics context. The caller must release the graphics context when it is no longer
needed.
if (url != NULL)
{
dataConsumer = CGDataConsumerCreateWithURL (url); // 2
if (dataConsumer != NULL)
{
myOutContext = CGPDFContextCreate (dataConsumer, // 3
inMediaBox,
NULL);
CGDataConsumerRelease (dataConsumer); // 4
}
CFRelease(url); // 5
}
return myOutContext; // 6
}
1. Calls the Core Foundation function to create a CFURL object from the CFString object supplied to the
MyPDFContextCreate function. You pass NULL as the first parameter to use the default allocator. You
also need to specify a path style, which for this example is a POSIX-style pathname.
2. Creates a Quartz data consumer object using the CFURL object. If you don’t want to use a CFURL object
(for example, you want to place the PDF data in a location that can’t be specified by a CFURL object),
you can instead create a data consumer from a set of callback functions that you implement in your
application. For more information, see “Data Management in Quartz 2D” (page 129).
3. Calls the Quartz 2D function to create a PDF graphics context passing as parameters the data consumer
and the rectangle (of type CGRect) that was passed to the MyPDFContextCreate function. This rectangle
is the default page media bounding box for the PDF.
6. Returns the PDF graphics context. The caller must release the graphics context when it is no longer
needed.
Listing 2-4 shows how to call the MyPDFContextCreate routine and draw to it. A detailed explanation for
each numbered line of code appears following the listing.
CFStringRef myKeys[1]; // 4
CFTypeRef myValues[1];
myKeys[0] = kCGPDFContextMediaBox;
myValues[0] = (CFTypeRef) CFDataCreate(NULL,(const UInt8 *)&mediaBox, sizeof
(CGRect));
CFDictionaryRef pageDictionary = CFDictionaryCreate(NULL, (const void **)
myKeys,
(const void **) myValues,
1,
&kCFTypeDictionaryKeyCallBacks,
&
kCFTypeDictionaryValueCallBacks);
CGPDFContextBeginPage(myPDFContext, &pageDictionary); // 5
// ********** Your drawing code here ********** // 6
CGContextSetRGBFillColor (myPDFContext, 1, 0, 0, 1);
CGContextFillRect (myPDFContext, CGRectMake (0, 0, 200, 100 ));
CGContextSetRGBFillColor (myPDFContext, 0, 0, 1, .5);
CGContextFillRect (myPDFContext, CGRectMake (0, 0, 100, 200 ));
CGPDFContextEndPage(myPDFContext); // 7
CFRelease(pageDictionary); // 8
CFRelease(myValues[0]);
CGContextRelease(myPDFContext);
1. Declares a variable for the rectangle that you use to define the PDF media box.
2. Sets the origin of the media box to (0,0) and the width and height to variables supplied by the
application.
3. Calls the function MyPDFContextCreate (See Listing 2-3 (page 33)) to obtain a PDF graphics context,
supplying a media box and a pathname. The macro CFSTR converts a string to a CFStringRef data
type.
4. Sets up a dictionary with the page options. In this example, only the media box is specified. You don’t
have to pass the same rectangle you used to set up the PDF graphics context. The media box you add
here supersedes the rectangle you pass to set up the PDF graphics context.
5. Signals the start of a page. This function is used for page-oriented graphics, which is what PDF drawing
is.
6. Calls Quartz 2D drawing functions. You replace this and the following four lines of code with the drawing
code appropriate for your application.
8. Releases the dictionary and the PDF graphics context when they are no longer needed.
You can write any content to a PDF that’s appropriate for your application—images, text, path drawing—and
you can add links and encryption. For more information see “PDF Document Creation, Viewing, and
Transforming” (page 173).
A bitmap graphics context accepts a pointer to a memory buffer that contains storage space for the bitmap.
When you paint into the bitmap graphics context, the buffer is updated. After you release the graphics
context, you have a fully updated bitmap in the pixel format you specify.
Note: Bitmap graphics contexts are sometimes used for drawing offscreen. Before you decide to use a bitmap
graphics context for this purpose, see “Core Graphics Layer Drawing” (page 163). CGLayer objects (CGLayerRef)
are optimized for offscreen drawing because, whenever possible, Quartz caches layers on the video card.
iOS Note: iOS applications should use the function UIGraphicsBeginImageContextWithOptions instead
of using the low-level Quartz functions described here. If your application creates an offscreen bitmap using
Quartz, the coordinate system used by bitmap graphics context is the default Quartz coordinate system. In
contrast, if your application creates an image context by calling the function
UIGraphicsBeginImageContextWithOptions, UIKit applies the same transformation to the context’s
coordinate system as it does to a UIView object’s graphics context. This allows your application to use the
same drawing code for either without having to worry about different coordinate systems. Although your
application can manually adjust the coordinate transformation matrix to achieve the correct results, in practice,
there is no performance benefit to doing so.
You use the function CGBitmapContextCreate to create a bitmap graphics context. This function takes
the following parameters:
● data. Supply a pointer to the destination in memory where you want the drawing rendered. The size
of this memory block should be at least (bytesPerRow*height) bytes.
● bitsPerComponent. Specify the number of bits to use for each component of a pixel in memory. For
example, for a 32-bit pixel format and an RGB color space, you would specify a value of 8 bits per
component. See “Supported Pixel Formats” (page 39).
● bytesPerRow. Specify the number of bytes of memory to use per row of the bitmap.
Tip: When you create a bitmap graphics context, you’ll get the best performance if you make sure the
data and bytesPerRow are 16-byte aligned.
● colorspace. The color space to use for the bitmap context. You can provide a Gray, RGB, CMYK, or
NULL color space when you create a bitmap graphics context. For detailed information on color spaces
and color management principles, see Color Management Overview. For information on creating and
using color spaces in Quartz, see “Color and Color Spaces” (page 67). For information about supported
color spaces, see “Color Spaces and Bitmap Layout” (page 137) in the “Bitmap Images and Image
Masks” (page 135) chapter.
● bitmapInfo. Bitmap layout information, expressed as a CGBitmapInfo constant, that specifies whether
the bitmap should contain an alpha component, the relative location of the alpha component (if there
is one) in a pixel, whether the alpha component is premultiplied, and whether the color components
are integer or floating-point values. For detailed information on what these constants are, when each is
used, and Quartz-supported pixel formats for bitmap graphics contexts and images, see “Color Spaces
and Bitmap Layout” (page 137) in the “Bitmap Images and Image Masks” (page 135) chapter.
Listing 2-5 shows how to create a bitmap graphics context. When you draw into the resulting bitmap graphics
context, Quartz records your drawing as bitmap data in the specified block of memory. A detailed explanation
for each numbered line of code follows the listing.
colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); // 2
bitmapData = calloc( bitmapByteCount ); // 3
if (bitmapData == NULL)
{
fprintf (stderr, "Memory not allocated!");
return NULL;
}
context = CGBitmapContextCreate (bitmapData, // 4
pixelsWide,
pixelsHigh,
8, // bits per component
bitmapBytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedLast);
if (context== NULL)
{
free (bitmapData); // 5
fprintf (stderr, "Context not created!");
return NULL;
}
CGColorSpaceRelease( colorSpace ); // 6
return context; // 7
}
1. Declares a variable to represent the number of bytes per row. Each pixel in the bitmap in this example
is represented by 4 bytes; 8 bits each of red, green, blue, and alpha.
2. Creates a generic RGB color space. You can also create a CMYK color space. See “Color and Color
Spaces” (page 67) for more information and for a discussion of generic color spaces versus device
dependent ones.
3. Calls the calloc function to create and clear a block of memory in which to store the bitmap data. This
example creates a 32-bit RGBA bitmap (that is, an array with 32 bits per pixel, each pixel containing 8
bits each of red, green, blue, and alpha information). Each pixel in the bitmap occupies 4 bytes of memory.
In Mac OS X 10.6 and iOS 4, this step can be omitted—if you pass NULL as bitmap data, Quartz
automatically allocates space for the bitmap.
4. Creates a bitmap graphics context, supplying the bitmap data, the width and height of the bitmap, the
number of bits per component, the bytes per row, the color space, and a constant that specifies whether
the bitmap should contain an alpha channel and its relative location in a pixel. The constant
kCGImageAlphaPremultipliedLast indicates that the alpha component is stored in the last byte of
each pixel and that the color components have already been multiplied by this alpha value. See “The
Alpha Value” (page 68) for more information on premultiplied alpha.
5. If the context isn’t created for some reason, frees the memory allocated for the bitmap data.
7. Returns the bitmap graphics context. The caller must release the graphics context when it is no longer
needed.
Listing 2-6 shows code that calls MyCreateBitmapContext to create a bitmap graphics context, uses the
bitmap graphics context to create a CGImage object, then draws the resulting image to a window graphics
context. Figure 2-3 (page 39) shows the image drawn to the window. A detailed explanation for each
numbered line of code follows the listing.
1. Declares a variable to store the origin and dimensions of the bounding box into which Quartz will draw
an image created from the bitmap graphics context.
2. Sets the origin of the bounding box to (0,0) and the width and height to variables previously declared,
but whose declaration are not shown in this code.
3. Calls the application-supplied function MyCreateBitmapContext (see Listing 2-5 (page 37)) to create
a bitmap context that is 400 pixels wide and 300 pixels high. You can create a bitmap graphics context
using any dimensions that are appropriate for your application.
4. Calls Quartz 2D functions to draw into the bitmap graphics context. You would replace this and the next
four lines of code with drawing code appropriate for your application.
6. Draws the image into the location in the window graphics context that is specified by the bounding
box. The bounding box specifies the location and dimensions in user space in which to draw the image.
This example does not show the creation of the window graphics context. See “Creating a Window
Graphics Context in Mac OS X” (page 29) for information on how to create one.
7. Gets the bitmap data associated with the bitmap graphics context.
Figure 2-3 An image created from a bitmap graphics context and drawn to a window graphics context
Anti-Aliasing
Bitmap graphics contexts support anti-aliasing, which is the process of artificially correcting the jagged (or
aliased) edges you sometimes see in bitmap images when text or shapes are drawn. These jagged edges
occur when the resolution of the bitmap is significantly lower than the resolution of your eyes. To make
objects appear smooth in the bitmap, Quartz uses different colors for the pixels that surround the outline of
the shape. By blending the colors in this way, the shape appears smooth. You can see the effect of using
anti-aliasing in Figure 2-4. You can turn anti-aliasing off for a particular bitmap graphics context by calling
the function CGContextSetShouldAntialias. The anti-aliasing setting is part of the graphics state.
You can control whether to allow anti-aliasing for a particular graphics context by using the function
CGContextSetAllowsAntialiasing. Pass true to this function to allow anti-aliasing; false not to allow
it. This setting is not part of the graphics state. Quartz performs anti-aliasing when the context and the graphic
state settings are set to true.
Cocoa applications in Mac OS X implement printing through custom NSView subclasses. A view is told to
print by invoking its print: method. The view then creates a graphics context that targets a printer and
calls its drawRect: method. Your application uses the same drawing code to draw to the printer that it uses
to draw to the screen. It can also customize the drawRect: call to an image to the printer that is different
from the one sent to the screen.
For a detailed discussion of printing in Cocoa, see Printing Programming Topics for Cocoa.
Paths
A path defines one or more shapes, or subpaths. A subpath can consist of straight lines, curves, or both. It
can be open or closed. A subpath can be a simple shape, such as a line, circle, rectangle, or star, or a more
complex shape such as the silhouette of a mountain range or an abstract doodle. Figure 3-1 shows some of
the paths you can create. The straight line (at the upper left of the figure) is dashed; lines can also be solid.
The squiggly path (in the middle top) is made up of several curves and is an open path. The concentric circles
are filled, but not stroked. The State of California is a closed path, made up of many curves and lines, and the
path is both stroked and filled. The stars illustrate two options for filling paths, which you’ll read about later
in this chapter.
In this chapter, you’ll learn about the building blocks that make up paths, how to stroke and paint paths,
and the parameters that affect the appearance of paths.
Path creation and path painting are separate tasks. First you create a path. When you want to render a path,
you request Quartz to paint it. As you can see in Figure 3-1, you can choose to stroke the path, fill the path,
or both stroke and fill the path. You can also use a path to constrain the drawing of other objects within the
bounds of the path creating, in effect, a clipping area.
Figure 3-2 shows a path that has been painted and that contains two subpaths. The subpath on the left is a
rectangle, and the subpath on the right is an abstract shape made up of straight lines and curves. Each
subpath is filled and its outline stroked.
Figure 3-3 shows multiple paths drawn independently. Each path contains a randomly generated curve,
some of which are filled and others stroked. Drawing is constrained to a circular area by a clipping area.
Subpaths are built from lines, arcs, and curves. Quartz also provides convenience functions to add rectangles
and ellipses with a single function call. Points are also essential building blocks of paths because points define
starting and ending locations of shapes.
Points
Points are x and y coordinates that specify a location in user space. You can call the function
CGContextMoveToPoint to specify a starting position for a new subpath. Quartz keeps track of the current
point, which is the last location used for path construction. For example, if you call the function
CGContextMoveToPoint to set a location at (10,10), that moves the current point to (10,10). If you then
draw a horizontal line 50 units long, the last point on the line, that is, (60,10), becomes the current point.
Lines, arcs, and curves are always drawn starting from the current point.
Most of the time you specify a point by passing to Quartz functions two floating-point values to specify x
and y coordinates. Some functions require that you pass a CGPoint data structure, which holds two
floating-point values.
Lines
A line is defined by its endpoints. Its starting point is always assumed to be the current point, so when you
create a line, you specify only its endpoint. You use the function CGContextAddLineToPoint to append a
single line to a subpath.
You can add a series of connected lines to a path by calling the function CGContextAddLines. You pass
this function an array of points. The first point must be the starting point of the first line; the remaining points
are endpoints. Quartz begins a new subpath at the first point and connects a straight line segment to each
endpoint.
Arcs
Arcs are circle segments. Quartz provides two functions that create arcs. The function CGContextAddArc
creates a curved segment from a circle. You specify the center of the circle, the radius, and the radial angle
(in radians). You can create a full circle by specifying a radial angle of 2 pi. Figure 3-4 shows multiple paths
drawn independently. Each path contains a randomly generated circle; some are filled and others are stroked.
Figure 3-4 Multiple paths; each path contains a randomly generated circle
The function CGContextAddArcToPoint is ideal to use when you want to round the corners of a rectangle.
Quartz uses the endpoints you supply to create two tangent lines. You also supply the radius of the circle
from which Quartz slices the arc. The center point of the arc is the intersection of two radii, each of which is
perpendicular to one of the two tangent lines. Each endpoint of the arc is a tangent point on one of the
tangent lines, as shown in Figure 3-5. The red portion of the circle is what’s actually drawn.
Figure 3-5 Defining an arc with two tangent lines and a radius
Tangent Tangent
line 1 point 1
Tangent
line 2
Radius
Tangent
point 2
If the current path already contains a subpath, Quartz appends a straight line segment from the current point
to the starting point of the arc. If the current path is empty, Quartz creates a new subpath at the starting
point for the arc and does not add the initial straight line segment.
Curves
Quadratic and cubic Bézier curves are algebraic curves that can specify any number of interesting curvilinear
shapes. Points on these curves are calculated by applying a polynomial formula to starting and ending points,
and one or more control points. Shapes defined in this way are the basis for vector graphics. A formula is
much more compact to store than an array of bits and has the advantage that the curve can be re-created
at any resolution.
Figure 3-6 shows a variety of curves created by drawing multiple paths independently. Each path contains
a randomly generated curve; some are filled and others are stroked.
Figure 3-6 Multiple paths; each path contains a randomly generated curve
The polynomial formulas that give to rise to quadratic and cubic Bézier curves, and the details on how to
generate the curves from the formulas, are discussed in many mathematics texts and online sources that
describe computer graphics. These details are not discussed here.
You use the function CGContextAddCurveToPoint to append a cubic Bézier curve from the current point,
using control points and an endpoint you specify. Figure 3-7 shows the cubic Bézier curve that results from
the current point, control points, and endpoint shown in the figure. The placement of the two control points
determines the geometry of the curve. If the control points are both above the starting and ending points,
the curve arches upward. If the control points are both below the starting and ending points, the curve arches
downward. If the second control point is closer to the current point (starting point) than the first control
point, the curve crosses over itself, creating a loop.
Point 2
Control point
You can append a quadratic Bézier curve from the current point by calling the function
CGContextAddQuadCurveToPoint, and specifying a control point and an endpoint. Figure 3-8 shows two
curves that result from using the same endpoints but different control points. The control point determines
the direction that the curve arches. It’s not possible to create as many interesting shapes with a quadratic
Bézier curve as you can with a cubic one because quadratic curves use only one control point. For example,
it’s not possible to create a crossover using a single control point.
B Control point
B Control point
Closing a Subpath
To close the current subpath, your application should call CGContextClosePath. This function adds a line
segment from the current point to the starting point of the subpath and closes the subpath. Lines, arcs, and
curves that end at the starting point of a subpath do not actually close the subpath. You must explicitly call
CGContextClosePath to close a subpath.
Some Quartz functions treat a path’s subpaths as if they were closed by your application. Those commands
treat each subpath as if your application had called CGContextClosePath to close it, implicitly adding a
line segment to the starting point of the subpath.
After closing a subpath, if your application makes additional calls to add lines, arcs, or curves to the path,
Quartz begins a new subpath starting at the starting point of the subpath you just closed.
Ellipses
An ellipse is essentially a squashed circle. You create one by defining two focus points and then plotting all
the points that lie at a distance such that adding the distance from any point on the ellipse to one focus to
the distance from that same point to the other focus point is always the same value. Figure 3-9 shows multiple
paths drawn independently. Each path contains a randomly generated ellipse; some are filled and others are
stroked.
Figure 3-9 Multiple paths; each path contains a randomly generated ellipse
You can add an ellipse to the current path by calling the function CGContextAddEllipseInRect. You
supply a rectangle that defines the bounds of the ellipse. Quartz approximates the ellipse using a sequence
of Bézier curves. The center of the ellipse is the center of the rectangle. If the width and height of the rectangle
are equal (that is, a square), the ellipse is circular, with a radius equal to one-half the width (or height) of the
rectangle. If the width and height of the rectangle are unequal, they define the major and minor axes of the
ellipse.
The ellipse that is added to the path starts with a move-to operation and ends with a close-subpath operation,
with all moves oriented in the clockwise direction.
Rectangles
You can add a rectangle to the current path by calling the function CGContextAddRect. You supply a CGRect
structure that contains the origin of the rectangle and its width and height.
The rectangle that is added to the path starts with a move-to operation and ends with a close-subpath
operation, with all moves oriented in the counter-clockwise direction.
You can add many rectangles to the current path by calling the function CGContextAddRects and supplying
an array of CGRect structures. Figure 3-10 shows multiple paths drawn independently. Each path contains
a randomly generated rectangle; some are filled and others are stroked.
Figure 3-10 Multiple paths; each path contains a randomly generated rectangle
Creating a Path
When you want to construct a path in a graphics context, you signal Quartz by calling the function
CGContextBeginPath . Next, you set the starting point for the first shape, or subpath, in the path by calling
the function CGContextMoveToPoint. After you establish the first point, you can add lines, arcs, and curves
to the path, keeping in mind the following:
● Lines, arcs, and curves are drawn starting at the current point. An empty path has no current point; you
must call CGContextMoveToPoint to set the starting point for the first subpath or call a convenience
function that implicitly does this for you.
● When you want to close the current subpath within a path, call the function CGContextClosePath to
connect a segment to the starting point of the subpath. Subsequent path calls begin a new subpath,
even if you do not explicitly set a new starting point.
● When you draw arcs, Quartz draws a line between the current point and the starting point of the arc.
● Quartz routines that add ellipses and rectangles add a new closed subpath to the path.
● You must call a painting function to fill or stroke the path because creating a path does not draw the
path. See “Painting a Path” (page 51) for detailed information.
50 Creating a Path
2010-11-19 | © 2001, 2010 Apple Inc. All Rights Reserved.
Other documents randomly have
different content
man's advice." Nevertheless, a great many do not hear and will not
believe, and matters go on very much as they did before.
All this is natural, and will continue as long as people do not believe
the wise man's words. But, we are told, a time will come when every
one on the farm will listen to and understand the words of the wise
man, and will realize that God spoke through his lips, and that the
wise man was himself none other than God in person; and all will
have faith in his words. Meanwhile, instead of living according to the
advice of the wise man, each struggles for his own, and they slay
each other without pity, saying, "The struggle for existence is
inevitable; we cannot do otherwise."
What does it all mean? Even the beasts graze in the fields without
interfering with each other's needs, and men, after having learned
the conditions of the true life, and after being convinced that God
himself has shown them how to live the true life, follow still their evil
ways, saying that it is impossible to live otherwise. What should we
think of the people at the farm if, after having heard the words of
the wise man, they had continued to live as before, snatching the
bread from each other's mouths, fighting, and trying to grasp
everything, to their own loss? We should say that they had
misunderstood the wise man's words, and imagined things to be
different from what they really were. The wise man said to them,
"Your life here is bad; amend your ways, and it will become good."
And they imagined that the wise man had condemned their life on
the farm, and had promised them another and a better life
somewhere else. They decided that the farm was only a temporary
dwelling-place, and that it was not worth while to try to live well
there; the important thing was not to be cheated out of the other
life promised them elsewhere. This is the only way in which we can
explain the strange conduct of the people on the farm, of whom
some believed that the wise man was God, and others that he was a
man of wisdom, but all continued to live as before in defiance of the
wise man's words. They understood everything but the one
significant truth in the wise man's teachings,—that they must work
out for themselves their own peace and happiness there on the
farm, which they took for a temporary abode thinking all the time of
the better life they were to possess elsewhere.
Here is the origin of the strange declaration that the precepts of the
wise man were admirable, even divine, but that they were difficult to
practise.
Oh, if men would only cease from evil ways while waiting for the
Christ to come in his chariot of fire to their aid; if they would only
cease to invoke the law of the differentiation or integration of forces,
or any historical law whatever! None will come to their aid if they do
not aid themselves. And to aid ourselves to a better life, we need
expect nothing from heaven or from earth; we need only to cease
from ways that result in our own loss.
CHAPTER VIII.
Let all the world practise the doctrine of Jesus, and the reign of God
will come upon earth; if I alone practise it, I shall do what I can to
better my own condition and the condition of those about me. There
is no salvation aside from the fulfilment of the doctrine of Jesus. But
who will give me the strength to practise it, to follow it without
ceasing, and never to fail? "Lord, I believe; help thou mine unbelief."
The disciples called upon Jesus to strengthen their faith. "When I
would do good," says the apostle Paul, "evil is present with me." It is
hard to work out one's salvation.
A drowning man calls for aid. A rope is thrown to him, and he says:
"Strengthen my belief that this rope will save me. I believe that the
rope will save me; but help my unbelief." What is the meaning of
this? If a man will not seize upon his only means of safety, it is plain
that he does not understand his condition.
How can a Christian who professes to believe in the divinity of Jesus
and of his doctrine, whatever may be the meaning that he attaches
thereto, say that he wishes to believe, and that he cannot believe?
God comes upon earth, and says, "Fire, torments, eternal darkness
await you; and here is your salvation—fulfil my doctrine." It is not
possible that a believing Christian should not believe and profit by
the salvation thus offered to him; it is not possible that he should
say, "Help my unbelief." If a man says this, he not only does not
believe in his perdition, but he must be certain that he shall not
perish.
A number of children have fallen from a boat into the water. For an
instant their clothes and their feeble struggles keep them on the
surface of the stream, and they do not realize their danger. Those in
the boat throw out a rope. They warn the children against their peril,
and urge them to grasp the rope (the parables of the woman and
the piece of silver, the shepherd and the lost sheep, the marriage
feast, the prodigal son, all have this meaning), but the children do
not believe; they refuse to believe, not in the rope, but that they are
in danger of drowning. Children as frivolous as themselves have
assured them that they can continue to float gaily along even when
the boat is far away. The children do not believe; but when their
clothes are saturated, the strength of their little arms exhausted,
they will sink and perish. This they do not believe, and so they do
not believe in the rope of safety.
Just as the children in the water will not grasp the rope that is
thrown to them, persuaded that they will not perish, so men who
believe in the resurrection of the soul, convinced that there is no
danger, do not practise the commandments of Jesus. They do not
believe in what is certain, simply because they do believe in what is
uncertain. It is for this cause they cry, "Lord, strengthen our faith,
lest we perish." But this is impossible. To have the faith that will save
them from perishing, they must cease to do what will lead them to
perdition, and they must begin to do something for their own safety;
they must grasp the rope of safety. Now this is exactly what they do
not wish to do; they wish to persuade themselves that they will not
perish, although they see their comrades perishing one after another
before their very eyes. They wish to persuade themselves of the
truth of what does not exist, and so they ask to be strengthened in
faith. It is plain that they have not enough faith, and they wish for
more.
When I understood the doctrine of Jesus, I saw that what these men
call faith is the faith denounced by the apostle James:[18]—
"What doth it profit, my brethren, if a man believe he hath faith, but
hath not works? can that faith save him? If a brother or sister be
naked and in lack of daily food, and one of you say unto them, Go in
peace, be ye warmed and filled; and yet ye give them not the things
needful to the body; what doth it profit? Even so faith, if it have not
works, is dead in itself. But some one will say, Thou hast faith, and I
have works: Shew me thy faith which is without works, and I, by my
works, will show thee my faith. Thou believest there is one God;
thou doest well: the demons also believe, and tremble. But wilt thou
know, O vain man, that faith without works is dead? Was not
Abraham our father justified by works when he offered up Isaac his
son upon the altar? Thou seest that faith wrought with his works,
and by works was faith made perfect.... Ye see that by works a man
is justified, and not only by faith.... For as the body without the spirit
is dead, so faith is dead without works." (James ii. 14-26.)
James says that the indication of faith is the acts that it inspires, and
consequently that a faith which does not result in acts is of words
merely, with which one cannot feed the hungry, or justify belief, or
obtain salvation. A faith without acts is not faith. It is only a
disposition to believe in something, a vain affirmation of belief in
something in which one does not really believe. Faith, as the apostle
James defines it, is the motive power of actions, and actions are a
manifestation of faith.
The Jews said to Jesus: "What signs shewest thou then, that we
may see, and believe thee? what dost thou work?" (John vi. 30. See
also Mark xv. 32; Matt. xxvii. 42). Jesus told them that their desire
was vain, and that they could not be made to believe what they did
not believe. "If I tell you," he said, "ye will not believe" (Luke xxii.
67); "I told you, and ye believed not.... But ye believe not because
ye are not of my sheep" (John x. 25, 26).
The Jews asked exactly what is asked by Christians brought up in
the Church; they asked for some outward sign which should make
them believe in the doctrine of Jesus. Jesus explained that this was
impossible, and he told them why it was impossible. He told them
that they could not believe because they were not of his sheep; that
is, they did not follow the road he had pointed out. He explained
why some believed, and why others did not believe, and he told
them what faith really was. He said: "How can ye believe which
receive your doctrine (δόξα[19]) one of another, and seek not the
doctrine that cometh only from God?" (John v. 44).
To believe, Jesus says, we must seek for the doctrine that comes
from God alone.
"He that speaketh of himself seeketh (to extend) his own doctrine,
δόξαν τὴν ἴδιαν, but he that seeketh (to extend) the doctrine of him
that sent him, the same is true, and no untruth is in him." (John vii.
18.)
The doctrine of life, δόξα, is the foundation of faith, and actions
result spontaneously from faith. But there are two doctrines of life:
Jesus denies the one and affirms the other. One of these doctrines, a
source of all error, consists of the idea that the personal life is one of
the essential and real attributes of man. This doctrine has been
followed, and is still followed, by the majority of men; it is the
source of divergent beliefs and acts. The other doctrine, taught by
Jesus and by all the prophets, affirms that our personal life has no
meaning save through fulfilment of the will of God. If a man confess
a doctrine that emphasizes his own personal life, he will consider
that his personal welfare is the most important thing in the world,
and he will consider riches, honors, glory, pleasure, as true sources
of happiness; he will have a faith in accordance with his inclination,
and his acts will always be in harmony with his faith. If a man
confess a different doctrine, if he find the essence of life in fulfilment
of the will of God in accordance with the example of Abraham and
the teaching and example of Jesus, his faith will accord with his
principles, and his acts will be conformable to his faith. And so those
who believe that true happiness is to be found in the personal life
can never have faith in the doctrine of Jesus. All their efforts to fix
their faith upon it will be always vain. To believe in the doctrine of
Jesus, they must look at life in an entirely different way. Their
actions will coincide always with their faith and not with their
intentions and their words.
In men who demand of Jesus that he shall work miracles we may
recognize a desire to believe in his doctrine; but this desire never
can be realized in life, however arduous the efforts to obtain it. In
vain they pray, and observe the sacraments, and give in charity, and
build churches, and convert others; they cannot follow the example
of Jesus because their acts are inspired by a faith based upon an
entirely different doctrine from that which they confess. They could
not sacrifice an only son as Abraham was ready to do, although
Abraham had no hesitation whatever as to what he should do, just
as Jesus and his disciples were moved to give their lives for others,
because such action alone constituted for them the true meaning of
life. This incapacity to understand the substance of faith explains the
strange moral state of men, who, acknowledging that they ought to
live in accordance with the doctrine of Jesus, endeavor to live in
opposition to this doctrine, conformably to their belief that the
personal life is a sovereign good.
The basis of faith is the meaning that we derive from life, the
meaning that determines whether we look upon life as important
and good, or trivial and corrupt. Faith is the appreciation of good
and of evil. Men with a faith based upon their own doctrines do not
succeed at all in harmonizing this faith with the faith inspired by the
doctrine of Jesus; and so it was with the early disciples. This
misapprehension is frequently referred to in the Gospels in clear and
decisive terms. Several times the disciples asked Jesus to strengthen
their faith in his words (Matt. xx. 20-28; Mark x. 35-48). After the
message, so terrible to every man who believes in the personal life
and who seeks his happiness in the riches of this world, after the
words, "How hardly shall they that have riches enter into the
kingdom of God," and after words still more terrible for men who
believe only in the personal life, "Sell whatsoever thou hast and give
to the poor;" after these warning words Peter asked, "Behold, we
have forsaken all and followed thee; what shall we have therefore?"
Then James and John and, according to the Gospel of Matthew, their
mother, asked him that they might be allowed to sit with him in
glory. They asked Jesus to strengthen their faith with a promise of
future recompense. To Peter's question Jesus replied with a parable
(Matt. xx. 1-16); to James he replied that they did not know what
they asked; that they asked what was impossible; that they did not
understand the doctrine, which meant a renunciation of the personal
life, while they demanded personal glory, a personal recompense;
that they should drink the cup he drank of (that is, live as he lived),
but to sit upon his right hand and upon his left was not his to give.
And Jesus added that the great of this world had their profit and
enjoyment of glory and personal power only in the worldly life; but
that his disciples ought to know that the true meaning of human life
is not in personal happiness, but in ministering to others; "the son of
man came not to be ministered unto, but to minister, and to give his
life a ransom for many." In reply to the unreasonable demands
which revealed their slowness to understand his doctrine, Jesus did
not command his disciples to have faith in his doctrine, that is, to
modify the ideas inspired by their own doctrine (he knew that to be
impossible), but he explained to them the meaning of that life which
is the basis of true faith, that is, taught them how to discern good
from evil, the important from the secondary.
To Peter's question, "What shall we receive?" Jesus replies with the
parable of the laborers in the vineyard (Matt. xx. 1-16), beginning
with the words "For the kingdom of heaven is like unto a man that is
a householder," and by this means Jesus explains to Peter that
failure to understand the doctrine is the cause of lack of faith; and
that remuneration in proportion to the amount of work done is
important only from the point of view of the personal life.
This faith is based upon the presumption of certain imaginary rights;
but a man has a right to nothing; he is under obligations for the
good he has received, and so he can exact nothing. Even if he were
to give up his whole life to the service of others, he could not pay
the debt he has incurred, and so he cannot complain of injustice. If
a man sets a value upon his rights to life, if he keeps a reckoning
with the Overruling Power from whom he has received life, he
proves simply that he does not understand the meaning of life. Men
who have received a benefit act far otherwise. The laborers
employed in the vineyard were found by the householder idle and
unhappy; they did not possess life in the proper meaning of the
term. And then the householder gave them the supreme welfare of
life,—work. They accepted the benefits offered, and were
discontented because their remuneration was not graduated
according to their imaginary deserts. They did the work, believing in
their false doctrine of life and work as a right, and consequently with
an idea of the remuneration to which they were entitled. They did
not understand that work is the supreme good, and that they should
be thankful for the opportunity to work, instead of exacting
payment. And so all men who look upon life as these laborers looked
upon it, never can possess true faith. This parable of the laborers,
related by Jesus in response to the request by his disciples that he
strengthen their faith, shows more clearly than ever the basis of the
faith that Jesus taught.
When Jesus told his disciples that they must forgive a brother who
trespassed against them not only once, but seventy times seven
times, the disciples were overwhelmed at the difficulty of observing
this injunction, and said, "Increase our faith," just as a little while
before they had asked, "What shall we receive?" Now they uttered
the language of would-be Christians: "We wish to believe, but
cannot; strengthen our faith that we may be saved; make us
believe" (as the Jews said to Jesus when they demanded miracles);
"either by miracles or promises of recompense, make us to have
faith in our salvation."
The disciples said what we all say: "How pleasant it would be if we
could live our selfish life, and at the same time believe that it is far
better to practise the doctrine of God by living for others." This
disposition of mind is common to us all; it is contrary to the meaning
of the doctrine of Jesus, and yet we are astonished at our lack of
faith. Jesus disposed of this misapprehension by means of a parable
illustrating true faith. Faith cannot come of confidence in his words;
faith can come only of a consciousness of our condition; faith is
based only upon the dictates of reason as to what is best to do in a
given situation. He showed that this faith cannot be awakened in
others by promises of recompense or threats of punishment, which
can only arouse a feeble confidence that will fail at the first trial; but
that the faith which removes mountains, the faith that nothing can
shatter, is inspired by the consciousness of our inevitable loss if we
do not profit by the salvation that is offered.
To have faith, we must not count on any promise of recompense; we
must understand that the only way of escape from a ruined life is a
life conformable to the will of the Master. He who understands this
will not ask to be strengthened in his faith, but will work out his
salvation without the need of any exhortation. The householder,
when he comes from the fields with his workman, does not ask the
latter to sit down at once to dinner, but directs him to attend first to
other duties and to wait upon him, the master, and then to take his
place at the table and dine. This the workman does without any
sense of being wronged; he does not boast of his labor nor does he
demand recognition or recompense, for he knows that labor is the
inevitable condition of his existence and the true welfare of his life.
So Jesus says that when we have done all that we are commanded
to do, we have only fulfilled our duty. He who understands his
relations to his master will understand that he has life only as he
obeys the master's will; he will know in what his welfare consists,
and he will have a faith that does not demand the impossible. This is
the faith taught by Jesus, which has for its foundation a thorough
perception of the true meaning of life. The source of faith is light:—
"That was the true light which lighteth every man that cometh into
the world. He was in the world, and the world was made by him,
and the world knew him not. He came unto his own, and his own
received him not. But as many as received him, to them gave he the
right to become the children of God, even to them that believe on
his name." (John i. 9-12.)
"And this is the condemnation, that light is come into the world, and
men loved darkness rather than light, because their deeds were evil.
For every one that doeth ill hateth the light, and cometh not to the
light, lest his works should be reproved. But he that doeth the truth
cometh to the light, that his works may be made manifest, because
they have been wrought in God." (John iii. 19-21.)
He who understands the doctrine of Jesus will not ask to be
strengthened in his faith. The doctrine of Jesus teaches that faith is
inspired by the light of truth. Jesus never asked men to have faith in
his person; he called upon them to have faith in truth. To the Jews
he said:—
"Ye seek to kill me, a man that hath told you the truth which I have
heard of God." (John viii. 40.)
"Which of you convicteth me of sin? If I say truth, why do ye not
believe me?" (John viii. 46.)
"To this end have I been born, and to this end am I come into the
world, that I should bear witness unto the truth. Every one that is of
the truth heareth my voice." (John xviii. 37.)
To his disciples he said:—
"I am the way, and the truth, and the life." (John xiv. 6.)
"The Father ... shall give you another Comforter, that he may be with
you forever, even the Spirit of truth: whom the world cannot receive;
for it beholdeth him not, neither knoweth him: ye know him; for he
abideth with you, and shall be in you." (John xiv. 16, 17.)
Jesus' doctrine, then, is truth, and he himself is truth. The doctrine
of Jesus is the doctrine of truth. Faith in Jesus is not belief in a
system based upon his personality, but a consciousness of truth. No
one can be persuaded to believe in the doctrine of Jesus, nor can
any one be stimulated by any promised reward to practise it. He who
understands the doctrine of Jesus will have faith in him, because this
doctrine is true. He who knows the truth indispensable to his
happiness must believe in it, just as a man who knows that he is
drowning grasps the rope of safety. Thus, the question, What must I
do to believe? is an indication that he who asks it does not
understand the doctrine of Jesus.
CHAPTER X.
ebookbell.com