Skip to content

Commit

Permalink
Preserve dash pattern on new page, fix #992 (#993)
Browse files Browse the repository at this point in the history
* Preserve dash pattern on new page, fix #992

* Update CHANGELOG.md

* Update new_page_graphics_state.pdf
  • Loading branch information
gmischler committed Nov 1, 2023
1 parent fb9fd9c commit d81018d
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ This can also be enabled programmatically with `warnings.simplefilter('default',
* [`TextColumns()`](https://py-pdf.github.io/fpdf2/TextColumns.html) can now have images inserted (both raster and vector).
* [`TextColumns()`](https://py-pdf.github.io/fpdf2/TextColumns.html) can now advance to the next column with the new `new_column()` method or a FORM_FEED character (`\u000c`) in the text.
### Fixed
* Previously set dash patterns were not transferred correctly to new pages.
* Inserted Vector images used to ignore the `keep_aspect_ratio` argument.

## [2.7.6] - 2023-10-11
Expand Down
27 changes: 17 additions & 10 deletions fpdf/fpdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@ def set_text_shaping(
"The uharfbuzz package could not be imported, but is required for text shaping. Try: pip install uharfbuzz"
) from exc
else:
self._text_shaping = None
self.text_shaping = None
return
#
# Features must be a dictionary contaning opentype features and a boolean flag
Expand Down Expand Up @@ -619,7 +619,7 @@ def set_text_shaping(
"FPDF2 only accept ltr (left to right) or rtl (right to left) directions for now."
)

self._text_shaping = {
self.text_shaping = {
"use_shaping_engine": True,
"features": features,
"direction": direction,
Expand Down Expand Up @@ -843,6 +843,7 @@ def add_page(
tc = self.text_color
stretching = self.font_stretching
char_spacing = self.char_spacing
dash_pattern = self.dash_pattern

if self.page > 0:
# Page footer
Expand Down Expand Up @@ -907,6 +908,11 @@ def add_page(
self.set_stretching(stretching)
if char_spacing != 0:
self.set_char_spacing(char_spacing)
if dash_pattern != dict(dash=0, gap=0, phase=0):
self._write_dash_pattern(
dash_pattern["dash"], dash_pattern["gap"], dash_pattern["phase"]
)

# END Page header

def _beginpage(
Expand Down Expand Up @@ -1203,16 +1209,17 @@ def set_dash_pattern(self, dash=0, gap=0, phase=0):

if pattern != self.dash_pattern:
self.dash_pattern = pattern
self._write_dash_pattern(dash, gap, phase)

if dash:
if gap:
dstr = f"[{dash * self.k:.3f} {gap * self.k:.3f}] {phase *self.k:.3f} d"
else:
dstr = f"[{dash * self.k:.3f}] {phase *self.k:.3f} d"
def _write_dash_pattern(self, dash, gap, phase):
if dash:
if gap:
dstr = f"[{dash * self.k:.3f} {gap * self.k:.3f}] {phase *self.k:.3f} d"
else:
dstr = "[] 0 d"

self._out(dstr)
dstr = f"[{dash * self.k:.3f}] {phase *self.k:.3f} d"
else:
dstr = "[] 0 d"
self._out(dstr)

@check_page
def line(self, x1, y1, x2, y2):
Expand Down
12 changes: 6 additions & 6 deletions fpdf/graphics_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def __init__(self, *args, **kwargs):
sup_lift=0.4,
nom_lift=0.2,
denom_lift=0.0,
_text_shaping=None,
text_shaping=None,
),
]
super().__init__(*args, **kwargs)
Expand Down Expand Up @@ -326,12 +326,12 @@ def denom_lift(self, v):
self.__statestack[-1]["denom_lift"] = float(v)

@property
def _text_shaping(self):
return self.__statestack[-1]["_text_shaping"]
def text_shaping(self):
return self.__statestack[-1]["text_shaping"]

@_text_shaping.setter
def _text_shaping(self, v):
self.__statestack[-1]["_text_shaping"] = v
@text_shaping.setter
def text_shaping(self, v):
self.__statestack[-1]["text_shaping"] = v

def font_face(self):
"""
Expand Down
2 changes: 1 addition & 1 deletion fpdf/line_break.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def lift(self):

@property
def _text_shaping(self):
return self.graphics_state["_text_shaping"]
return self.graphics_state["text_shaping"]

@property
def string(self):
Expand Down
Binary file added test/new_page_graphics_state.pdf
Binary file not shown.
39 changes: 39 additions & 0 deletions test/test_add_page.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,42 @@ def header(self):
pdf.set_x(100)
pdf.multi_cell(50, 10, f"Text {i} - Page {pdf.page}", 1, "C")
assert_pdf_equal(pdf, HERE / "break_or_add_page_draw_fill.pdf", tmp_path)


def test_new_page_graphics_state(tmp_path):
# Make sure that on a page break, all graphics state items are
# carried over correctly.
# issue #992 - dash patterns were not handled correctly.
pdf = fpdf.FPDF()
pdf.add_page()
pdf.set_auto_page_break(auto=False)
pdf.set_font("Courier", "iu", 16)
pdf.set_draw_color(255, 100, 0)
pdf.set_fill_color(100, 255, 0)
pdf.set_text_color(0, 0, 255)
# underline -> set_font()
# font_style -> set_font()
pdf.set_stretching(50)
pdf.set_char_spacing(5)
# font_family -> set_font()
# font_size_pt -> set_font()
# current_font -> set_font()
pdf.set_dash_pattern(dash=2, gap=4)
pdf.set_line_width(2)
# text_mode -> applied via Fragments
# char lift/scale -> applied via Fragments
# text_shaping -> applied in the creation of Fragments

def draw_stuff():
pdf.cell(
text="This text is blue, italic, underlined, and squished with wide char spacing.",
new_x="LEFT",
new_y="NEXT",
)
pdf.cell(text="The box below is green, with a thick, dashed, orange border.")
pdf.rect(50, 50, 60, 30, style="DF")

draw_stuff()
pdf.add_page()
draw_stuff()
assert_pdf_equal(pdf, HERE / "new_page_graphics_state.pdf", tmp_path)

0 comments on commit d81018d

Please sign in to comment.