Quartz 2D是一个二维绘图引擎,可在iOS环境中和内核之外的所有Mac OS X应用程序环境中访问。您可以使用Quartz 2D应用程序编程接口(API)访问基于路径的绘图,绘制透明度,着色,绘制阴影,透明层,颜色管理,反锯齿渲染,PDF文档生成和PDF等功能元数据访问。只要有可能,Quartz 2D利用图形硬件的力量。
在Mac OS X中,Quartz 2D可以使用所有其他图形和成像技术 - Core Image,Core Video,OpenGL和QuickTime。可以使用QuickTime函数GraphicsImportCreateCGImage从QuickTime图形导入器在Quartz中创建图像。有关详细信息,请参阅QuickTime Framework Reference。在Mac OS X中在Quartz 2D和Core Image之间移动数据描述了如何向Core Image提供图像,Core Image是一个支持图像处理的框架。
类似地,在iOS中,Quartz 2D使用所有可用的图形和动画技术,例如Core Animation,OpenGL ES和UIKit类。
The Page
Quartz 2D使用画家的模型进行成像。 在画家模型中,每个连续的绘制操作将一层“绘画”应用于输出“画布”,通常称为页面。 页面上的油漆可以通过额外的绘图操作覆盖更多的油漆来修改。 在页面上绘制的对象不能被修改,除非重叠更多的颜色。 此模型允许您从少量强大的图元构造非常复杂的图像。
图1-1显示了画家的模型如何工作。 为了在图的顶部获得图像,首先绘制左边的形状,然后绘制实心形状。 实心形状覆盖第一形状,遮蔽第一形状的周边以外的所有边界。 在图的底部以相反的顺序绘制形状,首先绘制实心形状。 正如你可以看到,在画家的模型中,绘图顺序很重要。
页面可以是真正的纸张(如果输出设备是打印机); 它可以是虚拟纸(如果输出设备是PDF文件); 它甚至可以是位图图像。 页面的确切性质取决于您使用的特定图形上下文。
绘图目的地:图形上下文(The Graphics Context)
图形上下文是一种不透明数据类型(CGContextRef),它封装了Quartz用于将图像绘制到输出设备的信息,例如PDF文件,位图或显示器上的窗口。 图形上下文中的信息包括页面上的涂料的图形绘制参数和设备特定表示。 Quartz中的所有对象都被绘制到或包含在图形上下文中。
您可以将图形上下文视为绘图目标,如图1-2所示。 当您使用Quartz绘制时,所有特定于设备的特性都包含在您使用的特定类型的图形上下文中。 换句话说,只需向Quartz绘图例程的同一序列提供不同的图形上下文,即可将同一图像绘制到不同的设备。 您不需要执行任何设备特定的计算; Quartz为你做。
这些图形上下文可供您的应用程序使用:
- ** bitmap graphics context **允许您将RGB颜色,CMYK颜色或灰度绘制到位图中。位图是像素的矩形阵列(或光栅),每个像素表示图像中的点。位图图像也称为采样图像。请参阅创建位图图形上下文。
- ** PDF graphics context **允许您创建PDF文件。在PDF文件中,您的绘图将保留为一系列命令。 PDF文件和位图之间存在一些显着差异:
- PDF文件与位图不同,可能包含多个页面。
- 当您从其他设备上的PDF文件中绘制页面时,生成的图像会针对该设备的显示特性进行优化。
- PDF文件是本质上独立的分辨率 - 它们绘制的大小可以无限增加或减少,而不会牺牲图像细节。位图图像的用户感知质量与打算观看位图的分辨率相关。
请参阅创建PDF图形上下文。
- ** window graphics context **是一个图形上下文,您可以使用它来绘制窗口。注意,因为Quartz 2D是一个图形引擎而不是一个窗口管理系统,你使用一个应用程序框架来获取一个窗口的图形上下文。有关详细信息,请参阅在Mac OS X中创建窗口图形上下文。
- ** *layer context * **(CGLayerRef)是与另一图形上下文相关联的离屏绘制目的地。它被设计为在将图层绘制到创建它的图形上下文时获得最佳性能。对于屏幕外绘制,层上下文可以是比位图图形上下文更好的选择。请参阅Core Graphics Layer Drawing。
- 当您要在Mac OS X中打印时,您将内容发送到由打印框架管理的PostScript图形上下文。有关详细信息,请参阅获取打印的图形上下文
Quartz 2D不透明数据类型
除了图形上下文,Quartz 2D API还定义了各种不透明的数据类型。 因为API是Core Graphics框架的一部分,所以操作它们的数据类型和例程使用CG前缀。
Quartz 2D从您的应用程序操作的不透明数据类型创建对象,以实现特定的图形输出。 图1-3显示了对Quartz 2D提供的三个对象应用绘制操作时可以实现的结果类型。 例如:
- 您可以通过创建PDF页面对象,对图形上下文应用旋转操作,并要求Quartz 2D将页面绘制到图形上下文来旋转和显示PDF页面。
- 您可以通过创建模式对象,定义组成模式的形状,并设置Quartz 2D,以便在绘制图形上下文时将模式用作绘画来绘制模式。
- 您可以通过创建阴影对象,提供一个确定阴影中每个点的颜色的函数,然后要求Quartz 2D将阴影用作填充颜色,通过轴向或径向阴影填充区域。
Quartz 2D中可用的不透明数据类型包括:
- CGPathRef,用于矢量图形创建您填充或描边的路径。请参阅路径。
- CGImageRef,用于基于您提供的样本数据表示位图图像和位图图像掩码。请参阅位图图像和图像掩码。
- CGLayerRef,用于表示可用于重复绘图(例如用于背景或图案)和离屏绘制的绘图图层。请参阅Core Graphics Layer Drawing
- CGPatternRef,用于重复绘图。请参阅模式。
- CGShadingRef和CGGradientRef,用于绘制渐变。请参阅渐变。
- CGFunctionRef,用于定义具有任意数量的浮点参数的回调函数。在为阴影创建渐变时,使用此数据类型。请参阅渐变。
- CGColorRef和CGColorSpaceRef,用于告知Quartz如何解释颜色。请参阅颜色和颜色空间。
- CGImageSourceRef和CGImageDestinationRef,用于将数据移入和移出Quartz。请参阅Quartz 2D和Image I / O编程指南中的数据管理。
- CGFontRef,用于绘制文本。参见文本。
- CGPDFDictionaryRef,CGPDFObjectRef,CGPDFPageRef,CGPDFStream,CGPDFStringRef和CGPDFArrayRef,它们提供对PDF元数据的访问。请参阅PDF文档创建,查看和转换。
- CGPDFScannerRef和CGPDFContentStreamRef,用于解析PDF元数据。请参阅PDF文档解析。
- CGPSConverterRef,用于将PostScript转换为PDF。它不适用于iOS。请参阅PostScript转换。
图形状态
Quartz根据当前图形状态下的参数修改绘图操作的结果。图形状态包含将被作为绘图例程的参数。绘制到图形上下文的例程参考图形状态以确定如何呈现其结果。例如,当您调用函数设置填充颜色时,您正在修改存储在当前图形状态中的值。当前图形状态的其他常用元素包括线宽,当前位置和文本字体大小。
图形上下文包含一叠图形状态。当Quartz创建一个图形上下文时,堆栈是空的。当保存图形状态时,Quartz将当前图形状态的副本推送到堆栈。当你恢复图形状态,Quartz从堆栈的顶部弹出图形状态。弹出状态变为当前图形状态。
要保存当前图形状态,请使用函数CGContextSaveGState将当前图形状态的副本推送到堆栈。要恢复以前保存的图形状态,请使用函数CGContextRestoreGState将当前图形状态替换为位于堆栈顶部的图形状态。
注意,并非当前绘图环境的所有方面都是图形状态的元素。例如,当前路径不被视为图形状态的一部分,因此在调用函数CGContextSaveGState时不会保存。调用此函数时保存的图形状态参数如下表所示。
Quartz 2D坐标系
坐标系统,如图1-4所示,定义了用于表示页面上要绘制的对象的位置和大小的位置范围。 您可以在用户空间坐标系中指定图形的位置和大小,或者更简单地指定用户空间。 坐标定义为浮点值。
因为不同的设备具有不同的底层成像能力,所以必须以设备无关的方式定义图形的位置和大小。例如,屏幕显示设备可能能够每英寸显示不超过96个像素,而打印机可能能够显示每英寸300个像素。如果在设备级别定义坐标系(在此示例中为96像素或300像素),则在该空间中绘制的对象如果在其他设备上再现。它们将显得太大或太小。
Quartz通过使用当前的变换矩阵或CTM,通过单独的坐标系统(用户空间映射)将输出设备的坐标系统(设备空间)完成设备独立性。矩阵是用于有效描述一组相关方程的数学构造。当前变换矩阵是称为仿射变换的特定类型的矩阵,其通过应用平移,旋转和缩放操作(移动,旋转和调整坐标系统的计算)将点从一个坐标空间映射到另一个坐标空间。
当前的变换矩阵有第二个目的:它允许你转换对象的绘制方式。例如,要绘制旋转45度的框,您在绘制框之前旋转页面的坐标系(CTM)。 Quartz使用旋转的坐标系统绘制到输出设备。
用户空间中的点由坐标对(x,y)表示,其中x表示沿水平轴(左和右)的位置,y表示垂直轴(上下)。用户坐标空间的原点是点(0,0)。原点位于页面的左下角,如图1-4所示。在Quartz的默认坐标系中,x轴随着从页面的左侧向右侧移动而增加。当y轴从页面的底部向顶部移动时,y轴的值增加。
一些技术使用与Quartz使用的默认坐标系不同的默认坐标系来设置它们的图形上下文。相对于Quartz,这样的坐标系是修改的坐标系,并且当执行一些Quartz绘图操作时必须被补偿。最常见的修改坐标系将原点放置在上下文的左上角,并将y轴更改为指向页面底部。您可能会看到这个特定坐标系统的几个地方如下:
- 在Mac OS X中,NSView的子类覆盖其isFlipped方法以返回YES。
- 在iOS中,由UIView返回的绘图上下文。
- 在iOS中,通过调用UIGraphicsBeginImageContextWithOptions函数创建的绘图上下文。
UIKit返回具有修改的坐标系的Quartz绘图上下文的原因是UIKit使用不同的默认坐标约定;它将变换应用到它创建的Quartz上下文,以便它们匹配其约定。如果应用程序想要使用相同的绘图例程来绘制到UIView对象和PDF图形上下文(由Quartz创建并使用默认坐标系),则需要应用变换,以便PDF图形上下文接收相同的修改坐标系。为此,应用将原点转换为PDF上下文左上角的变换,并将y坐标按-1缩放。
使用缩放变换来否定y坐标改变了Quartz图形中的一些约定。例如,如果调用CGContextDrawImage将图像绘制到上下文中,则在绘制到目标中时,图像将被变换修改。类似地,路径绘制例程接受指定是否在默认坐标系中沿顺时针或逆时针方向绘制弧的参数。如果坐标系被修改,结果也被修改,好像图像被反射镜反射。在图1-5中,将相同的参数传递到Quartz将导致默认坐标系中的顺时针圆弧和y坐标被变换取反后的逆时针圆弧。
它是由你的应用程序来调整任何Quartz调用它对应用了一个变换的上下文。 例如,如果您想要将图像或PDF正确绘制到图形上下文中,则应用程序可能需要临时调整图形上下文的CTM。 在iOS中,如果使用UIImage对象包装您创建的CGImage对象,则不需要修改CTM。 UIImage对象自动补偿UIKit应用的修改后的坐标系。
重要:上面的讨论对于了解你是否计划编写直接针对Quartz在iOS上的应用程序至关重要,但这是不够的。 在iOS 3.2及更高版本上,当UIKit为应用程序创建绘图上下文时,还会对上下文进行其他更改以匹配默认的UIKIt约定。 特别地,不受CTM影响的模式和阴影被单独调整,使得它们的约定匹配UIKit的坐标系。 在这种情况下,没有与CTM的等效机制,您的应用程序可以使用它来更改由Quartz创建的上下文以匹配UIKit提供的上下文的行为; 您的应用程序必须识别它正在绘制什么样的上下文,并调整其行为以匹配上下文的期望。
内存管理:对象所有权
Quartz使用Core Foundation内存管理模型,其中对象被引用计数。 创建时,Core Foundation对象以引用计数1开始。您可以通过调用函数来保留对象来增加引用计数,并通过调用函数释放对象来减少引用计数。 当引用计数减少到0时,对象被释放。 此模型允许对象安全地共享对其他对象的引用。
有几个简单的规则要记住:
- 如果您创建或复制对象,则您拥有它,因此您必须释放它。也就是说,一般来说,如果从名称中包含单词“Create”或“Copy”的函数中获取对象,则必须在完成该对象后释放该对象。否则,将导致内存泄漏。
- 如果从名称中不包含单词“Create”或“Copy”的函数获取对象,则不具有对对象的引用,并且不能释放它。对象将在未来的某个时间由其所有者释放。
- 如果你没有一个对象,你需要保持它的时候,你必须保留它,并当你完成它的时候,释放它。您使用特定于对象的Quartz 2D函数来保留和释放该对象。例如,如果接收到对CGColorspace对象的引用,则可以使用函数CGColorSpaceRetain和CGColorSpaceRelease根据需要保留和释放对象。您还可以使用Core Foundation函数CFRetain和CFRelease,但是必须小心不要将NULL传递给这些函数。