Quartz 2D 是一个二维图形绘制引擎,支持iOS环境和Mac OS X环境,我们可以使用Quartz 2D来实现许多功能,如基本的路径绘制、透明度、描影、绘制阴影、透明层、颜色管理、反锯齿、PDF文档生成和PDF元数据访问。在需要的时候,Quartz 2D还可以借助于图形硬件的功能。
在Mac OS X中,Quartz 2D可以与其它图形图像技术混合使用,如Core Image、Core Video、OpenGL、 QuickTime。例如,通过使用QuickTime的GraphicsImportCreateCGImage函数,可以用Quartz 2D从一个QuickTime图形导入器中创建一个图像。
相似的,在iOS,Quartz 2D能够使用各种绘图工作和动画技术,比如:Core Animation,OpenGL ES,UIKit classes.
Quartz 2D在图形中使用绘画者模型(painter’s model).在绘画者模型中,每个连续的绘制操作都是一个绘制层(a layer of paint)放置在画布上。我们通常称这个画布为Page.Page上的绘图可以通过额外的绘制操作来叠加更多的绘图。Page上的图像对象只能够通过叠加更多的图形来改变。这个模型允许我们使用小的图元来构建复杂的图形。
图1-1展示了绘画者模型如何工作。从图中可以看出不同的绘制顺序所产生的效果不一样。
Figure 1-1 The painter’s model
Page可以是一张纸(如果输出设备是打印机),也可以是虚拟的纸张(如果输出设备是PDF文件),还可以是bitmap图像,这些都根据实际使用的graphics context(绘图上下文)而定。
Drawing Destinations(绘制目标): The Graphics Context
Graphics Context是一个数据类型(CGContextRef),用于封装
Quartz绘制图像到输出设备的信息。设备可以是PDF文件,bitmap或者显示器窗口上。Graphics
Context中的信息包括在Page中的图像的图形绘制参数和设备相关的表现形式。Quartz中的所有对象都是绘制到一个Graphics Context中。
我们可以将Graphics Context想象成为绘制目标,如图1-2所示,当用Quartz绘图时,所有设备相关的特性都包含在我们所使用的Graphics Context中,换句话说,我们可以简单地给Quartz绘图序列指定不同的Graphics Context,就可将相同的图像绘制到不同的设备上,我们不需要任何设备相关的计算,这些都由Quartz替我们完成。
Figure 1-2 Quartz drawing destinations
我们可以获得以下graphics contexts:
A bitmap graphics context:A bitmap graphics context允许你使用RGB colors, CMYK colors, or grayscale到位图(bitmap)上。一个位图位图是一个矩形数组(或光栅)的像素,每一个像素都代表着图像的一个点。位图图像也称谓抽样图像。更多详情:Creating
a Bitmap Graphics Context。
A PDF graphics context:A PDF graphics context允许你创建PDF文件,在PDF文件中,你的绘制将被存储为一系列的指令。PDF文件和位图(bitmap)的一些重要的区别如下:
2):当你绘制页面从PDF文档到不同的设备,其结果图像将会根据设备的特征进行优化。
Quartz 2D Opaque Data Types
除Graphics contexts 之外,Quartz 2D API还定义了一些数据类型,由于这些API是Core Graphics框架的一部分,所以这些数据类型都是以CG开头的。
Quartz 2D使用这些数据类型来创建对象,通过操作这些对象来获取特定的图形,图1-3列举了三个使用Quartz 2D的绘制操作所获得的图像和相关说明:
你能够旋转并显示一个PDF页面
你能够使用一定的模式绘制模式对象。
你能够使用一定的像素填充某个区域,或者实现圆角效果。
Figure 1-3 Opaque data types are the basis of drawing primitives in Quartz 2D
Quartz 2D所包含的数据类型如下:
Graphics States(图形状态)
Quartz根据修改当前绘图状态的参数来修改绘制的结果。绘制程序根据这些绘图状态来决定如何渲染结果。例如:当你调用设置填充颜色的函数时,你将改变存储在当前绘图状态的颜色值。
Graphics contexts包含一个绘图状态栈,当Quartz创建一个Graphics contexts时,栈为空。当保存图像状态时,Quartz将当前图形形态的一个副本压入栈中。当还原图形状态是,Quartz将栈顶的图形状态出栈。出栈的状态为当前图形状态。
可使用函数CGContextSaveGState来保存图形状态,CGContextRestoreGState来还原图形状态。
注意:并不是当前绘制环境的所有方面都是图形状态的元素。如:图形状态不包含当前路径。下面列出了图形状态相关的参数:
Quartz 2D Coordinate Systems
坐标系统定义是被绘制到Page上的对象的位置及大小范围,如图1-4所示。我们在用户空间坐标系统(user-space coordination system,简称用户空间)中指定图形的位置及大小。坐标值是用浮点数来定义的。
Figure 1-4 The Quartz coordinate system
由于不同的设备有不同的图形功能,所以图像的位置及大小依赖于设备。例如,一个显示设备可能每英寸只能显示少于96个像素,而打印机可能每英寸能显示300个像素。如果在设备级别上定义坐标系统,则在一个设备上绘制的图形无法在其它设备上正常显示。
Quartz通过使用当前转换矩阵(current transformation matrix, CTM)将一个独立的坐标系统(user space)映射到输出设备的坐标系统(device space),以此来解决设备依赖问题。
CTM是一种特殊类型的矩阵(affine transform, 仿射矩阵),通过平移(translation)、旋转(rotation)、缩放(scale)操作将点从一个坐标空间映射到另外一个坐标空间。
CTM还有另外一个目的:允许你通过转换来决定对象如何被绘制。例如,为了绘制一个旋转了45度的盒子,我们可以在绘制盒子之前旋转Page的坐标系统。Quartz使用旋转过的坐标系统来将盒子绘制到输出设备中。
用户空间的点用坐标对(x, y)来表示,(0, 0)表示坐标原点。Quartz中默认的坐标系统是:沿着x轴从左到右坐标值逐渐增大;沿着y轴从下到上坐标值逐渐增大。
有一些技术在设置它们的graphics context时使用了不同于Quartz的默认坐标系统。相对于Quartz来说,这些坐标系统是修改的坐标系统(modified coordinate system),当在这些坐标系统中显示Quartz绘制的图形时,必须进行转换。最常见的一种修改的坐标系统是原点位于左上角,而沿着y轴从上到下坐标值逐渐增大。我们可以在如下一些地方见到这种坐标系统:
在Mac OS X中,重写过isFlipped方法以返回yes的NSView类的子类
在IOS中,由UIView返回的绘图上下文
在IOS中,通过调用UIGraphicsBeginImageContextWithOptions函数返回的绘图上下文
如果应用程序想以相同的绘制程序在一个UIView对象和PDF
Graphics Context上进行绘制,需要做一个变换以使PDF Graphics Context使用与UIView相同的坐标系。要达到这一目的,只需要对PDF的上下文的原点做一个平移(移到左上角)和用-1对y坐标值进行缩放。图1-5显示了这种变换操作:
我们的应用程序负责调整Quartz调用以确保有一个转换应用到上下文中。例如,如果你想要一个图片或PDF正确的绘制到一个Graphics Context中,你的应用程序可能需要临时调整Graphics
Context的CTM。在IOS中,如果使用UIImage对象来包裹创建的CGImage对象,可以不需要修改CTM。UIImage将自动进行补偿以适用UIKit的坐标系统。
注意:如果在iOS上开发与Quartz相关的程序,了解以上的知识点是非常有必要的,但是还不够。在iOS3.2和之后版本中,当UIKit为你的应用程序创建绘图上下文时,也对上下文进行了额外的修改以匹配UIkit的约定。特别是patterns和shadows不被CTM影响,需要单独调整来匹配UIkit坐标系。在这种情况下,没有一个等价的机制让CTM来转换Quartz和UIkit上下文。必须了解到在什么样的上下文中进行绘制,就需要匹配相预期的上下文。
内存管理:对象所有权
Quartz使用Core Foundation内存管理模型(引用计数)。所以,对象的创建与销毁与通常的方式是一样的。在Quartz中,需要记住如下一些规则:
如果创建或拷贝一个对象,你将拥有它,因此你必须释放它。通常,如果使用含有”Create”或“Copy”单词的函数获取一个对象,当使用完后必须释放,否则将导致内存泄露。
如果使用不含有”Create”或“Copy”单词的函数获取一个对象,你将不会拥有对象的引用,不需要释放它。
如果你不拥有一个对象而打算保持它,则必须retain它并且在不需要时release掉。可以使用Quartz 2D的函数来指定retain和release一个对象。例如,如果创建了一个CGColorspace对象,则使用函数CGColorSpaceRetain和CGColorSpaceRelease来retain和release对象。同样,可以使用Core
Foundation的CFRetain和CFRelease,但是注意不能传递NULL值给这些函数。
参考