def test_document(self, file):

        # create output directory if it does not exist yet
        if not self.output_dir.exists():
            self.output_dir.mkdir()

        # determine output location
        out_file = self.output_dir / (file.stem + "_out.pdf")

        # attempt to read PDF
        doc = None
        with open(file, "rb") as in_file_handle:
            print("\treading (1) ..")
            doc = PDF.loads(in_file_handle)

        # add annotation
        doc.get_page(0).append_square_annotation(
            rectangle=Rectangle(Decimal(128), Decimal(128), Decimal(64), Decimal(64)),
            stroke_color=HexColor("#F75C03"),
            fill_color=HexColor("#04A777"),
        )

        # attempt to store PDF
        with open(out_file, "wb") as out_file_handle:
            print("\twriting ..")
            PDF.dumps(out_file_handle, doc)

        # attempt to re-open PDF
        with open(out_file, "rb") as in_file_handle:
            print("\treading (2) ..")
            doc = PDF.loads(in_file_handle)

        return True
示例#2
0
 def _build_billing_and_shipping_information(self) -> LayoutElement:
     table_001: Table = Table(number_of_rows=6, number_of_columns=2)
     table_001.add(
         Paragraph(
             "BILL TO",
             background_color=HexColor("016934"),
             font_color=X11Color("White"),
         ))
     table_001.add(
         Paragraph(
             "SHIP TO",
             background_color=HexColor("016934"),
             font_color=X11Color("White"),
         ))
     table_001.add(Paragraph("[Recipient Name]"))  # BILLING
     table_001.add(Paragraph("[Recipient Name]"))  # SHIPPING
     table_001.add(Paragraph("[Company Name]"))  # BILLING
     table_001.add(Paragraph("[Company Name]"))  # SHIPPING
     table_001.add(Paragraph("[Street Address]"))  # BILLING
     table_001.add(Paragraph("[Street Address]"))  # SHIPPING
     table_001.add(Paragraph("[City, State, ZIP Code]"))  # BILLING
     table_001.add(Paragraph("[City, State, ZIP Code]"))  # SHIPPING
     table_001.add(Paragraph("[Phone]"))  # BILLING
     table_001.add(Paragraph("[Phone]"))  # SHIPPING
     table_001.set_padding_on_all_cells(Decimal(2), Decimal(2), Decimal(2),
                                        Decimal(2))
     table_001.no_borders()
     return table_001
示例#3
0
    def test_add_redact_annotation(self):

        # create output directory if it does not exist yet
        if not self.output_file.parent.exists():
            self.output_file.parent.mkdir()

        # attempt to read PDF
        doc = None
        with open(self.input_file, "rb") as in_file_handle:
            print("\treading (1) ..")
            doc = PDF.loads(in_file_handle)

        # add annotation
        doc.get_page(0).append_redact_annotation(
            fill_color=HexColor("8DE969"),
            stroke_color=HexColor("CBEF43"),
            line_width=Decimal(1),
            rectangle=Rectangle(Decimal(72.86), Decimal(486.82), Decimal(129),
                                Decimal(13)),
        )

        # attempt to store PDF
        with open(self.output_file, "wb") as out_file_handle:
            print("\twriting ..")
            PDF.dumps(out_file_handle, doc)

        # attempt to re-open PDF
        with open(self.output_file, "rb") as in_file_handle:
            print("\treading (2) ..")
            doc = PDF.loads(in_file_handle)

        return True
    def _test_document(self, file):

        # create output directory if it does not exist yet
        if not self.output_dir.exists():
            self.output_dir.mkdir()

        # determine output location
        out_file = self.output_dir / (file.stem + "_out.pdf")

        # attempt to read PDF
        doc = None
        with open(file, "rb") as in_file_handle:
            print("\treading (1) ..")
            doc = PDF.loads(in_file_handle)

        # determine free space
        space_finder = FreeSpaceFinder(doc.get_page(0))

        # debug purposes
        if self.in_debug:
            for i in range(0, len(space_finder.grid)):
                for j in range(0, len(space_finder.grid[i])):
                    if space_finder.grid[i][j]:
                        continue
                    w = Decimal(space_finder.grid_resolution)
                    x = Decimal(i) * w
                    y = Decimal(j) * w
                    doc.get_page(0).append_square_annotation(
                        Rectangle(x, y, w, w), stroke_color=X11Color("Salmon"))

        # add annotation
        w, h = doc.get_page(0).get_page_info().get_size()
        free_rect = space_finder.find_free_space(
            Rectangle(
                Decimal(w / Decimal(2)),
                Decimal(h * Decimal(2)),
                Decimal(64),
                Decimal(64),
            ))
        if free_rect is not None:
            doc.get_page(0).append_square_annotation(
                rectangle=free_rect,
                stroke_color=HexColor("#F75C03"),
                fill_color=HexColor("#04A777"),
            )

        # attempt to store PDF
        with open(out_file, "wb") as out_file_handle:
            print("\twriting ..")
            PDF.dumps(out_file_handle, doc)

        # attempt to re-open PDF
        with open(out_file, "rb") as in_file_handle:
            print("\treading (2) ..")
            doc = PDF.loads(in_file_handle)

        return True
    def test_write_document(self):

        # create output directory if it does not exist yet
        if not self.output_dir.exists():
            self.output_dir.mkdir()

        # create document
        pdf = Document()

        # add page
        page = Page()
        pdf.append_page(page)

        # generate maze
        m = Maze(20, 20)

        # add
        layout = SingleColumnLayout(page)

        # add title
        layout.add(
            Paragraph(
                "Square Maze",
                font_size=Decimal(20),
                font_color=HexColor("274029"),
            ))

        # add subtitle
        layout.add(
            Paragraph(
                """
                Can you solve this maze? 
                Try going from (lower) left to (upper) right.
                Good luck
                """,
                respect_newlines_in_text=True,
            ))

        # add maze
        layout.add(
            DisjointShape(
                m.get_walls(Decimal(10)),
                stroke_color=HexColor("315C2B"),
                line_width=Decimal(1),
                horizontal_alignment=Alignment.CENTERED,
                vertical_alignment=Alignment.MIDDLE,
            ))

        # determine output location
        out_file = self.output_dir / "output.pdf"

        # attempt to store PDF
        with open(out_file, "wb") as in_file_handle:
            PDF.dumps(in_file_handle, pdf)
    def test_write_document(self):

        # create output directory if it does not exist yet
        if not self.output_dir.exists():
            self.output_dir.mkdir()

        # create empty document
        pdf: Document = Document()

        # create empty page
        page: Page = Page()

        # add page to document
        pdf.append_page(page)

        # set layout
        layout = SingleColumnLayout(page)

        # add barcode
        layout.add(
            Barcode(
                data="123456789128",
                type=BarcodeType.CODE_128,
                width=Decimal(128),
                stroke_color=HexColor("#080708"),
            ))

        # write
        file = self.output_dir / "output.pdf"
        with open(file, "wb") as pdf_file_handle:
            PDF.dumps(pdf_file_handle, pdf)

        return True
    def _write_maze_page(self, pdf: Document, maze_url: str, title_color: str):

        # add page
        page = Page()
        pdf.append_page(page)

        # generate maze
        m = SilhouetteMaze(maze_url)

        # add
        layout = SingleColumnLayout(page)

        # add title
        layout.add(
            Paragraph(
                "MAZE NR %d" % (page.get_page_info().get_page_number() + 1),
                font="TimesRoman",
                font_size=Decimal(20),
                font_color=HexColor(title_color),
            )
        )

        # add subtitle
        layout.add(
            Paragraph(
                """
                Can you solve this maze? 
                Try going from (lower) left to (upper) right.
                Good luck
                """,
                respect_newlines_in_text=True,
                font_color=X11Color("SlateGray"),
                font_size=Decimal(8),
            )
        )

        # add maze
        layout.add(
            DisjointShape(
                m.get_walls(Decimal(10)),
                stroke_color=HexColor(title_color),
                line_width=Decimal(1),
                horizontal_alignment=Alignment.CENTERED,
                vertical_alignment=Alignment.MIDDLE,
            )
        )
示例#8
0
    def test_document(self, file):

        # create output directory if it does not exist yet
        if not self.output_dir.exists():
            self.output_dir.mkdir()

        # determine output location
        out_file = self.output_dir / (file.stem + "_out.pdf")

        # attempt to read PDF
        doc = None
        with open(file, "rb") as in_file_handle:
            print("\treading (1) ..")
            doc = PDF.loads(in_file_handle)

        # determine free space
        space_finder = FreeSpaceFinder(doc.get_page(0))

        # add annotation
        w, h = doc.get_page(0).get_page_info().get_size()
        free_rect = space_finder.find_free_space(
            Rectangle(
                Decimal(w / Decimal(2)),
                Decimal(h * Decimal(0.1)),
                Decimal(64),
                Decimal(64),
            ))
        if free_rect is not None:
            doc.get_page(0).append_square_annotation(
                rectangle=free_rect,
                stroke_color=HexColor("#F75C03"),
                fill_color=HexColor("#04A777"),
            )

        # attempt to store PDF
        with open(out_file, "wb") as out_file_handle:
            print("\twriting ..")
            PDF.dumps(out_file_handle, doc)

        # attempt to re-open PDF
        with open(out_file, "rb") as in_file_handle:
            print("\treading (2) ..")
            doc = PDF.loads(in_file_handle)

        return True
    def test_write_document(self):

        # create output directory if it does not exist yet
        if not self.output_dir.exists():
            self.output_dir.mkdir()

        # create document
        pdf = Document()

        # add page
        page = Page()
        pdf.append_page(page)

        layout = MultiColumnLayout(page, number_of_columns=2)
        layout.add(
            Paragraph(
                "The Raven",
                font_size=Decimal(20),
                font="Helvetica-Oblique",
                font_color=HexColor("708090"),
            ))

        layout.add(
            Paragraph(
                """Once upon a midnight dreary, while I pondered, weak and weary,
                                Over many a quaint and curious volume of forgotten lore-
                                While I nodded, nearly napping, suddenly there came a tapping,
                                As of some one gently rapping, rapping at my chamber door.
                                'Tis some visitor,' I muttered, 'tapping at my chamber door-
                                Only this and nothing more.'""",
                text_alignment=Alignment.CENTERED,
                font_size=Decimal(7),
                respect_newlines_in_text=True,
            ))

        # determine output location
        out_file = self.output_dir / "output.pdf"

        # attempt to store PDF
        with open(out_file, "wb") as in_file_handle:
            PDF.dumps(in_file_handle, pdf)
class TestWrite100Stars(unittest.TestCase):

    # fmt: off
    FIRST_100_STARS = [
        20948,      5761024,    6199849,    8897084,
        47014666,   30162978,   10934533,   14305330,
        28833521,   5593615,    6127739,    13665922,
        60891163,   40811120,   10265290,   25692082,
        38732059,   5165674,    9326700,    48793,
        47523691,   10300119,   1183729,    490222,
        38828319,   24482368,   445009,     10413016,
        28388427,   47697490,   26275724,   37651007,
        8905490,    355741,     5402068,    475578,
        35009,      12762442,   14140949,   65553994,
        12473742,   3680439,    43379688,   46769667,
        20150305,   32988819,   5372986,    66494041,
        2539015,    26300897,   2404461,    63579762,
        13872653,   60277705,   40031739,   175326,
        16610457,   214730,     33699775,   7403557,
        6440095,    19918901,   486331,     10211078,
        514888,     30214233,   5984934,    7837996,
        8367836,    10608766,   1114782,    8345813,
        1777629,    1889128,    20630069,   1728439,
        61306130,   2513172,    8989002,    11238,
        5347861,    1243475,    45919695,   236498,
        6311257,    6007526,    12981947,   887095,
        735802,     21070545,   6441339,    133845,
        4735784,    10510126,   769982,     20380,
        69243978,   12139796,   612826,     8690255,
    ]
    # fmt: on

    ACCENT_COLOR_1 = HexColor("F79F79")
    ACCENT_COLOR_2 = HexColor("F7D08A")
    ACCENT_COLOR_3 = HexColor("E3F09B")
    ACCENT_COLOR_4 = HexColor("87B6A7")
    ACCENT_COLOR_5 = HexColor("5B5941")

    def __init__(self, methodName="runTest"):
        super().__init__(methodName)
        self.output_dir = Path(get_output_dir(), "test-write-100-stars")

    def _write_background(self, page: Page):
        layout = SingleColumnLayout(page)
        t = Table(number_of_columns=10, number_of_rows=25)
        for i in range(0, 25):
            for j in range(0, 10):
                put_star = random.choice([x <= 3 for x in range(0, 10)])
                if i < 11 and j >= 5:
                    t.add(Paragraph(" ", respect_spaces_in_text=True))
                    continue
                if put_star:
                    c = random.choice(
                        [
                            self.ACCENT_COLOR_1,
                            self.ACCENT_COLOR_2,
                            self.ACCENT_COLOR_3,
                            self.ACCENT_COLOR_4,
                            self.ACCENT_COLOR_5,
                        ]
                    )
                    t.add(
                        Shape(
                            LineArtFactory.n_pointed_star(
                                bounding_box=Rectangle(
                                    Decimal(0), Decimal(0), Decimal(16), Decimal(16)
                                ),
                                n=random.choice([3, 5, 7, 12]),
                            ),
                            fill_color=c,
                            stroke_color=c,
                            line_width=Decimal(1),
                        )
                    )
                else:
                    t.add(Paragraph(" ", respect_spaces_in_text=True))
        t.no_borders()
        t.set_padding_on_all_cells(Decimal(5), Decimal(5), Decimal(5), Decimal(5))
        layout.add(t)

    def test_write_document(self):

        # create output directory if it does not exist yet
        if not self.output_dir.exists():
            self.output_dir.mkdir()

        # create document
        pdf = Document()

        # add page
        page = Page()
        pdf.append_page(page)

        layout = MultiColumnLayout(page)

        # background
        self._write_background(page)

        # table
        avatar_urls = [
            "https://avatars.githubusercontent.com/u/" + str(x)
            for x in self.FIRST_100_STARS
        ]
        t = Table(number_of_columns=4, number_of_rows=25)
        for s in avatar_urls[0 : (4 * 25)]:
            im = PILImage.open(requests.get(s, stream=True).raw)
            t.add(Image(im, width=Decimal(20), height=Decimal(20)))
        t.set_padding_on_all_cells(Decimal(2), Decimal(2), Decimal(2), Decimal(2))
        t.no_borders()
        layout.add(t)

        layout.add(
            Paragraph(
                "100 stars!",
                font="Helvetica-Bold",
                font_size=Decimal(20),
                font_color=self.ACCENT_COLOR_1,
                horizontal_alignment=Alignment.CENTERED,
            )
        )

        # next column
        layout.switch_to_next_column()

        # paragraph
        layout.add(
            Paragraph(
                "Thank you,",
                font="Helvetica-Bold",
                font_size=Decimal(20),
                font_color=self.ACCENT_COLOR_1,
            )
        )
        layout.add(
            Paragraph(
                "Your support and encouragement have always been the driving factors in the development of pText. "
                "I want you to know that I value your appreciation immensely!"
            )
        )
        layout.add(
            Paragraph(
                "-- Joris Schellekens",
                font="Helvetica-Oblique",
                font_size=Decimal(8),
                font_color=self.ACCENT_COLOR_2,
            )
        )

        layout.add(
            Barcode(
                data="https://github.com/jorisschellekens/ptext-release/stargazers",
                type=BarcodeType.QR,
                width=Decimal(128),
                stroke_color=self.ACCENT_COLOR_1,
            )
        )

        # footer
        rectangle_box = Rectangle(
            Decimal(0),
            Decimal(0),
            page.get_page_info().get_width(),
            page.get_page_info().get_height() * Decimal(0.1),
        )
        Shape(
            LineArtFactory.rectangle(rectangle_box),
            fill_color=self.ACCENT_COLOR_1,
            stroke_color=self.ACCENT_COLOR_1,
            line_width=Decimal(1),
        ).layout(page, rectangle_box)

        rectangle_box = Rectangle(
            Decimal(0),
            page.get_page_info().get_height() * Decimal(0.1),
            page.get_page_info().get_width(),
            Decimal(2),
        )
        Shape(
            LineArtFactory.rectangle(rectangle_box),
            fill_color=self.ACCENT_COLOR_2,
            stroke_color=self.ACCENT_COLOR_2,
            line_width=Decimal(1),
        ).layout(page, rectangle_box)

        # determine output location
        out_file = self.output_dir / "output.pdf"

        # attempt to store PDF
        with open(out_file, "wb") as in_file_handle:
            PDF.dumps(in_file_handle, pdf)

        with open(out_file, "rb") as in_file_handle:
            PDF.loads(in_file_handle)
    def test_write_document(self):

        # create output directory if it does not exist yet
        if not self.output_dir.exists():
            self.output_dir.mkdir()

        # create empty document
        pdf: Document = Document()

        # create empty page
        page: Page = Page()

        # add page to document
        pdf.append_page(page)

        # set layout
        layout = SingleColumnLayout(page)

        # add barcode
        layout.add(
            Table(number_of_rows=5,
                  number_of_columns=2).add(Paragraph("CODE 128")).add(
                      Barcode(
                          data="123456789128",
                          type=BarcodeType.CODE_128,
                          width=Decimal(128),
                          stroke_color=HexColor("#080708"),
                      )).add(Paragraph("CODE 39")).add(
                          Barcode(
                              data="123456789128",
                              type=BarcodeType.CODE_39,
                              width=Decimal(128),
                              stroke_color=HexColor("#3772FF"),
                          )).add(Paragraph("EAN 13")).add(
                              Barcode(
                                  data="123456789128",
                                  type=BarcodeType.EAN_13,
                                  width=Decimal(128),
                                  stroke_color=HexColor("#DF2935"),
                              )).add(Paragraph("EAN 14")).add(
                                  Barcode(
                                      data="1234567891280",
                                      type=BarcodeType.EAN_14,
                                      width=Decimal(128),
                                      stroke_color=HexColor("#FDCA40"),
                                  )).add(Paragraph("QR")).add(
                                      Barcode(
                                          data="1234567891280",
                                          type=BarcodeType.QR,
                                          width=Decimal(128),
                                          stroke_color=HexColor("#E6E8E6"),
                                          fill_color=HexColor("#DF2935"),
                                      )).set_padding_on_all_cells(
                                          Decimal(10), Decimal(5), Decimal(5),
                                          Decimal(5)))

        # write
        file = self.output_dir / "output.pdf"
        with open(file, "wb") as pdf_file_handle:
            PDF.dumps(pdf_file_handle, pdf)

        return True
    def test_write_document(self):

        # create output directory if it does not exist yet
        if not self.output_dir.exists():
            self.output_dir.mkdir()

        # create document
        pdf = Document()

        # fmt: off
        mazes = [
            ("https://i.pinimg.com/originals/1e/c2/a7/1ec2a73d0a45016c7d1b52ef9f11e740.png", "395E66"),
            ("https://i.pinimg.com/originals/f8/23/88/f823882e7c5fa42790e78f43ecf7e8bf.jpg", "387D7A"),
            ("https://i.pinimg.com/600x315/2d/94/33/2d94334b737efb5d3a5ef32aef9daefc.jpg", "32936F"),
            ("https://i.pinimg.com/originals/f1/c9/07/f1c907c09d65d5c86fba304fed1009ca.jpg", "26A96C"),
            ("https://cdn.pixabay.com/photo/2017/08/24/12/11/silhouette-2676573_960_720.png", "2BC016"),
            ("https://images-na.ssl-images-amazon.com/images/I/61bqYbAeUgL._AC_SL1500_.jpg", "395E66"),
            ("https://i.pinimg.com/originals/55/e8/91/55e891af7de086a8868e1a8e02fb4426.jpg","387D7A"),
            ("https://cdn.shopify.com/s/files/1/2123/8425/products/166422700-LRG_242a4c8b-cad5-476e-afd1-c8b882d48fc2_530x.jpg","32936F"),
            ("http://www.silhcdn.com/3/i/shapes/lg/7/6/d124067.jpg","26A96C"),
            ("https://cdn.pixabay.com/photo/2018/03/04/23/28/frog-3199601_1280.png","2BC016")
        ]
        # fmt: on

        # add mazes
        for (url, color) in mazes:
            for _ in range(0, 3):
                self._write_maze_page(pdf, url, color)

        # add ack page
        page = Page()
        pdf.append_page(page)
        layout = SingleColumnLayout(page)

        # content of ack page
        layout.add(
            Paragraph(
                "Hi there,",
                font_color=HexColor("32936F"),
                font_size=Decimal(20),
            )
        )
        layout.add(
            Paragraph(
                "This PDF was made by pText. Check out the GitHub repository to find more fun examples of what you can do with PDF's.",
                font_color=X11Color("SlateGray"),
                font_size=Decimal(12),
            )
        )
        layout.add(
            Barcode(
                data="https://github.com/jorisschellekens/ptext-release",
                type=BarcodeType.QR,
                width=Decimal(64),
            )
        )

        # determine output location
        out_file = self.output_dir / "output.pdf"

        # attempt to store PDF
        with open(out_file, "wb") as in_file_handle:
            PDF.dumps(in_file_handle, pdf)
示例#13
0
    def _build_itemized_description_table(self) -> LayoutElement:
        table_001: Table = Table(number_of_rows=15, number_of_columns=4)
        for h in ["DESCRIPTION", "QTY", "UNIT PRICE", "AMOUNT"]:
            table_001.add(
                TableCell(
                    Paragraph(h, font_color=X11Color("White")),
                    background_color=HexColor("016934"),
                ))

        odd_color: Color = HexColor("BBBBBB")
        even_color: Color = HexColor("FFFFFF")
        for row_number, item in enumerate([("Product 1", 2, 50),
                                           ("Product 2", 4, 60),
                                           ("Labor", 14, 60)]):
            c = even_color if row_number % 2 == 0 else odd_color
            table_001.add(TableCell(Paragraph(item[0]), background_color=c))
            table_001.add(
                TableCell(Paragraph(str(item[1])), background_color=c))
            table_001.add(
                TableCell(Paragraph("$ " + str(item[2])), background_color=c))
            table_001.add(
                TableCell(Paragraph("$ " + str(item[1] * item[2])),
                          background_color=c))

        for row_number in range(3, 10):
            c = even_color if row_number % 2 == 0 else odd_color
            for _ in range(0, 4):
                table_001.add(TableCell(Paragraph(" "), background_color=c))

        table_001.add(
            TableCell(
                Paragraph(
                    "Subtotal",
                    font="Helvetica-Bold",
                    horizontal_alignment=Alignment.RIGHT,
                ),
                col_span=3,
            ))
        table_001.add(
            TableCell(
                Paragraph("$ 1,180.00", horizontal_alignment=Alignment.RIGHT)))
        table_001.add(
            TableCell(
                Paragraph(
                    "Discounts",
                    font="Helvetica-Bold",
                    horizontal_alignment=Alignment.RIGHT,
                ),
                col_span=3,
            ))
        table_001.add(
            TableCell(
                Paragraph("$ 177.00", horizontal_alignment=Alignment.RIGHT)))
        table_001.add(
            TableCell(
                Paragraph("Taxes",
                          font="Helvetica-Bold",
                          horizontal_alignment=Alignment.RIGHT),
                col_span=3,
            ))
        table_001.add(
            TableCell(
                Paragraph("$ 100.30", horizontal_alignment=Alignment.RIGHT)))
        table_001.add(
            TableCell(
                Paragraph("Total",
                          font="Helvetica-Bold",
                          horizontal_alignment=Alignment.RIGHT),
                col_span=3,
            ))
        table_001.add(
            TableCell(
                Paragraph("$ 1163.30", horizontal_alignment=Alignment.RIGHT)))
        table_001.set_padding_on_all_cells(Decimal(2), Decimal(2), Decimal(2),
                                           Decimal(2))
        table_001.no_borders()
        return table_001
    def test_write_document(self):

        # create output directory if it does not exist yet
        if not self.output_dir.exists():
            self.output_dir.mkdir()

        # create document
        pdf = Document()

        # add page
        page = Page()
        pdf.append_page(page)

        # first layer, displaying a raven
        layout = SingleColumnLayout(page)
        for _ in range(0, 12):
            layout.add(Paragraph(" ", respect_spaces_in_text=True))
        layout.add(
            Image(
                "https://cdn3.vectorstock.com/i/1000x1000/03/47/black-raven-on-white-background-vector-4780347.jpg"
            ))

        # second layer, displaying the poem
        layout = MultiColumnLayout(page, number_of_columns=2)
        layout.add(
            Paragraph(
                "The Raven",
                font_size=Decimal(20),
                font="Helvetica-Oblique",
                font_color=HexColor("708090"),
            ))
        layout.add(
            Paragraph(
                """Once upon a midnight dreary, while I pondered, weak and weary,
                                Over many a quaint and curious volume of forgotten lore-
                                While I nodded, nearly napping, suddenly there came a tapping,
                                As of some one gently rapping, rapping at my chamber door.
                                'Tis some visitor,' I muttered, 'tapping at my chamber door-
                                Only this and nothing more.'""",
                horizontal_alignment=Alignment.CENTERED,
                font_size=Decimal(7),
                respect_newlines_in_text=True,
            ))
        layout.add(
            Paragraph(
                """Ah, distinctly I remember it was in the bleak December;
                                And each separate dying ember wrought its ghost upon the floor.
                                Eagerly I wished the morrow;-vainly I had sought to borrow
                                From my books surcease of sorrow-sorrow for the lost Lenore-
                                For the rare and radiant maiden whom the angels name Lenore-
                                Nameless here for evermore.""",
                horizontal_alignment=Alignment.CENTERED,
                font_size=Decimal(7),
                respect_newlines_in_text=True,
            ))
        layout.add(
            Paragraph(
                """And the silken, sad, uncertain rustling of each purple curtain
                                Thrilled me-filled me with fantastic terrors never felt before;
                                So that now, to still the beating of my heart, I stood repeating
                                'Tis some visitor entreating entrance at my chamber door-
                                Some late visitor entreating entrance at my chamber door;-
                                This it is and nothing more.'""",
                horizontal_alignment=Alignment.CENTERED,
                font_size=Decimal(7),
                respect_newlines_in_text=True,
            ))
        layout.add(
            Paragraph(
                """Presently my soul grew stronger; hesitating then no longer,
                                'Sir,' said I, 'or Madam, truly your forgiveness I implore;
                                But the fact is I was napping, and so gently you came rapping,
                                And so faintly you came tapping, tapping at my chamber door,
                                That I scarce was sure I heard you'-here I opened wide the door;-
                                Darkness there and nothing more.""",
                horizontal_alignment=Alignment.CENTERED,
                font_size=Decimal(7),
                respect_newlines_in_text=True,
            ))
        layout.switch_to_next_column()
        layout.add(
            Paragraph(
                """Deep into that darkness peering, long I stood there wondering, fearing,
                                Doubting, dreaming dreams no mortal ever dared to dream before;
                                But the silence was unbroken, and the stillness gave no token,
                                And the only word there spoken was the whispered word, 'Lenore?'
                                This I whispered, and an echo murmured back the word, 'Lenore!'-
                                Merely this and nothing more.""",
                horizontal_alignment=Alignment.CENTERED,
                font_size=Decimal(7),
                respect_newlines_in_text=True,
            ))
        layout.add(
            Paragraph(
                """Back into the chamber turning, all my soul within me burning,
                                Soon again I heard a tapping somewhat louder than before.
                                'Surely,' said I, 'surely that is something at my window lattice;
                                Let me see, then, what thereat is, and this mystery explore-
                                Let my heart be still a moment and this mystery explore;-
                                'Tis the wind and nothing more!'""",
                horizontal_alignment=Alignment.CENTERED,
                font_size=Decimal(7),
                respect_newlines_in_text=True,
            ))
        layout.add(
            Paragraph(
                """Open here I flung the shutter, when, with many a flirt and flutter,
                                In there stepped a stately Raven of the saintly days of yore;
                                Not the least obeisance made he; not a minute stopped or stayed he;
                                But, with mien of lord or lady, perched above my chamber door-
                                Perched upon a bust of Pallas just above my chamber door-
                                Perched, and sat, and nothing more.""",
                horizontal_alignment=Alignment.CENTERED,
                font_size=Decimal(7),
                respect_newlines_in_text=True,
            ))
        layout.add(
            Paragraph(
                """Then this ebony bird beguiling my sad fancy into smiling,
                                By the grave and stern decorum of the countenance it wore,
                                'Though thy crest be shorn and shaven, thou,' I said, 'art sure no craven,
                                Ghastly grim and ancient Raven wandering from the Nightly shore-
                                Tell me what thy lordly name is on the Night's Plutonian shore!'
                                Quoth the Raven 'Nevermore.'""",
                horizontal_alignment=Alignment.CENTERED,
                font_size=Decimal(7),
                respect_newlines_in_text=True,
            ))
        layout.add(
            Paragraph(
                """Much I marvelled this ungainly fowl to hear discourse so plainly,
                                Though its answer little meaning-little relevancy bore;
                                For we cannot help agreeing that no living human being
                                Ever yet was blessed with seeing bird above his chamber door-
                                Bird or beast upon the sculptured bust above his chamber door,
                                With such name as 'Nevermore.'""",
                horizontal_alignment=Alignment.CENTERED,
                font_size=Decimal(7),
                respect_newlines_in_text=True,
            ))
        layout.add(
            Paragraph(
                """But the Raven, sitting lonely on the placid bust, spoke only
                    That one word, as if his soul in that one word he did outpour.
                    Nothing farther then he uttered-not a feather then he fluttered-
                    Till I scarcely more than muttered 'Other friends have flown before-
                    On the morrow he will leave me, as my Hopes have flown before.'
                    Then the bird said 'Nevermore.'""",
                horizontal_alignment=Alignment.CENTERED,
                font_size=Decimal(7),
                respect_newlines_in_text=True,
            ))
        # determine output location
        out_file = self.output_dir / "output.pdf"

        # attempt to store PDF
        with open(out_file, "wb") as in_file_handle:
            PDF.dumps(in_file_handle, pdf)

        with open(out_file, "rb") as in_file_handle:
            PDF.loads(in_file_handle)
    def test_hex_to_hsv(self):

        for hex_string in ["ACEB98", "87FF65", "A4C2A8", "5A5A66", "2A2B2E"]:
            c0 = HexColor(hex_string).to_rgb()
            c1 = HSVColor.from_rgb(c0)
            TestColorConversion.assert_hsv_is_rgb(c1, c0)
    def test_write_document(self):

        # create output directory if it does not exist yet
        if not self.output_dir.exists():
            self.output_dir.mkdir()

        # create document
        pdf = Document()

        # add page
        page = Page()
        pdf.append_page(page)

        # path to font
        font_path: Path = Path(__file__).parent / "Jsfont-Regular.ttf"
        assert font_path.exists()

        # layout
        layout: PageLayout = SingleColumnLayout(page)
        layout.add(
            Paragraph(
                "Hello World,",
                font=TrueTypeFont.true_type_font_from_file(font_path),
                font_size=Decimal(40),
                font_color=HexColor("FFCC00"),
            ))

        layout.add(
            Paragraph(
                """
                pText can now write in any custom TTF font. Like this one, which is a stylized copy of my handwriting. 
                Of course, you could also pick a more sensible font. Like Comic Sans, Roboto, Open Sans, and many others.
                In fact, pText can use any TTF font. 
                """,
                font=TrueTypeFont.true_type_font_from_file(font_path),
                font_size=Decimal(20),
                font_color=HexColor("646E78"),
            ))

        layout.add(
            Paragraph(
                """
                Finally, you have the option to match your own custom style and brand.
                For more examples, check out GitHub. Don't forget to star the repo :-)
                """,
                font=TrueTypeFont.true_type_font_from_file(font_path),
                font_size=Decimal(20),
                font_color=HexColor("68C3D4"),
            ))

        layout.add(
            Barcode(
                data="https://github.com/jorisschellekens/ptext-release",
                type=BarcodeType.QR,
                width=Decimal(64),
                height=Decimal(64),
                stroke_color=HexColor("FFCC00"),
            ))

        # determine output location
        out_file = self.output_dir / "output.pdf"

        # attempt to store PDF
        with open(out_file, "wb") as in_file_handle:
            PDF.dumps(in_file_handle, pdf)

        # attempt to re-open PDF
        with open(out_file, "rb") as in_file_handle:
            PDF.loads(in_file_handle)