Skip to content

Commit

Permalink
New ul_bullet_color parameter for FPDF.write_html()
Browse files Browse the repository at this point in the history
  • Loading branch information
Lucas-C committed Feb 28, 2024
1 parent e85ec4e commit 4d6d75e
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ This can also be enabled programmatically with `warnings.simplefilter('default',
## [2.7.9] - Not released yet
### Added
* support for overriding paragraph direction on bidirectional text
* new optional `ul_bullet_color` parameter for `FPDF.write_html()`
### Fixed

### Changed
Expand Down
10 changes: 10 additions & 0 deletions fpdf/drawing.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,11 @@ def colors(self):
"""The color components as a tuple in order `(r, g, b)` with alpha omitted."""
return self[:-1]

@property
def colors255(self):
"The color components as a tuple in order `(r, g, b)` with alpha omitted, in range 0-255."
return tuple(255 * v for v in self.colors)

def serialize(self) -> str:
return " ".join(number_to_str(val) for val in self.colors) + f" {self.OPERATOR}"

Expand Down Expand Up @@ -260,6 +265,11 @@ def colors(self):
"""The color components as a tuple in order (g,) with alpha omitted."""
return self[:-1]

@property
def colors255(self):
"The color components as a tuple in order `(r, g, b)` with alpha omitted, in range 0-255."
return tuple(255 * v for v in self.colors)

def serialize(self) -> str:
return " ".join(number_to_str(val) for val in self.colors) + f" {self.OPERATOR}"

Expand Down
1 change: 1 addition & 0 deletions fpdf/fpdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ def write_html(self, text, *args, **kwargs):
dd_tag_indent (int): numeric indentation of <dd> elements
table_line_separators (bool): enable horizontal line separators in <table>
ul_bullet_char (str): bullet character for <ul> elements
ul_bullet_color (tuple | str | drawing.Device* instance): color of the <ul> bullets
heading_sizes (dict): font size per heading level names ("h1", "h2"...)
pre_code_font (str): font to use for <pre> & <code> blocks
warn_on_tags_not_matching (bool): control warnings production for unmatched HTML tags
Expand Down
22 changes: 10 additions & 12 deletions fpdf/html.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from html.parser import HTMLParser
import logging, re, warnings

from .drawing import color_from_hex_string, convert_to_device_color
from .enums import TextEmphasis, XPos, YPos
from .errors import FPDFException
from .deprecation import get_stack_level
Expand Down Expand Up @@ -215,17 +216,7 @@ def color_as_decimal(color="#000000"):

# Checks if color is a name and gets the hex value
hexcolor = COLOR_DICT.get(color.lower(), color)

if len(hexcolor) == 4:
r = int(hexcolor[1] * 2, 16)
g = int(hexcolor[2] * 2, 16)
b = int(hexcolor[3] * 2, 16)
return r, g, b

r = int(hexcolor[1:3], 16)
g = int(hexcolor[3:5], 16)
b = int(hexcolor[5:7], 16)
return r, g, b
return color_from_hex_string(hexcolor).colors255


class HTML2FPDF(HTMLParser):
Expand All @@ -241,6 +232,7 @@ def __init__(
dd_tag_indent=10,
table_line_separators=False,
ul_bullet_char=BULLET_WIN1252,
ul_bullet_color=(190, 0, 0),
heading_sizes=None,
pre_code_font="courier",
warn_on_tags_not_matching=True,
Expand All @@ -255,6 +247,7 @@ def __init__(
dd_tag_indent (int): numeric indentation of <dd> elements
table_line_separators (bool): enable horizontal line separators in <table>
ul_bullet_char (str): bullet character for <ul> elements
ul_bullet_color (tuple | str | drawing.Device* instance): color of the <ul> bullets
heading_sizes (dict): font size per heading level names ("h1", "h2"...)
pre_code_font (str): font to use for <pre> & <code> blocks
warn_on_tags_not_matching (bool): control warnings production for unmatched HTML tags
Expand All @@ -265,6 +258,11 @@ def __init__(
self.li_tag_indent = li_tag_indent
self.dd_tag_indent = dd_tag_indent
self.ul_bullet_char = ul_bullet_char
self.ul_bullet_color = (
color_as_decimal(ul_bullet_color)
if isinstance(ul_bullet_color, str)
else convert_to_device_color(ul_bullet_color).colors255
)
self.heading_sizes = dict(**DEFAULT_HEADING_SIZES)
if heading_sizes:
self.heading_sizes.update(heading_sizes)
Expand Down Expand Up @@ -519,7 +517,7 @@ def handle_starttag(self, tag, attrs):
self._new_paragraph()
if tag == "li":
self._ln(2)
self.set_text_color(190, 0, 0)
self.set_text_color(*self.ul_bullet_color)
if self.bullet:
bullet = self.bullet[self.indent - 1]
else:
Expand Down
Binary file added test/html/html_ul_bullet_color.pdf
Binary file not shown.
20 changes: 20 additions & 0 deletions test/html/test_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import pytest

from fpdf import FPDF, HTMLMixin, TitleStyle
from fpdf.drawing import DeviceRGB
from fpdf.errors import FPDFException
from test.conftest import assert_pdf_equal, LOREM_IPSUM

Expand Down Expand Up @@ -215,6 +216,25 @@ class CustomPDF(FPDF):
assert_pdf_equal(pdf, HERE / "html_customize_ul.pdf", tmp_path)


def test_html_ul_bullet_color(tmp_path):
html = """<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ul>"""

pdf = FPDF()
pdf.set_font_size(30)
pdf.add_page()
pdf.write_html(html, ul_bullet_color=0) # black
pdf.ln()
pdf.write_html(html, ul_bullet_color="green")
pdf.ln()
pdf.write_html(html, ul_bullet_color=DeviceRGB(r=0.5, g=1, b=0))
pdf.ln()
assert_pdf_equal(pdf, HERE / "html_ul_bullet_color.pdf", tmp_path)


def test_html_align_paragraph(tmp_path):
pdf = FPDF()
pdf.add_page()
Expand Down

0 comments on commit 4d6d75e

Please sign in to comment.