diff --git a/tests/draw/test_text.py b/tests/draw/test_text.py index 95440ba2c..26c17a8d8 100644 --- a/tests/draw/test_text.py +++ b/tests/draw/test_text.py @@ -453,6 +453,59 @@ def test_text_align_justify(assert_pixels):
a c e
''') +def test_text_align_justify_nbsp(assert_pixels): + assert_pixels(''' + _________ + _RR___RR_ + _RR___RR_ + _RR______ + _RR______ + _________ + ''', ''' + +
a c e
''') + +def test_text_align_justify_nbsp_2(assert_pixels): + assert_pixels(''' + _________ + _RR_RR_RR + _RR_RR_RR + _________ + _________ + _________ + ''', ''' + +
a\u202Fc\u202Fe
''') + + def test_text_word_spacing(assert_pixels): assert_pixels(''' ___________________ diff --git a/weasyprint/layout/inline.py b/weasyprint/layout/inline.py index d67806d2e..1ab8ad59c 100644 --- a/weasyprint/layout/inline.py +++ b/weasyprint/layout/inline.py @@ -1128,7 +1128,8 @@ def justify_line(context, line, extra_width): def count_spaces(box): if isinstance(box, boxes.TextBox): # TODO: remove trailing spaces correctly - return box.text.count(' ') + # here we count spaces and non-breaking spaces + return box.text.count(' ') + box.text.count("\u00A0") elif isinstance(box, (boxes.LineBox, boxes.InlineBox)): return sum(count_spaces(child) for child in box.children) else: diff --git a/weasyprint/text/line_break.py b/weasyprint/text/line_break.py index 27bf471d9..32c55ab94 100644 --- a/weasyprint/text/line_break.py +++ b/weasyprint/text/line_break.py @@ -186,14 +186,31 @@ def add_attr(start, end, spacing): text, bytestring = unicode_to_char_p(self.text) pango.pango_layout_set_text(self.layout, text, -1) + nbsp = b'\xC2\xA0' # somehow \u00A0 is converted into this space_spacing = int(word_spacing * TO_UNITS + letter_spacing) - position = bytestring.find(b' ') + + def find_next_pos(start=0): + """ + search for first occurrence of ' ' or NBSP + return index (or -1) and lenght of searched string + """ + p1 = bytestring.find(b' ', start) + p2 = bytestring.find(nbsp, start) + if p1 == -1 and p2 == -1: + return -1, None + if p2 == -1: + return p1, 1 + if p1 == -1 or p2 < p1: + return p2, 2 + return p1, 1 + + position, splen = find_next_pos() # Pango gives only half of word-spacing on boundaries boundary_positions = (0, len(bytestring) - 1) while position != -1: factor = 1 + (position in boundary_positions) - add_attr(position, position + 1, factor * space_spacing) - position = bytestring.find(b' ', position + 1) + add_attr(position, position + splen, factor * space_spacing) + position, splen = find_next_pos(position + splen) if word_breaking: attr = pango.pango_attr_insert_hyphens_new(False)