summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--meson.build8
-rw-r--r--pango/break.c75
-rw-r--r--pango/meson.build38
-rw-r--r--pango/pango-break.h5
-rw-r--r--pango/pango-context.c9
-rw-r--r--pango/pango-engine-private.h2
-rw-r--r--pango/pango-layout.c109
-rw-r--r--tests/breaks/one.expected10
-rw-r--r--tests/itemize/one.expected7
-rw-r--r--tests/itemize/one.items1
-rw-r--r--tests/meson.build29
-rw-r--r--tests/test-break.c5
-rw-r--r--tests/test-itemize.c269
-rw-r--r--utils/meson.build2
14 files changed, 429 insertions, 140 deletions
diff --git a/meson.build b/meson.build
index 73b5da2b..d1150907 100644
--- a/meson.build
+++ b/meson.build
@@ -183,6 +183,8 @@ endif
# Dependencies
pango_deps = []
+pangoxft_deps = []
+pangocairo_deps = []
glib_req_version = '>= 2.59.2'
fribidi_req_version = '>= 0.19.7'
@@ -314,8 +316,8 @@ endif
xft_dep = dependency('xft', version: xft_req_version, required: false)
if xft_dep.found() and fontconfig_dep.found() and freetype_dep.found()
pango_conf.set('HAVE_XFT', 1)
- pango_deps += dependency('xrender', required: false)
- pango_deps += xft_dep
+ pangoxft_deps += dependency('xrender', required: false)
+ pangoxft_deps += xft_dep
endif
if host_system == 'darwin'
@@ -488,7 +490,7 @@ endif
if cairo_dep.found()
pango_conf.set('HAVE_CAIRO', 1)
- pango_deps += cairo_dep
+ pangocairo_deps += cairo_dep
pangocairo_requires = ''
diff --git a/pango/break.c b/pango/break.c
index 13ccbdaf..11a1e34a 100644
--- a/pango/break.c
+++ b/pango/break.c
@@ -22,7 +22,6 @@
#include "config.h"
#include "pango-break.h"
-#include "pango-engine-private.h"
#include "pango-script-private.h"
#include "pango-emoji-private.h"
#include "pango-break-table.h"
@@ -984,7 +983,6 @@ pango_default_break (const gchar *text,
attrs[i].is_char_break = FALSE;
attrs[i].is_line_break = FALSE;
attrs[i].is_mandatory_break = FALSE;
- attrs[i].is_soft_hyphen = FALSE;
/* Rule LB1:
assign a line breaking class to each code point of the input. */
@@ -1365,15 +1363,9 @@ pango_default_break (const gchar *text,
case BREAK_ALLOWED:
attrs[i].is_line_break = TRUE;
- /* fall through */
+ break;
case BREAK_ALREADY_HANDLED:
- if (attrs[i].is_line_break)
- {
- /* After Soft Hyphen */
- if (prev_wc == 0x00AD)
- attrs[i].is_soft_hyphen = TRUE;
- }
break;
default:
@@ -1581,23 +1573,25 @@ pango_default_break (const gchar *text,
}
static gboolean
+break_script (const char *item_text,
+ unsigned int item_length,
+ const PangoAnalysis *analysis,
+ PangoLogAttr *attrs,
+ int attrs_len);
+
+static gboolean
tailor_break (const gchar *text,
gint length,
PangoAnalysis *analysis,
PangoLogAttr *attrs,
int attrs_len)
{
- if (analysis->lang_engine && PANGO_ENGINE_LANG_GET_CLASS (analysis->lang_engine)->script_break)
- {
- if (length < 0)
- length = strlen (text);
- else if (text == NULL)
- text = "";
+ if (length < 0)
+ length = strlen (text);
+ else if (text == NULL)
+ text = "";
- PANGO_ENGINE_LANG_GET_CLASS (analysis->lang_engine)->script_break (analysis->lang_engine, text, length, analysis, attrs, attrs_len);
- return TRUE;
- }
- return FALSE;
+ return break_script (text, length, analysis, attrs, attrs_len);
}
/**
@@ -1794,7 +1788,6 @@ pango_get_log_attrs (const char *text,
g_return_if_fail (log_attrs != NULL);
analysis.level = level;
- analysis.lang_engine = _pango_get_language_engine ();
pango_default_break (text, length, &analysis, log_attrs, attrs_len);
@@ -1824,7 +1817,7 @@ pango_get_log_attrs (const char *text,
#include "break-indic.c"
#include "break-thai.c"
-static void
+static gboolean
break_script (const char *item_text,
unsigned int item_length,
const PangoAnalysis *analysis,
@@ -1853,43 +1846,9 @@ break_script (const char *item_text,
case PANGO_SCRIPT_THAI:
break_thai (item_text, item_length, analysis, attrs, attrs_len);
break;
+ default:
+ return FALSE;
}
-}
-
-/* Wrap language breaker in PangoEngineLang to pass it through old API,
- * from times when there were modules and engines. */
-typedef PangoEngineLang PangoLanguageEngine;
-typedef PangoEngineLangClass PangoLanguageEngineClass;
-static GType pango_language_engine_get_type (void) G_GNUC_CONST;
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-G_DEFINE_TYPE (PangoLanguageEngine, pango_language_engine, PANGO_TYPE_ENGINE_LANG);
-G_GNUC_END_IGNORE_DEPRECATIONS
-static void
-_pango_language_engine_break (PangoEngineLang *engine G_GNUC_UNUSED,
- const char *item_text,
- int item_length,
- PangoAnalysis *analysis,
- PangoLogAttr *attrs,
- int attrs_len)
-{
- break_script (item_text, item_length, analysis, attrs, attrs_len);
-}
-static void
-pango_language_engine_class_init (PangoEngineLangClass *class)
-{
- class->script_break = _pango_language_engine_break;
-}
-static void
-pango_language_engine_init (PangoEngineLang *object)
-{
-}
-
-PangoEngineLang *
-_pango_get_language_engine (void)
-{
- static PangoEngineLang *engine;
- if (g_once_init_enter (&engine))
- g_once_init_leave (&engine, g_object_new (pango_language_engine_get_type(), NULL));
- return engine;
+ return TRUE;
}
diff --git a/pango/meson.build b/pango/meson.build
index 4ca062ec..faf38780 100644
--- a/pango/meson.build
+++ b/pango/meson.build
@@ -56,6 +56,27 @@ pango_headers = [
'pango-version-macros.h',
]
+pango_requires = [
+ 'gobject-2.0',
+]
+
+if fontconfig_dep.found()
+ pango_headers += [
+ 'pangofc-font.h',
+ 'pangofc-fontmap.h',
+ 'pangofc-decoder.h',
+ ]
+ pango_sources += [
+ 'pangofc-font.c',
+ 'pangofc-fontmap.c',
+ 'pangofc-decoder.c',
+ 'pangofc-shape.c',
+ ]
+ pango_requires += [
+ fontconfig_pc,
+ ]
+endif
+
install_headers(pango_headers, subdir: pango_api_path)
# Features header
@@ -155,7 +176,7 @@ pkgconfig.generate(libpango,
name: 'Pango',
description: 'Internationalized text handling',
version: meson.project_version(),
- requires: ['gobject-2.0'],
+ requires: pango_requires,
filebase: 'pango',
subdirs: pango_api_name,
install_dir: join_paths(pango_libdir, 'pkgconfig'),
@@ -165,17 +186,10 @@ pkgconfig.generate(libpango,
if build_pangoft2
pangoft2_headers = [
'pango-ot.h',
- 'pangofc-font.h',
- 'pangofc-fontmap.h',
- 'pangofc-decoder.h',
'pangoft2.h',
]
pangoft2_public_sources = [
- 'pangofc-font.c',
- 'pangofc-fontmap.c',
- 'pangofc-decoder.c',
- 'pangofc-shape.c',
'pangoft2.c',
]
@@ -282,7 +296,7 @@ if xft_dep.found() and fontconfig_dep.found()
soversion: pango_soversion,
darwin_versions : pango_osxversion,
install: true,
- dependencies: pango_deps + [ libpango_dep, libpangoft2_dep ],
+ dependencies: pango_deps + pangoxft_deps + [ libpango_dep, libpangoft2_dep ],
include_directories: [ root_inc, pango_inc ],
c_args: common_cflags + pango_debug_cflags + pango_cflags + [
'-DPANGO_DISABLE_DEPRECATION_WARNINGS',
@@ -408,15 +422,13 @@ if cairo_dep.found()
'pangocairo-render.c',
]
- pangocairo_deps = pango_deps + [ libpango_dep ]
+ pangocairo_deps += libpango_dep
if pango_font_backends.contains('freetype')
pangocairo_sources += [
'pangocairo-fcfont.c',
'pangocairo-fcfontmap.c',
]
-
- pangocairo_deps += libpangoft2_dep
endif
if host_system == 'windows' and pango_font_backends.contains('win32')
@@ -486,7 +498,7 @@ if cairo_dep.found()
libpangocairo_dep = declare_dependency(
link_with: libpangocairo,
include_directories: root_inc,
- dependencies: pango_deps + [ libpango_dep ],
+ dependencies: pangocairo_deps + pango_deps + [ libpango_dep ],
sources: pangocairo_dep_sources,
)
diff --git a/pango/pango-break.h b/pango/pango-break.h
index 66d81631..92af390b 100644
--- a/pango/pango-break.h
+++ b/pango/pango-break.h
@@ -79,9 +79,6 @@ G_BEGIN_DECLS
* This flag implements Unicode's
* <ulink url="http://www.unicode.org/reports/tr29/">Word
* Boundaries</ulink> semantics. (Since: 1.22)
- * @is_soft_hyphen: is a line break due to a Soft Hyphen (0x00AD).
- * This indicates a position where a hyphen should be inserted
- * if the break is taken.
*
* The #PangoLogAttr structure stores information
* about the attributes of a single character.
@@ -89,6 +86,7 @@ G_BEGIN_DECLS
struct _PangoLogAttr
{
guint is_line_break : 1; /* Can break line in front of character */
+
guint is_mandatory_break : 1; /* Must break line in front of character */
guint is_char_break : 1; /* Can break here when doing char wrap */
@@ -132,7 +130,6 @@ struct _PangoLogAttr
/* Word boundary as defined by UAX#29 */
guint is_word_boundary : 1; /* is NOT in the middle of a word */
- guint is_soft_hyphen : 1; /* line break due to a soft hyphen */
};
/* Determine information about cluster/word/line breaks in a string
diff --git a/pango/pango-context.c b/pango/pango-context.c
index f187a92f..413119f3 100644
--- a/pango/pango-context.c
+++ b/pango/pango-context.c
@@ -758,7 +758,6 @@ struct _ItemizeState
PangoEmojiIter emoji_iter;
PangoLanguage *derived_lang;
- PangoEngineLang *lang_engine;
PangoFontset *current_fonts;
FontCache *cache;
@@ -1061,7 +1060,6 @@ itemize_state_init (ItemizeState *state,
state->gravity_hint = state->context->gravity_hint;
state->resolved_gravity = PANGO_GRAVITY_AUTO;
state->derived_lang = NULL;
- state->lang_engine = NULL;
state->current_fonts = NULL;
state->cache = NULL;
state->base_font = NULL;
@@ -1165,7 +1163,6 @@ itemize_state_add_character (ItemizeState *state,
}
if (!force_break &&
- state->item->analysis.lang_engine == state->lang_engine &&
state->item->analysis.shape_engine == shape_engine &&
state->item->analysis.font == font)
{
@@ -1181,7 +1178,6 @@ itemize_state_add_character (ItemizeState *state,
state->item->length = 0;
state->item->num_chars = 1;
state->item->analysis.shape_engine = shape_engine;
- state->item->analysis.lang_engine = state->lang_engine;
if (font)
g_object_ref (font);
@@ -1404,11 +1400,6 @@ itemize_state_update_for_new_run (ItemizeState *state)
state->changed |= DERIVED_LANG_CHANGED;
}
- if ((state->changed & DERIVED_LANG_CHANGED) || !state->lang_engine)
- {
- state->lang_engine = _pango_get_language_engine ();
- }
-
if (state->changed & (EMOJI_CHANGED))
{
state->changed |= FONT_CHANGED;
diff --git a/pango/pango-engine-private.h b/pango/pango-engine-private.h
index de54ee09..cd0b6103 100644
--- a/pango/pango-engine-private.h
+++ b/pango/pango-engine-private.h
@@ -42,8 +42,6 @@ PangoCoverageLevel _pango_engine_shape_covers (PangoEngineShape *engine,
PangoEngineShape *_pango_get_fallback_shaper (void) /* XXX got to go when we switch to harfbuzz-only. */;
-PangoEngineLang *_pango_get_language_engine (void);
-
G_END_DECLS
#endif /* __PANGO_ENGINE_PRIVATE_H__ */
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index baf81bd4..2b07954e 100644
--- a/pango/pango-layout.c
+++ b/pango/pango-layout.c
@@ -3297,6 +3297,8 @@ struct _ParaBreakState
/* maintained per line */
int line_width; /* Goal width of line currently processing; < 0 is infinite */
int remaining_width; /* Amount of space remaining on line; < 0 is infinite */
+
+ int hyphen_width; /* How much space a hyphen will take */
};
static gboolean
@@ -3436,6 +3438,64 @@ create_hyphen_run (PangoLayout *layout,
return hyphen;
}
+static gboolean
+break_needs_hyphen (PangoLayout *layout,
+ ParaBreakState *state,
+ int num_chars)
+{
+ gunichar ch;
+
+ if (state->start_offset + num_chars == 0)
+ return FALSE;
+
+ ch = g_utf8_get_char (layout->text + state->start_offset + num_chars - 1);
+
+ /* Just look for soft hyphen, for now */
+ if (ch == 0xAD)
+ return TRUE;
+
+ return FALSE;
+}
+
+static int
+find_break_extra_width (PangoLayout *layout,
+ ParaBreakState *state,
+ int num_chars)
+{
+ PangoItem *item = state->items->data;
+
+ /* Check whether to insert a hyphen */
+ if (break_needs_hyphen (layout, state, num_chars))
+ {
+ if (state->hyphen_width < 0)
+ {
+ PangoLayoutRun *run;
+
+ run = create_hyphen_run (layout, item, state->start_offset);
+ state->hyphen_width = pango_glyph_string_get_width (run->glyphs);
+ pango_glyph_item_free (run);
+ }
+
+ return state->hyphen_width;
+ }
+ else
+ return 0;
+}
+
+static void
+insert_hyphen (PangoLayoutLine *line,
+ ParaBreakState *state,
+ PangoItem *item,
+ int num_chars)
+{
+ PangoLayout *layout = line->layout;
+ PangoLayoutRun *run;
+
+ run = create_hyphen_run (layout, item, state->start_offset + num_chars);
+ line->runs = g_slist_prepend (line->runs, run);
+ state->remaining_width -= pango_glyph_string_get_width (run->glyphs);
+}
+
#if 0
# define DEBUG debug
void
@@ -3507,6 +3567,7 @@ process_item (PangoLayout *layout,
{
insert_run (line, state, item, TRUE);
state->log_widths_offset += item->num_chars;
+
return BREAK_LINE_SEPARATOR;
}
@@ -3544,7 +3605,6 @@ process_item (PangoLayout *layout,
int break_width = width;
int orig_width = width;
int break_extra_width;
- int hyphen_width;
gboolean retrying_with_char_breaks = FALSE;
if (processing_new_item)
@@ -3554,14 +3614,6 @@ process_item (PangoLayout *layout,
pango_glyph_item_get_logical_widths (&glyph_item, layout->text, state->log_widths);
}
- {
- PangoLayoutRun *run;
-
- run = create_hyphen_run (layout, item, state->start_offset);
- hyphen_width = pango_glyph_string_get_width (run->glyphs);
- pango_glyph_item_free (run);
- }
-
retry_break:
/* See how much of the item we can stuff in the line. */
@@ -3579,11 +3631,7 @@ process_item (PangoLayout *layout,
break_num_chars = num_chars;
break_width = width;
- /* Check whether to insert a hyphen */
- if (layout->log_attrs[state->start_offset + num_chars].is_soft_hyphen)
- break_extra_width = hyphen_width;
- else
- break_extra_width = 0;
+ break_extra_width = find_break_extra_width (layout, state, num_chars);
}
width += state->log_widths[state->log_widths_offset + num_chars];
@@ -3620,14 +3668,8 @@ process_item (PangoLayout *layout,
if (break_num_chars == item->num_chars)
{
insert_run (line, state, item, TRUE);
- if (layout->log_attrs[state->start_offset + break_num_chars].is_soft_hyphen)
- {
- PangoLayoutRun *run;
-
- run = create_hyphen_run (layout, item, state->start_offset + break_num_chars);
- line->runs = g_slist_prepend (line->runs, run);
- state->remaining_width -= pango_glyph_string_get_width (run->glyphs);
- }
+ if (break_needs_hyphen (layout, state, break_num_chars))
+ insert_hyphen (line, state, item, break_num_chars);
return BREAK_ALL_FIT;
}
@@ -3654,14 +3696,8 @@ process_item (PangoLayout *layout,
/* Shaped items should never be broken */
g_assert (!shape_set);
- if (layout->log_attrs[state->start_offset + break_num_chars].is_soft_hyphen)
- {
- PangoLayoutRun *run;
-
- run = create_hyphen_run (layout, item, state->start_offset + break_num_chars);
- line->runs = g_slist_prepend (line->runs, run);
- state->remaining_width -= pango_glyph_string_get_width (run->glyphs);
- }
+ if (break_needs_hyphen (layout, state, break_num_chars))
+ insert_hyphen (line, state, new_item, break_num_chars);
return BREAK_SOME_FIT;
}
@@ -3912,13 +3948,8 @@ get_items_log_attrs (const char *text,
PangoItem *next_item = items->next->data;
/* FIXME: Handle language tags */
- if (next_item->analysis.lang_engine != tmp_item.analysis.lang_engine)
- break;
- else
- {
- tmp_item.length += next_item->length;
- tmp_item.num_chars += next_item->num_chars;
- }
+ tmp_item.length += next_item->length;
+ tmp_item.num_chars += next_item->num_chars;
items = items->next;
}
@@ -3931,7 +3962,7 @@ get_items_log_attrs (const char *text,
}
/* XXX This is wrong. we should call pango_default_break on the entire
- * layout text and then tailor_break on each lang_engine change, like
+ * layout text and then tailor_break on each language change, like
* pango_get_log_attrs does.
*/
pango_break (text + index, tmp_item.length, &tmp_item.analysis,
@@ -4154,6 +4185,8 @@ pango_layout_check_lines (PangoLayout *layout)
state.remaining_width = -1;
state.log_widths_offset = 0;
+ state.hyphen_width = -1;
+
if (state.items)
{
while (state.items)
diff --git a/tests/breaks/one.expected b/tests/breaks/one.expected
index 7fb600e6..d474c6e4 100644
--- a/tests/breaks/one.expected
+++ b/tests/breaks/one.expected
@@ -1,5 +1,5 @@
-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 lhc c c c c lc c c c Lc
-Whitespace: x x w w
-Words: bs be bs be bs be b bs be b
-Sentences: bs e bs e b
+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
+Whitespace: x x w w
+Words: bs be bs be bs be b bs be b
+Sentences: bs e bs e b
diff --git a/tests/itemize/one.expected b/tests/itemize/one.expected
new file mode 100644
index 00000000..1fe2824d
--- /dev/null
+++ b/tests/itemize/one.expected
@@ -0,0 +1,7 @@
+<span font="Cantarell 11" fallback="false">a b
c</span>
+
+Items: a b |[0x2028] |c
+Font: Cantarell 11|Cantarell 11|Cantarell 11
+Script: Latn |Latn |Latn
+Lang: en-us |en-us |en-us
+Bidi: 0 |0 |0
diff --git a/tests/itemize/one.items b/tests/itemize/one.items
new file mode 100644
index 00000000..45b9c149
--- /dev/null
+++ b/tests/itemize/one.items
@@ -0,0 +1 @@
+<span font="Cantarell 11" fallback="false">a b
c</span>
diff --git a/tests/meson.build b/tests/meson.build
index 6357cd8a..b2d2d3e1 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -21,8 +21,8 @@ tests = [
[ 'testboundaries_ucd' ],
[ 'testcolor' ],
[ 'testscript' ],
- [ 'cxx-test', [ 'cxx-test.cpp' ] ],
- [ 'test-break', [ 'test-break.c', 'test-common.c' ] ],
+ [ 'cxx-test', [ 'cxx-test.cpp' ], [ libpangocairo_dep ] ],
+ [ 'test-break', [ 'test-break.c', 'test-common.c' ], [libpangocairo_dep ] ],
]
if build_pangoft2
@@ -38,6 +38,7 @@ if cairo_dep.found()
[ 'testiter', [ 'testiter.c' ], [ libpangocairo_dep ] ],
[ 'markup-parse', [ 'markup-parse.c' , 'test-common.c' ], [ libpangocairo_dep ] ],
[ 'test-layout', [ 'test-layout.c', 'test-common.c' ], [ libpangocairo_dep ] ],
+ [ 'test-itemize', [ 'test-itemize.c', 'test-common.c' ], [ libpangocairo_dep ] ],
[ 'test-font', [ 'test-font.c' ], [ libpangocairo_dep ] ],
[ 'testattributes', [ 'testattributes.c', 'test-common.c' ], [ libpangocairo_dep ] ],
]
@@ -80,6 +81,16 @@ test_markups_data = [
'markups/valid-9',
]
+test_breaks_data = [
+ 'breaks/one',
+ 'breaks/two',
+ 'breaks/three',
+]
+
+test_items_data = [
+ 'itemize/one',
+]
+
installed_test_layouts_data = []
foreach d: test_layouts_data
installed_test_layouts_data += d + '.markup'
@@ -92,6 +103,18 @@ foreach d: test_markups_data
installed_test_markups_data += d + '.expected'
endforeach
+installed_test_breaks_data = []
+foreach d: test_breaks_data
+ installed_test_breaks_data += d + '.break'
+ installed_test_breaks_data += d + '.expected'
+endforeach
+
+installed_test_items_data = []
+foreach d: test_items_data
+ installed_test_items_data += d + '.items'
+ installed_test_items_data += d + '.expected'
+endforeach
+
installed_test_datadir = join_paths(pango_datadir, 'installed-tests', 'pango')
installed_test_bindir = join_paths(pango_libexecdir, 'installed-tests', 'pango')
@@ -99,6 +122,8 @@ if get_option('install-tests')
install_data(installed_test_data, install_dir: installed_test_bindir)
install_data(installed_test_layouts_data, install_dir: join_paths(installed_test_bindir, 'layouts'))
install_data(installed_test_markups_data, install_dir: join_paths(installed_test_bindir, 'markups'))
+ install_data(installed_test_breaks_data, install_dir: join_paths(installed_test_bindir, 'breaks'))
+ install_data(installed_test_items_data, install_dir: join_paths(installed_test_bindir, 'itemize'))
endif
python = import('python3').find_python()
diff --git a/tests/test-break.c b/tests/test-break.c
index e4c5bd28..00bc7be0 100644
--- a/tests/test-break.c
+++ b/tests/test-break.c
@@ -103,11 +103,6 @@ test_file (const gchar *filename, GString *string)
g_string_append (s1, "l");
b++;
}
- if (log.is_soft_hyphen)
- {
- g_string_append (s1, "h");
- b++;
- }
if (log.is_char_break)
{
g_string_append (s1, "c");
diff --git a/tests/test-itemize.c b/tests/test-itemize.c
new file mode 100644
index 00000000..c9fb4c53
--- /dev/null
+++ b/tests/test-itemize.c
@@ -0,0 +1,269 @@
+/* Pango
+ * test-break.c: Test Pango line breaking
+ *
+ * Copyright (C) 2019 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <glib.h>
+#include <string.h>
+#include <locale.h>
+
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
+#include "config.h"
+#include <pango/pangocairo.h>
+#include "test-common.h"
+
+
+static PangoContext *context;
+
+static const char *
+script_name (GUnicodeScript s)
+{
+ const char *names[] = {
+ "Zyyy", "Zinh", "Arab", "Armn", "Beng", "Bopo", "Cher",
+ "Copt", "Cyrl", "Dsrt", "Deva", "Ethi", "Geor", "Goth",
+ "Grek", "Gujr", "Guru", "Hani", "Hang", "Hebr", "Hira",
+ "Knda", "Kana", "Khmr", "Laoo", "Latn", "Mlym", "Mong",
+ "Mymr", "Ogam", "Ital", "Orya", "Runr", "Sinh", "Syrc",
+ "Taml", "Telu", "Thaa", "Thai", "Tibt", "Cans", "Yiii",
+ "Tglg", "Hano", "Buhd", "Tagb", "Brai", "Cprt", "Limb",
+ "Osma", "Shaw", "Linb", "Tale", "Ugar", "Talu", "Bugi",
+ "Glag", "Tfng", "Sylo", "Xpeo", "Khar", "Zzzz", "Bali",
+ "Xsux", "Phnx", "Phag", "Nkoo", "Kali", "Lepc", "Rjng",
+ "Sund", "Saur", "Cham", "Olck", "Vaii", "Cari", "Lyci",
+ "Lydi", "Avst", "Bamu", "Egyp", "Armi", "Phli", "Prti",
+ "Java", "Kthi", "Lisu", "Mtei", "Sarb", "Orkh", "Samr",
+ "Lana", "Tavt", "Batk", "Brah", "Mand", "Cakm", "Merc",
+ "Mero", "Plrd", "Shrd", "Sora", "Takr", "Bass", "Aghb",
+ "Dupl", "Elba", "Gran", "Khoj", "Sind", "Lina", "Mahj",
+ "Mani", "Mend", "Modi", "Mroo", "Nbat", "Narb", "Perm",
+ "Hmng", "Palm", "Pauc", "Phlp", "Sidd", "Tirh", "Wara",
+ "Ahom", "Hluw", "Hatr", "Mult", "Hung", "Sgnw", "Adlm",
+ "Bhks", "Marc", "Newa", "Osge", "Tang", "Gonm", "Nshu",
+ "Soyo", "Zanb", "Dogr", "Gong", "Rohg", "Maka", "Medf",
+ "Sogo", "Sogd", "Elym", "Nand", "Rohg", "Wcho"
+ };
+ return names[s];
+}
+
+static void
+append_text (GString *s,
+ const char *text,
+ int len)
+{
+ char *p;
+
+ for (p = text; p < text + len; p = g_utf8_next_char (p))
+ {
+ gunichar ch = g_utf8_get_char (p);
+ if (ch == 0x0A || ch == 0x2028 || !g_unichar_isprint (ch))
+ g_string_append_printf (s, "[%#04x]", ch);
+ else
+ g_string_append_unichar (s, ch);
+ }
+}
+static void
+test_file (const gchar *filename, GString *string)
+{
+ gchar *contents;
+ gsize length;
+ GError *error = NULL;
+ GString *s1, *s2, *s3, *s4, *s5;
+ char *test;
+ char *text;
+ PangoAttrList *attrs;
+ GList *items, *l;
+ const char *sep = "";
+
+ if (!g_file_get_contents (filename, &contents, &length, &error))
+ {
+ fprintf (stderr, "%s\n", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ test = contents;
+
+ /* Skip initial comments */
+ while (test[0] == '#')
+ test = strchr (test, '\n') + 1;
+
+
+ if (!pango_parse_markup (test, -1, 0, &attrs, &text, NULL, &error))
+ {
+ fprintf (stderr, "%s\n", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ s1 = g_string_new ("Items: ");
+ s2 = g_string_new ("Font: ");
+ s3 = g_string_new ("Script: ");
+ s4 = g_string_new ("Lang: ");
+ s5 = g_string_new ("Bidi: ");
+
+ length = strlen (text);
+ if (text[length - 1] == '\n')
+ length--;
+
+ items = pango_itemize (context, text, 0, length, attrs, NULL);
+
+ for (l = items; l; l = l->next)
+ {
+ PangoItem *item = l->data;
+ PangoFontDescription *desc;
+ char *font;
+ int m;
+
+ desc = pango_font_describe (item->analysis.font);
+ font = pango_font_description_to_string (desc);
+
+ if (l != items)
+ sep = "|";
+ g_string_append (s1, sep);
+ append_text (s1, text + item->offset, item->length);
+
+ g_string_append_printf (s2, "%s%s", sep, font);
+ g_string_append_printf (s3, "%s%s", sep, script_name (item->analysis.script));
+ g_string_append_printf (s4, "%s%s", sep, pango_language_to_string (item->analysis.language));
+ g_string_append_printf (s5, "%s%d", sep, item->analysis.level);
+
+ g_free (font);
+ pango_font_description_free (desc);
+
+ m = MAX (MAX (MAX (s1->len, s2->len), MAX (s3->len, s4->len)), s5->len);
+
+ g_string_append_printf (s1, "%*s", (int)(m - s1->len), "");
+ g_string_append_printf (s2, "%*s", (int)(m - s2->len), "");
+ g_string_append_printf (s3, "%*s", (int)(m - s3->len), "");
+ g_string_append_printf (s4, "%*s", (int)(m - s4->len), "");
+ g_string_append_printf (s5, "%*s", (int)(m - s5->len), "");
+ }
+
+ g_string_append_printf (string, "%s\n", test);
+ g_string_append_printf (string, "%s\n", s1->str);
+ g_string_append_printf (string, "%s\n", s2->str);
+ g_string_append_printf (string, "%s\n", s3->str);
+ g_string_append_printf (string, "%s\n", s4->str);
+ g_string_append_printf (string, "%s\n", s5->str);
+
+ g_string_free (s1, TRUE);
+ g_string_free (s2, TRUE);
+ g_string_free (s3, TRUE);
+ g_string_free (s4, TRUE);
+ g_string_free (s5, TRUE);
+
+ g_list_free_full (items, (GDestroyNotify)pango_item_free);
+ pango_attr_list_unref (attrs);
+ g_free (text);
+ g_free (contents);
+}
+
+static gchar *
+get_expected_filename (const gchar *filename)
+{
+ gchar *f, *p, *expected;
+
+ f = g_strdup (filename);
+ p = strstr (f, ".items");
+ if (p)
+ *p = 0;
+ expected = g_strconcat (f, ".expected", NULL);
+
+ g_free (f);
+
+ return expected;
+}
+
+static void
+test_itemize (gconstpointer d)
+{
+ const gchar *filename = d;
+ gchar *expected_file;
+ GError *error = NULL;
+ GString *dump;
+ gchar *diff;
+
+ expected_file = get_expected_filename (filename);
+
+ dump = g_string_sized_new (0);
+
+ test_file (filename, dump);
+
+ diff = diff_with_file (expected_file, dump->str, dump->len, &error);
+ g_assert_no_error (error);
+
+ if (diff && diff[0])
+ {
+ g_printerr ("Contents don't match expected contents:\n%s", diff);
+ g_test_fail ();
+ g_free (diff);
+ }
+
+ g_string_free (dump, TRUE);
+ g_free (expected_file);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GDir *dir;
+ GError *error = NULL;
+ const gchar *name;
+ gchar *path;
+
+ g_setenv ("LC_ALL", "en_US.UTF-8", TRUE);
+ setlocale (LC_ALL, "");
+
+ g_test_init (&argc, &argv, NULL);
+
+ context = pango_font_map_create_context (pango_cairo_font_map_get_default ());
+
+ /* allow to easily generate expected output for new test cases */
+ if (argc > 1)
+ {
+ GString *string;
+
+ string = g_string_sized_new (0);
+ test_file (argv[1], string);
+ printf ("%s", string->str);
+
+ return 0;
+ }
+
+ path = g_test_build_filename (G_TEST_DIST, "itemize", NULL);
+ dir = g_dir_open (path, 0, &error);
+ g_free (path);
+ g_assert_no_error (error);
+ while ((name = g_dir_read_name (dir)) != NULL)
+ {
+ if (!strstr (name, "items"))
+ continue;
+
+ path = g_strdup_printf ("/itemize/%s", name);
+ g_test_add_data_func_full (path, g_test_build_filename (G_TEST_DIST, "itemize", name, NULL),
+ test_itemize, g_free);
+ g_free (path);
+ }
+ g_dir_close (dir);
+
+ return g_test_run ();
+}
diff --git a/utils/meson.build b/utils/meson.build
index 510d1b7e..855f6e36 100644
--- a/utils/meson.build
+++ b/utils/meson.build
@@ -19,7 +19,7 @@ if xft_dep.found() and build_pangoft2
'viewer-pangoxft.c',
'viewer-x.c',
]
- pango_view_deps += [ libpangoft2_dep, libpangoxft_dep, ]
+ pango_view_deps += pangoxft_deps + [ libpangoft2_dep, libpangoxft_dep, ]
endif
if cairo_dep.found()