版本记录
版本号 | 时间 |
---|---|
V1.0 | 2018.09.03 |
前言
Quartz 2D
框架相信大家都知道,也都一直在使用。Quartz 2D
的API是纯C语言的,它是一个二维绘图引擎,同时支持iOS和Mac系统。Quartz 2D
的API来自于Core Graphics
框架,数据类型和函数基本都以CG作为前缀,接下来几篇我们就一起来看一下这个框架。感兴趣可以看上面几篇文章。
1. Quartz 2D编程指南 (一) —— 简介(一)
Overview of Quartz 2D - Quartz 2D概览
Quartz 2D
是一个二维绘图引擎,可在iOS环境中访问,也可从内核以外的所有Mac OS X应用程序环境中访问。您可以使用Quartz 2D
应用程序编程接口(API)来访问基于路径的绘图,绘制透明度,阴影,绘制阴影,透明层,颜色管理,抗锯齿渲染,PDF文档生成和PDF元数据访问。 Quartz 2D
尽可能利用图形硬件的强大功能。
在Mac OS X
中,Quartz 2D
可以与所有其他图形和成像技术一起使用 - Core Image, Core Video, OpenGL, and QuickTime
。可以使用QuickTime
函数GraphicsImportCreateCGImage从QuickTime
图形导入器在Quartz中创建图像。有关详细信息,请参阅QuickTime Framework Reference
。在Mac OS X中在Moving Data Between Quartz 2D and Core Image in Mac OS X描述了如何向Core Image
提供图像,Core Image
是一个支持图像处理的框架。
同样,在iOS中,Quartz 2D
可与所有可用的图形和动画技术配合使用,例如Core Animation
,OpenGL ES
和UIKit
类。
The Page - 页面
Quartz 2D
使用painter’s model
进行成像。 在painter’s model
中,每个连续的绘图操作都将一层“paint”
应用于输出画布(canvas),通常称为page
。 可以通过在其他绘图操作中覆盖更多绘制来修改页面上的绘制。 除非覆盖更多颜料,否则无法修改页面上绘制的对象。 此模型允许您从少量强大的基元构造极其复杂的图像。
图1-1显示了painter’s model
的工作原理。 要在图的顶部获取图像,首先绘制左侧的形状,然后绘制实心形状。 实心形状覆盖第一个形状,遮挡除第一个形状的周边之外的所有形状。 形状在图的底部以相反的顺序绘制,首先绘制实心形状。 如您所见,在painter’s model
中,绘制顺序很重要。
page
可以是真正的纸张(如果输出设备是打印机); 它可能是一张虚拟纸(如果输出设备是PDF文件); 它甚至可能是位图图像。 page
的确切性质取决于您使用的特定图形上下文。
Drawing Destinations: The Graphics Context - 绘制目的地:上下文
graphics context
是一种不透明的数据类型(CGContextRef),它封装了Quartz用于将图像绘制到输出设备的信息,例如PDF文件,位图或显示器上的窗口。 图形上下文中的信息包括图形绘制参数和page
上绘制的设备特定表示。 Quartz中的所有对象都被绘制或者被包含到图形上下文。
您可以将图形上下文视为绘图目标,如图1-2所示。 使用Quartz绘制时,所有特定于设备的特征都包含在您使用的特定类型的图形上下文中。 换句话说,您可以通过为相同的Quartz绘图例程序列提供不同的图形上下文,将相同的图像绘制到不同的设备。 您无需执行任何特定于设备的计算,Quartz为您做到了。
这些图形上下文可供您的应用程序使用:
- 位图图形上下文
(bitmap graphics context)
允许您将RGB颜色,CMYK颜色或灰度绘制到位图中。位图(bitmap
)是像素的矩形阵列(或光栅),每个像素表示图像中的一个点。位图图像也称为采样图像(sampled images)
。请参阅Creating a Bitmap Graphics Context。 - PDF图形上下文
(PDF graphics context)
允许您创建PDF文件。在PDF文件中,您的绘图将保留为一系列命令。 PDF文件和位图之间存在一些显着差异:- 与位图不同,PDF文件可能包含多个页面。
- 当您从另一台设备上的PDF文件中绘制页面时,生成的图像会针对该设备的显示特性进行优化。
- PDF文件本质上是分辨率无关的 - 绘制它们的大小可以无限增加或减少,而不会牺牲图像细节。用户感知的位图图像质量与要查看位图的分辨率相关联。
请参阅Creating a PDF Graphics Context。
- 窗口图形上下文
(window graphics context)
是可用于绘制到窗口中的图形上下文。请注意,由于Quartz 2D是图形引擎而不是窗口管理系统,因此您可以使用其中一个应用程序框架来获取窗口的图形上下文。有关详细信息,请参阅 Creating a Window Graphics Context in Mac OS X。 - 图层上下文
(layer context)
(CGLayerRef)是与另一个图形上下文关联的屏幕外绘图目标。它旨在将图层绘制到创建它的图形上下文时获得最佳性能。与位图图形上下文相比,图层上下文可以是屏幕外绘制的更好选择。请参阅Core Graphics Layer Drawing。 - 如果要在Mac OS X中进行打印,可以将内容发送到由打印框架管理的PostScript图形上下文
(PostScript graphics context)
。有关详细信息,请参阅Obtaining a Graphics Context for Printing。
Quartz 2D Opaque Data Types - Quartz 2D不透明数据类型
除了图形上下文之外,Quartz 2D API
还定义了各种不透明数据类型。由于API是Core Graphics
框架的一部分,因此数据类型和对其进行操作的例程使用CG
前缀。
Quartz 2D
根据应用程序操作的不透明数据类型创建对象,以实现特定的绘图输出。图1-3显示了将绘图操作应用于Quartz 2D提供的三个对象时可以实现的各种结果。例如:
- 您可以通过创建PDF页面对象,将旋转操作应用于图形上下文,并要求Quartz 2D将页面绘制到图形上下文来旋转和显示PDF页面。
- 您可以通过创建图案
(pattern)
对象,定义构成图案的形状以及设置Quartz 2D以在绘制图形上下文时将图案用作绘图来绘制图案。 - 您可以通过创建着色对象来填充具有轴向或径向着色的区域,提供确定着色中每个点的颜色的函数,然后要求
Quartz 2D
将着色用作填充颜色。
Quartz 2D
中提供的不透明数据类型包括以下内容:
- CGPathRef,用于矢量图形以创建您填充或描边的路径。见Paths。
- CGImageRef,用于根据您提供的样本数据表示位图图像和位图图像蒙版。请参见 Bitmap Images and Image Masks。
- CGLayerRef,用于表示可用于重复绘图(例如背景或图案)和屏幕外绘图的绘图层。请参阅Core Graphics Layer Drawing
- CGPatternRef,用于重复绘图。见Patterns。
- CGShadingRef和CGGradientRef,用于绘制渐变。请参阅Gradients。
- CGFunctionRef,用于定义带有任意数量浮点参数的回调函数。在为着色创建渐变时使用此数据类型。请参阅Gradients。
- CGColorRef和CGColorSpaceRef,用于告知Quartz如何解释颜色。请参阅Color and Color Spaces。
- CGImageSourceRef和CGImageDestinationRef,用于将数据移入和移出Quartz。请参阅Data Management in Quartz 2D和mage I/O Programming Guide。
- CGFontRef,用于绘制文本。见Text。
- CGPDFDictionaryRef, CGPDFObjectRef, CGPDFPageRef, CGPDFStream, CGPDFStringRef和CGPDFArrayRef,它们提供对PDF元数据的访问。请参阅PDF Document Creation, Viewing, and Transforming。
- CGPDFScannerRef和CGPDFContentStreamRef,用于解析PDF元数据。请参阅PDF Document Parsing。
-
CGPSConverterRef,用于将
PostScript
转换为PDF
。它在iOS中不可用。请参阅PostScript Conversion。
Graphics States - 图形状态
Quartz根据当前图形状态(current graphics state)
中的参数修改绘制操作的结果。图形状态包含参数,这些参数将作为绘图例程的参数。绘制到图形上下文的例程会查询图形状态以确定如何呈现其结果。例如,当您调用函数来设置填充颜色时,您正在修改存储在当前图形状态中的值。当前图形状态的其他常用元素包括线宽,当前位置和文本字体大小。
图形上下文包含一堆图形状态。当Quartz创建图形上下文时,堆栈为空。保存图形状态时,Quartz会将当前图形状态的副本推送到堆栈中。当您恢复图形状态时,Quartz会将图形状态从堆栈顶部弹出。弹出状态变为当前图形状态。
要保存当前图形状态,请使用函数CGContextSaveGState
将当前图形状态的副本推送到堆栈。要恢复以前保存的图形状态,请使用函数CGContextRestoreGState
将当前图形状态替换为堆栈顶部的图形状态。
请注意,并非当前绘图环境的所有方面都是图形状态的元素。例如,当前路径不被视为图形状态的一部分,因此在调用函数CGContextSaveGState
时不会保存。表1-1列出了调用此函数时保存的图形状态参数。
Table 1-1 Parameters that are associated with the graphics state
Parameters | Discussed in this chapter |
---|---|
Current transformation matrix (CTM) | Transforms |
Clipping area | Paths |
Line: width, join, cap, dash, miter limit | Paths |
Accuracy of curve estimation (flatness) | Paths |
Anti-aliasing setting | Graphics Contexts |
Color: fill and stroke settings | Color and Color Spaces |
Alpha value (transparency) | Color and Color Spaces |
Rendering intent | Color and Color Spaces |
Color space: fill and stroke settings | Color and Color Spaces |
Text: font, font size, character spacing, text drawing mode | Text |
Blend mode | Paths and Bitmap Images and Image Masks |
Quartz 2D Coordinate Systems - Quartz 2D坐标系统
坐标系统(如图1-4所示)定义了用于表示要在页面上绘制的对象的位置和大小的位置范围。 您可以在用户空间坐标系中指定图形的位置和大小,或者更简单地说,指定用户空间。 坐标定义为浮点值。
由于不同的设备具有不同的底层成像功能,因此必须以与设备无关的方式定义图形的位置和大小。例如,屏幕显示设备可能能够显示每英寸不超过96个像素,而打印机可能能够显示每英寸300个像素。如果在设备级别定义坐标系(在此示例中为96像素或300像素),则在该空间中绘制的对象无法在没有可见失真的其他设备上再现。它们看起来太大或太小。
Quartz通过单独的坐标系统 - 用户空间(user space)
- 使用当前变换矩阵(current transformation matrix)
或CTM将其映射到输出设备 - 设备空间(device space)
的坐标系来实现设备独立性。矩阵是用于有效地描述一组相关方程的数学构造。当前变换矩阵是称为仿射变换的特定类型的矩阵,其通过应用平移,旋转和缩放操作(移动,旋转和调整坐标系的大小的计算)将点从一个坐标空间映射到另一个坐标空间。
当前转换矩阵具有次要目的:它允许您转换对象的绘制方式。例如,要绘制旋转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图形上下文接收相同的修改坐标系(modified coordinate system)
。要执行此操作,请应用将原点转换为PDF上下文左上角的变换,并将y坐标缩放-1。
使用缩放变换来让y坐标为负值会改变Quartz绘图中的一些约定。例如,如果调用CGContextDrawImage将图像绘制到上下文中,则在将图像绘制到目标时,图像将被变换修改。类似地,路径绘制例程接受指定是否在默认坐标系中以顺时针或逆时针方向绘制弧的参数。如果修改了坐标系,则也会修改结果,就像图像在镜像中显示一样。在图1-5中,将相同的参数传递给Quartz会导致默认坐标系中的顺时针圆弧和y坐标被变换抵消后的逆时针圆弧。
您的应用程序可以调整它对已应用转换的上下文进行的任何Quartz调用。例如,如果要将图像或PDF正确绘制到图形上下文中,则应用程序可能需要临时调整图形上下文的CTM。在iOS中,如果使用UIImage
对象来包装您创建的CGImage
对象,则无需修改CTM。 UIImage
对象自动补偿UIKit应用的修改坐标系。
重要提示:上述讨论对于了解您是否计划在iOS上编写直接针对Quartz的应用程序至关重要,但这还不够。在iOS 3.2及更高版本中,当UIKit为您的应用程序创建绘图上下文时,它还会对上下文进行其他更改以匹配默认的UIKIt约定。特别是,不受CTM影响的图案和阴影会单独调整,以使其惯例与UIKit的坐标系相匹配。在这种情况下,没有与CTM等效的机制,您的应用程序可以使用它来更改Quartz创建的上下文以匹配UIKit提供的上下文的行为;您的应用程序必须识别它正在绘制的上下文类型并调整其行为以匹配上下文的期望。
Memory Management: Object Ownership - 内存管理:对象所有权
Quartz
使用Core Foundation
内存管理模型,其中对象被引用计数。创建时,Core Foundation对象的引用计数为1。您可以通过调用引用对象的函数来增加引用计数,并通过调用函数来减少引用计数以释放对象。当引用计数递减到0时,将释放该对象。此模型允许对象安全地共享对其他对象的引用。
要记住一些简单的规则:
- 如果您创建或复制对象,则拥有它,因此您必须将其释放。也就是说,通常,如果从名称中使用
Create
或Copy
字样的函数获取对象,则必须在完成后释放该对象。否则,会导致内存泄漏。 - 如果从名称中不包含
Create
或Copy
字样的函数中获取对象,则不具有对该对象的引用,并且不得释放该对象。该对象将在未来的某个时刻由其所有者发布。 - 如果您没有拥有对象并且需要保留它,则必须引用它并在完成后将其释放。您可以使用特定于对象的Quartz 2D函数来保留和释放该对象。例如,如果您收到对
CGColorspace
对象的引用,则使用CGColorSpaceRetain
和CGColorSpaceRelease
函数根据需要保留和释放对象。您还可以使用Core Foundation
函数CFRetain
和CFRelease
,但必须注意不要将NULL
传递给这些函数。
后记
本篇主要讲述了Quartz 2D概览,感兴趣的给个赞或者关注~~~