コード例 #1
0
def generate_content_page(header_to_pagenumber, headers_and_subheaders, page_height, page_width):
    """
    Generates a document that serves as a Table of Contents, with header and subheader information.
    """
    doc = fitz.open()
    page = doc.newPage(height=page_height, width=page_width)
    horizontal_start_point = 40
    vertical_start_point = 60
    spacing = 15
    num_lines = 1
    tab = 30

    # Add Table of Contents heading (centered)
    rect_topleft = fitz.Point(0, vertical_start_point + num_lines * spacing)
    num_lines += 4
    rect_bottomright = fitz.Point(page_width, vertical_start_point + num_lines * spacing)
    rect = fitz.Rect(rect_topleft, rect_bottomright)
    page.insertTextbox(rect, "Table of Contents", fontsize=32, align=fitz.TEXT_ALIGN_CENTER)
    num_lines += 2

    # Create a TextWriter (per page)
    wr = fitz.TextWriter(page.rect)
    for h1_item, h2_items in headers_and_subheaders.items():
        # Insert the h1_item
        p = fitz.Point(
            horizontal_start_point, vertical_start_point + num_lines * spacing
        )
        wr.append(p, h1_item, fontsize=24, font=fitz.Font("Arial"))
        num_lines += 2
        for h2_item in h2_items:
            # Insert each h2_item
            p_tab = fitz.Point(
                tab + horizontal_start_point, vertical_start_point + num_lines * spacing
            )
            wr.append(p_tab, h2_item, fontsize=16)

            # Insert ... between h2_item and page number
            p_tab_number = fitz.Point(
                tab + horizontal_start_point + 500,
                vertical_start_point + num_lines * spacing,
            )
            add_dot_connector(wr, wr.lastPoint, p_tab_number)

            # Insert page number for h2_item
            wr.append(p_tab_number, str(header_to_pagenumber[h2_item]), fontsize=16)
            num_lines += 1

            # Move to new page if nearing end of page
            if num_lines >= 45:
                wr.writeText(page)
                page = doc.newPage(height=page_height, width=page_width)
                wr = fitz.TextWriter(page.rect)
                num_lines = 0
        num_lines += 2

    wr.writeText(page)
    return doc
コード例 #2
0
def generate_content_page(header_to_pagenumber, headers_and_subheaders,
                          page_height, page_width):
    doc = fitz.open()
    page = doc.newPage(height=page_height, width=page_width)
    horizontal_start_point = 40
    vertical_start_point = 60
    spacing = 15
    num_lines = 1
    tab = 30
    p = fitz.Point(horizontal_start_point + 250,
                   vertical_start_point + num_lines * spacing)
    page.insertText(p, "Table of Contents", fontname="helv", fontsize=32)
    num_lines += 4

    # Create a TextWriter (per page)
    wr = fitz.TextWriter(page.rect)
    for h1_item, h2_items in headers_and_subheaders.items():
        # Insert the h1_item
        p = fitz.Point(horizontal_start_point,
                       vertical_start_point + num_lines * spacing)
        wr.append(p, h1_item, fontsize=24)
        num_lines += 2
        for h2_item in h2_items:
            # Insert each h2_item
            p_tab = fitz.Point(tab + horizontal_start_point,
                               vertical_start_point + num_lines * spacing)
            wr.append(p_tab, h2_item, fontsize=16)

            # Insert ... between h2_item and page number
            p_tab_number = fitz.Point(
                tab + horizontal_start_point + 500,
                vertical_start_point + num_lines * spacing,
            )
            add_dot_connector(wr, wr.lastPoint, p_tab_number)

            # Insert page number for h2_item
            wr.append(p_tab_number,
                      str(header_to_pagenumber[h2_item]),
                      fontsize=16)
            num_lines += 1

            # Move to new page if nearing end of page
            if num_lines >= 45:
                wr.writeText(page)
                page = doc.newPage(height=page_height, width=page_width)
                wr = fitz.TextWriter(page.rect)
                num_lines = 0
        num_lines += 2

    wr.writeText(page)
    return doc
コード例 #3
0
def generate_pdf(kanji_code, kanji):
    try:
        file_handle = fitz.open(template)
        page = file_handle[0]
        page.clean_contents()
        image_path = os.path.join(
            settings.BASE_DIR,
            'kanjis/kanjivg/kanji/{}.svg'.format(kanji_code))
        # x0, y0, x1, y1 - https://pymupdf.readthedocs.io/en/latest/rect.html#rect
        img_rect = fitz.Rect(page.rect.width - 67, 28, page.rect.width - 20,
                             82)

        png_path = os.path.join(settings.BASE_DIR,
                                'kanjis/pdf/tmp/{}.png'.format(kanji_code))
        svg2png(url=image_path, write_to=png_path)
        page.insertImage(img_rect, filename=png_path)
        page.insertText((page.rect.width - 62, 18), 'JLPT' + str(kanji.jlpt)
                        or '?')
        text_writer = fitz.TextWriter(
            (0, 0, page.rect.width - 70, page.rect.height))
        text_writer.append(fitz.Point(20, 38),
                           'Kun: ' + ', '.join(kanji.kun_readings))
        text_writer.append(fitz.Point(20, 53),
                           'On: ' + ', '.join(kanji.on_readings))
        text_writer.append(fitz.Point(20, 68),
                           'Meanings: ' + ', '.join(kanji.meanings))
        text_writer.writeText(page)
        file_handle.save('{}/{}.pdf'.format(settings.MEDIA_ROOT, kanji_code),
                         deflate=True)
        os.remove(png_path)
    except Exception as e:
        raise e
コード例 #4
0
    def __init__(
        self,
        path: str,
        width: int,
        height: int,
        buffer_width: int,
        buffer_height: int,
        supplementary_path: str = None,
        turbo_skip: int = 2,
        zoom_multiplier: float = 1.5,
    ) -> None:
        self.path = path
        self.width = width
        self.height = height
        self.buffer_width = buffer_width
        self.buffer_height = buffer_height
        self.supplementary_path = supplementary_path
        self.zoom_multiplier = zoom_multiplier
        self.zoom_level = 0
        self.page_number = None
        self.page_image = None
        self.clip_rect = fitz.Rect()

        if self.path and Path(self.path).exists():
            self.document = fitz.open(self.path)
        else:
            # Create an empty pdf
            self.document = fitz.open()

            # Calculate width of text
            text_width = math.ceil(
                fitz.get_text_length(self.NO_MANUAL_TEXT,
                                     fontsize=self.NO_MANUAL_FONTSIZE))

            # Create page that's wider than the text so that it scales well
            page = self.document.new_page(width=text_width * 3,
                                          height=self.NO_MANUAL_HEIGHT)

            # Draw a black background
            page.draw_rect(page.rect,
                           color=(0, 0, 0),
                           fill=(0, 0, 0),
                           overlay=False)

            # Draw the text, positioned in the center
            text_writer = fitz.TextWriter(page.rect)
            text_writer.fill_textbox(
                page.rect,
                self.NO_MANUAL_TEXT,
                pos=(int((page.rect.width - text_width) / 2),
                     self.NO_MANUAL_FONTSIZE),
                fontsize=self.NO_MANUAL_FONTSIZE,
            )
            text_writer.write_text(page, color=(1, 1, 1))

        # Add supplementary material (usually reference info)
        if self.supplementary_path and Path(self.supplementary_path).exists():
            pdf = fitz.open(self.supplementary_path)
            self.document.insert_pdf(pdf)
            pdf.close()
コード例 #5
0
def print_descr(annot):
    """Print a short description to the right of the annot rect."""
    rect = annot.rect
    page = annot.parent
    writer = fitz.TextWriter(page_rect, color=red)
    writer.append(rect.br + (10, -5),
                  "%s annotation" % annot.type[1],
                  font=font)
    writer.writeText(page)
コード例 #6
0
ファイル: TextSpan.py プロジェクト: pyarchinit/pyarchinit
    def _change_font_and_update_bbox(self, font_name: str):
        '''Set new font, and update font size, span/char bbox accordingly.

        It's generally used for span with unnamed fonts. 
        See this `issue <https://github.com/pymupdf/PyMuPDF/issues/642>`_.        

        In corner case, where the PDF file containing unnamed and not embedded fonts, the span bbox
        extracted from ``PyMuPDF`` is not correct. ``PyMuPDF`` provides feature to replace these 
        unnamed fonts with specified fonts, then extract correct bbox from the updated PDF. Since we 
        care less about the original PDF itself but its layout, the idea here is to set a default font 
        for text spans with unnamed fonts, and estimate the updated bbox with method from 
        ``fitz.TextWriter``.

        Args:
            font_name (str): Font name.
        '''
        # set new font property
        self.font = font_name

        # compute text length under new font with that size
        font = fitz.Font(font_name)
        new_length = font.text_length(self.text, fontsize=self.size)
        if new_length > self.bbox.width:
            self.size *= self.bbox.width / new_length

        # estimate occupied rect when added with TextWriter
        x0, y0, x1, y1 = self.bbox
        tw = fitz.TextWriter((0, 0, x1, y1))
        rect, _ = tw.append(
            self.chars[0].
            origin,  # the bottom left point of the first character
            self.text,
            font=font,
            fontsize=self.size)

        # update span bbox
        # - x-direction: use original horizontal range
        # - y-direction: centerline defined by estimated vertical range, and height by font size
        buff = (rect.height - self.size) / 2.0
        y0 = rect.y0 + buff
        y1 = rect.y1 - buff
        self.update_bbox((x0, y0, x1, y1))

        # update contained char bbox
        for char in self.chars:
            x0, _, x1, _ = char.bbox
            char.update_bbox((x0, y0, x1, y1))
コード例 #7
0
def test_textbox1():
    """Use TextWriter for text insertion."""
    doc = fitz.open()
    page = doc.new_page()
    rect = fitz.Rect(50, 50, 400, 400)
    blue = (0, 0, 1)
    tw = fitz.TextWriter(page.rect, color=blue)
    tw.fill_textbox(
        rect,
        text,
        align=fitz.TEXT_ALIGN_LEFT,
        fontsize=12,
    )
    tw.write_text(page, morph=(rect.tl, fitz.Matrix(1, 1)))
    # check text containment
    assert page.get_text() == page.get_text(clip=rect)
    page.write_text(writers=tw)
コード例 #8
0
def tilted_span(page, wdir, span, font):
    """Output a non-horizontal span."""
    cos, sin = wdir  # writing direction from the line
    matrix = fitz.Matrix(cos, -sin, sin, cos, 0, 0)  # corresp. matrix
    text = span["text"]  # text to write
    bbox = fitz.Rect(span["bbox"])
    fontsize = span["size"]  # adjust fontsize
    tl = font.text_length(text, fontsize)  # text length with new font
    m = max(bbox.width, bbox.height)  # must not exceed max bbox dimension
    if tl > m:
        fontsize *= m / tl  # otherwise adjust
    opa = 0.1 if fontsize > 100 else 1  # fake opacity for large fontsizes
    tw = fitz.TextWriter(page.rect, opacity=opa, color=fitz.sRGB_to_pdf(span["color"]))
    origin = fitz.Point(span["origin"])
    if sin > 0:  # clockwise rotation
        origin.y = bbox.y0
    tw.append(origin, text, font=font, fontsize=fontsize)
    tw.writeText(page, morph=(origin, matrix))
コード例 #9
0
def test_textbox4():
    """Use TextWriter for text insertion."""
    doc = fitz.open()
    ocg = doc.add_ocg("ocg1")
    page = doc.new_page()
    rect = fitz.Rect(50, 50, 400, 600)
    blue = (0, 0, 1)
    tw = fitz.TextWriter(page.rect, color=blue)
    tw.fill_textbox(
        rect,
        text,
        align=fitz.TEXT_ALIGN_LEFT,
        fontsize=12,
        font=fitz.Font("cour"),
        right_to_left=True,
    )
    tw.write_text(page, oc=ocg, morph=(rect.tl, fitz.Matrix(1, 1)))
    # check text containment
    assert page.get_text() == page.get_text(clip=rect)
コード例 #10
0
def test_textbox3():
    """Use TextWriter for text insertion."""
    doc = fitz.open()
    page = doc.new_page()
    font = fitz.Font("cjk")
    rect = fitz.Rect(50, 50, 400, 400)
    blue = (0, 0, 1)
    tw = fitz.TextWriter(page.rect, color=blue)
    tw.fill_textbox(
        rect,
        text,
        align=fitz.TEXT_ALIGN_LEFT,
        font=font,
        fontsize=12,
        right_to_left=True,
    )
    tw.write_text(page, morph=(rect.tl, fitz.Matrix(1, 1)))
    # check text containment
    assert page.get_text() == page.get_text(clip=rect)
    doc.scrub()
    doc.subset_fonts()
コード例 #11
0
                    continue

                font = fitz.Font(fontbuffer=font_buffers[new_fontname])
                text = span["text"].replace(chr(0xFFFD), chr(0xB6))
                # guard against non-utf8 characters
                textb = text.encode("utf8", errors="backslashreplace")
                text = textb.decode("utf8", errors="backslashreplace")
                span["text"] = text
                if wdir != [1, 0]:  # special treatment for tilted text
                    tilted_span(page, wdir, span, font)
                    continue
                color = span["color"]  # make or reuse textwriter for the color
                if color in textwriters.keys():  # already have a textwriter?
                    tw = textwriters[color]  # re-use it
                else:  # make new
                    tw = fitz.TextWriter(page.rect)  # make text writer
                    textwriters[color] = tw  # store it for later use
                try:
                    tw.append(
                        span["origin"],
                        text,
                        font=font,
                        fontsize=resize(span, font),  # use adjusted fontsize
                        wmode=wmode,
                        markup_dir=markup_dir,
                        bidi_level=bidi_level,
                    )
                except:
                    print("page %i exception:" % page.number, text)

    # now write all text stored in the list of text writers
コード例 #12
0
annot.setBorder(width=0.3, dashes=[2])
annot.update(text_color=blue, fill_color=gold)

print_descr(annot)
r = annot.rect + displ

annot = page.addTextAnnot(r.tl, t1)
print_descr(annot)

# Adding text marker annotations: For each annotation type, first insert a
# a (unique) text and tilt it a bit. Then calculate the quad of the text
# and feed it into annot creation.
pos = annot.rect.tl + displ.tl
mat = fitz.Matrix(-15)

writer = fitz.TextWriter(page_rect)  # create TextWriter object
writer.append(pos, highlight, font=font)  # append text
writer.writeText(page, morph=(pos, mat))  # write to the page with rotation
writer.textRect.x0 = pos.x  # use actual text start / end
writer.textRect.x1 = writer.lastPoint.x
quad_highlight = writer.textRect.morph(pos, ~mat)  # calculate text quad
pos = quad_highlight.rect.bl  # the next writing position

writer = fitz.TextWriter(page_rect)
writer.append(pos, underline, font=font)
writer.writeText(page, morph=(pos, mat))
writer.textRect.x0 = pos.x
writer.textRect.x1 = writer.lastPoint.x
quad_underline = writer.textRect.morph(pos, ~mat)
pos = quad_underline.rect.bl
コード例 #13
0
text = """This is a text of mixed languages to demonstrate MuPDF's text output capabilities.
Font used for the non-CJK characters: '%s', font size: %g, color: %s.
Euro: €, some special signs: |~°²³, general Latin: ñäöüßâ
Japan: 熊野三山本願所は、15世紀末以降における熊野三山(熊野本宮、熊野新宮
Greece: Στα ερείπια της πόλης, που ήταν ένα σημαντικό
Korea: 에듀롬은 하나의 계정으로 전 세계 고등교육 기관의 인터넷에 접속할
Russia: Ко времени восшествия на престол Якова I в значительной
China: 北京作为城市的历史可以追溯到3,000年前。西周初年,周武王封召公奭于燕國。
This longer text part checks, whether the very last line will not be justified either.""" % (
    font.name,
    fsize,
    blue,
)

fill_rect = fitz.Rect(72, 72, 372, 372)  #  keep above text in here
writer = fitz.TextWriter(page_rect, color=blue)  # start a text writer

writer.fillTextbox(  # fill in above text
    fill_rect,  # keep text inside this
    text,  # the text
    align=fitz.TEXT_ALIGN_JUSTIFY,  # alignment
    warn=True,  # keep going if too much text
    fontsize=fsize,
    font=font,
)

# write our results to the PDF page.
writer.writeText(page)

# To show what happened, draw the rectangles, etc.
shape = page.newShape()
コード例 #14
0
def page_out(doc, text):
    page = doc.newPage(width=w, height=h)  # make new page
    tw = fitz.TextWriter(page_rect)  # make text writer
    tw.fillTextbox(print_rect, text, font=font, fontsize=fontsize)
    tw.writeText(page)  # write the text to the page
コード例 #15
0
ファイル: demo.py プロジェクト: zbelial/PyMuPDF-Utilities
import fitz, os

thisdir = lambda f: os.path.join(os.path.dirname(__file__), f)
thisfile = os.path.abspath(__file__)
outfile = thisfile.replace(".py", ".pdf")

font1 = fitz.Font("helv")
font2 = fitz.Font("tiro")
doc = fitz.open()
page = doc.newPage()
point = fitz.Point(50, 72)
matrix = fitz.Matrix(-20)

wrt1 = fitz.TextWriter(page.rect, color=(0, 0, 1))
wrt2 = fitz.TextWriter(page.rect, color=(1, 0, 0))

_, last = wrt1.append(point, "This text changes color,", font1, 11)
_, last = wrt2.append(last, " font and fontsize", font2, 18)
_, last = wrt1.append(last, " several", font1, 11)
_, last = wrt2.append(last, " times!", font2, 24)

# output both text writers on current page in arbitrary sequence
wrt1.writeText(page, morph=(point, matrix))  # using the same morph parameter
wrt2.writeText(page, morph=(point, matrix))  # also preserves the joint text.

# make a new page
page = doc.newPage()
rect = wrt1.textRect | wrt2.textRect  # join rect of blue and red text
# make new rectangle from it, rotated by 90 degrees
nrect = fitz.Rect(
    rect.tl,  # same top-left, but width and height exchanged