Quartz 2D

来源:互联网 发布:电脑锣编程代码 编辑:程序博客网 时间:2024/06/13 05:11

       Quartz 2D是一个二维绘图引擎,同时支持iOS和Mac OS X系统(跨平台,纯 C 语言的),包含在 Core Graphics 框架中。 Quartz 2D能完成的工作有:绘制图形如线条、三角形、矩形、圆、弧等 ,绘制文字, 绘制、生成图片(图像) ,读取、生成PDF, 截图、裁剪图片 ,自定义UI控件(环形下载进度条等) … …

       Quartz2D的API是纯C语言的。 Quartz2D的API来自于Core Graphics框架,数据类型和函数基本都以CG作为前缀:CGContextRef、CGPathRef、CGContextStrokePath()……


Quartz2D 绘图主要步骤

1.获取【图形上下文】“对象”

2.向【图形上下文】”对象“中添加【路径】

3.渲染(把【图形上下文】中的图形绘制到对应的设备上)


图形上下文CGContextRef

图形上下文(Graphics Context):是一个CGContextRef类型的数据。 图形上下文中主要包含如下信息 :

1.绘图路径(各种各样的图形)

2.绘图状态(颜色、线宽、样式、旋转、缩放、平移、图片裁剪区域等) 

3.输出目标(绘制到什么地方去?UIView、图片、pdf、打印机等, 输出目标可以是PDF文件、Bitmap或者显示器的窗口上)


相同的一套绘图序列,指定不同的Graphics Context,就可将相同的图像绘制到不同的目标上。


图形上下文

       、Quartz2D提供了以下几种类型的Graphics Context: Bitmap Graphics Context、 PDF Graphics Context、 Window Graphics Context、 Layer Graphics Context(UI控件) 、Printer Graphics Context。




使用 Quartz2D 绘图

方式一:直接调用 Quartz2D 的 API 进行绘图

 代码量稍大、功能全面 

步骤: 1> 获取绘图上下文 

          2> 把图形绘制到绘图上下文上

          3> 把绘图上下文上的图形渲染到对应的设备上 


方式二:调用 UIKit 框架封装好的 API 进行绘图 

(1)代码相对简单、只对部分 Quartz2D 的 API 做了封装 ,比如:画图片、文字到控件上。(UIKit 已经封装好了)

(2)对于没有封装的功能只能调用 Quartz2D 原生 API



方式一:Quartz2D绘图的代码步骤

1.获得图形上下文:

CGContextRef ctx = UIGraphicsGetCurrentContext();


2.拼接路径(下面代码是搞一条线段):

CGContextMoveToPoint(ctx, 10, 10);

CGContextAddLineToPoint(ctx, 100, 100);


3.“渲染”(绘制路径):

CGContextStrokePath(ctx); // CGContextFillPath(ctx);


StrokeXxxx 表示画线(边线)(空心图形)

FillXxx 表示画填充的图形(实心图)


方式二:使用路径对象绘制图形(更简单)

通过UIBezierPath对象实现绘图:

1. 获取“图形上下文”对象

2. 创建 UIBezierPath 对象

3. 向 UIBezierPath 对象中绘制图形

4. 把 UIBezierPath 对象添加到上下文中

5. 把上下文对象渲染到设备上

注意: UIBezierPath 对象可以独立使用,  无需手动获取“图形上下文”对象。


绘图顺序对最终结果的影响



在 UIView 上绘图

      获取与 UIView 相关的绘图上下文,然后在drawRect:方法中取得上下文,在drawRect:方法中取得上下文后,就可以绘制东西到view上了。View内部有个layer(图层)属性,drawRect:方法中取得的是一个Layer Graphics Context,因此,绘制的东西其实是绘制到view的layer上去了。View之所以能显示东西,完全是因为它内部的layer。


重写drawRect:方法来绘图

为什么要实现drawRect:方法才能绘图到view上?

因为在drawRect:方法中才能取得跟view相关联的图形上下文。


drawRect:方法在什么时候被调用?

1.当view第一次显示到屏幕上时(加到UIWindow上显示出来);

2.重绘的时候:调用view的setNeedsDisplay或者setNeedsDisplayInRect:时。


注意:不要手动去调用 drawRect: 这个方法, 否则可能无法正确的获取绘图上下文,rect 表示当前 UIView 的 bounds。




几种不同的渲染方式

空心 StrokePath

实心 FillPath 和 EOFillPath (填充)

填充一个路径的时候,路径里面的子路径都是独立填充的。假如是重叠的路径,决定一个点是否被填充,有两种规则:

1,nonzero winding number rule(非零绕数规则),假如一个点被从左到右跨过,计数器+1,从右到左跨过,计数器-1,最后,如果结果是0,那么不填充,如果是非零,那么填充。

2,even-odd rule(奇偶规则),假如一个点被跨过1次,被跨过了奇数次,那么要被填充,被跨过偶数次则不填充,和方向没有关系。


even-odd rule:奇偶填充规则



nonzero winding number rule:非零绕数规则




矩阵操作 -  仿射变换

仿射变换,又称仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间。利用矩阵操作,能让绘制到上下文中的所有路径一起发生变化。

缩放:

void CGContextScaleCTM(CGContextRef c, CGFloat sx, CGFloat sy)

旋转:

void CGContextRotateCTM(CGContextRef c, CGFloat angle)

平移:

void CGContextTranslateCTM(CGContextRef c, CGFloat tx, CGFloat ty)


注意 : 此处是先把上下文旋转、缩放、平移了, 然后后面再绘制的所有图形就都是在旋转、缩放、平移之后的上下文中进行了。







Quartz2D的内存管理

使用Path 对象时的内存管理问题:

1> 凡是遇到 retain 、 copy 、 create 出的对象, 都需要进行 release。

2> 但是类似的方法:CGPathCreateMutable()不是 OC 方法, 所以不是调用某个对象的 release方法。

3> CGXxxxxCreate 对应的就有 CGXxxxxRelease。

4> 通过 CFRelease(任何类型);可以释放任何CoreFoundation类型。



图片裁剪











0 0