mirror of
https://github.com/Kozea/WeasyPrint.git
synced 2024-10-05 08:27:22 +03:00
Don't store Pango layout between page layout and drawing steps
Creating Pango layouts during page layout and recreating them when drawing pages is a little bit slower but frees A LOT of memory.
This commit is contained in:
parent
3cbb2e6143
commit
4e6d449c5c
@ -1015,7 +1015,7 @@ def draw_text(context, textbox, enable_hinting):
|
||||
|
||||
context.move_to(textbox.position_x, textbox.position_y + textbox.baseline)
|
||||
context.set_source_rgba(*textbox.style['color'])
|
||||
show_first_line(context, textbox.pango_layout)
|
||||
show_first_line(context, textbox)
|
||||
values = textbox.style['text_decoration']
|
||||
|
||||
thickness = textbox.style['font_size'] / 18 # Like other browsers do
|
||||
|
@ -970,7 +970,7 @@ def split_text_box(context, box, available_width, skip):
|
||||
# No need to encode what’s after resume_at (if set) or length (if
|
||||
# resume_at is not set). One code point is one or more byte, so
|
||||
# UTF-8 indexes are always bigger or equal to Unicode indexes.
|
||||
new_text = layout.text_bytes.decode('utf8')
|
||||
new_text = layout.text
|
||||
encoded = text.encode('utf8')
|
||||
if resume_at is not None:
|
||||
between = encoded[length:resume_at].decode('utf8')
|
||||
|
@ -139,6 +139,8 @@ ffi.cdef('''
|
||||
PangoLayout *layout, const PangoFontDescription *desc);
|
||||
void pango_layout_set_wrap (
|
||||
PangoLayout *layout, PangoWrapMode wrap);
|
||||
void pango_layout_set_single_paragraph_mode (
|
||||
PangoLayout *layout, gboolean setting);
|
||||
int pango_layout_get_baseline (PangoLayout *layout);
|
||||
|
||||
PangoLayoutIter * pango_layout_get_iter (PangoLayout *layout);
|
||||
@ -600,7 +602,7 @@ def first_line_metrics(first_line, text, layout, resume_at, space_collapse,
|
||||
if u'\u00ad' in first_line_text:
|
||||
if first_line_text[0] == u'\u00ad':
|
||||
length += 2 # len(u'\u00ad'.encode('utf8'))
|
||||
for i in range(len(layout.text_bytes.decode('utf8'))):
|
||||
for i in range(len(layout.text)):
|
||||
while i + soft_hyphens + 1 < len(first_line_text):
|
||||
if first_line_text[i + soft_hyphens + 1] == u'\u00ad':
|
||||
soft_hyphens += 1
|
||||
@ -609,12 +611,16 @@ def first_line_metrics(first_line, text, layout, resume_at, space_collapse,
|
||||
length += soft_hyphens * 2 # len(u'\u00ad'.encode('utf8'))
|
||||
width, height = get_size(first_line, style)
|
||||
baseline = units_to_double(pango.pango_layout_get_baseline(layout.layout))
|
||||
layout.deactivate()
|
||||
return layout, length, resume_at, width, height, baseline
|
||||
|
||||
|
||||
class Layout(object):
|
||||
"""Object holding PangoLayout-related cdata pointers."""
|
||||
def __init__(self, context, font_size, style):
|
||||
self.setup(context, font_size, style)
|
||||
|
||||
def setup(self, context, font_size, style):
|
||||
from .fonts import ZERO_FONTSIZE_CRASHES_CAIRO
|
||||
|
||||
# Cairo crashes with font-size: 0 when using Win32 API
|
||||
@ -676,8 +682,7 @@ class Layout(object):
|
||||
# Keep only the first two lines, we don't need the other ones
|
||||
text, bytestring = unicode_to_char_p(
|
||||
'\n'.join(text.split('\n', 3)[:2]))
|
||||
self.text = text
|
||||
self.text_bytes = bytestring
|
||||
self.text = bytestring.decode('utf-8')
|
||||
pango.pango_layout_set_text(self.layout, text, -1)
|
||||
|
||||
def get_font_metrics(self):
|
||||
@ -705,6 +710,15 @@ class Layout(object):
|
||||
pango.pango_tab_array_free)
|
||||
pango.pango_layout_set_tabs(self.layout, array)
|
||||
|
||||
def deactivate(self):
|
||||
del self.layout
|
||||
del self.font
|
||||
del self.language
|
||||
|
||||
def reactivate(self, style):
|
||||
self.setup(self.context, style['font_size'], style)
|
||||
self.set_text(self.text)
|
||||
|
||||
|
||||
class FontMetrics(object):
|
||||
def __init__(self, context, font, language):
|
||||
@ -850,7 +864,7 @@ def create_layout(text, style, context, max_width, justification_spacing):
|
||||
pango.pango_layout_set_width(
|
||||
layout.layout, units_from_double(max_width))
|
||||
|
||||
text_bytes = layout.text_bytes
|
||||
text_bytes = layout.text.encode('utf-8')
|
||||
|
||||
# Word and letter spacings
|
||||
word_spacing = style['word_spacing'] + justification_spacing
|
||||
@ -1149,15 +1163,14 @@ def split_first_line(text, style, context, max_width, justification_spacing,
|
||||
style['hyphenate_character'])
|
||||
|
||||
|
||||
def show_first_line(context, pango_layout):
|
||||
"""Draw the given ``line`` to the Cairo ``context``."""
|
||||
def show_first_line(context, textbox):
|
||||
"""Draw the given ``textbox`` line to the Cairo ``context``."""
|
||||
textbox.pango_layout.reactivate(textbox.style)
|
||||
pango.pango_layout_set_single_paragraph_mode(
|
||||
textbox.pango_layout.layout, True)
|
||||
first_line, _ = textbox.pango_layout.get_first_line()
|
||||
context = ffi.cast('cairo_t *', context._pointer)
|
||||
# Set an infinite width as we don't want to break lines when drawing, the
|
||||
# lines have already been split and the size may differ for example because
|
||||
# of hinting.
|
||||
pango.pango_layout_set_width(pango_layout.layout, -1)
|
||||
pangocairo.pango_cairo_show_layout_line(
|
||||
context, pango_layout.get_first_line()[0])
|
||||
pangocairo.pango_cairo_show_layout_line(context, first_line)
|
||||
|
||||
|
||||
def can_break_text(text, lang):
|
||||
|
Loading…
Reference in New Issue
Block a user