Quartz 2D编程指南 (二) —— Quartz 2D概览(二)

版本记录

版本号 时间
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函数GraphicsImportCreateCGImageQuickTime图形导入器在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 AnimationOpenGL ESUIKit类。


The Page - 页面

Quartz 2D使用painter’s model进行成像。 在painter’s model中,每个连续的绘图操作都将一层“paint”应用于输出画布(canvas),通常称为page。 可以通过在其他绘图操作中覆盖更多绘制来修改页面上的绘制。 除非覆盖更多颜料,否则无法修改页面上绘制的对象。 此模型允许您从少量强大的基元构造极其复杂的图像。

图1-1显示了painter’s model的工作原理。 要在图的顶部获取图像,首先绘制左侧的形状,然后绘制实心形状。 实心形状覆盖第一个形状,遮挡除第一个形状的周边之外的所有形状。 形状在图的底部以相反的顺序绘制,首先绘制实心形状。 如您所见,在painter’s model中,绘制顺序很重要。

Figure 1-1 The painter’s model

page可以是真正的纸张(如果输出设备是打印机); 它可能是一张虚拟纸(如果输出设备是PDF文件); 它甚至可能是位图图像。 page的确切性质取决于您使用的特定图形上下文。


Drawing Destinations: The Graphics Context - 绘制目的地:上下文

graphics context是一种不透明的数据类型(CGContextRef),它封装了Quartz用于将图像绘制到输出设备的信息,例如PDF文件,位图或显示器上的窗口。 图形上下文中的信息包括图形绘制参数和page上绘制的设备特定表示。 Quartz中的所有对象都被绘制或者被包含到图形上下文。

您可以将图形上下文视为绘图目标,如图1-2所示。 使用Quartz绘制时,所有特定于设备的特征都包含在您使用的特定类型的图形上下文中。 换句话说,您可以通过为相同的Quartz绘图例程序列提供不同的图形上下文,将相同的图像绘制到不同的设备。 您无需执行任何特定于设备的计算,Quartz为您做到了。

Figure 1-2 Quartz drawing destinations

这些图形上下文可供您的应用程序使用:

  • 位图图形上下文(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将着色用作填充颜色。
Figure 1-3 Opaque data types are the basis of drawing primitives in Quartz 2D

Quartz 2D中提供的不透明数据类型包括以下内容:


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所示)定义了用于表示要在页面上绘制的对象的位置和大小的位置范围。 您可以在用户空间坐标系中指定图形的位置和大小,或者更简单地说,指定用户空间。 坐标定义为浮点值。

Figure 1-4 The Quartz coordinate system

由于不同的设备具有不同的底层成像功能,因此必须以与设备无关的方式定义图形的位置和大小。例如,屏幕显示设备可能能够显示每英寸不超过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轴更改为指向页面底部。您可能会看到使用此特定坐标系的几个地方如下:

UIKit返回带有修改坐标系的Quartz绘图上下文的原因是UIKit使用不同的默认坐标约定;它将变换应用于它创建的Quartz上下文,以便它们匹配其约定。如果您的应用程序想要使用相同的绘图例程来绘制UIView对象和PDF图形上下文(由Quartz创建并使用默认坐标系),则需要应用变换以便PDF图形上下文接收相同的修改坐标系(modified coordinate system)。要执行此操作,请应用将原点转换为PDF上下文左上角的变换,并将y坐标缩放-1。

使用缩放变换来让y坐标为负值会改变Quartz绘图中的一些约定。例如,如果调用CGContextDrawImage将图像绘制到上下文中,则在将图像绘制到目标时,图像将被变换修改。类似地,路径绘制例程接受指定是否在默认坐标系中以顺时针或逆时针方向绘制弧的参数。如果修改了坐标系,则也会修改结果,就像图像在镜像中显示一样。在图1-5中,将相同的参数传递给Quartz会导致默认坐标系中的顺时针圆弧和y坐标被变换抵消后的逆时针圆弧。

Figure 1-5 Modifying the coordinate system creates a mirrored image

您的应用程序可以调整它对已应用转换的上下文进行的任何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时,将释放该对象。此模型允许对象安全地共享对其他对象的引用。

要记住一些简单的规则:

  • 如果您创建或复制对象,则拥有它,因此您必须将其释放。也就是说,通常,如果从名称中使用CreateCopy字样的函数获取对象,则必须在完成后释放该对象。否则,会导致内存泄漏。
  • 如果从名称中不包含CreateCopy字样的函数中获取对象,则不具有对该对象的引用,并且不得释放该对象。该对象将在未来的某个时刻由其所有者发布。
  • 如果您没有拥有对象并且需要保留它,则必须引用它并在完成后将其释放。您可以使用特定于对象的Quartz 2D函数来保留和释放该对象。例如,如果您收到对CGColorspace对象的引用,则使用CGColorSpaceRetainCGColorSpaceRelease函数根据需要保留和释放对象。您还可以使用Core Foundation函数CFRetainCFRelease,但必须注意不要将NULL传递给这些函数。

后记

本篇主要讲述了Quartz 2D概览,感兴趣的给个赞或者关注~~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容