標籤:des style blog http color os 使用 io strong
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對象及擷取文檔的頁數。
複製代碼
- CGPDFDocumentRefMyGetPDFDocumentRef (const char *filename)
- {
- CFStringRef path;
- CFURLRef url;
- CGPDFDocumentRef document;
- size_t count;
-
- path = CFStringCreateWithCString (NULL, filename, kCFStringEncodingUTF8);
-
- url = CFURLCreateWithFileSystemPath (NULL, path, kCFURLPOSIXPathStyle,0); // 1 建立CFURL對象
-
- CFRelease (path);
-
- document = CGPDFDocumentCreateWithURL (url); // 2 建立CFPDFDocument對象
- CFRelease(url);
-
- count = CGPDFDocumentGetNumberOfPages (document); // 3 擷取文檔頁數
- if (count == 0) {
- printf("`%s‘ needs at least onepage!", filename);
- return NULL;
- }
-
- return document;
- }
|
代碼清單顯示了如何將一個PDF頁繪製到圖形上下文中。
複製代碼
- void MyDisplayPDFPage (CGContextRefmyContext, size_t pageNumber, const char *filename)
- {
- CGPDFDocumentRef document;
- CGPDFPageRef page;
-
- document = MyGetPDFDocumentRef (filename); // 1 建立PDFDocument對象
- page = CGPDFDocumentGetPage (document, pageNumber); // 2 擷取指定頁的PDF文檔
- CGContextDrawPDFPage (myContext, page); // 3 將PDF繪製到圖形上下文中
- CGPDFDocumentRelease (document);
- }
|
為PDF頁建立一個轉換
Quartz提供了函數CGPDFPageGetDrawingTransform來建立一個仿射變換,該變換基於將PDF頁的BOX映射到指定的矩形中。函數原型是:
複製代碼
- CGAffineTransformCGPDFPageGetDrawingTransform (
- CGPPageRef page,
- CGPDFBox box,
- CGRect rect,
- int rotate,
- bool preserveAspectRatio
- );
|
該函數通過如下演算法來返回一個仿射變換:
· 將在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。
複製代碼
- Listing 13-3 Creating an affine transform for aPDF page
- void MyDrawPDFPageInRect(CGContextRef context, CGPDFPageRef page, CGPDFBox box, CGRect rect, int rotation, bool preserveAspectRatio)
- {
- CGAffineTransform m;
-
- m = CGPDFPageGetDrawingTransform (page, box, rect, rotation, preserveAspectRato);
-
- CGContextSaveGState (context);
-
- CGContextConcatCTM (context, m);
-
- CGContextClipToRect (context,CGPDFPageGetBoxRect (page, box));
-
- CGContextDrawPDFPage (context, page);
-
- 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
複製代碼
- void MyCreatePDFFile (CGRectpageRect, const char *filename)
- {
- CGContextRef pdfContext;
- CFStringRef path;
- CFURLRef url;
- CFData boxData = NULL;
- CFMutableDictionaryRef myDictionary = NULL;
- CFMutableDictionaryRef pageDictionary = NULL;
-
- path = CFStringCreateWithCString (NULL, filename, kCFStringEncodingUTF8);
-
- url = CFURLCreateWithFileSystemPath (NULL, path, kCFURLPOSIXPathStyle, 0);
-
- CFRelease (path);
-
- myDictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-
- CFDictionarySetValue(myDictionary, kCGPDFContextTitle, CFSTR("MyPDF File"));
-
- CFDictionarySetValue(myDictionary, kCGPDFContextCreator, CFSTR("MyName"));
-
- pdfContext = CGPDFContextCreateWithURL (url, &pageRect,myDictionary);
-
- CFRelease(myDictionary);
-
- CFRelease(url);
-
- pageDictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-
- boxData = CFDataCreate(NULL,(const UInt8 *)&pageRect, sizeof(CGRect));
-
- CFDictionarySetValue(pageDictionary, kCGPDFContextMediaBox, boxData);
-
- CGPDFContextBeginPage (pdfContext, &pageRect);
-
- myDrawContent (pdfContext);
-
- CGPDFContextEndPage (pdfContext);
-
- CGContextRelease (pdfContext);
-
- CFRelease(pageDictionary);
-
- CFRelease(boxData);
- }
|
添加連結
我們可以在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文檔的建立、顯示及轉換