diff --git a/weasyprint/draw.py b/weasyprint/draw.py index dbacd4fa5..3d3d5fc3f 100644 --- a/weasyprint/draw.py +++ b/weasyprint/draw.py @@ -16,7 +16,7 @@ from .matrix import Matrix from .stacking import StackingContext from .text.ffi import ffi, pango, units_from_double, units_to_double -from .text.fonts import get_hb_face_data, get_pango_font_hb_face +from .text.fonts import get_hb_object_data, get_pango_font_hb_face from .text.line_break import get_last_word_end SIDES = ('top', 'right', 'bottom', 'left') @@ -1449,8 +1449,7 @@ def draw_first_line(stream, textbox, text_overflow, block_ellipsis, matrix): previous_utf8_position = utf8_position if font.svg: - hb_face = get_pango_font_hb_face(pango_font) - svg_data = get_hb_face_data(hb_face, ot_color='svg') + svg_data = get_hb_object_data(font.hb_face, 'svg', glyph) if svg_data: # Do as explained in specification # https://learn.microsoft.com/typography/opentype/spec/svg @@ -1466,8 +1465,7 @@ def draw_first_line(stream, textbox, text_overflow, block_ellipsis, matrix): a = d = font.widths[glyph] / 1000 / font.upem * font_size emojis.append([image, font, a, d, x_advance, 0]) elif font.png: - hb_face = get_pango_font_hb_face(pango_font) - png_data = get_hb_face_data(hb_face, ot_color='png') + png_data = get_hb_object_data(font.hb_font, 'png', glyph) if png_data: pillow_image = Image.open(BytesIO(png_data)) image_id = f'{font.hash}{glyph}' diff --git a/weasyprint/pdf/stream.py b/weasyprint/pdf/stream.py index 2125fd4da..a8f47c710 100644 --- a/weasyprint/pdf/stream.py +++ b/weasyprint/pdf/stream.py @@ -12,13 +12,15 @@ from ..matrix import Matrix from ..text.constants import PANGO_STRETCH_PERCENT from ..text.ffi import ffi, harfbuzz, pango, units_to_double -from ..text.fonts import get_hb_face_data, get_pango_font_hb_face, get_pango_font_key +from ..text.fonts import get_hb_object_data, get_pango_font_hb_face, get_pango_font_key class Font: def __init__(self, pango_font): - hb_face = get_pango_font_hb_face(pango_font) - self.file_content = get_hb_face_data(hb_face) + self.hb_font = pango.pango_font_get_hb_font(pango_font) + self.hb_face = get_pango_font_hb_face(pango_font) + self.file_content = get_hb_object_data(self.hb_face) + self.index = harfbuzz.hb_face_get_index(self.hb_face) pango_metrics = pango.pango_font_get_metrics(pango_font, ffi.NULL) self.description = description = ffi.gc( @@ -81,9 +83,8 @@ def __init__(self, pango_font): # Fonttools full_font = io.BytesIO(self.file_content) - index = harfbuzz.hb_face_get_index(hb_face) try: - self.ttfont = TTFont(full_font, fontNumber=index) + self.ttfont = TTFont(full_font, fontNumber=self.index) except Exception: LOGGER.warning('Unable to read font') self.ttfont = None @@ -95,9 +96,9 @@ def __init__(self, pango_font): # Various properties self.italic_angle = 0 # TODO: this should be different - self.upem = harfbuzz.hb_face_get_upem(hb_face) - self.png = harfbuzz.hb_ot_color_has_png(hb_face) - self.svg = harfbuzz.hb_ot_color_has_svg(hb_face) + self.upem = harfbuzz.hb_face_get_upem(self.hb_face) + self.png = harfbuzz.hb_ot_color_has_png(self.hb_face) + self.svg = harfbuzz.hb_ot_color_has_svg(self.hb_face) self.stemv = 80 self.stemh = 80 self.widths = {} diff --git a/weasyprint/text/ffi.py b/weasyprint/text/ffi.py index 613cd10db..8775721b3 100644 --- a/weasyprint/text/ffi.py +++ b/weasyprint/text/ffi.py @@ -225,6 +225,8 @@ PangoLayoutLine * pango_layout_get_line_readonly ( PangoLayout *layout, int line); + hb_font_t * pango_font_get_hb_font (PangoFont *font); + PangoFontDescription * pango_font_description_new (void); void pango_font_description_free (PangoFontDescription *desc); PangoFontDescription * pango_font_description_copy ( diff --git a/weasyprint/text/fonts.py b/weasyprint/text/fonts.py index 8c4726bf6..98aa0a0bd 100644 --- a/weasyprint/text/fonts.py +++ b/weasyprint/text/fonts.py @@ -366,24 +366,27 @@ def get_pango_font_hb_face(pango_font): return pangoft2.pango_fc_font_map_get_hb_face(fontmap, fc_font) -def get_hb_face_data(hb_face, ot_color=None): - """Get binary data out of given Harfbuzz face. +def get_hb_object_data(hb_object, ot_color=None, glyph=None): + """Get binary data out of given Harfbuzz font or face. If ``ot_color`` is 'svg', return the SVG color glyph reference. If it’s 'png', return the PNG color glyph reference. Otherwise, return the whole face blob. """ if ot_color == 'png': - function = harfbuzz.hb_ot_color_glyph_reference_svg + hb_blob = harfbuzz.hb_ot_color_glyph_reference_png(hb_object, glyph) elif ot_color == 'svg': - function = harfbuzz.hb_ot_color_glyph_reference_png + hb_blob = harfbuzz.hb_ot_color_glyph_reference_svg(hb_object, glyph) else: - function = harfbuzz.hb_face_reference_blob - hb_blob = ffi.gc(function(hb_face), harfbuzz.hb_blob_destroy) + hb_blob = harfbuzz.hb_face_reference_blob(hb_object) with ffi.new('unsigned int *') as length: hb_data = harfbuzz.hb_blob_get_data(hb_blob, length) - if hb_data != ffi.NULL: - return ffi.unpack(hb_data, int(length[0])) + if hb_data == ffi.NULL: + data = None + else: + data = ffi.unpack(hb_data, int(length[0])) + harfbuzz.hb_blob_destroy(hb_blob) + return data @lru_cache()