Pythonでborbを使って美しいPDFフライヤーを作成する

PDF(Portable Document Format)は、WYSIWYG(What You See is What You Get)形式ではありません。

プラットフォームに依存せず、基盤となるオペレーティングシステムやレンダリングエンジンに依存しないように開発されました。

これを実現するために、PDFはプログラミング言語のようなもので操作できるように構築されており、結果を得るためには一連の命令と操作に依存することになります。

実際、PDFはスクリプト言語であるPostScriptをベースにしています。

PostScriptは、デバイスに依存しない最初のページ記述言語でした。

このガイドでは、PDF文書の読み取り、操作、生成に特化したPythonライブラリであるborbを使用します。

borbは、低レベルモデル(正確な座標やレイアウトにアクセスできる)と高レベルモデル(余白や位置などの正確な計算をレイアウトマネージャーに委ねることができる)の両方を提供します。

>
> このガイドでは、カスタムグラフィックス(PDFオペレータで表現)を含むフライヤーを生成する方法を紹介します。

borbのインストール

borbはGitHubのソースからダウンロードするか、pip経由でインストールすることができます。

$ pip install borb


これから作るもの

やみくもに作るより、スケッチしてそれに向かっていく方が楽なことが多いので、身近にある紙にフライヤーをスケッチして、その創造力をキャンバスにぶつけてみてください。

今回は、ある会社のある商品を宣伝するために、このようなチラシを作ります。

borb による PDF 文書の作成

borb`でPDFドキュメントを作るには、通常、同じような2、3のステップを踏みます。

  • 空の Document を作成する。
    空の Document を作成する * 空の Page を作成し、 Document に追加する
    空の Page を作成して Document に追加する * PagePageLayout を設定する
  • PageLayout にコンテンツを追加する
  • Document を永続化する

コードでどのように見えるか見てみましょう。

from borb.pdf.document import Document
from borb.pdf.page.page import Page
from borb.pdf.canvas.layout.page_layout.multi_column_layout import SingleColumnLayout
from borb.pdf.canvas.layout.page_layout.page_layout import PageLayout
from borb.pdf.pdf import PDF


def main():
  # Create empty Document
  pdf = Document()


# Create empty Page
  page = Page()


# Add Page to Document
  pdf.append_page(page)


# Create PageLayout
  layout: PageLayout = SingleColumnLayout(page)


# Future content-rendering-code to be inserted here

  # Attempt to store PDF
  with open("output.pdf", "wb") as pdf_file_handle:
      PDF.dumps(pdf_file_handle, pdf)

if __name__ == '__main__':
  main()


borbでPDFフライヤーを作成する方法

さて、空のキャンバスができたので、基本的な内容を追加してみましょう。

まず、「貴社」のようなタイトルを追加します。

# New imports
from borb.pdf.canvas.layout.text.paragraph import Paragraph  
from borb.pdf.canvas.color.color import HexColor  
from decimal import Decimal  

# Contact information
layout.add(
  Paragraph("Your Company", 
            font_color=HexColor("#6d64e8"), 
            font_size=Decimal(20)
    )
)


次に、QRコードと連絡先情報を追加します。

これらのコンテンツを簡単に並べて表示するために、Tableを使用します。

また、QRコードの座標も必要です(後で特別なものを追加する予定です)。

まずはそれを宣言することから始めましょう。

# New imports
from borb.pdf.canvas.layout.image.barcode import Barcode, BarcodeType  
from borb.pdf.canvas.layout.layout_element import LayoutElement

# Code to generate a QR code LayoutElement
qr_code: LayoutElement = Barcode(
    data="https://www.borbpdf.com",
    width=Decimal(64),
    height=Decimal(64),
    type=BarcodeType.QR,
)


これでTableを構築して追加することができます。

 # New imports
from borb.pdf.canvas.layout.table.flexible_column_width_table import FlexibleColumnWidthTable

layout.add(
    FlexibleColumnWidthTable(number_of_columns=2, number_of_rows=1)
    .add(qr_code)
    .add(
        Paragraph(
            """
            500 South Buena Vista Street
            Burbank CA
            91521-0991 USA
            """,
            padding_top=Decimal(12),
            respect_newlines_in_text=True,
            font_color=HexColor("#666666"),
            font_size=Decimal(10),
        )
    )
    .no_borders()
)


このコードを実行して、生成されたPDFがどのように見えるか見てみましょう。

UI/UXの細かい部分を調整するのに最適な方法だと思います。

いい感じですね。

QRコードは会社名のすぐ下にあり、正しい連絡先情報を含み、実際に私たちが提供した連絡先データをエンコードしています。

>
次に、リモート・ゴーイング・アノテーションを追加します。

これは、PDF用語で「PDFの外に出るためのクリック可能なリンク」という意味です。

QRコード全体が、実際に読者を当社のウェブサイトに導くリンクであることを確認するつもりです。

そうすれば、このPDFの印刷版を持っている人は、QRコードをスキャンするだけでいいのです。

デジタル版であれば、QRコードをクリックすればいいのです。

このように、単純な追加機能ですが、ユーザー側のナビゲーションをより快適なものにしています。

page.append_remote_go_to_annotation(
  qr_code.get_bounding_box(), uri="https://www.borbpdf.com"
)


製品情報の追加

次に、チラシを作成する製品に関するタイトルとサブタイトルを追加します。

# Title
layout.add(
    Paragraph(
        "Productbrochure", font_color=HexColor("#283592"), font_size=Decimal(34)
    )
)


# Subtitle
layout.add(
    Paragraph(
        "September 4th, 2021",
        font_color=HexColor("#e01b84"),
        font_size=Decimal(11),
    )
)


同様に、製品概要のタイトルと、ダミーテキストを追加します。

# product overview
layout.add(
    Paragraph(
        "Product Overview", font_color=HexColor("000000"), font_size=Decimal(21)
    )
)


layout.add(
   Paragraph(
        """
        Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. 
        Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean. 
        A small river named Duden flows by their place and supplies it with the necessary regelialia.
        """
    )
)


layout.add(
    Paragraph(
        """
        It is a paradisematic country, in which roasted parts of sentences fly into your mouth. 
        Even the all-powerful Pointing has no control about the blind texts it is an almost unorthographic life. 
        One day however a small line of blind text by the name of Lorem Ipsum decided to leave for the far World of Grammar.
        """,
        margin_bottom=Decimal(12)
    )
)


注:最後の「段落」では、下部の余白を明示的に追加しています。

これは、「パラグラフ」と次のコンテンツ(画像)の間に少し余裕を持たせるための視覚的な微調整に過ぎません。

このコードを実行すると、次のようなものが表示されます。

最後に、製品情報を追加します。

画像と、その商品の特徴を示すリストを並べることができます。

この場合も、テーブル`を使用することで、横に並べたような見た目にすることができます。

多くの場合、特徴のリストの上にタイトルがあるので、2列(画像と特徴)と2行(タイトルと特徴)のTableを用意します。

このテーブルはテーブルとしてではなく、単に横並びの見た目を実現するために使用するので、テーブルにボーダーを追加することはありません。

# New imports
from borb.pdf.canvas.layout.image.image import Image
from borb.pdf.canvas.layout.table.table import TableCell  
from borb.pdf.canvas.layout.table.fixed_column_width_table import FixedColumnWidthTable
from borb.pdf.canvas.layout.list.unordered_list import UnorderedList

# Table with image and key features
layout.add(
    FixedColumnWidthTable(
        number_of_rows=2,
        number_of_columns=2,
        column_widths=[Decimal(0.3), Decimal(0.7)],
    )
    .add(
        TableCell(
            Image(
                  "https://www.att.com/catalog/en/skus/images/apple-iphone%2012-purple-450x350.png",
                width=Decimal(128),
                height=Decimal(128),
            ),
            row_span=2,
        )
    )
    .add(
        Paragraph(
            "Key Features",
            font_color=HexColor("e01b84"),
            font="Helvetica-Bold",
            padding_bottom=Decimal(10),
        )
    )
    .add(
        UnorderedList()
        .add(Paragraph("Nam aliquet ex eget felis lobortis aliquet sit amet ut risus."))
        .add(Paragraph("Maecenas sit amet odio ut erat tincidunt consectetur accumsan ut nunc."))
        .add(Paragraph("Phasellus eget magna et justo malesuada fringilla."))
        .add(Paragraph("Maecenas vitae dui ac nisi aliquam malesuada in consequat sapien."))
    )
    .no_borders()
)


また、Tableのいくつかのセルにpadding_bottomを追加して、余分なスペースを確保しています。

出来上がったPDFはほぼ完成です。

残る最後のステップは、右上隅のアートワークとフッターを追加することです。

borbでShapeオブジェクトを使う

borbは任意のShapePageにレンダリングすることができます。

Shapeは任意の点列(typing.Tuple[Decimal, Decimal]`として表されます)を表し、これらはすべて連続した線を形成します。

これは、作成したい図形をかなり創造的にすることができることを意味します。

まずは、ページの右上にある三角形と四角形をレンダリングするメソッドを定義することから始めましょう。

# New imports
from borb.pdf.canvas.geometry.rectangle import Rectangle
from borb.pdf.canvas.layout.image.shape import Shape
from borb.pdf.page.page_size import PageSize
import typing
import random


def add_gray_artwork_upper_right_corner(page: Page) -> None:
  """
  This method will add a gray artwork of squares and triangles in the upper right corner
  of the given Page
  """
    grays: typing.List[HexColor] = [
        HexColor("A9A9A9"),
        HexColor("D3D3D3"),
        HexColor("DCDCDC"),
        HexColor("E0E0E0"),
        HexColor("E8E8E8"),
        HexColor("F0F0F0"),
    ]
    ps: typing.Tuple[Decimal, Decimal] = PageSize.A4_PORTRAIT.value
    N: int = 4
    M: Decimal = Decimal(32)

    # Draw triangles
    for i in range(0, N):
        x: Decimal = ps[0] - N * M + i * M
        y: Decimal = ps[1] - (i + 1) * M
        rg: HexColor = random.choice(grays)
        Shape(
            points=[(x + M, y), (x + M, y + M), (x, y + M)],
            stroke_color=rg,
            fill_color=rg,
        ).layout(page, Rectangle(x, y, M, M))

    # Draw squares
    for i in range(0, N - 1):
        for j in range(0, N - 1):
            if j > i:
                continue
            x: Decimal = ps[0] - (N - 1) * M + i * M
            y: Decimal = ps[1] - (j + 1) * M
            rg: HexColor = random.choice(grays)
            Shape(
                points=[(x, y), (x + M, y), (x + M, y + M), (x, y + M)],
                stroke_color=rg,
                fill_color=rg,
            ).layout(page, Rectangle(x, y, M, M))


このメソッドをmainメソッドで呼び出すことで、PDFをより華やかにすることができます。

同様に、ページの下部にもいくつかのグラフィックを追加することができます。

  • フッターをページのメインコンテンツから分離するための線
  • ページ上部の幾何学的なグラフィックとバランスをとるための小さな幾何学的要素

これらすべてを行うための別のメソッドを書いてみましょう。

from borb.pdf.canvas.line_art.line_art_factory import LineArtFactory


def add_colored_artwork_bottom_right_corner(page: Page) -> None:
  """
  This method will add a blue/purple artwork of lines 
  and squares to the bottom right corner
  of the given Page
  """
    ps: typing.Tuple[Decimal, Decimal] = PageSize.A4_PORTRAIT.value

    # Square
    Shape(
      points=[
          (ps[0] - 32, 40),
          (ps[0], 40),
          (ps[0], 40 + 32),
          (ps[0] - 32, 40 + 32),
      ],
      stroke_color=HexColor("d53067"),
      fill_color=HexColor("d53067"),
    ).layout(page, Rectangle(ps[0] - 32, 40, 32, 32))

    # Square
    Shape(
      points=[
          (ps[0] - 64, 40),
          (ps[0] - 32, 40),
          (ps[0] - 32, 40 + 32),
          (ps[0] - 64, 40 + 32),
      ],
      stroke_color=HexColor("eb3f79"),
      fill_color=HexColor("eb3f79"),
    ).layout(page, Rectangle(ps[0] - 64, 40, 32, 32))

    # Triangle
    Shape(
      points=[
          (ps[0] - 96, 40),
          (ps[0] - 64, 40),
          (ps[0] - 64, 40 + 32),
      ],
      stroke_color=HexColor("e01b84"),
      fill_color=HexColor("e01b84"),
    ).layout(page, Rectangle(ps[0] - 96, 40, 32, 32))

    # Line
    r: Rectangle = Rectangle(Decimal(0), Decimal(32), ps[0], Decimal(8))
    Shape(
      points=LineArtFactory.rectangle(r),
      stroke_color=HexColor("283592"),
      fill_color=HexColor("283592"),
    ).layout(page, r)


ここでも、mainメソッドからこのメソッドを呼び出すことができます。

結果として、ページはこのようになります。

結論

このガイドでは、borbを使ったPDFドキュメントの基本的な構成要素をいくつか見てきました。

パディングとマージン、そしてフォントサイズとフォントカラーを設定しました。

また、Shapeオブジェクトを使用してグラフィックを生成し、クリック可能なQRコードも作りました。

これらの構成要素を用いて、架空の会社の架空の製品のチラシを作成し、インタラクティブな PDF 文書の作成プロセスを自動化しました。

タイトルとURLをコピーしました