PDF 文書の作成、表示、および変換


PDF 文書は、コンパクトなプログラミング言語で書かれた一連のコマンドとして、解像度に依存しないベクトルグラフィックス、テキスト、およびイメージを格納します。PDF 文書には複数ページのイメージとテキストを含めることができます。PDF は、クロスプラットフォーム、読み取り専用文書の作成、および解像度に依存しないグラフィックスの描画に役立ちます。


Quartz は、すべてのアプリケーションに対して、図 13-1 に示したように、アプリケーションの描画操作を保存する高品質な PDF ドキュメントを作成します。結果として得られる PDF は、システムの他の部分やサードパーティ製の製品によって、特定の用途(特定のプリンタや Web 用など) に最適化されます。Quartz で生成された PDF 文書は、プレビューと Acrobat で正しく表示されます。


Quartz は PDF を"デジタルペーパー" として使用するだけでなく、API の一部として、PDF ファイルを表示および生成したり、他の多くの PDF 関連のタスクを実行するために使用できるさまざまな機能を備えています。


PDF 言語と構文を含む PDF の詳細については、PDF リファレンス、第 4 版、バージョン 1.5 を参照してください。


PDF を開いて表示


Quartz は、PDF 文書を表す CGPDFDocumentRef データ型を提供します。CGPDFDocumentCreateWithProvider 関数または CGPDFDocumentCreateWithURL 関数を使用して CGPDFDocument オブジェクトを作成します。CGPDFDocument オブジェクトを作成した後、グラフィックスコンテキストに描画できます。図 13-2 に、ウィンドウ内に表示された PDF 文書を示します。


リスト 13-1 に、CGPDFDocument オブジェクトを作成し、文書内のページ数を取得する方法を示します。番号付きコード行の詳細な説明は、リストの後に示します。


リスト 13-1 PDF ファイルから CGPDFDocument オブジェクトを作成


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 関数を呼び出して、表示する PDF ファイルのファイル名を表す CFString オブジェクトから CFURL オブジェクトを作成します。
  2. CFURL オブジェクトから CGPDFDocument オブジェクトを作成します。
  3. コード内の次のステートメントが文書に少なくとも 1 ページあることを保証できるように、PDF 内のページ数を取得します。

リスト 13-2 のコードを見ると、PDF ページをグラフィックスコンテキストに描画する方法を見ることができます。番号付きコード行の詳細な説明は、リストの後に示します。


リスト 13-2 PDF ページの描画


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. 指定したファイル名から CGPDFDocument オブジェクトを作成するために関数を呼び出します(リスト 13-1 を参照)。
  2. 指定されたページ番号のページを PDF 文書から取得します。
  3. CGContextDrawPDFPage 関数を呼び出すことによって、PDF ファイルから指定されたページを描画します。グラフィックスコンテキストと描画するページを指定する必要があります。
  4. CGPDFDocument オブジェクトを解放します。

PDF ページの変換を作成する


Quartz は、CGPDFPageGetDrawingTransform という関数を提供します。これは、PDF ページ内のボックスをあなたが指定した長方形にマッピングすることによって、アフィン変換を作成します。この関数のプロトタイプは以下のとおりです:


CGAffineTransform CGPDFPageGetDrawingTransform (
        CGPPageRef page,
        CGPDFBox box,
        CGRect rect,
        int rotate,
        bool preserveAspectRatio
);


この関数は、以下のアルゴリズムを使用してアフィン変換を返します。


たとえば、図 13-3 に示したような PDF 表示アプリケーションを書いている場合は、この関数を使用できます。左回転/右回転 機能を提供する場合は、CGPDFPageGetDrawingTransform を呼び出して、現在のウィンドウサイズと回転設定の適切な変換を計算することができます。


リスト 13-3 は、関数に渡されたパラメーターを使用して PDF ページのアフィン変換を作成し、変換を適用してから PDF ページを描画する関数を示しています。番号付きコード行の詳細な説明は、リストの後に示します。


リスト 13-3   PDF ページ用のアフィン変換を作成


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 関数は、指定した定数(kCGPDFMediaBox、kCGPDFCropBox、kCGPDFBleedBox、kCGPDFTrimBox、または kCGPDFArtBox) に関連したページ境界ボックス(media, crop, bleed, trim, and art boxes) を取得します。
  5. PDF ページを、変換され、クリップされたコンテキストに描画します。
  6. グラフィックス状態を復元します。

PDF ファイルの作成


Quartz 2D を使用して PDF ファイルを作成するのは、グラフィックスコンテキストに描画するのと同じくらい簡単です。PDF ファイルの位置を指定し、PDF グラフィックスコンテキストを設定し、任意のグラフィックスコンテキストに使用したのと同じ描画ルーチンを使用します。リスト 13-4 に示した MyCreatePDFFile 関数は、コードが PDF ファイルを作成するために実行するすべてのタスクを示しています。各番号付きコード行の詳細な説明は、リストの後に示します。


このコードは、CGPDFContextBeginPageCGPDFContextEndPage 関数を呼び出して PDF ページを記述していることに注意してください。CFDictionary オブジェクトを渡すと、media、 crop、 bleed、 trim、 及び art boxes を含むページプロパティを指定できます。辞書キー定数のリストとそれぞれの詳細な説明については、CGPDFContext リファレンス を参照してください。


リスト 13-4 PDF ファイルの作成


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 オブジェクトを作成します。次の 2 行は、タイトルとクリエーターを追加します。CFDictionarySetValue 関数を使用して、必要な数だけキー値ペアを追加できます。辞書の作成の詳細については、CFDictionary リファレンス を参照してください。
  5. 以下の 3 つのパラメータを渡して、PDF グラフィックスコンテキストを作成します:
    • PDF データの位置を指定する CFURL オブジェクト。
    • PDF ページのデフォルトのサイズと位置を定義する長方形へのポインタ。長方形の原点は、通常(0、0) です。Quartz はこの長方形をページメディアボックスのデフォルトの境界として使用します。NULL を渡すと、Quartz はデフォルトのページサイズを 8.5 x 11 インチ(612 x 792 ポイント) にします。
    • PDF メタデータを含む CFDictionary オブジェクト。追加するメタデータがない場合は NULL を渡します。

      出力インテントオプション-インテントのサブタイプ、条件、条件 ID、レジストリ名、出力先プロファイル、および意図したターゲットデバイスまたは生産条件に関する追加情報またはコメントを含む人間が判読可能なテキスト文字列を指定するには、CFDictionary オブジェクトを使用します。出力インテントオプションの詳細については、CGPDFContext リファレンス を参照してください。

  6. PDF ページのページボックスを保持する CFDictionary オブジェクトを作成します。この例では、メディアボックスを設定します。
  7. ページの開始を知らせます。複数のページ(PDF など) をサポートするグラフィックスコンテキストを使用する場合は、CGPDFContextBeginPageCGPDFContextEndPage とともに呼び出して、出力内のページ境界を区切ります。各ページは、CGPDFContextBeginPageCGPDFContextEndPage の呼び出しで囲まなければなりません。Quartz は、ページベースのコンテキストのページ境界外で実行されるすべての描画操作を無視します。
  8. アプリケーション定義の関数を呼び出して、PDF コンテキストにコンテンツを描画します。ここで描画ルーチンを提供します。
  9. ページベースのグラフィックスコンテキストでページの終わりを通知します。
  10. PDF コンテキストを解放します。
  11. ページ辞書を解放します。

リンクの追加


作成した PDF コンテキストにリンクやアンカーを追加できます。Quartz は 3 つの関数を提供し、それぞれの関数は、PDF グラフィックスコンテキストをパラメータとしてリンクに関する情報と共に取ります。


PDF コンテンツの保護


PDF コンテンツを保護するために、CGPDFContextCreate 関数に渡す補助辞書に指定できるセキュリティのオプションがいくつかあります。補助辞書に以下のキーを含めることで、所有者のパスワード、ユーザーのパスワード、PDF が印刷可か、またはコピー可かを設定できます。


リスト 14-4 (次の章) は、PDF 文書がロックされているかどうかを確認するコードを示しており、ロックされている場合は、パスワードで文書を開こうとします。



前の章 次の章



目次
Xcode 10 の新機能

  • 前書き
  • 誰がこの文書を読むべきか?
    この文書の構成
  • Quartz 2D の概要
  • ページ
    描画先:グラフィックスコンテキスト
    Quartz 2D 不透明(Opaque) データ型
    グラフィックス状態
    Quartz 2D 座標系
    メモリー管理:オブジェクトの所有権
  • グラフィックスコンテキスト
  • iOS のビューグラフィックスコンテキストに描画する
    Mac OS X でのウィンドウグラフィックスコンテキストの作成
    PDF グラフィックスコンテキストの作成
  • ビットマップグラフィックスコンテキストの作成
  • サポートされるピクセル形式
    アンチエイリアス
    印刷用のグラフィックスコンテキストの取得
  • パス
  • パスの作成とパスの描画
  • ビルディングブロック
  • パスの作成
  • パスのペイント (Painting a Path)
  • ブレンドモードの設定
  • パスをクリップする
  • 色と色空間
  • 色と色空間について
    アルファ値
    色空間の作成
    色の設定と作成
    レンダリングインテントの設定
  • 変換
  • Quartz 変換関数について
    現在の変換配列の変更
    アフィン変換の作成
    アフィン変換の評価
    ユーザをデバイス空間変換に導く
    配列の背後の数学
  • パターン
  • パターンの構造
    色付きパターンとステンシル(無色の) パターン
    タイル張り
    パターンの仕組み
  • 色付きパターンのペイント
  • ステンシルパターンのペイント
  • 陰影
  • 陰影の仕組み
    コンテキストに基づいて変化する陰影描画規則
    陰影を用いたペイント
  • グラデーション
  • 軸方向および放射状グラデーションの例
    CGShading と CGGradient オブジェクトの比較
    グラデーションの端を超えて色を拡張
    CGGradient オブジェクトの使用
  • CGShading オブジェクトの使用
  • CGShading オブジェクトを使用して軸方向のグラデーションをペイント
  • CGShading オブジェクトを使用して放射状グラデーションをペイント
  • 以下も見よ
  • 透過レイヤー
  • 透過レイヤーの仕組み
    透過レイヤーへのペイント
  • Quartz 2D でのデータ管理
  • Quartz 2D へのデータの移動
    Quartz 2D からのデータの移動
    Mac OS X で Quartz 2D と Core Image 間でデータを移動
  • ビットマップイメージとイメージマスク
  • ビットマップイメージとイメージマスクについて
    ビットマップイメージ情報
  • イメージの作成
  • イメージマスクの作成
  • イメージをマスクする
  • イメージにブレンドモードを使用
  • Core Graphics のレイヤー描画
  • レイヤー描画のしくみ
  • レイヤーを使った描画
  • 複数の CGLayer オブジェクトを使用して旗を描画する例
  • PDF 文書の作成、表示、および変換
  • PDF を開いて表示
    PDF ページの変換を作成する
    PDF ファイルの作成
    リンクの追加
    PDF コンテンツの保護
  • PDF 文書の解析
  • PDF 文書の構造の検査
  • PDF コンテンツの解析
  • PostScript 変換
  • 呼び出し関数を書く
    呼び出し関数構造体を埋める
    PostScript 変換オブジェクトの作成
    データプロバイダおよびデータコンシューマオブジェクトの作成
    変換の実行
    テキスト
    用語集
    文書改訂履歴












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)












    トップ(Quartz 2D プログラミングガイド)