Skip to content

Commit e4a09d8

Browse files
committed
Supporting <text> tags from SVG files
* introduce TextRendererMixin
1 parent 2f8195d commit e4a09d8

18 files changed

+990
-841
lines changed

fpdf/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@
2424
from .fpdf import (
2525
FPDF,
2626
TitleStyle,
27-
FPDF_FONT_DIR as _FPDF_FONT_DIR,
2827
FPDF_VERSION as _FPDF_VERSION,
2928
)
3029
from .html import HTMLMixin, HTML2FPDF
3130
from .prefs import ViewerPreferences
3231
from .template import Template, FlexTemplate
32+
from .text_renderer import FPDF_FONT_DIR as _FPDF_FONT_DIR
3333
from .util import get_scale_factor
3434

3535
try:

fpdf/drawing.py

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2800,14 +2800,14 @@ def __init__(self):
28002800
def add_item(
28012801
self,
28022802
item: Union["GraphicsContext", "PaintedPath", "PaintComposite"],
2803-
_copy: bool = True,
2803+
clone: bool = True,
28042804
) -> None:
28052805
"""
28062806
Append an item to this drawing context
28072807
28082808
Args:
28092809
item (GraphicsContext, PaintedPath): the item to be appended.
2810-
_copy (bool): if true (the default), the item will be copied before being
2810+
clone (bool): if true (the default), the item will be copied before being
28112811
appended. This prevents modifications to a referenced object from
28122812
"retroactively" altering its style/shape and should be disabled with
28132813
caution.
@@ -2816,7 +2816,7 @@ def add_item(
28162816
if not isinstance(item, (GraphicsContext, PaintedPath, PaintComposite)):
28172817
raise TypeError(f"{item} doesn't belong in a DrawingContext")
28182818

2819-
if _copy:
2819+
if clone:
28202820
item = deepcopy(item)
28212821

28222822
self._subitems.append(item)
@@ -3097,24 +3097,24 @@ def transform_group(self, transform):
30973097
ctxt.transform = transform
30983098
yield self
30993099

3100-
def add_path_element(self, item, _copy=True):
3100+
def add_path_element(self, item, clone=True):
31013101
"""
31023102
Add the given element as a path item of this path.
31033103
31043104
Args:
31053105
item: the item to add to this path.
3106-
_copy (bool): if true (the default), the item will be copied before being
3106+
clone (bool): if true (the default), the item will be copied before being
31073107
appended. This prevents modifications to a referenced object from
31083108
"retroactively" altering its style/shape and should be disabled with
31093109
caution.
31103110
"""
31113111
if self._starter_move is not None:
31123112
self._closed = False
3113-
self._graphics_context.add_item(self._starter_move, _copy=False)
3113+
self._graphics_context.add_item(self._starter_move, clone=False)
31143114
self._close_context = self._graphics_context
31153115
self._starter_move = None
31163116

3117-
self._graphics_context.add_item(item, _copy=_copy)
3117+
self._graphics_context.add_item(item, clone=clone)
31183118

31193119
def remove_last_path_element(self):
31203120
self._graphics_context.remove_last_item()
@@ -3144,7 +3144,7 @@ def rectangle(self, x, y, w, h, rx=0, ry=0):
31443144

31453145
self._insert_implicit_close_if_open()
31463146
self.add_path_element(
3147-
RoundedRectangle(Point(x, y), Point(w, h), Point(rx, ry)), _copy=False
3147+
RoundedRectangle(Point(x, y), Point(w, h), Point(rx, ry)), clone=False
31483148
)
31493149
self._closed = True
31503150
self.move_to(x, y)
@@ -3179,7 +3179,7 @@ def ellipse(self, cx, cy, rx, ry):
31793179
The path, to allow chaining method calls.
31803180
"""
31813181
self._insert_implicit_close_if_open()
3182-
self.add_path_element(Ellipse(Point(rx, ry), Point(cx, cy)), _copy=False)
3182+
self.add_path_element(Ellipse(Point(rx, ry), Point(cx, cy)), clone=False)
31833183
self._closed = True
31843184
self.move_to(cx, cy)
31853185

@@ -3223,7 +3223,7 @@ def move_relative(self, x, y):
32233223
self._insert_implicit_close_if_open()
32243224
if self._starter_move is not None:
32253225
self._closed = False
3226-
self._graphics_context.add_item(self._starter_move, _copy=False)
3226+
self._graphics_context.add_item(self._starter_move, clone=False)
32273227
self._close_context = self._graphics_context
32283228
self._starter_move = RelativeMove(Point(x, y))
32293229
return self
@@ -3239,7 +3239,7 @@ def line_to(self, x, y):
32393239
Returns:
32403240
The path, to allow chaining method calls.
32413241
"""
3242-
self.add_path_element(Line(Point(x, y)), _copy=False)
3242+
self.add_path_element(Line(Point(x, y)), clone=False)
32433243
return self
32443244

32453245
def line_relative(self, dx, dy):
@@ -3256,7 +3256,7 @@ def line_relative(self, dx, dy):
32563256
Returns:
32573257
The path, to allow chaining method calls.
32583258
"""
3259-
self.add_path_element(RelativeLine(Point(dx, dy)), _copy=False)
3259+
self.add_path_element(RelativeLine(Point(dx, dy)), clone=False)
32603260
return self
32613261

32623262
def horizontal_line_to(self, x):
@@ -3270,7 +3270,7 @@ def horizontal_line_to(self, x):
32703270
Returns:
32713271
The path, to allow chaining method calls.
32723272
"""
3273-
self.add_path_element(HorizontalLine(x), _copy=False)
3273+
self.add_path_element(HorizontalLine(x), clone=False)
32743274
return self
32753275

32763276
def horizontal_line_relative(self, dx):
@@ -3286,7 +3286,7 @@ def horizontal_line_relative(self, dx):
32863286
Returns:
32873287
The path, to allow chaining method calls.
32883288
"""
3289-
self.add_path_element(RelativeHorizontalLine(dx), _copy=False)
3289+
self.add_path_element(RelativeHorizontalLine(dx), clone=False)
32903290
return self
32913291

32923292
def vertical_line_to(self, y):
@@ -3300,7 +3300,7 @@ def vertical_line_to(self, y):
33003300
Returns:
33013301
The path, to allow chaining method calls.
33023302
"""
3303-
self.add_path_element(VerticalLine(y), _copy=False)
3303+
self.add_path_element(VerticalLine(y), clone=False)
33043304
return self
33053305

33063306
def vertical_line_relative(self, dy):
@@ -3316,7 +3316,7 @@ def vertical_line_relative(self, dy):
33163316
Returns:
33173317
The path, to allow chaining method calls.
33183318
"""
3319-
self.add_path_element(RelativeVerticalLine(dy), _copy=False)
3319+
self.add_path_element(RelativeVerticalLine(dy), clone=False)
33203320
return self
33213321

33223322
def curve_to(self, x1, y1, x2, y2, x3, y3):
@@ -3338,7 +3338,7 @@ def curve_to(self, x1, y1, x2, y2, x3, y3):
33383338
ctrl2 = Point(x2, y2)
33393339
end = Point(x3, y3)
33403340

3341-
self.add_path_element(BezierCurve(ctrl1, ctrl2, end), _copy=False)
3341+
self.add_path_element(BezierCurve(ctrl1, ctrl2, end), clone=False)
33423342
return self
33433343

33443344
def curve_relative(self, dx1, dy1, dx2, dy2, dx3, dy3):
@@ -3372,7 +3372,7 @@ def curve_relative(self, dx1, dy1, dx2, dy2, dx3, dy3):
33723372
c2d = Point(dx2, dy2)
33733373
end = Point(dx3, dy3)
33743374

3375-
self.add_path_element(RelativeBezierCurve(c1d, c2d, end), _copy=False)
3375+
self.add_path_element(RelativeBezierCurve(c1d, c2d, end), clone=False)
33763376
return self
33773377

33783378
def quadratic_curve_to(self, x1, y1, x2, y2):
@@ -3390,7 +3390,7 @@ def quadratic_curve_to(self, x1, y1, x2, y2):
33903390
"""
33913391
ctrl = Point(x1, y1)
33923392
end = Point(x2, y2)
3393-
self.add_path_element(QuadraticBezierCurve(ctrl, end), _copy=False)
3393+
self.add_path_element(QuadraticBezierCurve(ctrl, end), clone=False)
33943394
return self
33953395

33963396
def quadratic_curve_relative(self, dx1, dy1, dx2, dy2):
@@ -3412,7 +3412,7 @@ def quadratic_curve_relative(self, dx1, dy1, dx2, dy2):
34123412
"""
34133413
ctrl = Point(dx1, dy1)
34143414
end = Point(dx2, dy2)
3415-
self.add_path_element(RelativeQuadraticBezierCurve(ctrl, end), _copy=False)
3415+
self.add_path_element(RelativeQuadraticBezierCurve(ctrl, end), clone=False)
34163416
return self
34173417

34183418
def arc_to(self, rx, ry, rotation, large_arc, positive_sweep, x, y):
@@ -3459,7 +3459,7 @@ def arc_to(self, rx, ry, rotation, large_arc, positive_sweep, x, y):
34593459
end = Point(x, y)
34603460

34613461
self.add_path_element(
3462-
Arc(radii, rotation, large_arc, positive_sweep, end), _copy=False
3462+
Arc(radii, rotation, large_arc, positive_sweep, end), clone=False
34633463
)
34643464
return self
34653465

@@ -3508,21 +3508,21 @@ def arc_relative(self, rx, ry, rotation, large_arc, positive_sweep, dx, dy):
35083508
end = Point(dx, dy)
35093509

35103510
self.add_path_element(
3511-
RelativeArc(radii, rotation, large_arc, positive_sweep, end), _copy=False
3511+
RelativeArc(radii, rotation, large_arc, positive_sweep, end), clone=False
35123512
)
35133513
return self
35143514

35153515
def close(self):
35163516
"""
35173517
Explicitly close the current (sub)path.
35183518
"""
3519-
self.add_path_element(Close(), _copy=False)
3519+
self.add_path_element(Close(), clone=False)
35203520
self._closed = True
35213521
self.move_relative(0, 0)
35223522

35233523
def _insert_implicit_close_if_open(self):
35243524
if not self._closed:
3525-
self._close_context.add_item(ImplicitClose(), _copy=False)
3525+
self._close_context.add_item(ImplicitClose(), clone=False)
35263526
self._close_context = self._graphics_context
35273527
self._closed = True
35283528

@@ -3744,19 +3744,19 @@ def clipping_path(self) -> Optional[ClippingPath]:
37443744
def clipping_path(self, new_clipath: ClippingPath) -> None:
37453745
self._clipping_path = new_clipath
37463746

3747-
def add_item(self, item: Renderable, _copy: bool = True) -> None:
3747+
def add_item(self, item: Renderable, clone: bool = True):
37483748
"""
37493749
Add a path element to this graphics context.
37503750
37513751
Args:
37523752
item: the path element to add. May be a primitive element or another
37533753
`GraphicsContext` or a `PaintedPath`.
3754-
_copy (bool): if true (the default), the item will be copied before being
3754+
clone (bool): if true (the default), the item will be copied before being
37553755
appended. This prevents modifications to a referenced object from
37563756
"retroactively" altering its style/shape and should be disabled with
37573757
caution.
37583758
"""
3759-
if _copy:
3759+
if clone:
37603760
item = deepcopy(item)
37613761

37623762
self.path_items.append(item)

fpdf/font_type_3.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ def draw_glyph_colrv0(self, layers):
283283
glyph.draw(pen)
284284
path.style.fill_color = self.get_color(layer.colorID)
285285
path.style.stroke_color = self.get_color(layer.colorID)
286-
gc.add_item(item=path, _copy=False)
286+
gc.add_item(item=path, clone=False)
287287
return gc
288288

289289
def draw_glyph_colrv1(self, glyph_name):
@@ -318,7 +318,7 @@ def draw_colrv1_paint(
318318
parent=group,
319319
ctm=ctm,
320320
)
321-
parent.add_item(item=group, _copy=False)
321+
parent.add_item(item=group, clone=False)
322322
return parent, target_path
323323

324324
if paint.Format in (
@@ -403,8 +403,8 @@ def draw_colrv1_paint(
403403
ctm=Transform.identity(),
404404
)
405405
if surface_path is not None:
406-
group.add_item(item=surface_path, _copy=False)
407-
parent.add_item(item=group, _copy=False)
406+
group.add_item(item=surface_path, clone=False)
407+
parent.add_item(item=group, clone=False)
408408
return parent, None
409409

410410
if paint.Format == PaintFormat.PaintColrGlyph:
@@ -419,7 +419,7 @@ def draw_colrv1_paint(
419419

420420
group = GraphicsContext()
421421
self.draw_colrv1_paint(paint=rec.Paint, parent=group, ctm=ctm)
422-
parent.add_item(item=group, _copy=False)
422+
parent.add_item(item=group, clone=False)
423423
return parent, target_path
424424

425425
if paint.Format in (
@@ -465,7 +465,7 @@ def draw_colrv1_paint(
465465
ctm=ctm,
466466
)
467467
if backdrop_path is not None:
468-
backdrop_node.add_item(item=backdrop_path, _copy=False)
468+
backdrop_node.add_item(item=backdrop_path, clone=False)
469469

470470
source_node = GraphicsContext()
471471
_, source_path = self.draw_colrv1_paint(
@@ -474,20 +474,20 @@ def draw_colrv1_paint(
474474
ctm=ctm,
475475
)
476476
if source_path is not None:
477-
source_node.add_item(item=source_path, _copy=False)
477+
source_node.add_item(item=source_path, clone=False)
478478

479479
composite_type, composite_mode = self.get_composite_mode(
480480
paint.CompositeMode
481481
)
482482
if composite_type == "Blend":
483483
source_node.style.blend_mode = composite_mode
484-
parent.add_item(item=backdrop_node, _copy=False)
485-
parent.add_item(item=source_node, _copy=False)
484+
parent.add_item(item=backdrop_node, clone=False)
485+
parent.add_item(item=source_node, clone=False)
486486
elif composite_type == "Compositing":
487487
composite_node = PaintComposite(
488488
backdrop=backdrop_node, source=source_node, operation=composite_mode
489489
)
490-
parent.add_item(item=composite_node, _copy=False)
490+
parent.add_item(item=composite_node, clone=False)
491491
else:
492492
raise ValueError(""" Composite operation not supported """)
493493
return parent, None

fpdf/fonts.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,8 @@ class CoreFont:
224224
"emphasis",
225225
)
226226

227-
def __init__(self, fpdf, fontkey, style):
228-
self.i = len(fpdf.fonts) + 1
227+
def __init__(self, i, fontkey, style):
228+
self.i = i
229229
self.type = "core"
230230
self.name = CORE_FONTS[fontkey]
231231
self.sp = 250 # strikethrough horizontal position

0 commit comments

Comments
 (0)