Quartz 2D編程指南之十三:PDF文檔的創(chuàng)建贰您、顯示及轉(zhuǎn)換

本文轉(zhuǎn)載自:

PDF文檔存儲(chǔ)依賴于分辨率的向量圖形、文本和位圖舶替,并用于程序的一系列指令中杠园。一個(gè)PDF文檔可以包含多頁的圖形和文本。PDF可用于創(chuàng)建跨平臺(tái)陈醒、只讀的文檔瞧甩,也可用于繪制依賴于分辨率的圖形。

Quartz為所有應(yīng)用程序創(chuàng)建高保真的PDF文檔爷辙,這些文檔保留應(yīng)用的繪制操作朦促,如圖13-1所示务冕。PDF文檔的結(jié)果將通過系統(tǒng)的其它部分或第三方法的產(chǎn)品來有針對性地進(jìn)行優(yōu)化。Quartz創(chuàng)建的PDF文檔在Preview和Acrobat中都能正確的顯示。

Figure 13-1 Quartz creates high-quality PDF documents

Quartz不僅僅只使用PDF作為它的數(shù)字頁坯屿,它同樣包含一些API來顯示和生成PDF文件,及完成一些其它PDF相關(guān)的工作乏德。

打開和查看PDF

Quartz提供了CGPDFDocumentRef數(shù)據(jù)類型來表示PDF文檔。我們可以使用CGPDFDocumentCreateWithProvider或CGPDFDocumentCreateWithURL來創(chuàng)建CGPDFDocument對象胧瓜。在創(chuàng)建CGPDFDocument對象后郑什,我們可以將其繪制到圖形上下文中。圖13-2顯示了在一個(gè)窗體中繪制PDF文檔钝满。

Figure 13-2 A PDF document

代碼清單13-1顯示了如何創(chuàng)建一個(gè)CGPDFDocument對象及獲取文檔的頁數(shù)弯蚜。

Listing 13-1 Creating a CGPDFDocument object from a PDF file

CGPDFDocumentRefMyGetPDFDocumentRef(constchar*filename)

{

CFStringRef path;

CFURLRef url;

CGPDFDocumentRef document;

size_tcount;

path = CFStringCreateWithCString (NULL, filename,

kCFStringEncodingUTF8);

url = CFURLCreateWithFileSystemPath (NULL, path,

kCFURLPOSIXPathStyle,0);

CFRelease (path);

document = CGPDFDocumentCreateWithURL (url);

CFRelease(url);

count = CGPDFDocumentGetNumberOfPages (document);

if(count ==0) {

printf("`%s' needs at least one page!", filename);

returnNULL;

}

returndocument;

}

代碼清單顯示了如何將一個(gè)PDF頁繪制到圖形上下文中剃法。

Listing 13-2 Drawing a PDF page

void MyDisplayPDFPage(CGContextRef myContext,size_tpageNumber,constchar*filename)

{

CGPDFDocumentRef document;

CGPDFPageRef page;

document = MyGetPDFDocumentRef (filename);

page = CGPDFDocumentGetPage (document, pageNumber);

CGContextDrawPDFPage (myContext, page);

CGPDFDocumentRelease (document);

}

為PDF頁創(chuàng)建一個(gè)轉(zhuǎn)換

Quartz提供了函數(shù)CGPDFPageGetDrawingTransform來創(chuàng)建一個(gè)仿射變換贷洲,該變換基于將PDF頁的BOX映射到指定的矩形中。函數(shù)原型是:

CGAffineTransformCGPDFPageGetDrawingTransform(

CGPPageRef page,

CGPDFBox box,

CGRect rect,

introtate,

boolpreserveAspectRatio

);

該函數(shù)通過如下算法來返回一個(gè)仿射變換:

將在box參數(shù)中指定的PDF box的類型相關(guān)的矩形(media, crop, bleed, trim, art)與指定的PDF頁的/MediaBox入口求交集帽氓。相交的部分即為一個(gè)有效的矩形(effectiverectangle)俩块。

將effective rectangle旋轉(zhuǎn)參數(shù)/Rotate入口指定的角度。

將得到的矩形放到rect參數(shù)指定的中間势腮。

如果rotate參數(shù)是一個(gè)非零且是90的倍數(shù)漫仆,函數(shù)將effective rectangel旋轉(zhuǎn)該值指定的角度盲厌。正值往右旋轉(zhuǎn);負(fù)值往左旋轉(zhuǎn)建芙。需要注意的是我們傳入的是角度懂扼,而不是弧度右蒲。記住PDF頁的/Rotate入口也包含一個(gè)旋轉(zhuǎn)赶熟,我們提供的rotate參數(shù)是與/Rotate入口接合在一起的映砖。

如果需要,可以縮放矩形眶诈,從而與我們提供的矩形保持一致瓜饥。

如果我們通過傳遞true值給preserveAspectRadio參數(shù)以指定保持長寬比,則最后的矩形將與rect參數(shù)的矩形的邊一致宪潮。

【注:上面這段翻譯得不是很好】

例如趣苏,我們可以使用這個(gè)函數(shù)來創(chuàng)建一個(gè)與圖13-3類似的PDF瀏覽程序。如果我們提供一個(gè)Rotate Left/Rotate Right屬性尽棕,則可以調(diào)用CGPDFPageGetDrawingTransform來根據(jù)當(dāng)前的窗體大小和旋轉(zhuǎn)設(shè)置計(jì)算出適當(dāng)?shù)霓D(zhuǎn)換彬伦。

Figure 13-3 A PDF page rotated 90 degrees to the right

程序清單13-3顯示了為一個(gè)PDF頁創(chuàng)建及應(yīng)用仿射變換单绑,然后繪制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,

preserveAspectRato);

CGContextSaveGState (context);

CGContextConcatCTM (context, m);

CGContextClipToRect (context,CGPDFPageGetBoxRect (page, box));

CGContextDrawPDFPage (context, page);

CGContextRestoreGState (context);

}

創(chuàng)建PDF文件

使用Quartz創(chuàng)建PDF與繪制其它圖形上下文一下簡單歉提。我們指定一個(gè)PDF文件地址区转,設(shè)置一個(gè)PDF圖形上下文废离,并使用與其它圖形上下文一樣的繪制程序。如代碼清單13-4所示的MyCreatePDFFile函數(shù)蔬顾,顯示了創(chuàng)建一個(gè)PDF的所有工作湘捎。

注意,代碼在CGPDFContextBeginPage和CGPDFContextEndPage中來繪制PDF舷胜。我們可以傳遞一個(gè)CFDictionary對象來指定頁屬性活翩,包括media, crop, bleed,trim和art boxes材泄。

Listing 13-4 Creating a PDF file

void MyCreatePDFFile(CGRect pageRect,const char *filename)

{

CGContextRef pdfContext;

CFStringRef path;

CFURLRef url;

CFDataRef 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("My PDF File"));

CFDictionarySetValue(myDictionary, kCGPDFContextCreator, CFSTR("My Name"));

pdfContext = CGPDFContextCreateWithURL (url, &pageRect, myDictionary);

CFRelease(myDictionary);

CFRelease(url);

pageDictionary = CFDictionaryCreateMutable(NULL,0,

&kCFTypeDictionaryKeyCallBacks,

&kCFTypeDictionaryValueCallBacks);

boxData = CFDataCreate(NULL,(constUInt8 *)&pageRect,sizeof(CGRect));

CFDictionarySetValue(pageDictionary, kCGPDFContextMediaBox, boxData);

CGPDFContextBeginPage (pdfContext, pageDictionary);

myDrawContent (pdfContext);

CGPDFContextEndPage (pdfContext);

CGContextRelease (pdfContext);

CFRelease(pageDictionary);

CFRelease(boxData);

}

添加鏈接

我們可以在PDF上下文中添加鏈接和錨點(diǎn)拉宗。Quartz提供了三個(gè)函數(shù),每個(gè)函數(shù)都以PDF圖形上下文作為參數(shù)旦事,還有鏈接的信息:

CGPDFContextSetURLForRect可以讓我們指定在點(diǎn)擊當(dāng)前PDF頁中的矩形時(shí)打開一個(gè)URL姐浮。

CGPDFContextSetDestinationForRect指定在點(diǎn)擊當(dāng)前PDF頁中的矩形區(qū)域時(shí)設(shè)置目標(biāo)以進(jìn)行跳轉(zhuǎn)。我們需要提供一個(gè)目標(biāo)名肾扰。

CGPDFContextAddDestinationAtPoint指定在點(diǎn)擊當(dāng)前PDF頁中的一個(gè)點(diǎn)時(shí)設(shè)置目標(biāo)以進(jìn)行跳轉(zhuǎn)扫尖。我們需要提供一個(gè)目標(biāo)名。

保護(hù)PDF內(nèi)容

為了保護(hù)PDF內(nèi)容甩恼,我們可以在輔助字典中指定一些安全選項(xiàng)并傳遞給CGPDFContextCreate条摸。我們可以通過包含如下關(guān)鍵字來設(shè)置所有者密碼铸屉、用戶密碼、PDF是否可以被打印或拷貝:

kCGPDFContextOwnerPassword: 定義PDF文檔的所有者密碼彻坛。如果指定該值顷啼,則文檔使用所有者密碼來加密踏枣;否則文檔不加密。該關(guān)鍵字的值必須是ASCII編碼的CFString對象钙蒙。只有前32位是用于密碼的茵瀑。該值沒有默認(rèn)值。如果該值不能表示成ASCII躬厌,則無法創(chuàng)建文檔并返回NULL马昨。Quartz使用40-bit加密。

kCGPDFContextUserPassword: 定義PDF文檔的用戶密碼扛施。如果文檔加密了鸿捧,則該值是文檔的用戶密碼疙渣。如果沒有指定匙奴,則用戶密碼為空。該關(guān)鍵字的值必須是ASCII編碼的CFString對象妄荔。只有前32位是用于密碼的饥脑。如果該值不能表示成ASCII,則無法創(chuàng)建文檔并返回NULL懦冰。

kCGPDFContextAllowsPrinting:指定當(dāng)使用用戶密碼鎖定時(shí)文檔是否可以打印灶轰。該值必須是CFBoolean對象。默認(rèn)值是kCGBooleanTrue刷钢。

kCGPDFContextAllowsCopying: 指定當(dāng)使用用戶密碼鎖定時(shí)文檔是否可以拷貝笋颤。該值必須是CFBoolean對象。默認(rèn)值是kCGBooleanTrue内地。

代碼清單14-4(下一章)顯示了確認(rèn)PDF文檔是否被鎖定伴澄,及用密碼打開文檔。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末阱缓,一起剝皮案震驚了整個(gè)濱河市非凌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌荆针,老刑警劉巖敞嗡,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異航背,居然都是意外死亡喉悴,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門玖媚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來箕肃,“玉大人,你說我怎么就攤上這事今魔∩紫瘢” “怎么了障贸?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吟宦。 經(jīng)常有香客問我惹想,道長,這世上最難降的妖魔是什么督函? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮激挪,結(jié)果婚禮上辰狡,老公的妹妹穿的比我還像新娘。我一直安慰自己垄分,他們只是感情好宛篇,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著薄湿,像睡著了一般叫倍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上豺瘤,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天吆倦,我揣著相機(jī)與錄音,去河邊找鬼坐求。 笑死蚕泽,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的桥嗤。 我是一名探鬼主播须妻,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼泛领!你這毒婦竟也來了荒吏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤渊鞋,失蹤者是張志新(化名)和其女友劉穎绰更,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锡宋,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡动知,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了员辩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盒粮。...
    茶點(diǎn)故事閱讀 38,605評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖奠滑,靈堂內(nèi)的尸體忽然破棺而出丹皱,到底是詐尸還是另有隱情妒穴,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布摊崭,位于F島的核電站讼油,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏呢簸。R本人自食惡果不足惜矮台,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望根时。 院中可真熱鬧瘦赫,春花似錦、人聲如沸蛤迎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽替裆。三九已至校辩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間辆童,已是汗流浹背宜咒。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留把鉴,地道東北人荧呐。 一個(gè)月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像纸镊,于是被迫代替她去往敵國和親倍阐。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容