PDF文档存储依赖于分辨率的向量图形、文本和位图,并用于程序的一系列指令中。一个PDF文档可以包含多页的图形和文本。PDF可用于创建跨平台、只读的文档,也可用于绘制依赖于分辨率的图形。
         Quartz为所有应用程序创建高保真的PDF文档,这些文档保留应用的绘制操作,如图13-1所示。PDF文档的结果将通过系统的其它部分或第三方法的产品来有针对性地进行优化。Quartz创建的PDF文档在Preview和Acrobat中都能正确的显示。

Quartz不仅仅只使用PDF作为它的数字页,它同样包含一些API来显示和生成PDF文件,及完成一些其它PDF相关的工作。

打开和查看PDF
         Quartz提供了CGPDFDocumentRef数据类型来表示PDF文档。我们可以使用CGPDFDocumentCreateWithProvider或CGPDFDocumentCreateWithURL来创建CGPDFDocument对象。在创建CGPDFDocument对象后,我们可以将其绘制到图形上下文中。图13-2显示了在一个窗体中绘制PDF文档。

代码清单13-1显示了如何创建一个CGPDFDocument对象及获取文档的页数。

 

复制代码

  1. CGPDFDocumentRefMyGetPDFDocumentRef (const char *filename)
  2. {
  3. CFStringRef path;
  4. CFURLRef url;
  5. CGPDFDocumentRef document;
  6. size_t count;
  7. path = CFStringCreateWithCString (NULL, filename, kCFStringEncodingUTF8);
  8. url = CFURLCreateWithFileSystemPath (NULL, path, kCFURLPOSIXPathStyle,0);  // 1 创建CFURL对象
  9. CFRelease (path);
  10. document = CGPDFDocumentCreateWithURL (url);                 // 2 创建CFPDFDocument对象
  11. CFRelease(url);
  12. count = CGPDFDocumentGetNumberOfPages (document);    // 3 获取文档页数
  13. if (count == 0) {
  14. printf("`%s' needs at least onepage!", filename);
  15. return NULL;
  16. }
  17. return document;
  18. }

代码清单显示了如何将一个PDF页绘制到图形上下文中。

 

复制代码

  1. void MyDisplayPDFPage (CGContextRefmyContext, size_t pageNumber, const char *filename)
  2. {
  3. CGPDFDocumentRef document;
  4. CGPDFPageRef page;
  5. document = MyGetPDFDocumentRef (filename);                                   // 1 创建PDFDocument对象
  6. page = CGPDFDocumentGetPage (document, pageNumber);           // 2 获取指定页的PDF文档
  7. CGContextDrawPDFPage (myContext, page);                                       // 3 将PDF绘制到图形上下文中
  8. CGPDFDocumentRelease (document);
  9. }

为PDF页创建一个转换
     Quartz提供了函数CGPDFPageGetDrawingTransform来创建一个仿射变换,该变换基于将PDF页的BOX映射到指定的矩形中。函数原型是:

 

复制代码

  1. CGAffineTransformCGPDFPageGetDrawingTransform (
  2. CGPPageRef page,
  3. CGPDFBox box,
  4. CGRect rect,
  5. int rotate,
  6. bool preserveAspectRatio
  7. );

该函数通过如下算法来返回一个仿射变换:
· 将在box参数中指定的PDF box的类型相关的矩形(media, crop, bleed, trim, art)与指定的PDF页的/MediaBox入口求交集。相交的部分即为一个有效的矩形(effectiverectangle)。
· 将effective rectangle旋转参数/Rotate入口指定的角度。
· 将得到的矩形放到rect参数指定的中间。
· 如果rotate参数是一个非零且是90的倍数,函数将effective rectangel旋转该值指定的角度。正值往右旋转;负值往左旋转。需要注意的是我们传入的是角度,而不是弧度。记住PDF页的/Rotate入口也包含一个旋转,我们提供的rotate参数是与/Rotate入口接合在一起的。
· 如果需要,可以缩放矩形,从而与我们提供的矩形保持一致。
· 如果我们通过传递true值给preserveAspectRadio参数以指定保持长宽比,则最后的矩形将与rect参数的矩形的边一致。

【注:上面这段翻译得不是很好】

例如,我们可以使用这个函数来创建一个与图13-3类似的PDF浏览程序。如果我们提供一个Rotate Left/Rotate Right属性,则可以调用CGPDFPageGetDrawingTransform来根据当前的窗体大小和旋转设置计算出适当的转换。

程序清单13-3显示了为一个PDF页创建及应用仿射变换,然后绘制PDF。

 

复制代码

  1. Listing 13-3  Creating an affine transform for aPDF page
  2. void MyDrawPDFPageInRect(CGContextRef context, CGPDFPageRef page, CGPDFBox box, CGRect rect, int rotation, bool preserveAspectRatio)
  3. {
  4. CGAffineTransform m;
  5. m = CGPDFPageGetDrawingTransform (page, box, rect, rotation, preserveAspectRato);
  6. CGContextSaveGState (context);
  7. CGContextConcatCTM (context, m);
  8. CGContextClipToRect (context,CGPDFPageGetBoxRect (page, box));
  9. CGContextDrawPDFPage (context, page);
  10. CGContextRestoreGState (context);

创建PDF文件
使用Quartz创建PDF与绘制其它图形上下文一下简单。我们指定一个PDF文件地址,设置一个PDF图形上下文,并使用与其它图形上下文一样的绘制程序。如代码清单13-4所示的MyCreatePDFFile函数,显示了创建一个PDF的所有工作。
注意,代码在CGPDFContextBeginPage和CGPDFContextEndPage中来绘制PDF。我们可以传递一个CFDictionary对象来指定页属性,包括media, crop, bleed,trim和art boxes。
Listing 13-4  Creating a PDF file

 

复制代码

  1. void MyCreatePDFFile (CGRectpageRect, const char *filename)
  2. {
  3. CGContextRef pdfContext;
  4. CFStringRef path;
  5. CFURLRef url;
  6. CFData boxData = NULL;
  7. CFMutableDictionaryRef myDictionary = NULL;
  8. CFMutableDictionaryRef pageDictionary = NULL;
  9. path = CFStringCreateWithCString (NULL, filename, kCFStringEncodingUTF8);
  10. url = CFURLCreateWithFileSystemPath (NULL, path, kCFURLPOSIXPathStyle, 0);
  11. CFRelease (path);
  12. myDictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
  13. CFDictionarySetValue(myDictionary, kCGPDFContextTitle, CFSTR("MyPDF File"));
  14. CFDictionarySetValue(myDictionary, kCGPDFContextCreator, CFSTR("MyName"));
  15. pdfContext = CGPDFContextCreateWithURL (url, &pageRect,myDictionary);
  16. CFRelease(myDictionary);
  17. CFRelease(url);
  18. pageDictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
  19. boxData = CFDataCreate(NULL,(const UInt8 *)&pageRect, sizeof(CGRect));
  20. CFDictionarySetValue(pageDictionary, kCGPDFContextMediaBox, boxData);
  21. CGPDFContextBeginPage (pdfContext, &pageRect);
  22. myDrawContent (pdfContext);
  23. CGPDFContextEndPage (pdfContext);
  24. CGContextRelease (pdfContext);
  25. CFRelease(pageDictionary);
  26. CFRelease(boxData);
  27. }

添加链接
我们可以在PDF上下文中添加链接和锚点。Quartz提供了三个函数,每个函数都以PDF图形上下文作为参数,还有链接的信息:
· CGPDFContextSetURLForRect可以让我们指定在点击当前PDF页中的矩形时打开一个URL。
· CGPDFContextSetDestinationForRect指定在点击当前PDF页中的矩形区域时设置目标以进行跳转。我们需要提供一个目标名。
· CGPDFContextAddDestinationAtPoint指定在点击当前PDF页中的一个点时设置目标以进行跳转。我们需要提供一个目标名。

保护PDF内容
为了保护PDF内容,我们可以在辅助字典中指定一些安全选项并传递给CGPDFContextCreate。我们可以通过包含如下关键字来设置所有者密码、用户密码、PDF是否可以被打印或拷贝:
· kCGPDFContextOwnerPassword: 定义PDF文档的所有者密码。如果指定该值,则文档使用所有者密码来加密;否则文档不加密。该关键字的值必须是ASCII编码的CFString对象。只有前32位是用于密码的。该值没有默认值。如果该值不能表示成ASCII,则无法创建文档并返回NULL。Quartz使用40-bit加密。
· kCGPDFContextUserPassword: 定义PDF文档的用户密码。如果文档加密了,则该值是文档的用户密码。如果没有指定,则用户密码为空。该关键字的值必须是ASCII编码的CFString对象。只有前32位是用于密码的。如果该值不能表示成ASCII,则无法创建文档并返回NULL。
· kCGPDFContextAllowsPrinting:指定当使用用户密码锁定时文档是否可以打印。该值必须是CFBoolean对象。默认值是kCGBooleanTrue。
· kCGPDFContextAllowsCopying: 指定当使用用户密码锁定时文档是否可以拷贝。该值必须是CFBoolean对象。默认值是kCGBooleanTrue。
代码清单14-4(下一章)显示了确认PDF文档是否被锁定,及用密码打开文档。

原文链接:http://www.cocoachina.com/bbs/read.php?tid=83761

Quartz 2D编程指南- PDF文档的创建、显示及转换的更多相关文章

  1. Quartz 2D编程指南(1) - 概览

    Quartz 2D编程指南是论坛会员德鲁伊翻译的国外的Quartz 2D一系列学习资料,供大家参考 Quartz 2D是一个二维图形绘制引擎,支持iOS环境和Mac OS X环境.我们可以使用Quar ...

  2. C# 如何在PDF文档中创建表格

    表格能够直观的传达数据信息,使信息显得条理化,便于阅读同时也利于管理.那在PDF类型的文档中如何来添加表格并且对表格进行格式化操作呢?使用常规方法直接在PDF中添加表格行不通,那我们可以在借助第三方组 ...

  3. qt 利用 HTML 生成PDF文档,不能显示jpg图片

    利用 QPrinter 和html 生成 pdf文档 其中用html语句有显示图片的语句 但只能显示png格式的图片,不能显示jpg格式图片. 经过排查:语法,文件路径等都正确,最终在stack ov ...

  4. [.NET开发] C# 如何在PDF文档中创建表格

    表格能够直观的传达数据信息,使信息显得条理化,便于阅读同时也利于管理.那在PDF类型的文档中如何来添加表格并且对表格进行格式化操作呢?使用常规方法直接在PDF中添加表格行不通,那我们可以在借助第三方组 ...

  5. Quartz 2D编程指南(4) - 颜色和颜色空间

    不同的设备(显示器.打印机.扫描仪.摄像头)处理颜色的方式是不同的.每种设备都有其所能支持的颜色值范围.一种设备能支持的颜色可能在其它设备中无法支持.为了有效的使用颜色及理解Quartz 2D中用于颜 ...

  6. Quartz 2D编程指南(5) - 变换(Transforms)

    Quartz 2D 绘制模型定义了两种独立的坐标空间:用户空间(用于表现文档页)和设备空间(用于表现设备的本地分辨率).用户坐标空间用浮点数表示坐标,与设备空间的像素分辨率没有关系.当我们需要一个点或 ...

  7. Quartz 2D编程指南(7) - 阴影(Shadows)

    阴影是绘制在一个图形对象下的且有一定偏移的图片,它用于模拟光源照射到图形对象上所形成的阴影效果,如果7-1所示.文本也可以有阴影.阴影可以让一幅图像看上去是立体的或者是浮动的. 阴影有三个属性: 1. ...

  8. Quartz 2D编程指南(2) - 图形上下文

    一个Graphics Context表示一个绘制目标.它包含绘制系统用于完成绘制指令的绘制参数和设备相关信息.Graphics Context定义了基本的绘制属性,如颜色.裁减区域.线条宽度和样式信息 ...

  9. Quartz 2D编程指南(2)图形上下文(Graphics Contexts)

    Graphics Contexts       一个Graphics Context表示一个绘制目标(也能够理解为图形上下文).它包括绘制系统用于完毕绘制指令的绘制參数和设备相关信息.Graphics ...

随机推荐

  1. Codeforces Round #357 (Div. 2) 优先队列+模拟

    C. Heap Operations time limit per test 1 second memory limit per test 256 megabytes input standard i ...

  2. Normalize.css与CSS reset区别

    Normalize.css 只是一个很小的CSS文件,但它在默认的HTML元素样式上提供了跨浏览器的高度一致性.相比于传统的CSS reset,Normalize.css是一种现代的.为HTML5准备 ...

  3. mongodb安装、运行

    1.下载安装: 切换到:/usr/local/ mkdir -p mongodb groupadd -g 800 mongodb useradd -u 801 -g mongodb mongodb c ...

  4. Hive 元数据库表信息

    Hive 的元数据信息通常存储在关系型数据库中,常用MySQL数据库作为元数据库管理. 1. 版本表 i) VERSION   -- 查询版本信息 2. 数据库.文件存储相关 i) DBS -- 存储 ...

  5. opencv颜色提取color filting

    # -*- coding: utf-8 -* import numpy as np import cv2 cap = cv2.VideoCapture(0) while True: _ , frame ...

  6. syslinux启动盘制作

    # <font color=DarkCyan >syslinux启动盘制作</font> # ### 准备工具 ### 1. BOOTICEx64 软件 ##分区引导制作工具 ...

  7. MySQLdb和PIL安装

    最近将个人博客部署到树莓派上海真是颇费周折,尤其是在MySQLdb和PIL的安装上 MySQLdb 先说Windows吧(比较简单) 直接pip安装即可或者下载编译版更方便:http://source ...

  8. Java复习8.多线程

    Java复习8 多线程知识 20131007 前言: 在Java中本身就是支持多线程程序的,而不是像C++那样,对于多线程的程序,需要调用操作系统的API 接口去实现多线程的程序,而Java是支持多线 ...

  9. log4cpp之Appender

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  10. bzip2压缩 解压缩

    压缩/解压缩压缩/解压缩之后的文件名称 必须是bz2 首先是  -z   压缩文件-d 解压缩!