版本记录
版本号 | 时间 |
---|---|
V1.0 | 2018.09.08 |
前言
Quartz 2D
框架相信大家都知道,也都一直在使用。Quartz 2D
的API是纯C语言的,它是一个二维绘图引擎,同时支持iOS和Mac系统。Quartz 2D
的API来自于Core Graphics
框架,数据类型和函数基本都以CG作为前缀,接下来几篇我们就一起来看一下这个框架。感兴趣可以看上面几篇文章。
1. Quartz 2D编程指南 (一) —— 简介(一)
2. Quartz 2D编程指南 (二) —— Quartz 2D概览(二)
3. Quartz 2D编程指南 (三) —— 图形上下文(三)
4. Quartz 2D编程指南 (四) —— Paths路径(一)
5. Quartz 2D编程指南 (五) —— Paths路径(二)
6. Quartz 2D编程指南 (六) —— 颜色和颜色空间(一)
7. Quartz 2D编程指南 (七) —— 变换(一)
8. Quartz 2D编程指南 (八) —— Patterns图案样式(一)
9. Quartz 2D编程指南 (九) —— 阴影(一)
10. Quartz 2D编程指南 (十) —— 渐变(一)
11. Quartz 2D编程指南 (十一) —— 透明层(一)
12. Quartz 2D编程指南 (十二) —— Quartz 2D中的数据管理(一)
13. Quartz 2D编程指南 (十三) —— 位图图像和图像蒙版(一)
14. Quartz 2D编程指南 (十四) —— 位图图像和图像蒙版(二)
15. Quartz 2D编程指南 (十五) —— Core Graphics图层绘制(一)
PDF Document Creation, Viewing, and Transforming - PDF文档创建,查看和转换
PDF文档将与分辨率无关的矢量图形,文本和图像存储为以紧凑编程语言编写的一系列命令。 PDF文档可以包含多页图像和文本。 PDF对于创建跨平台,只读文档和绘制与分辨率无关的图形非常有用。
对于所有应用程序,Quartz为保留应用程序绘图操作创建高保真PDF文档,如图13-1所示。 生成的PDF可以针对特定用途(例如特定打印机或Web)针对系统的其他部分或第三方产品进行优化。 Quartz
产生的PDF文档可以在Preview
和Acrobat
中正确显示。
Quartz不仅使用PDF作为其“数字纸”,还包括作为其API的一部分,可用于显示和生成PDF文件以及完成许多其他PDF相关任务的许多功能。
有关PDF的详细信息,包括PDF语言和语法,请参阅PDF Reference, Fourth Edition, Version 1.5
。
Opening and Viewing a PDF - 打开和显示一个PDF
Quartz
提供数据类型CGPDFDocumentRef
来表示PDF文档。 使用函数CGPDFDocumentCreateWithProvider
或函数CGPDFDocumentCreateWithURL
创建CGPDFDocument
对象。 创建CGPDFDocument
对象后,可以将其绘制到图形上下文。 图13-2显示了窗口内显示的PDF文档。
Listing 13-1
显示了如何创建CGPDFDocument
对象并获取文档中的页数。 列表后面会显示每个编号行代码的详细说明。
// Listing 13-1 Creating a CGPDFDocument object from a PDF file
CGPDFDocumentRef MyGetPDFDocumentRef (const char *filename)
{
CFStringRef path;
CFURLRef url;
CGPDFDocumentRef document;
size_t count;
path = CFStringCreateWithCString (NULL, filename,
kCFStringEncodingUTF8);
url = CFURLCreateWithFileSystemPath (NULL, path, // 1
kCFURLPOSIXPathStyle, 0);
CFRelease (path);
document = CGPDFDocumentCreateWithURL (url);// 2
CFRelease(url);
count = CGPDFDocumentGetNumberOfPages (document);// 3
if (count == 0) {
printf("`%s' needs at least one page!", filename);
return NULL;
}
return document;
}
这是代码的作用:
- 1) 调用
Core Foundation
函数从CFString
对象创建CFURL
对象,该对象表示要显示的PDF文件的文件名。 - 2) 从
CFURL
对象创建CGPDFDocument
对象。 - 3) 获取PDF中的页数,以便代码中的下一个语句可以确保文档至少有一个页面。
通过查看Listing 13-2
中的代码,您可以了解如何将PDF页面绘制到图形上下文。 列表后面会显示每个编号行代码的详细说明。
// Listing 13-2 Drawing a PDF page
void MyDisplayPDFPage (CGContextRef myContext,
size_t pageNumber,
const char *filename)
{
CGPDFDocumentRef document;
CGPDFPageRef page;
document = MyGetPDFDocumentRef (filename);// 1
page = CGPDFDocumentGetPage (document, pageNumber);// 2
CGContextDrawPDFPage (myContext, page);// 3
CGPDFDocumentRelease (document);// 4
}
这是代码的作用:
- 1) 调用您的函数(参见Listing 13-1)从您提供的文件名创建
CGPDFDocument
对象。 - 2) 从PDF文档中获取指定页码的页面。
- 3) 通过调用函数
CGContextDrawPDFPage
从PDF文件中绘制指定的页面。 您需要提供图形上下文和要绘制的页面。 - 4) 释放
CGPDFDocument
对象。
Creating a Transform for a PDF Page - 为PDF页面创建转换
Quartz
提供了一个函数-CGPDFPageGetDrawingTransform
,它通过将PDF页面中的框映射到您指定的矩形来创建仿射变换。 该函数的原型是:
CGAffineTransform CGPDFPageGetDrawingTransform (
CGPPageRef page,
CGPDFBox box,
CGRect rect,
int rotate,
bool preserveAspectRatio
);
该函数使用以下算法返回仿射变换:
- 将与您在
box
参数(media,crop,bleed,trim或art)
中指定的PDF框类型相关联的矩形与指定PDF页面的/ MediaBox
条目相交。交叉点产生有效的矩形。 - 按照PDF页面的
/ Rotate
条目指定的量旋转有效矩形。 - 将生成的矩形居中放在您在
rect
参数中提供的矩形上。 - 如果您提供的
rotate
参数的值为非零且为90的倍数,则该函数会将有效矩形旋转您提供的度数。正值将矩形向右旋转,负值将矩形向左旋转。请注意,您传递度数,而不是弧度。请记住,PDF页面的/ Rotate
条目也包含旋转,您提供的rotate
参数与/ Rotate
条目组合在一起。 - 如有必要,缩放有效矩形,使其与您提供的矩形的边缘重合。
- 如果通过在
preserveAspectRatio
参数中传递true
来指定保留纵横比,则最终矩形与您在rect
参数中提供的矩形的限制性更大的维度的边缘重合。
例如,如果您正在编写类似于图13-3中所示的PDF查看应用程序,则可以使用此函数。如果要提供“向左旋转/向右旋转”功能,则可以调用CGPDFPageGetDrawingTransform
来计算当前窗口大小和旋转设置的相应变换。
Listing 13-3
显示了一个函数,该函数使用传递给函数的参数为PDF页面创建仿射变换,应用变换,然后绘制PDF页面。 列表后面会显示每个编号行代码的详细说明。
// Listing 13-3 Creating an affine transform for a PDF page
void MyDrawPDFPageInRect (CGContextRef context,
CGPDFPageRef page,
CGPDFBox box,
CGRect rect,
int rotation,
bool preserveAspectRatio)
{
CGAffineTransform m;
m = CGPDFPageGetDrawingTransform (page, box, rect, rotation,// 1
preserveAspectRato);
CGContextSaveGState (context);// 2
CGContextConcatCTM (context, m);// 3
CGContextClipToRect (context,CGPDFPageGetBoxRect (page, box));// 4
CGContextDrawPDFPage (context, page);// 5
CGContextRestoreGState (context);// 6
}
这是代码的作用:
- 1)根据提供给函数的参数创建仿射变换。
- 2)保存图形状态。
- 3)将CTM与仿射变换连接起来。
- 4)将图形上下文剪切为
box
参数指定的矩形。 函数CGPDFPageGetBoxRect
获取与您提供的常量相关联的页面边界框(media, crop, bleed, trim, and art boxes)
-kCGPDFMediaBox
,kCGPDFCropBox
,kCGPDFBleedBox
,kCGPDFTrimBox
或kCGPDFArtBox
。 - 5)将PDF页面绘制到已变换和剪切的上下文中。
- 6)恢复图形状态。
Creating a PDF File - 创建PDF文件
使用Quartz 2D
创建PDF文件非常容易,因为它可以绘制到任何图形上下文。 您可以指定PDF文件的位置,设置PDF图形上下文,并使用与任何图形上下文相同的绘图例程。 Listing 13-4
中显示的函数MyCreatePDFFile
显示了代码为创建PDF文件而执行的所有任务。 列表后面会显示每个编号行代码的详细说明。
请注意,代码通过调用函数CGPDFContextBeginPage
和CGPDFContextEndPage
来描述PDF页面。 您可以传递CFDictionary
对象以指定页面属性,包括media, crop, bleed, trim, and art boxes
。 有关字典键常量的列表以及每个常量的更详细说明,请参阅CGPDFContext Reference。
// Listing 13-4 Creating a PDF file
void MyCreatePDFFile (CGRect pageRect, const char *filename)// 1
{
CGContextRef pdfContext;
CFStringRef path;
CFURLRef url;
CFDataRef boxData = NULL;
CFMutableDictionaryRef myDictionary = NULL;
CFMutableDictionaryRef pageDictionary = NULL;
path = CFStringCreateWithCString (NULL, filename, // 2
kCFStringEncodingUTF8);
url = CFURLCreateWithFileSystemPath (NULL, path, // 3
kCFURLPOSIXPathStyle, 0);
CFRelease (path);
myDictionary = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks); // 4
CFDictionarySetValue(myDictionary, kCGPDFContextTitle, CFSTR("My PDF File"));
CFDictionarySetValue(myDictionary, kCGPDFContextCreator, CFSTR("My Name"));
pdfContext = CGPDFContextCreateWithURL (url, &pageRect, myDictionary); // 5
CFRelease(myDictionary);
CFRelease(url);
pageDictionary = CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks); // 6
boxData = CFDataCreate(NULL,(const UInt8 *)&pageRect, sizeof (CGRect));
CFDictionarySetValue(pageDictionary, kCGPDFContextMediaBox, boxData);
CGPDFContextBeginPage (pdfContext, pageDictionary); // 7
myDrawContent (pdfContext);// 8
CGPDFContextEndPage (pdfContext);// 9
CGContextRelease (pdfContext);// 10
CFRelease(pageDictionary); // 11
CFRelease(boxData);
}
这是代码的作用:
- 1) 将参数设置为指定PDF页面大小的矩形和指定文件名的字符串。
- 2) 从传递给函数
MyCreatePDFFile
的文件名创建CFString
对象。 - 3) 从
CFString
对象创建CFURL
对象。 - 4) 创建一个空的
CFDictionary
对象来保存元数据。接下来的两行添加标题和创建者。您可以使用函数CFDictionarySetValue添加任意数量的键值对。有关创建字典的更多信息,请参阅CFDictionary Reference。 - 5) 创建PDF图形上下文,传递三个参数:
-
CFURL
对象,用于指定PDF数据的位置。 - 指向矩形的指针,用于定义PDF页面的默认大小和位置。矩形的原点通常为
(0,0)
。 Quartz使用此矩形作为页面媒体框的默认边界。如果传递NULL
,Quartz使用的默认页面大小为8.5 x 11
英寸(612 x 792点)
。 - 包含PDF元数据的
CFDictionary
对象。如果您没有要添加的元数据,请传递NULL
。您可以使用CFDictionary
对象指定输出方法选项 - 意图子类型,条件,条件标识符,注册表名称,目标输出配置文件以及包含有关预期目标设备或生产条件的其他信息或注释的人类可读文本字符串。有关输出方法选项的更多信息,请参阅CGPDFContext Reference。
-
- 6) 创建
CFDictionary
对象以保存PDF页面的页面框。此示例设置media box
。 - 7) 表示页面的开头。当您使用支持多个页面(例如PDF)的图形上下文时,可以使用
CGPDFContextBeginPage
和CGPDFContextEndPage
调用函数来描述输出中的页面边界。每个页面必须通过调用CGPDFContextBeginPage
和CGPDFContextEndPage
进行括号。 Quartz忽略在基于页面的上下文中在页边界外执行的所有绘制操作。 - 8) 调用应用程序定义的函数以将内容绘制到PDF上下文。您可以在此处提供绘图程序。
- 9) 在基于页面的图形上下文中指示页面的结尾。
- 10) 释放PDF上下文。
- 11) 释放页面词典。
Adding Links - 添加链接
您可以为您创建的PDF上下文添加链接和锚点。 Quartz提供了三个函数,每个函数都将PDF图形上下文以及有关链接的信息作为参数:
-
CGPDFContextSetURLForRect
允许您指定在用户单击当前PDF页面中的矩形时打开的URL。 -
CGPDFContextSetDestinationForRect
允许您设置当用户单击当前PDF页面中的矩形时跳转到的目标。 您必须提供目的地名称。 -
CGPDFContextAddDestinationAtPoint
允许您设置当用户单击当前PDF页面中的点时跳转到的目标。 您必须提供目的地名称。
Protecting PDF Content - 保护PDF内容
为了保护PDF内容,您可以在辅助字典中指定许多安全选项,并将其传递给函数CGPDFContextCreate
。您可以通过在辅助字典中包含以下键来设置所有者密码,用户密码以及是否可以打印或复制PDF:
-
kCGPDFContextOwnerPassword
,用于定义PDF文档的所有者密码。如果指定了此key,则使用值作为所有者密码对文档进行加密;否则,文档未加密。此键的值必须是可以ASCII
编码表示的CFString
对象。只有前32个字节用于密码。此key没有默认值。如果此键的值无法用ASCII表示,则不会创建文档,并且创建函数将返回NULL
。Quartz
使用40位加密。 -
kCGPDFContextUserPassword
,用于定义PDF文档的用户密码。如果文档已加密,则此键的值是文档的用户密码。如果未指定,则用户密码为空字符串。此键的值必须是可以ASCII编码表示的CFString对象;只有前32个字节用于密码。如果此键的值无法用ASCII表示,则不会创建文档,并且创建函数将返回NULL。 -
kCGPDFContextAllowsPrinting
指定在使用用户密码解锁文档时是否可以打印文档。此键的值必须是CFBoolean
对象。此键的默认值为kCFBooleanTrue
。 -
kCGPDFContextAllowsCopying
指定在使用用户密码解锁文档时是否可以复制文档。此键的值必须是CFBoolean
对象。此键的默认值为kCFBooleanTrue
。
Listing 14-4(在下一章中)显示了检查PDF文档是否被锁定的代码,如果是,则尝试使用密码打开文档。
后记
本篇主要讲述了PDF文档创建,查看和转换,感兴趣的给个赞或者关注~~~