diff --git a/pango/break.c b/pango/break.c index 3af083cee1c59fd8e583292cfa10c96c0c57f621..5622ca21607079280cfd8b896af8314eb67b546f 100644 --- a/pango/break.c +++ b/pango/break.c @@ -170,6 +170,8 @@ default_break (const char *text, GUnicodeBreakType prev_break_type; GUnicodeBreakType prev_prev_break_type; + PangoScript prev_script; + /* See Grapheme_Cluster_Break Property Values table of UAX#29 */ typedef enum { @@ -262,6 +264,7 @@ default_break (const char *text, prev_break_type = G_UNICODE_BREAK_UNKNOWN; prev_prev_break_type = G_UNICODE_BREAK_UNKNOWN; prev_wc = 0; + prev_script = PANGO_SCRIPT_COMMON; prev_jamo = NO_JAMO; prev_space_or_hyphen = FALSE; @@ -539,7 +542,6 @@ default_break (const char *text, } script = (PangoScript)g_unichar_get_script (wc); - /* ---- UAX#29 Word Boundaries ---- */ { is_word_boundary = FALSE; @@ -1571,9 +1573,11 @@ default_break (const char *text, attrs[i].break_inserts_hyphen = FALSE; attrs[i].break_removes_preceding = FALSE; - switch ((int)script) + switch ((int)prev_script) { case PANGO_SCRIPT_COMMON: + insert_hyphens = prev_wc == 0x00ad; + break; case PANGO_SCRIPT_HAN: case PANGO_SCRIPT_HANGUL: case PANGO_SCRIPT_HIRAGANA: @@ -1634,6 +1638,7 @@ default_break (const char *text, } prev_wc = wc; + prev_script = script; /* wc might not be a valid Unicode base character, but really all we * need to know is the last non-combining character */ diff --git a/pango/pango-attributes.h b/pango/pango-attributes.h index 5ea6bd9e01fc15c3fcaed7d369fcb0a84e47f334..f1bd56353537dbc06cae28cf053c004496e24639 100644 --- a/pango/pango-attributes.h +++ b/pango/pango-attributes.h @@ -739,6 +739,10 @@ void pango_attr_iterator_get_font (PangoAttrIterator * PANGO_AVAILABLE_IN_1_2 GSList * pango_attr_iterator_get_attrs (PangoAttrIterator *iterator); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoAttribute, pango_attribute_destroy) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoAttrList, pango_attr_list_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoAttrIterator, pango_attr_iterator_destroy) + G_END_DECLS #endif /* __PANGO_ATTRIBUTES_H__ */ diff --git a/pango/pango-coverage.h b/pango/pango-coverage.h index dbee7e9f2c37f4d2f4b18e97bd10efa307a59e76..b24d73d5fa3916b59e6b31638e600599fd9638be 100644 --- a/pango/pango-coverage.h +++ b/pango/pango-coverage.h @@ -101,6 +101,8 @@ PANGO_DEPRECATED_IN_1_44 PangoCoverage *pango_coverage_from_bytes (guchar *bytes, int n_bytes); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoCoverage, pango_coverage_unref) + G_END_DECLS #endif /* __PANGO_COVERAGE_H__ */ diff --git a/pango/pango-font.h b/pango/pango-font.h index 6f3284fadd26a2bfc396f85631d298f74ed4fc94..c56fb792c9e73b06d32e1e28799aff4e2e7cfb6f 100644 --- a/pango/pango-font.h +++ b/pango/pango-font.h @@ -689,6 +689,7 @@ PangoLanguage ** pango_font_get_languages (PangoFont *font); G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoFontFamily, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoFontFace, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoFont, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoFontDescription, pango_font_description_free) G_END_DECLS diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 050138dff38819f89ea7c1c3bdd867ef137ac84e..a5806774b0c3911c8c4175dd4ed8001a724d5278 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -3930,15 +3930,29 @@ process_item (PangoLayout *layout, width += state->log_widths[state->log_widths_offset + i]; } - if ((width <= state->remaining_width || (item->num_chars == 1 && !line->runs)) && + if (!no_break_at_end && + can_break_at (layout, state->start_offset + item->num_chars, wrap)) + { + if (processing_new_item) + { + compute_log_widths (layout, state); + processing_new_item = FALSE; + } + + extra_width = find_break_extra_width (layout, state, item->num_chars); + } + else + extra_width = 0; + + if ((width + extra_width <= state->remaining_width || (item->num_chars == 1 && !line->runs)) && !no_break_at_end) { - DEBUG1 ("%d <= %d", width, state->remaining_width); + DEBUG1 ("%d + %d <= %d", width, extra_width, state->remaining_width); insert_run (line, state, item, NULL, FALSE); width = pango_glyph_string_get_width (((PangoGlyphItem *)(line->runs->data))->glyphs); - if (width <= state->remaining_width || (item->num_chars == 1 && !line->runs)) + if (width + extra_width <= state->remaining_width || (item->num_chars == 1 && !line->runs)) { state->remaining_width -= width; state->remaining_width = MAX (state->remaining_width, 0); @@ -4007,7 +4021,7 @@ retry_break: if (can_break_at (layout, state->start_offset + num_chars, wrap) && (num_chars > 0 || line->runs)) { - DEBUG1 ("possible breakpoint: %d", num_chars); + DEBUG1 ("possible breakpoint: %d, extra_width %d", num_chars, extra_width); if (num_chars == 0 || width + extra_width < state->remaining_width - safe_distance) { @@ -4044,10 +4058,13 @@ retry_break: if (num_chars > 0 && layout->log_attrs[state->start_offset + num_chars - 1].is_white) extra_width = - state->log_widths[state->log_widths_offset + num_chars - 1]; + else if (item == new_item && + break_needs_hyphen (layout, state, num_chars)) + extra_width = state->hyphen_width; else extra_width = 0; - DEBUG1 ("measured breakpoint %d: %d", num_chars, new_break_width); + DEBUG1 ("measured breakpoint %d: %d, extra %d", num_chars, new_break_width, extra_width); if (new_item != item) { @@ -4107,7 +4124,8 @@ retry_break: if (break_num_chars == item->num_chars) { - if (break_needs_hyphen (layout, state, break_num_chars)) + if (can_break_at (layout, state->start_offset + break_num_chars, wrap) && + break_needs_hyphen (layout, state, break_num_chars)) item->analysis.flags |= PANGO_ANALYSIS_FLAG_NEED_HYPHEN; insert_run (line, state, item, NULL, TRUE); @@ -5946,6 +5964,7 @@ add_missing_hyphen (PangoLayoutLine *line, int width; int start_offset; + DEBUG1("add a missing hyphen"); /* The last run fit onto the line without breaking it, but it still needs a hyphen */ width = pango_glyph_string_get_width (run->glyphs); diff --git a/pango/pango-layout.h b/pango/pango-layout.h index 502f5e2931152ae2beda99731fbb56db87f66a91..3b725adcbb433ed517263630a86328063bb74b53 100644 --- a/pango/pango-layout.h +++ b/pango/pango-layout.h @@ -494,6 +494,10 @@ int pango_layout_iter_get_baseline (PangoLayoutIter *iter); PANGO_AVAILABLE_IN_1_50 int pango_layout_iter_get_run_baseline (PangoLayoutIter *iter); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoLayout, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoLayoutIter, pango_layout_iter_free) + G_END_DECLS #endif /* __PANGO_LAYOUT_H__ */ diff --git a/pango/pango-tabs.h b/pango/pango-tabs.h index e8ce1b97fd18360ca691cf502f2a83b433992faa..d2a68d5ade84ce7ddd7616a2345eefc90b2e1f98 100644 --- a/pango/pango-tabs.h +++ b/pango/pango-tabs.h @@ -92,6 +92,9 @@ char * pango_tab_array_to_string (PangoTabArray *tab_array); PANGO_AVAILABLE_IN_1_50 PangoTabArray * pango_tab_array_from_string (const char *text); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoTabArray, pango_tab_array_free) + G_END_DECLS #endif /* __PANGO_TABS_H__ */ diff --git a/tests/breaks/eight.expected b/tests/breaks/eight.expected index 39794d224b8fc6f6676f1976f9898c6bce58422a..d71bb02f8f6c2bad2c24446749d05f2038f67a6b 100644 --- a/tests/breaks/eight.expected +++ b/tests/breaks/eight.expected @@ -4,4 +4,4 @@ Whitespace: x x x x Sentences: bs e b Words: bs be bs e s be bs be b bs be bs be bs be bs be bs be b Graphemes: b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b -Hyphens: i i i i i i i i i i i i i i i i +Hyphens: i i i i i i i i i i i i i i i i diff --git a/tests/breaks/eleven.expected b/tests/breaks/eleven.expected index 8df898693b421846aafeaf9559a54bbcafefe375..b4a33897d6ef394b6dcfb0cc19150ab7f9d788e2 100644 --- a/tests/breaks/eleven.expected +++ b/tests/breaks/eleven.expected @@ -1,7 +1,7 @@ -Text: ⁦❤⁩ ⁦️⁩ ⁦︎⁩ ⁦︎⁩ ⁦👨⁩ [0x200d]⁦🦰⁩ ⁦👨⁩⁦🏿⁩ [0x200d]⁦🦱⁩ ⁦0⁩ ⁦️⁩ ⁦⃣⁩ ⁦🏴⁩[0xe0075][0xe0073][0xe0063][0xe0061][0xe007f] ⁦🇩⁩⁦🇪⁩ ⁦️⁩ [0x0a] -Breaks: c lc lc lc lc lc c lc -Whitespace: w w -Sentences: bs e b -Words: b b b bs be b b b -Graphemes: b b b b b b b b -Hyphens: i i i i i i i i +Text: ⁦❤⁩⁦️⁩ ⁦︎⁩ ⁦︎⁩ ⁦👨⁩[0x200d] ⁦🦰⁩ ⁦👨⁩⁦🏿⁩[0x200d] ⁦🦱⁩ ⁦0⁩⁦️⁩ ⁦⃣⁩ ⁦🏴⁩[0xe0075][0xe0073][0xe0063][0xe0061][0xe007f] ⁦🇩⁩⁦🇪⁩⁦️⁩ [0x0a] +Breaks: c lc lc lc lc lc c Lc +Whitespace: w w +Sentences: bs e b +Words: b b b bs be b b b +Graphemes: b b b b b b b b +Hyphens: i i i i i diff --git a/tests/breaks/fifteen.expected b/tests/breaks/fifteen.expected index 93b37c39378aaa6a155b57a57357cc04f1c43d68..3521a70bd44126679ebb5660231e6c0ba4852132 100644 --- a/tests/breaks/fifteen.expected +++ b/tests/breaks/fifteen.expected @@ -1,7 +1,7 @@ Text: ⁦o⁩ ⁦n⁩ ⁦e⁩ [ ] ⁦t⁩ ⁦w⁩ ⁦o⁩ ⁦-⁩ ⁦t⁩ ⁦h⁩ ⁦r⁩ ⁦e⁩ ⁦e⁩ [ ] ⁦f⁩ ⁦o⁩ [0xad] ⁦u⁩ ⁦r⁩ [0x0a] -Breaks: c c c c lc c c c lc c c c c c lc c c lc c c lc +Breaks: c c c c lc c c c lc c c c c c lc c c lc c c Lc Whitespace: x x w w Sentences: bs e b Words: bs be bs be bs be bs be b Graphemes: b b b b b b b b b b b b b b b b b b b b b -Hyphens: i i i i i i i i i +Hyphens: i i i i i i i i i i diff --git a/tests/breaks/one.expected b/tests/breaks/one.expected index 44fee3eff79fd884be7367802a2d22946566cff4..6c81125613da803c074dcfa5f3a0920ea8c1bbcd 100644 --- a/tests/breaks/one.expected +++ b/tests/breaks/one.expected @@ -1,7 +1,7 @@ Text: ⁦a⁩ ⁦b⁩ ⁦c⁩ ⁦/⁩ ⁦d⁩ ⁦e⁩ ⁦f⁩ [ ] ⁦g⁩ ⁦h⁩ ⁦i⁩ [0xad] ⁦j⁩ ⁦k⁩ ⁦l⁩ ⁦.⁩ [ ] ⁦B⁩ ⁦l⁩ ⁦a⁩ [0x0a] -Breaks: c c c c lc c c c lc c c c lc c c c c lc c c c lc +Breaks: c c c c lc c c c lc c c c lc c c c c lc c c c Lc Whitespace: x x w w Sentences: bs e bs e b Words: bs be bs be bs be b bs be b Graphemes: b b b b b b b b b b b b b b b b b b b b b b -Hyphens: i i i i i i i i i i i +Hyphens: i i i i i i i i i i i i diff --git a/tests/breaks/seventeen.expected b/tests/breaks/seventeen.expected index 8f5f2749ade6d9d4f3e88e2835542b3909f5f69d..35fb512043036ef022c2baa838e499b2ac6213fc 100644 --- a/tests/breaks/seventeen.expected +++ b/tests/breaks/seventeen.expected @@ -4,4 +4,4 @@ Whitespace: x x x w Sentences: bs e bs e bs e b Words: bs be bs be bs be bs e s be bs be bs be bs be bs e s be bs be bs be bs be bs e s e s be b Graphemes: b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b -Hyphens: i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i +Hyphens: i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i diff --git a/tests/breaks/sixteen.expected b/tests/breaks/sixteen.expected index 0fd06fb2137a9e8c6256e7bc75b2c7f2174a394c..2868b8e49169de48d461264919112da1311d0f2c 100644 --- a/tests/breaks/sixteen.expected +++ b/tests/breaks/sixteen.expected @@ -1,7 +1,7 @@ Text: ⁦h⁩ ⁦y⁩ ⁦‧⁩ ⁦p⁩ ⁦h⁩ ⁦e⁩ ⁦n⁩ ⁦|⁩ ⁦a⁩ ⁦t⁩ ⁦i⁩ ⁦o⁩ ⁦n⁩ [ ] ⁦o⁩ ⁦v⁩ ⁦e⁩ ⁦r⁩ [0xad] ⁦l⁩ ⁦o⁩ ⁦a⁩ ⁦d⁩ [0x0a] -Breaks: c c c lc c c c c lc c c c c c lc c c c c lc c c c c lc +Breaks: c c c lc c c c c lc c c c c c lc c c c c lc c c c c Lc Whitespace: x w w Sentences: bs e b Words: bs e s be bs be bs be b Graphemes: b b b b b b b b b b b b b b b b b b b b b b b b b -Hyphens: i ri i i i i i i i i i i i i i i +Hyphens: i ri i i i i i i i i i i i i i i i diff --git a/tests/breaks/thirteen.expected b/tests/breaks/thirteen.expected index e6b1787d37ed0d610b4173364fd9cec3b255636d..25a38150d834663bcb15cb5e82f249c4236f1d47 100644 --- a/tests/breaks/thirteen.expected +++ b/tests/breaks/thirteen.expected @@ -1,7 +1,7 @@ Text: ⁦a⁩ [ ] ⁦a⁩ ⁦b⁩ [0x200b] ⁦s⁩ ⁦p⁩ [0x200b] [ ] [ ] ⁦d⁩ ⁦e⁩ [0xad] ⁦f⁩ ⁦g⁩ [ ] ⁦b⁩ [0x0a] -Breaks: c c lc c c lc c c c c lc c c lc c c lc c lc +Breaks: c c lc c c lc c c c c lc c c lc c c lc c Lc Whitespace: x x x x w w Sentences: bs e b Words: bs be bs be bs be b Graphemes: b b b b b b b b b b b b b b b b b b b -Hyphens: i i i i i i +Hyphens: i i i i i i i i diff --git a/tests/breaks/two.break b/tests/breaks/two.break index 6ff0a36e65b0a8e785b983301ad166b3ae54992f..53c39c5cb976e273da7a3b10a898001b23e4b26a 100644 --- a/tests/breaks/two.break +++ b/tests/breaks/two.break @@ -1,3 +1,3 @@ # Example from https://gitlab.gnome.org/GNOME/pango/issues/218 # This shows difference between word start/end and boundary -goril·les +goril‧les diff --git a/tests/breaks/two.expected b/tests/breaks/two.expected index 2921d22490f9241bbd30a2193c78008f8a7dbbe0..58d1518622a71e9461b07533b6e3af25f7fa937b 100644 --- a/tests/breaks/two.expected +++ b/tests/breaks/two.expected @@ -1,7 +1,7 @@ -Text: ⁦g⁩ ⁦o⁩ ⁦r⁩ ⁦i⁩ ⁦l⁩ ⁦·⁩ ⁦l⁩ ⁦e⁩ ⁦s⁩ [0x0a] -Breaks: c c c c c c c c c c lc -Whitespace: w w -Sentences: bs e b -Words: bs e s be b -Graphemes: b b b b b b b b b b b -Hyphens: i i i i i i i +Text: ⁦g⁩ ⁦o⁩ ⁦r⁩ ⁦i⁩ ⁦l⁩ ⁦‧⁩ ⁦l⁩ ⁦e⁩ ⁦s⁩ [0x0a] +Breaks: c c c c c c lc c c c Lc +Whitespace: w w +Sentences: bs e b +Words: bs e s be b +Graphemes: b b b b b b b b b b b +Hyphens: i i i i ri i i diff --git a/tests/layouts/bratwurst.expected b/tests/layouts/bratwurst.expected new file mode 100644 index 0000000000000000000000000000000000000000..f81dbaeb7091c383c9be2f80539d849a046db6e2 --- /dev/null +++ b/tests/layouts/bratwurst.expected @@ -0,0 +1,32 @@ +Bratwurst +--- parameters + +wrapped: 0 +ellipsized: 0 +lines: 1 +width: 102400 + +--- attributes + +range 0 4 +range 4 2147483647 +4 4294967295 style italic +range 2147483647 2147483647 + +--- directions + +0 0 0 0 0 0 0 0 0 + +--- cursor positions + +0(0) 1(0) 2(0) 3(0) 4(0) 5(0) 6(0) 7(0) 8(0) 8(1) + +--- lines + +i=1, index=0, paragraph-start=1, dir=ltr 'Bratwurst' + +--- runs + +i=1, index=0, chars=4, level=0, gravity=south, flags=0, font=OMITTED, script=latin, language=en-us, 'Brat' +i=2, index=4, chars=5, level=0, gravity=south, flags=0, font=OMITTED, script=latin, language=en-us, 'wurst' +i=3, index=9, no run, line end diff --git a/tests/layouts/bratwurst.layout b/tests/layouts/bratwurst.layout new file mode 100644 index 0000000000000000000000000000000000000000..651042769ea63c2e902a36ea076b30c09bc34c19 --- /dev/null +++ b/tests/layouts/bratwurst.layout @@ -0,0 +1,21 @@ +{ + "text" : "Bratwurst", + "attributes" : [ + { + "start" : 4, + "type" : "style", + "value" : "italic" + } + ], + "font" : "Sans Bold 32", + "tabs" : { + "positions-in-pixels" : true, + "positions" : [ + 0, + 50, + 100 + ] + }, + "width" : 102400, + "line-spacing" : 1.2999999523162842 +} \ No newline at end of file