版本记录
版本号 | 时间 |
---|---|
V1.0 | 2017.08.08 |
前言
quartz
是一个通用的术语,用于描述在iOS
和MAC OS X
中整个媒体层用到的多种技术 包括图形、动画、音频、适配。Quart 2D
是一组二维绘图和渲染API
,Core Graphic
会使用到这组API
,Quartz Core
专指Core Animation
用到的动画相关的库、API
和类。CoreGraphics
是UIKit
下的主要绘图系统,频繁的用于绘制自定义视图。Core Graphics
是高度集成于UIView
和其他UIKit
部分的。Core Graphics
数据结构和函数可以通过前缀CG
来识别。在app中很多时候绘图等操作我们要利用CoreGraphic
框架,它能绘制字符串、图形、渐变色等等,是一个很强大的工具。下面几篇就主要介绍CoreGraphics
这个工具。
框架概览
我们先看一下框架CoreGraphics
的组成。
#import <CoreGraphics/CoreGraphics.h>
这个框架包含以下的文件。
#ifndef COREGRAPHICS_H_
#define COREGRAPHICS_H_
#include <CoreGraphics/CGBase.h>
#include <CoreGraphics/CGAffineTransform.h>
#include <CoreGraphics/CGBitmapContext.h>
#include <CoreGraphics/CGColor.h>
#include <CoreGraphics/CGColorConversionInfo.h>
#include <CoreGraphics/CGColorSpace.h>
#include <CoreGraphics/CGContext.h>
#include <CoreGraphics/CGDataConsumer.h>
#include <CoreGraphics/CGDataProvider.h>
#include <CoreGraphics/CGError.h>
#include <CoreGraphics/CGFont.h>
#include <CoreGraphics/CGFunction.h>
#include <CoreGraphics/CGGeometry.h>
#include <CoreGraphics/CGGradient.h>
#include <CoreGraphics/CGImage.h>
#include <CoreGraphics/CGLayer.h>
#include <CoreGraphics/CGPDFArray.h>
#include <CoreGraphics/CGPDFContentStream.h>
#include <CoreGraphics/CGPDFContext.h>
#include <CoreGraphics/CGPDFDictionary.h>
#include <CoreGraphics/CGPDFDocument.h>
#include <CoreGraphics/CGPDFObject.h>
#include <CoreGraphics/CGPDFOperatorTable.h>
#include <CoreGraphics/CGPDFPage.h>
#include <CoreGraphics/CGPDFScanner.h>
#include <CoreGraphics/CGPDFStream.h>
#include <CoreGraphics/CGPDFString.h>
#include <CoreGraphics/CGPath.h>
#include <CoreGraphics/CGPattern.h>
#include <CoreGraphics/CGShading.h>
#endif /* COREGRAPHICS_H_ */
使用这些文件时必须显式的引用。
#import <CoreGraphics/CoreGraphics.h>
框架的应用
1. 几个应用方向
这个框架主要应用的方向其实就是绘制自定义视图,几个具有代表性的方向:
- 绘制文字
- 根据任意路径绘制图像
- 绘制渐变色
- 抗锯齿渲染
2. 几个专业术语
还需要注意下面几个专业术语:
- 路径
path
- 阴影
shadow
- 笔画
stroke
- 剪裁路径
Clip Path
- 线条粗细
Line Width
- 混合模式
Blend Mode
- 填充色 Fill
Color
- 当前形变矩阵
Current Transform Matrix
- 线条图案
Line Dash
3. 几个重要概念
上下文 Context
这个是绘图中最重要的概念,相当于我们画图的画布,我们可以简单地给Quartz
绘图序列指定不同的Graphics Context
,就可将相同的图像绘制到不同的设备上。而不需要任何设备相关的计算,这些都由Quartz
替我们完成。
我们还可以从下面角度理解上下文。
- 一个
Graphics Context
表示一个绘制目标。它包含绘制系统用于完成绘制指令的绘制参数和设备相关信息。 -
Graphics Context
定义了基本的绘制属性,如颜色、裁减区域、线条宽度和样式信息、字体信息、混合模式等。 - 在
iOS
应用程序中,如果要在屏幕上进行绘制,需要创建一个UIView
对象,并实现它的drawRect:
方法。视图的drawRect:
方法在视图显示在屏幕上及它的内容需要更新时被调用,通过调用UIGraphicsGetCurrentContext()
方法可以获取当前的Graphics Context
。 -
Quartz2D
的坐标系统原点是左下角,UI控件的坐标系统原点是左上角,如果绘图的上下文,是使用UIGraphicsGetCurrentContext
或者其他以UI开头的方法获取到的,在绘图时无需进行坐标转换。
主要有下面几种上下文:
Bitmap Graphics Context
PDF Graphics Context
Window Graphics Context
Layer Graphics Context
Printer Graphics Context
4. 框架架构及原理
下面看一下ios图像处理模块的经典原理配图。
最上层是UIKit
框架,这是服务于Application
的最前端框架,封装了所有控件类和操作;在其之下是Core Animation
框架,借助与这个框架,Apple向开发人员提供了非常方便的动画处理功能和图像渲染功能。再往下,分离成基于GPU
绘图的OpenGL ES
层和基于CPU
绘图的Core Graphic
层。最底层的就是支持最终绘图的硬件平台,包括GPU,CPU,缓存,总线等等。
下面看一下CoreAnimation
渲染。
这里虽然画着是他们都具有很明显的分隔,但是实际上他们的应用是十分紧密的,可以看一下下面的原理图。
这里可以看见,CPU
和GPU
都可以绘图,不过最终都是送到GPU
进行显示了。
下面看几个容易混淆的概念CoreGraphics
、QuartzCore
和Quartz
。
-
CoreGraphics.framework
- Quartz 2D : API manages the graphic context and implements drawing.
- Quartz Services : API provides low level access to the window server. This includes display hardware, resolution, refresh rate, and others.
-
QuartzCore.framework
- Core Animation : Objective-C API to do 2D animation.
- Core Image: image and video processing (filters, warp, transitions).iOS 5
-
Quartz.framework (OS X only)
- Image Kit: display and edit images.
- PDF Kit: display and edit PDFs.
- Quartz Composer: display Quartz Composer compositions.
- QuickLookUI: preview media elements.
-
其它一些Quartz技术:
- Quartz Extreme: GPU acceleration for Quartz Composer.
- QuartzGL (aka "Quartz 2D Extreme"): GPU acceleration for Quartz 2D.
5. 几个重要的问题
Quartz2D坐标转换
-
CGContextRotateCTM(CGContextRef c, CGFloat angle)
方法可以相对原点旋转上下文坐标系。
-CGContextTranslateCTM(CGContextRef c, CGFloat tx, CGFloat ty)
方法可以相对原点平移上下文坐标系。 -
CGContextScaleCTM(CGContextRef c, CGFloat sx, CGFloat sy)
方法可以缩放上下文坐标系。
注意:
- 转换坐标系前,使用
CGContextSaveGState(CGContextRef c)
保存当前上下文状态。 - 坐标系转换后,使用
CGContextRestoreGState(CGContextRef c)
可以恢复之前保存的上下文状态。
drawRect:方法注意事项
- 是在
UIViewController
的loadView
和viewDidLoad
两方法之后调用的。 - 如果在
UIView
初始化时没有设置CGRect
,drawRect:
将不会被自动调用。 - 如果设置UIView的
contentMode
属性值为UIViewContentModeRedraw
,那么将在每次更改frame时自动调用drawRect:
。 - 如果使用UIView绘图,只能在
drawRect
:方法中获取相应的CGContextRef
并绘图。而在其他方法中获取的CGContextRef不能用于绘图。 - 重绘时应该调用
setNeedsDisplay
,而不能直接调用drawRect:
,setNeedsDisplay
会自动调用drawRect:
。
内存管理问题
- Quartz2D是C语言的框架,并且部分需要自己管理内存,使用含
Create
或Copy
的函数创建的对象,使用完后必须释放,否则将导致内存泄露。 - 使用不含有
Create
或Copy
的函数获取的对象,则不需要释放。 - 如果
retain
了一个对象,不再使用时,需要将其release
掉。可以使用Quartz 2D
的函数来指定retain和release一个对象。例如,如果创建了一个CGColorSpace
对象,则使用函数CGColorSpaceRetain
和CGColorSpaceRelease
来retain和release对象。也可以使用Core Foundation
的CFRetain
和CFRelease
。注意不能传递NULL
值给这些函数。
参考文章
1. iOS 2D Graphic(1)—— Concept 基本概念和原理
2. 整理一下CoreGraphic和Quartz2D的知识(一)
后记
未完,待续~~~