diff options
40 files changed, 1925 insertions, 898 deletions
@@ -1,3 +1,63 @@ +Tue Sep 23 18:03:57 2003 Owen Taylor <otaylor@redhat.com> + + * pango/pango-engines.[ch] pango/pango-engines-private.h: + Modules now declare a list of scripts that they cover instead of a + list of code point ranges. Also, there is now a ->covers() virtual + function that allows a module to decide live whether the font + covers a particular codepoint; remove old get_coverage() method. + + * pango/pango-fontset.[ch]: Add a foreach() function to + iterate over all the fonts in a fontset (with a true + return stopping iteration). + + * pango/pango-context.c: Complete rewrite using script-run + information to improve language tags. Switch to an approach + where we handle one run at a time rather than computing + information for each character individually then later + breaking the result into runs. + + * pango/pango-fontset.[ch]: Switch over to using + pango-impl-utils.h. + + * modules/basic/basic-x.c pango/pangox-fontmap.c: Adapt to + the change from get_coverage => covers. + + * pango/pango-modules.h pango/modules.c: Switch PangoMap + over to being based on script rather than being based + on codepoint. Remove the no longer needed pango_map_get_entry(). + + * pango/modules.c: Handle new script-based modules. + + * pango/pango-fc-fontmap.c pango/pango-win32-fontmap.c + pango/pang-fontmap.[ch]: Add a shape_engine_type field + to PangoFontmapClass, pango_font_map_get_shape_engine_type(); + this allows generic code to find a shaper for a particular + fontmap. + + * pango/pango-script.[ch]: Add pango_script_get_sample_language(), + pango_language_includes_script(); functions for determining + the relationship between scripts and language. + + * tools/gen-script-for-lang.c: Modify to spit out a + useful table. + + * pango/pango-script-lang-table.h: Version of table + generated from current fontconfig data. + + * pango/pangox.c: Remove complicated code to compute + coverages; no longer useful now that we just have + the basic shaper as a legacy thing. + + * modules/*/*.c: Adapt to identifying shape engines + by language range. + + * modules/thai/thai-fc.c modules/thai/thai-shaper.[ch]: + Remove now unused "has_glyph" function and XTIS support. + + * modules/thai/thai-fc.c: Handle non-Thai characters + as well, since the Thai module now gets spaces, + punctuation, and so forth. + Mon Sep 15 17:16:59 2003 Owen Taylor <otaylor@redhat.com> * pango/opentype/fterrcompat.h: Fix gcc-3.3 versions of diff --git a/ChangeLog.pre-1-10 b/ChangeLog.pre-1-10 index 8a754a31..5bbb8adf 100644 --- a/ChangeLog.pre-1-10 +++ b/ChangeLog.pre-1-10 @@ -1,3 +1,63 @@ +Tue Sep 23 18:03:57 2003 Owen Taylor <otaylor@redhat.com> + + * pango/pango-engines.[ch] pango/pango-engines-private.h: + Modules now declare a list of scripts that they cover instead of a + list of code point ranges. Also, there is now a ->covers() virtual + function that allows a module to decide live whether the font + covers a particular codepoint; remove old get_coverage() method. + + * pango/pango-fontset.[ch]: Add a foreach() function to + iterate over all the fonts in a fontset (with a true + return stopping iteration). + + * pango/pango-context.c: Complete rewrite using script-run + information to improve language tags. Switch to an approach + where we handle one run at a time rather than computing + information for each character individually then later + breaking the result into runs. + + * pango/pango-fontset.[ch]: Switch over to using + pango-impl-utils.h. + + * modules/basic/basic-x.c pango/pangox-fontmap.c: Adapt to + the change from get_coverage => covers. + + * pango/pango-modules.h pango/modules.c: Switch PangoMap + over to being based on script rather than being based + on codepoint. Remove the no longer needed pango_map_get_entry(). + + * pango/modules.c: Handle new script-based modules. + + * pango/pango-fc-fontmap.c pango/pango-win32-fontmap.c + pango/pang-fontmap.[ch]: Add a shape_engine_type field + to PangoFontmapClass, pango_font_map_get_shape_engine_type(); + this allows generic code to find a shaper for a particular + fontmap. + + * pango/pango-script.[ch]: Add pango_script_get_sample_language(), + pango_language_includes_script(); functions for determining + the relationship between scripts and language. + + * tools/gen-script-for-lang.c: Modify to spit out a + useful table. + + * pango/pango-script-lang-table.h: Version of table + generated from current fontconfig data. + + * pango/pangox.c: Remove complicated code to compute + coverages; no longer useful now that we just have + the basic shaper as a legacy thing. + + * modules/*/*.c: Adapt to identifying shape engines + by language range. + + * modules/thai/thai-fc.c modules/thai/thai-shaper.[ch]: + Remove now unused "has_glyph" function and XTIS support. + + * modules/thai/thai-fc.c: Handle non-Thai characters + as well, since the Thai module now gets spaces, + punctuation, and so forth. + Mon Sep 15 17:16:59 2003 Owen Taylor <otaylor@redhat.com> * pango/opentype/fterrcompat.h: Fix gcc-3.3 versions of diff --git a/ChangeLog.pre-1-4 b/ChangeLog.pre-1-4 index 8a754a31..5bbb8adf 100644 --- a/ChangeLog.pre-1-4 +++ b/ChangeLog.pre-1-4 @@ -1,3 +1,63 @@ +Tue Sep 23 18:03:57 2003 Owen Taylor <otaylor@redhat.com> + + * pango/pango-engines.[ch] pango/pango-engines-private.h: + Modules now declare a list of scripts that they cover instead of a + list of code point ranges. Also, there is now a ->covers() virtual + function that allows a module to decide live whether the font + covers a particular codepoint; remove old get_coverage() method. + + * pango/pango-fontset.[ch]: Add a foreach() function to + iterate over all the fonts in a fontset (with a true + return stopping iteration). + + * pango/pango-context.c: Complete rewrite using script-run + information to improve language tags. Switch to an approach + where we handle one run at a time rather than computing + information for each character individually then later + breaking the result into runs. + + * pango/pango-fontset.[ch]: Switch over to using + pango-impl-utils.h. + + * modules/basic/basic-x.c pango/pangox-fontmap.c: Adapt to + the change from get_coverage => covers. + + * pango/pango-modules.h pango/modules.c: Switch PangoMap + over to being based on script rather than being based + on codepoint. Remove the no longer needed pango_map_get_entry(). + + * pango/modules.c: Handle new script-based modules. + + * pango/pango-fc-fontmap.c pango/pango-win32-fontmap.c + pango/pang-fontmap.[ch]: Add a shape_engine_type field + to PangoFontmapClass, pango_font_map_get_shape_engine_type(); + this allows generic code to find a shaper for a particular + fontmap. + + * pango/pango-script.[ch]: Add pango_script_get_sample_language(), + pango_language_includes_script(); functions for determining + the relationship between scripts and language. + + * tools/gen-script-for-lang.c: Modify to spit out a + useful table. + + * pango/pango-script-lang-table.h: Version of table + generated from current fontconfig data. + + * pango/pangox.c: Remove complicated code to compute + coverages; no longer useful now that we just have + the basic shaper as a legacy thing. + + * modules/*/*.c: Adapt to identifying shape engines + by language range. + + * modules/thai/thai-fc.c modules/thai/thai-shaper.[ch]: + Remove now unused "has_glyph" function and XTIS support. + + * modules/thai/thai-fc.c: Handle non-Thai characters + as well, since the Thai module now gets spaces, + punctuation, and so forth. + Mon Sep 15 17:16:59 2003 Owen Taylor <otaylor@redhat.com> * pango/opentype/fterrcompat.h: Fix gcc-3.3 versions of diff --git a/ChangeLog.pre-1-6 b/ChangeLog.pre-1-6 index 8a754a31..5bbb8adf 100644 --- a/ChangeLog.pre-1-6 +++ b/ChangeLog.pre-1-6 @@ -1,3 +1,63 @@ +Tue Sep 23 18:03:57 2003 Owen Taylor <otaylor@redhat.com> + + * pango/pango-engines.[ch] pango/pango-engines-private.h: + Modules now declare a list of scripts that they cover instead of a + list of code point ranges. Also, there is now a ->covers() virtual + function that allows a module to decide live whether the font + covers a particular codepoint; remove old get_coverage() method. + + * pango/pango-fontset.[ch]: Add a foreach() function to + iterate over all the fonts in a fontset (with a true + return stopping iteration). + + * pango/pango-context.c: Complete rewrite using script-run + information to improve language tags. Switch to an approach + where we handle one run at a time rather than computing + information for each character individually then later + breaking the result into runs. + + * pango/pango-fontset.[ch]: Switch over to using + pango-impl-utils.h. + + * modules/basic/basic-x.c pango/pangox-fontmap.c: Adapt to + the change from get_coverage => covers. + + * pango/pango-modules.h pango/modules.c: Switch PangoMap + over to being based on script rather than being based + on codepoint. Remove the no longer needed pango_map_get_entry(). + + * pango/modules.c: Handle new script-based modules. + + * pango/pango-fc-fontmap.c pango/pango-win32-fontmap.c + pango/pang-fontmap.[ch]: Add a shape_engine_type field + to PangoFontmapClass, pango_font_map_get_shape_engine_type(); + this allows generic code to find a shaper for a particular + fontmap. + + * pango/pango-script.[ch]: Add pango_script_get_sample_language(), + pango_language_includes_script(); functions for determining + the relationship between scripts and language. + + * tools/gen-script-for-lang.c: Modify to spit out a + useful table. + + * pango/pango-script-lang-table.h: Version of table + generated from current fontconfig data. + + * pango/pangox.c: Remove complicated code to compute + coverages; no longer useful now that we just have + the basic shaper as a legacy thing. + + * modules/*/*.c: Adapt to identifying shape engines + by language range. + + * modules/thai/thai-fc.c modules/thai/thai-shaper.[ch]: + Remove now unused "has_glyph" function and XTIS support. + + * modules/thai/thai-fc.c: Handle non-Thai characters + as well, since the Thai module now gets spaces, + punctuation, and so forth. + Mon Sep 15 17:16:59 2003 Owen Taylor <otaylor@redhat.com> * pango/opentype/fterrcompat.h: Fix gcc-3.3 versions of diff --git a/ChangeLog.pre-1-8 b/ChangeLog.pre-1-8 index 8a754a31..5bbb8adf 100644 --- a/ChangeLog.pre-1-8 +++ b/ChangeLog.pre-1-8 @@ -1,3 +1,63 @@ +Tue Sep 23 18:03:57 2003 Owen Taylor <otaylor@redhat.com> + + * pango/pango-engines.[ch] pango/pango-engines-private.h: + Modules now declare a list of scripts that they cover instead of a + list of code point ranges. Also, there is now a ->covers() virtual + function that allows a module to decide live whether the font + covers a particular codepoint; remove old get_coverage() method. + + * pango/pango-fontset.[ch]: Add a foreach() function to + iterate over all the fonts in a fontset (with a true + return stopping iteration). + + * pango/pango-context.c: Complete rewrite using script-run + information to improve language tags. Switch to an approach + where we handle one run at a time rather than computing + information for each character individually then later + breaking the result into runs. + + * pango/pango-fontset.[ch]: Switch over to using + pango-impl-utils.h. + + * modules/basic/basic-x.c pango/pangox-fontmap.c: Adapt to + the change from get_coverage => covers. + + * pango/pango-modules.h pango/modules.c: Switch PangoMap + over to being based on script rather than being based + on codepoint. Remove the no longer needed pango_map_get_entry(). + + * pango/modules.c: Handle new script-based modules. + + * pango/pango-fc-fontmap.c pango/pango-win32-fontmap.c + pango/pang-fontmap.[ch]: Add a shape_engine_type field + to PangoFontmapClass, pango_font_map_get_shape_engine_type(); + this allows generic code to find a shaper for a particular + fontmap. + + * pango/pango-script.[ch]: Add pango_script_get_sample_language(), + pango_language_includes_script(); functions for determining + the relationship between scripts and language. + + * tools/gen-script-for-lang.c: Modify to spit out a + useful table. + + * pango/pango-script-lang-table.h: Version of table + generated from current fontconfig data. + + * pango/pangox.c: Remove complicated code to compute + coverages; no longer useful now that we just have + the basic shaper as a legacy thing. + + * modules/*/*.c: Adapt to identifying shape engines + by language range. + + * modules/thai/thai-fc.c modules/thai/thai-shaper.[ch]: + Remove now unused "has_glyph" function and XTIS support. + + * modules/thai/thai-fc.c: Handle non-Thai characters + as well, since the Thai module now gets spaces, + punctuation, and so forth. + Mon Sep 15 17:16:59 2003 Owen Taylor <otaylor@redhat.com> * pango/opentype/fterrcompat.h: Fix gcc-3.3 versions of diff --git a/docs/pango-sections.txt b/docs/pango-sections.txt index d1306e0b..22ea5f4f 100644 --- a/docs/pango-sections.txt +++ b/docs/pango-sections.txt @@ -468,7 +468,7 @@ pango_script_get_type <TITLE>Engines</TITLE> <FILE>engines</FILE> PangoEngineInfo -PangoEngineRange +PangoEngineScriptInfo PangoEngine PangoEngineClass PANGO_RENDER_TYPE_NONE diff --git a/docs/tmpl/engines.sgml b/docs/tmpl/engines.sgml index 754540ce..fb7fdfd2 100644 --- a/docs/tmpl/engines.sgml +++ b/docs/tmpl/engines.sgml @@ -37,23 +37,20 @@ engine. It contains the following fields: @id: a unique string ID for the engine. @engine_type: a string identifying the engine type. @render_type: a string identifying the render type. -@ranges: a pointer to an array of #PangoEngineRange - structures. Each structure contains information - about a range of Unicode code points that - this engine handles. -@n_ranges: the number of elements in <structfield>ranges</structfield>. +@scripts: +@n_scripts: -<!-- ##### STRUCT PangoEngineRange ##### --> +<!-- ##### STRUCT PangoEngineScriptInfo ##### --> <para> -The PangoEngineRange structure contains -information about a range of Unicode code -points. It contains the following fields: +The PangoEngineScriptInfo structure contains +information about how the shaper covers a particular +script. </para> -@start: the first code point in the range. -@end: the last code point for the range. +@script: a #PangoScript. The value %PANGO_SCRIPT_COMMON has + the special meaning here of "all scripts" @langs: a semicolon separated list of languages that this - engine handles for this range. This may be empty, + engine handles for this script. This may be empty, in which case the engine is saying that it is a fallback choice for all languages for this range, but should not be used if another engine diff --git a/docs/tmpl/fonts.sgml b/docs/tmpl/fonts.sgml index e5385006..6d134866 100644 --- a/docs/tmpl/fonts.sgml +++ b/docs/tmpl/fonts.sgml @@ -697,6 +697,7 @@ a particular #PangoFontMap implementation. @list_families: A function to list available font families. See pango_font_map_list_families(). @load_fontset: +@shape_engine_type: <!-- ##### MACRO PANGO_FONT_MAP_CLASS ##### --> <para> @@ -785,6 +786,7 @@ a particular #PangoFontset implementation. @get_metrics: a function to get overall metric information for the fonts in the fontset; see pango_fontset_get_metrics(). @get_language: a function to get the language of the fontset. +@foreach: <!-- ##### FUNCTION pango_fontset_get_font ##### --> <para> diff --git a/docs/tmpl/modules.sgml b/docs/tmpl/modules.sgml index 32172efd..893fffe5 100644 --- a/docs/tmpl/modules.sgml +++ b/docs/tmpl/modules.sgml @@ -40,8 +40,6 @@ for the codepoint to which this entry belongs and also whether the engine matches the language tag for this entry's map exactly or just approximately. </para> -@info: -@is_exact: <!-- ##### FUNCTION pango_find_map ##### --> <para> @@ -54,24 +52,16 @@ matches the language tag for this entry's map exactly or just approximately. @Returns: -<!-- ##### FUNCTION pango_map_get_entry ##### --> -<para> - -</para> - -@map: -@wc: -@Returns: - - <!-- ##### FUNCTION pango_map_get_engine ##### --> <para> </para> @map: -@wc: +@script: @Returns: +<!-- # Unused Parameters # --> +@wc: <!-- ##### FUNCTION pango_module_register ##### --> diff --git a/docs/tmpl/pango-engine-shape.sgml b/docs/tmpl/pango-engine-shape.sgml index 2e0f91ce..68c37707 100644 --- a/docs/tmpl/pango-engine-shape.sgml +++ b/docs/tmpl/pango-engine-shape.sgml @@ -26,6 +26,7 @@ Rendering-system dependent script engines @script_shape: @get_coverage: +@covers: <!-- ##### MACRO PANGO_ENGINE_TYPE_SHAPE ##### --> <para> diff --git a/modules/arabic/arabic-fc.c b/modules/arabic/arabic-fc.c index fd425d2e..d3e2fcd9 100644 --- a/modules/arabic/arabic-fc.c +++ b/modules/arabic/arabic-fc.c @@ -35,9 +35,8 @@ typedef PangoEngineShapeClass ArabicEngineFcClass ; #define SCRIPT_ENGINE_NAME "ArabicScriptEngineFc" #define RENDER_TYPE PANGO_RENDER_TYPE_FC -static PangoEngineRange arabic_ranges[] = { - /* Language characters */ - { 0x060c, 0x06f9, "*" }, /* Arabic */ +static PangoEngineScriptInfo arabic_scripts[] = { + { PANGO_SCRIPT_ARABIC, "*" }, }; static PangoEngineInfo script_engines[] = { @@ -45,7 +44,7 @@ static PangoEngineInfo script_engines[] = { SCRIPT_ENGINE_NAME, PANGO_ENGINE_TYPE_SHAPE, RENDER_TYPE, - arabic_ranges, G_N_ELEMENTS(arabic_ranges) + arabic_scripts, G_N_ELEMENTS(arabic_scripts) } }; diff --git a/modules/basic/basic-fc.c b/modules/basic/basic-fc.c index 6de50e8c..6fb28ecf 100644 --- a/modules/basic/basic-fc.c +++ b/modules/basic/basic-fc.c @@ -36,35 +36,35 @@ typedef PangoEngineShapeClass BasicEngineFcClass; #define SCRIPT_ENGINE_NAME "BasicScriptEngineFc" #define RENDER_TYPE PANGO_RENDER_TYPE_FC -static PangoEngineRange basic_ranges[] = { - /* Basic Latin, Latin-1 Supplement, Latin Extended-A, Latin Extended-B, - * IPA Extensions - */ - { 0x0000, 0x02af, "*" }, - { 0x0380, 0x058f, "*" }, /* Greek, Cyrillic, Armenian */ - { 0x10a0, 0x10ff, "*" }, /* Georgian */ - { 0x1200, 0x16ff, "*" }, /* Ethiopic,Cherokee,Canadian,Ogham,Runic */ - { 0x1e00, 0x1fff, "*" }, /* Latin Extended Additional, Greek Extended */ - - /* General Punctuation, Superscripts and Subscripts, Currency Symbols, - * Combining Marks for Symbols, Letterlike Symbols, Number Forms, - * Arrows, Mathematical Operators, Miscellaneous Technical, - * Control Pictures, Optical Character Recognition, Enclosed Alphanumerics, - * Box Drawing, Block Elements, Geometric Shapes, Miscellaneous Symbols, - * Dingbats, Braille Patterns, CJK Radicals Supplement, Kangxi Radicals, - * Ideographic Description Characters, CJK Symbols and Punctuation, - * Hiragana, Katakana, Bopomofo, Hangul Compatibility Jamo, Kanbun, - * Bopomofo Extended, Enclosed CJK Letters and Months, CJK Compatibility, - * CJK Unified Ideographs Extension A, CJK Unified Ideographs - */ - { 0x2000, 0x3029, "*" }, /* Gap for Hangul diacritics */ - { 0x3030, 0x9fff, "*" }, - { 0xa000, 0xa4c6, "*" }, /* Yi */ - { 0xe000, 0xf7ee, "*" }, /* HKSCS-1999 */ - { 0xf900, 0xfa2d, "*" }, /* CJK Compatibility Ideographs */ - { 0xfe30, 0xfe6b, "*" }, /* CJK Compatibility Forms and Small Form Variants */ - { 0xff00, 0xffe3, "*" }, /* Halfwidth and Fullwidth Forms (partly) */ - { 0x0000, 0xffff, "" }, +static PangoEngineScriptInfo basic_scripts[] = { + { PANGO_SCRIPT_ARMENIAN, "*" }, + { PANGO_SCRIPT_BOPOMOFO, "*" }, + { PANGO_SCRIPT_CHEROKEE, "*" }, + { PANGO_SCRIPT_COPTIC, "*" }, + { PANGO_SCRIPT_CYRILLIC, "*" }, + { PANGO_SCRIPT_DESERET, "*" }, + { PANGO_SCRIPT_ETHIOPIC, "*" }, + { PANGO_SCRIPT_GEORGIAN, "*" }, + { PANGO_SCRIPT_GOTHIC, "*" }, + { PANGO_SCRIPT_GREEK, "*" }, + { PANGO_SCRIPT_HAN, "*" }, + { PANGO_SCRIPT_HIRAGANA, "*" }, + { PANGO_SCRIPT_KATAKANA, "*" }, + { PANGO_SCRIPT_LATIN, "*" }, + { PANGO_SCRIPT_OGHAM, "*" }, + { PANGO_SCRIPT_OLD_ITALIC, "*" }, + { PANGO_SCRIPT_RUNIC, "*" }, + { PANGO_SCRIPT_CANADIAN_ABORIGINAL, "*" }, + { PANGO_SCRIPT_YI, "*" }, + { PANGO_SCRIPT_BRAILLE, "*" }, + { PANGO_SCRIPT_CYPRIOT, "*" }, + { PANGO_SCRIPT_LIMBU, "*" }, + { PANGO_SCRIPT_OSMANYA, "*" }, + { PANGO_SCRIPT_SHAVIAN, "*" }, + { PANGO_SCRIPT_LINEAR_B, "*" }, + { PANGO_SCRIPT_UGARITIC, "*" }, + + { PANGO_SCRIPT_COMMON, "" } }; static PangoEngineInfo script_engines[] = { @@ -72,7 +72,7 @@ static PangoEngineInfo script_engines[] = { SCRIPT_ENGINE_NAME, PANGO_ENGINE_TYPE_SHAPE, RENDER_TYPE, - basic_ranges, G_N_ELEMENTS(basic_ranges) + basic_scripts, G_N_ELEMENTS(basic_scripts) } }; diff --git a/modules/basic/basic-win32.c b/modules/basic/basic-win32.c index 82c8b88c..52e720ee 100644 --- a/modules/basic/basic-win32.c +++ b/modules/basic/basic-win32.c @@ -126,89 +126,47 @@ static int nscripts; #endif #ifdef HAVE_USP10_H -static PangoEngineRange uniscribe_ranges[] = { +static PangoEngineScriptInfo uniscribe_scripts[] = { /* We claim to cover everything ;-) */ - { 0x0020, 0xffee, "*" } + { PANGO_SCRIPT_COMMON, "" }, }; #endif -static PangoEngineRange basic_ranges[] = { +static PangoEngineScriptInfo basic_scripts[] = { /* Those characters that can be rendered legibly without Uniscribe. * I am not certain this list is correct. */ - - /* Basic Latin, Latin-1 Supplement, Latin Extended-A, Latin Extended-B, - * IPA Extensions - */ - { 0x0020, 0x02af, "*" }, - - /* Spacing Modifier Letters */ - { 0x02b0, 0x02ff, "" }, - - /* Not covered: Combining Diacritical Marks */ - - /* Greek, Cyrillic, Armenian */ - { 0x0380, 0x058f, "*" }, - - /* Hebrew */ - { 0x0591, 0x05f4, "*" }, - - /* Arabic */ - { 0x060c, 0x06f9, "" }, - - /* Not covered: Syriac, Thaana, Devanagari, Bengali, Gurmukhi, Gujarati, - * Oriya, Tamil, Telugu, Kannada, Malayalam, Sinhala - */ - - /* Thai */ - { 0x0e01, 0x0e5b, "" }, - - /* Not covered: Lao, Tibetan, Myanmar */ - - /* Georgian */ - { 0x10a0, 0x10ff, "*" }, - - /* Not covered: Hangul Jamo */ - - /* Ethiopic, Cherokee, Unified Canadian Aboriginal Syllabics, Ogham, - * Runic */ - { 0x1200, 0x16ff, "*" }, - - /* Not covered: Khmer, Mongolian */ - - /* Latin Extended Additional, Greek Extended */ - { 0x1e00, 0x1fff, "*" }, - - /* General Punctuation, Superscripts and Subscripts, Currency - * Symbols, Combining Marks for Symbols, Letterlike Symbols, Number - * Forms, Arrows, Mathematical Operators, Miscellaneous Technical, - * Control Pictures, Optical Character Recognition, Enclosed - * Alphanumerics, Box Drawing, Block Elements, Geometric Shapes, - * Miscellaneous Symbols, Dingbats, Braille Patterns, CJK Radicals - * Supplement, Kangxi Radicals, Ideographic Description Characters, - * CJK Symbols and Punctuation, Hiragana, Katakana, Bopomofo, Hangul - * Compatibility Jamo, Kanbun, Bopomofo Extended, Enclosed CJK - * Letters and Months, CJK Compatibility, CJK Unified Ideographs - * Extension A, CJK Unified Ideographs, Yi Syllables, Yi Radicals - */ - { 0x2000, 0xa4c6, "*" }, - - /* Hangul Syllables */ - { 0xac00, 0xd7a3, "kr" }, - - /* Not covered: Private Use */ - - /* CJK Compatibility Ideographs (partly) */ - { 0xf900, 0xfa0b, "kr" }, - - /* Not covered: CJK Compatibility Ideographs (partly), Alphabetic - * Presentation Forms, Arabic Presentation Forms-A, Combining Half - * Marks, CJK Compatibility Forms, Small Form Variants, Arabic - * Presentation Forms-B, Specials - */ - - /* Halfwidth and Fullwidth Forms */ - { 0xff00, 0xffed, "*" } + { PANGO_SCRIPT_ARMENIAN, "*" }, + { PANGO_SCRIPT_BOPOMOFO, "*" }, + { PANGO_SCRIPT_CHEROKEE, "*" }, + { PANGO_SCRIPT_COPTIC, "*" }, + { PANGO_SCRIPT_CYRILLIC, "*" }, + { PANGO_SCRIPT_DESERET, "*" }, + { PANGO_SCRIPT_ETHIOPIC, "*" }, + { PANGO_SCRIPT_GEORGIAN, "*" }, + { PANGO_SCRIPT_GOTHIC, "*" }, + { PANGO_SCRIPT_GREEK, "*" }, + { PANGO_SCRIPT_HAN, "*" }, + { PANGO_SCRIPT_HANGUL, "*" }, + { PANGO_SCRIPT_HIRAGANA, "*" }, + { PANGO_SCRIPT_KATAKANA, "*" }, + { PANGO_SCRIPT_LATIN, "*" }, + { PANGO_SCRIPT_OGHAM, "*" }, + { PANGO_SCRIPT_OLD_ITALIC, "*" }, + { PANGO_SCRIPT_RUNIC, "*" }, + { PANGO_SCRIPT_THAI, "*" }, + { PANGO_SCRIPT_CANADIAN_ABORIGINAL, "*" }, + { PANGO_SCRIPT_YI, "*" }, + { PANGO_SCRIPT_BRAILLE, "*" }, + { PANGO_SCRIPT_CYPRIOT, "*" }, + { PANGO_SCRIPT_LIMBU, "*" }, + { PANGO_SCRIPT_OSMANYA, "*" }, + { PANGO_SCRIPT_SHAVIAN, "*" }, + { PANGO_SCRIPT_LINEAR_B, "*" }, + { PANGO_SCRIPT_UGARITIC, "*" }, + + /* Claim to handle everything as a fallback */ + { PANGO_SCRIPT_COMMON, "" } }; static PangoEngineInfo script_engines[] = { @@ -1189,8 +1147,8 @@ PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines, { init_uniscribe (); - script_engines[0].ranges = basic_ranges; - script_engines[0].n_ranges = G_N_ELEMENTS (basic_ranges); + script_engines[0].scripts = basic_scripts; + script_engines[0].n_scripts = G_N_ELEMENTS (basic_scripts); #ifdef HAVE_USP10_H if (have_uniscribe) diff --git a/modules/basic/basic-x.c b/modules/basic/basic-x.c index 9b9431a2..d0ba9c48 100644 --- a/modules/basic/basic-x.c +++ b/modules/basic/basic-x.c @@ -83,6 +83,7 @@ struct _CharCache CharsetOrdering *ordering; MaskTable *mask_tables[256]; GIConv converters[MAX_CHARSETS]; + PangoCoverage *coverage; }; struct _CharCachePointer @@ -115,25 +116,8 @@ static PangoGlyph conv_euctw (CharCache *cache, #include "tables-big.i" -static PangoEngineRange basic_ranges[] = { - /* Language characters */ - { 0x0000, 0x02af, "*" }, - { 0x02b0, 0x02ff, "" }, - { 0x0380, 0x058f, "*" }, - { 0x0591, 0x05f4, "" }, /* Hebrew */ - { 0x060c, 0x06f9, "" }, /* Arabic */ - { 0x0e01, 0x0e5b, "" }, /* Thai */ - { 0x10a0, 0x10ff, "*" }, /* Georgian */ - { 0x1200, 0x16ff, "*" }, /* Ethiopic,Cherokee,Canadian,Ogham,Runic */ - { 0x1e00, 0x1fff, "*" }, - { 0x2000, 0x33ff, "*" }, - { 0x3400, 0x9fa5, "*" }, /* Unihan */ - { 0xa000, 0xa4c6, "*" }, /* Yi */ - { 0xac00, 0xd7a3, "" }, - { 0xe000, 0xf7ee, "*" }, /* HKSCS-1999 */ - { 0xf900, 0xfa2d, "*" }, /* CJK Compatibility Ideographs */ - { 0xfe30, 0xfe6b, "*" }, /* CJK Compatibility Forms and Small Form Variants */ - { 0xff00, 0xffee, "*" } /* Halfwidth and Fullwidth Forms */ +static PangoEngineScriptInfo basic_scripts[] = { + { PANGO_SCRIPT_COMMON, "" }, }; static PangoEngineInfo script_engines[] = { @@ -141,7 +125,7 @@ static PangoEngineInfo script_engines[] = { SCRIPT_ENGINE_NAME, PANGO_ENGINE_TYPE_SHAPE, PANGO_RENDER_TYPE_X, - basic_ranges, G_N_ELEMENTS(basic_ranges) + basic_scripts, G_N_ELEMENTS(basic_scripts) } }; @@ -684,31 +668,24 @@ basic_engine_shape (PangoEngineShape *engine, } } -static PangoCoverage * -basic_engine_get_coverage (PangoEngineShape *engine, - PangoFont *font, - PangoLanguage *lang) +static PangoCoverageLevel +basic_engine_covers (PangoEngineShape *engine, + PangoFont *font, + PangoLanguage *lang, + gunichar wc) { CharCache *cache = get_char_cache (font, lang); - PangoCoverage *result = pango_coverage_new (); - gunichar wc; + char buf[6]; - for (wc = 0; wc < 65536; wc++) - { - char buf[6]; + g_unichar_to_utf8 (wc, buf); - g_unichar_to_utf8 (wc, buf); - if (find_char (cache, font, wc, buf)) - pango_coverage_set (result, wc, PANGO_COVERAGE_EXACT); - } - - return result; + return find_char (cache, font, wc, buf) ? PANGO_COVERAGE_EXACT : PANGO_COVERAGE_NONE; } static void basic_engine_x_class_init (PangoEngineShapeClass *class) { - class->get_coverage = basic_engine_get_coverage; + class->covers = basic_engine_covers; class->script_shape = basic_engine_shape; } diff --git a/modules/hangul/hangul-fc.c b/modules/hangul/hangul-fc.c index 94216695..c64d6de7 100644 --- a/modules/hangul/hangul-fc.c +++ b/modules/hangul/hangul-fc.c @@ -36,11 +36,8 @@ typedef PangoEngineShapeClass HangulEngineFcClass ; #define SCRIPT_ENGINE_NAME "HangulScriptEngineFc" #define RENDER_TYPE PANGO_RENDER_TYPE_FC -static PangoEngineRange hangul_ranges[] = { - /* Language characters */ - { 0x1100, 0x11ff, "*" }, /* Hangul Jamo */ - { 0x302e, 0x302f, "*" }, /* Hangul Tone Marks */ - { 0xac00, 0xd7a3, "*" }, /* Hangul Syllables */ +static PangoEngineScriptInfo hangul_scripts[] = { + { PANGO_SCRIPT_HANGUL, "*" } }; static PangoEngineInfo script_engines[] = { @@ -48,7 +45,7 @@ static PangoEngineInfo script_engines[] = { SCRIPT_ENGINE_NAME, PANGO_ENGINE_TYPE_SHAPE, RENDER_TYPE, - hangul_ranges, G_N_ELEMENTS(hangul_ranges) + hangul_scripts, G_N_ELEMENTS(hangul_scripts) } }; diff --git a/modules/hebrew/hebrew-fc.c b/modules/hebrew/hebrew-fc.c index 01a7f2e3..7e257f96 100644 --- a/modules/hebrew/hebrew-fc.c +++ b/modules/hebrew/hebrew-fc.c @@ -33,10 +33,8 @@ typedef PangoEngineShapeClass HebrewEngineFcClass ; #define MAX_CLUSTER_CHRS 20 -static PangoEngineRange hebrew_ranges[] = { - /* Language characters */ - { 0x0591, 0x05f4, "*" }, /* Hebrew */ - { 0xfb1d, 0xfb4f, "*" } /* Hebrew presentation forms */ +static PangoEngineScriptInfo hebrew_scripts[] = { + { PANGO_SCRIPT_HEBREW, "*" } }; #define SCRIPT_ENGINE_NAME "HebrewScriptEngineFc" @@ -47,7 +45,7 @@ static PangoEngineInfo script_engines[] = { SCRIPT_ENGINE_NAME, PANGO_ENGINE_TYPE_SHAPE, RENDER_TYPE, - hebrew_ranges, G_N_ELEMENTS(hebrew_ranges) + hebrew_scripts, G_N_ELEMENTS(hebrew_scripts) } }; diff --git a/modules/indic/indic-fc.c b/modules/indic/indic-fc.c index f70fadfb..68b28662 100644 --- a/modules/indic/indic-fc.c +++ b/modules/indic/indic-fc.c @@ -52,12 +52,10 @@ struct _PangoIndicInfo #define ENGINE_SUFFIX "ScriptEngineFc" #define RENDER_TYPE PANGO_RENDER_TYPE_FC -#define INDIC_ENGINE_INFO(script) {#script ENGINE_SUFFIX, PANGO_ENGINE_TYPE_SHAPE, RENDER_TYPE, script##_ranges, G_N_ELEMENTS(script##_ranges)} +#define INDIC_ENGINE_INFO(script) {#script ENGINE_SUFFIX, PANGO_ENGINE_TYPE_SHAPE, RENDER_TYPE, script##_scripts, G_N_ELEMENTS(script##_scripts)} #define PANGO_INDIC_INFO(script) {OT_TAG_##script, &script##_class_table, "pango-indic-" #script "-GSUB-ruleset", "pango-indic-" #script "-GPOS-rulsest"} -#define INDIC_SCRIPT_RANGE(script) {SCRIPT_RANGE_##script, "*"} - #define OT_TAG_deva FT_MAKE_TAG('d','e','v','a') #define OT_TAG_beng FT_MAKE_TAG('b','e','n','g') #define OT_TAG_guru FT_MAKE_TAG('g','u','r','u') @@ -68,40 +66,40 @@ struct _PangoIndicInfo #define OT_TAG_knda FT_MAKE_TAG('k','n','d','a') #define OT_TAG_mlym FT_MAKE_TAG('m','l','y','m') -static PangoEngineRange deva_ranges[] = { - INDIC_SCRIPT_RANGE(deva), /* Devanagari */ +static PangoEngineScriptInfo deva_scripts[] = { + { PANGO_SCRIPT_DEVANAGARI, "*" } }; -static PangoEngineRange beng_ranges[] = { - INDIC_SCRIPT_RANGE(beng), /* Bengali */ +static PangoEngineScriptInfo beng_scripts[] = { + {PANGO_SCRIPT_BENGALI, "*" } }; -static PangoEngineRange guru_ranges[] = { - INDIC_SCRIPT_RANGE(guru), /* Gurmukhi */ +static PangoEngineScriptInfo guru_scripts[] = { + { PANGO_SCRIPT_GURMUKHI, "*" } }; -static PangoEngineRange gujr_ranges[] = { - INDIC_SCRIPT_RANGE(gujr), /* Gujarati */ +static PangoEngineScriptInfo gujr_scripts[] = { + { PANGO_SCRIPT_GUJARATI, "*" } }; -static PangoEngineRange orya_ranges[] = { - INDIC_SCRIPT_RANGE(orya), /* Oriya */ +static PangoEngineScriptInfo orya_scripts[] = { + { PANGO_SCRIPT_ORIYA, "*" } }; -static PangoEngineRange taml_ranges[] = { - INDIC_SCRIPT_RANGE(taml), /* Tamil */ +static PangoEngineScriptInfo taml_scripts[] = { + { PANGO_SCRIPT_TAMIL, "*" } }; -static PangoEngineRange telu_ranges[] = { - INDIC_SCRIPT_RANGE(telu), /* Telugu */ +static PangoEngineScriptInfo telu_scripts[] = { + { PANGO_SCRIPT_TELUGU, "*" } }; -static PangoEngineRange knda_ranges[] = { - INDIC_SCRIPT_RANGE(knda), /* Kannada */ +static PangoEngineScriptInfo knda_scripts[] = { + { PANGO_SCRIPT_KANNADA, "*" } }; -static PangoEngineRange mlym_ranges[] = { - INDIC_SCRIPT_RANGE(mlym), /* Malayalam */ +static PangoEngineScriptInfo mlym_scripts[] = { + { PANGO_SCRIPT_MALAYALAM, "*" } }; static PangoEngineInfo script_engines[] = { diff --git a/modules/indic/indic-ot-class-tables.c b/modules/indic/indic-ot-class-tables.c index cc18a9be..c4acf4ce 100644 --- a/modules/indic/indic-ot-class-tables.c +++ b/modules/indic/indic-ot-class-tables.c @@ -213,7 +213,7 @@ static const IndicOTSplitMatra mlymSplitTable[] = {{0x0D46, 0x0D3E}, {0x0D47, 0x #define TAML_SCRIPT_FLAGS (SF_MPRE_FIXUP | SF_NO_POST_BASE_LIMIT) #define TELU_SCRIPT_FLAGS (SF_MATRAS_AFTER_BASE | 3) #define KNDA_SCRIPT_FLAGS (SF_MATRAS_AFTER_BASE | 3) -#define MLYM_SCRIPT_FLAGS (SF_NO_POST_BASE_LIMIT) +#define MLYM_SCRIPT_FLAGS (SF_MPRE_FIXUP | SF_NO_POST_BASE_LIMIT) /* * Indic Class Tables diff --git a/modules/indic/indic-ot.h b/modules/indic/indic-ot.h index caf229d4..9730db53 100644 --- a/modules/indic/indic-ot.h +++ b/modules/indic/indic-ot.h @@ -138,27 +138,6 @@ enum indic_glyph_property_ }; /* - * Per-script character ranges - */ -#define SCRIPT_RANGE_deva 0x0900, 0x0970 - -#define SCRIPT_RANGE_beng 0x0980, 0x09FA - -#define SCRIPT_RANGE_guru 0x0A00, 0x0A74 - -#define SCRIPT_RANGE_gujr 0x0A80, 0x0AEF - -#define SCRIPT_RANGE_orya 0x0B00, 0x0B70 - -#define SCRIPT_RANGE_taml 0x0B80, 0x0BF2 - -#define SCRIPT_RANGE_telu 0x0C00, 0x0C6F - -#define SCRIPT_RANGE_knda 0x0C80, 0x0CEF - -#define SCRIPT_RANGE_mlym 0x0D00, 0x0D6F - -/* * Macros to test the charClass flags for various things. */ #define IS_VM_ABOVE(charClass) ((charClass & CF_CLASS_MASK) == CC_MODIFYING_MARK_ABOVE) diff --git a/modules/thai/thai-fc.c b/modules/thai/thai-fc.c index 9a9839a9..65351ac1 100644 --- a/modules/thai/thai-fc.c +++ b/modules/thai/thai-fc.c @@ -44,8 +44,8 @@ typedef PangoEngineShapeClass ThaiEngineFcClass ; /* We handle the range U+0e01 to U+0e5b exactly */ -static PangoEngineRange thai_ranges[] = { - { 0x0e01, 0x0e5b, "*" }, /* Thai */ +static PangoEngineScriptInfo thai_scripts[] = { + { PANGO_SCRIPT_THAI, "*" } }; static PangoEngineInfo script_engines[] = { @@ -53,7 +53,7 @@ static PangoEngineInfo script_engines[] = { SCRIPT_ENGINE_NAME, PANGO_ENGINE_TYPE_SHAPE, RENDER_TYPE, - thai_ranges, G_N_ELEMENTS(thai_ranges) + thai_scripts, G_N_ELEMENTS(thai_scripts) } }; @@ -196,14 +196,6 @@ thai_make_unknown_glyph (ThaiFontInfo *font_info, unsigned int c) return pango_fc_font_get_unknown_glyph ((PangoFcFont *)font_info->font, c); } -/* Unused; used only for X backend and XTIS encoding - */ -gboolean -thai_has_glyph (ThaiFontInfo *font_info, PangoGlyph glyph) -{ - return TRUE; -} - static void thai_engine_fc_class_init (PangoEngineShapeClass *class) { diff --git a/modules/thai/thai-shaper.c b/modules/thai/thai-shaper.c index 4cd98283..5fcbc429 100644 --- a/modules/thai/thai-shaper.c +++ b/modules/thai/thai-shaper.c @@ -561,8 +561,6 @@ get_glyphs_list (ThaiFontInfo *font_info, gint num_chrs, PangoGlyph *glyph_lists) { - PangoGlyph glyph; - gint xtis_index; gint i; switch (font_info->font_set) @@ -572,26 +570,6 @@ get_glyphs_list (ThaiFontInfo *font_info, glyph_lists[i] = thai_make_unknown_glyph (font_info, glyph_lists[i]); return num_chrs; - case THAI_FONT_XTIS: - /* If we are rendering with an XTIS font, we try to find a precomposed - * glyph for the cluster. - */ - xtis_index = 0x100 * (cluster[0] - 0xe00 + 0x20) + 0x30; - if (cluster[1]) - xtis_index +=8 * group1_map[cluster[1] - 0xe30]; - if (cluster[2]) - xtis_index += group2_map[cluster[2] - 0xe30]; - glyph = thai_make_glyph (font_info, xtis_index); - if (thai_has_glyph (font_info, glyph)) { - glyph_lists[0] = glyph; - return 1; - } - for (i=0; i < num_chrs; i++) - glyph_lists[i] = - thai_make_glyph (font_info, - 0x100 * (cluster[i] - 0xe00 + 0x20) + 0x30); - return num_chrs; - case THAI_FONT_TIS: /* TIS620-0 + Wtt2.0 Extension */ @@ -629,11 +607,21 @@ add_cluster (ThaiFontInfo *font_info, PangoGlyph glyphs_list[MAX_GLYPHS]; gint num_glyphs; gint i; - - num_glyphs = get_glyphs_list(font_info, cluster, num_chrs, glyphs_list); - for (i=0; i<num_glyphs; i++) - add_glyph (font_info, glyphs, cluster_start, glyphs_list[i], - i == 0 ? FALSE : TRUE); + + if (!isthai (cluster[0])) + { + g_assert (num_chrs == 1); + add_glyph (font_info, glyphs, cluster_start, + thai_make_glyph (font_info, cluster[0]), + FALSE); + } + else + { + num_glyphs = get_glyphs_list(font_info, cluster, num_chrs, glyphs_list); + for (i=0; i<num_glyphs; i++) + add_glyph (font_info, glyphs, cluster_start, glyphs_list[i], + i == 0 ? FALSE : TRUE); + } } static gboolean @@ -669,16 +657,26 @@ get_next_cluster(const char *text, while (p < text + length && n_chars < 3) { gunichar current = g_utf8_get_char (p); - - if (n_chars == 0 || - is_wtt_composible ((gunichar)(cluster[n_chars - 1]), current) || - (n_chars == 1 && - is_char_type (cluster[0], Cons) && - is_char_type (current, SaraAm)) || - (n_chars == 2 && - is_char_type (cluster[0], Cons) && - is_char_type (cluster[1], Tone) && - is_char_type (current, SaraAm))) + + /* Non-thai characters get split into a single character cluster */ + if (!isthai (current)) + { + if (n_chars == 0) + { + cluster[n_chars++] = current; + p = g_utf8_next_char (p); + } + break; + } + else if (n_chars == 0 || + is_wtt_composible ((gunichar)(cluster[n_chars - 1]), current) || + (n_chars == 1 && + is_char_type (cluster[0], Cons) && + is_char_type (current, SaraAm)) || + (n_chars == 2 && + is_char_type (cluster[0], Cons) && + is_char_type (cluster[1], Tone) && + is_char_type (current, SaraAm))) { cluster[n_chars++] = current; p = g_utf8_next_char (p); diff --git a/modules/thai/thai-shaper.h b/modules/thai/thai-shaper.h index b745da86..8055ce85 100644 --- a/modules/thai/thai-shaper.h +++ b/modules/thai/thai-shaper.h @@ -1,10 +1,7 @@ #ifndef __THAI_SHAPER_H__ #define __THAI_SHAPER_H__ -#ifdef HAVE_X -#include "pangox.h" -#endif - +#define isthai(wc) (wc >= 0xE00 && wc < 0xE80) #define ucs2tis(wc) (unsigned int)((unsigned int)(wc) - 0x0E00 + 0xA0) #define tis2uni(c) ((gunichar)(c) - 0xA0 + 0x0E00) @@ -14,7 +11,6 @@ typedef struct _ThaiFontInfo ThaiFontInfo; */ typedef enum { THAI_FONT_NONE, - THAI_FONT_XTIS, THAI_FONT_TIS, THAI_FONT_TIS_MAC, THAI_FONT_TIS_WIN, @@ -30,9 +26,6 @@ struct _ThaiFontInfo { PangoFont *font; ThaiFontSet font_set; -#ifdef HAVE_X - PangoXSubfont subfont; /* For X backend */ -#endif }; /* @@ -47,9 +40,6 @@ thai_make_glyph (ThaiFontInfo *font_info, unsigned int c); PangoGlyph thai_make_unknown_glyph (ThaiFontInfo *font_info, unsigned int c); -gboolean -thai_has_glyph (ThaiFontInfo *font_info, PangoGlyph glyph); - /* * Public functions */ diff --git a/pango/modules.c b/pango/modules.c index 84cffff5..2f11dbdb 100644 --- a/pango/modules.c +++ b/pango/modules.c @@ -27,6 +27,7 @@ #include <gmodule.h> +#include "pango-enum-types.h" #include "pango-modules.h" #include "pango-utils.h" #include "pango-impl-utils.h" @@ -42,19 +43,15 @@ typedef struct _PangoMapInfo PangoMapInfo; typedef struct _PangoEnginePair PangoEnginePair; typedef struct _PangoSubmap PangoSubmap; -struct _PangoSubmap +struct _PangoMap { - gboolean is_leaf; - union { - PangoMapEntry entry; - PangoMapEntry *leaves; - } d; + GArray *entries; }; -struct _PangoMap +struct _PangoMapEntry { - gint n_submaps; - PangoSubmap *submaps; + GSList *exact; + GSList *fallback; }; struct _PangoMapInfo @@ -341,6 +338,21 @@ find_or_create_module (const char *raw_path) return module; } +static PangoScript +script_from_string (const char *str) +{ + static GEnumClass *class = NULL; + GEnumValue *value; + if (!class) + class = g_type_class_ref (PANGO_TYPE_SCRIPT); + + value = g_enum_get_value_by_nick (class, str); + if (!value) + return PANGO_SCRIPT_INVALID_CODE; + + return value->value; +} + static gboolean /* Returns true if succeeded, false if failed */ process_module_file (FILE *module_file) { @@ -351,13 +363,14 @@ process_module_file (FILE *module_file) while (pango_read_line (module_file, line_buf)) { PangoEnginePair *pair = g_new (PangoEnginePair, 1); - PangoEngineRange *range; - GList *ranges = NULL; + PangoEngineScriptInfo *script_info; + PangoScript script; + GList *scripts = NULL; GList *tmp_list; - const char *p, *q; + const char *p; + char *q; int i; - int start, end; p = line_buf->str; @@ -391,26 +404,25 @@ process_module_file (FILE *module_file) pair->info.render_type = g_strdup (tmp_buf->str); break; default: - range = g_new (PangoEngineRange, 1); - if (sscanf(tmp_buf->str, "%d-%d:", &start, &end) != 2) + q = strchr (tmp_buf->str, ':'); + if (!q) { - g_printerr ("Error reading modules file"); have_error = TRUE; goto error; } - q = strchr (tmp_buf->str, ':'); - if (!q) + *q = '\0'; + script = script_from_string (tmp_buf->str); + if (script == PANGO_SCRIPT_INVALID_CODE) { - g_printerr ( "Error reading modules file"); have_error = TRUE; goto error; } - q++; - range->start = start; - range->end = end; - range->langs = g_strdup (q); - ranges = g_list_prepend (ranges, range); + script_info = g_new (PangoEngineScriptInfo, 1); + script_info->script = script; + script_info->langs = g_strdup (q + 1); + + scripts = g_list_prepend (scripts, script_info); } if (!pango_skip_space (&p)) @@ -421,19 +433,18 @@ process_module_file (FILE *module_file) if (i<3) { - g_printerr ("Error reading modules file"); have_error = TRUE; goto error; } - ranges = g_list_reverse (ranges); - pair->info.n_ranges = g_list_length (ranges); - pair->info.ranges = g_new (PangoEngineRange, pair->info.n_ranges); + scripts = g_list_reverse (scripts); + pair->info.n_scripts = g_list_length (scripts); + pair->info.scripts = g_new (PangoEngineScriptInfo, pair->info.n_scripts); - tmp_list = ranges; - for (i=0; i<pair->info.n_ranges; i++) + tmp_list = scripts; + for (i=0; i<pair->info.n_scripts; i++) { - pair->info.ranges[i] = *(PangoEngineRange *)tmp_list->data; + pair->info.scripts[i] = *(PangoEngineScriptInfo *)tmp_list->data; tmp_list = tmp_list->next; } @@ -442,11 +453,12 @@ process_module_file (FILE *module_file) dlloaded_engines = g_slist_prepend (dlloaded_engines, pair); error: - g_list_foreach (ranges, (GFunc)g_free, NULL); - g_list_free (ranges); + g_list_foreach (scripts, (GFunc)g_free, NULL); + g_list_free (scripts); if (have_error) { + g_printerr ("Error reading Pango modules file\n"); g_free(pair); break; } @@ -497,17 +509,6 @@ read_modules (void) } static void -set_entry (PangoMapEntry *entry, gboolean is_exact, PangoEngineInfo *info) -{ - if ((is_exact && !entry->is_exact) || - !entry->info) - { - entry->is_exact = is_exact; - entry->info = info; - } -} - -static void init_modules (void) { static gboolean init = FALSE; @@ -523,90 +524,35 @@ init_modules (void) read_modules (); } -static PangoSubmap * -map_get_submap (PangoMap *map, - int index) -{ - if (index >= map->n_submaps) - { - /* Round up to a multiple of 256 */ - int new_n_submaps = (index + 0x100) & ~0xff; - int i; - - map->submaps = g_renew (PangoSubmap, map->submaps, new_n_submaps); - for (i=map->n_submaps; i<new_n_submaps; i++) - { - map->submaps[i].is_leaf = TRUE; - map->submaps[i].d.entry.info = NULL; - map->submaps[i].d.entry.is_exact = FALSE; - } - - map->n_submaps = new_n_submaps; - } - - return &map->submaps[index]; -} - static void map_add_engine (PangoMapInfo *info, PangoEnginePair *pair) { - int submap; - int i, j; PangoMap *map = info->map; + int i; - for (i=0; i<pair->info.n_ranges; i++) + for (i=0; i<pair->info.n_scripts; i++) { + PangoScript script; + PangoMapEntry *entry; gboolean is_exact = FALSE; - if (pair->info.ranges[i].langs) + if (pair->info.scripts[i].langs) { - if (pango_language_matches (info->language, pair->info.ranges[i].langs)) + if (pango_language_matches (info->language, pair->info.scripts[i].langs)) is_exact = TRUE; } - - for (submap = pair->info.ranges[i].start / 256; - submap <= pair->info.ranges[i].end / 256; - submap ++) - { - PangoSubmap *submap_struct = map_get_submap (map, submap); - gunichar start; - gunichar end; - if (submap == pair->info.ranges[i].start / 256) - start = pair->info.ranges[i].start % 256; - else - start = 0; - - if (submap == pair->info.ranges[i].end / 256) - end = pair->info.ranges[i].end % 256; - else - end = 255; - - if (submap_struct->is_leaf && - start == 0 && end == 255) - { - set_entry (&submap_struct->d.entry, - is_exact, &pair->info); - } - else - { - if (submap_struct->is_leaf) - { - PangoMapEntry old_entry = submap_struct->d.entry; - - submap_struct->is_leaf = FALSE; - submap_struct->d.leaves = g_new (PangoMapEntry, 256); - for (j=0; j<256; j++) - submap_struct->d.leaves[j] = old_entry; - } - - for (j=start; j<=end; j++) - set_entry (&submap_struct->d.leaves[j], - is_exact, &pair->info); - - } - } + script = pair->info.scripts[i].script; + if (script >= map->entries->len) + g_array_set_size (map->entries, script + 1); + + entry = &g_array_index (map->entries, PangoMapEntry, script); + + if (is_exact) + entry->exact = g_slist_prepend (entry->exact, pair); + else + entry->exact = g_slist_prepend (entry->fallback, pair); } } @@ -662,73 +608,110 @@ build_map (PangoMapInfo *info) } info->map = map = g_new (PangoMap, 1); - map->submaps = NULL; - map->n_submaps = 0; - + map->entries = g_array_new (FALSE, TRUE, sizeof (PangoMapEntry)); + map_add_engine_list (info, dlloaded_engines, engine_type, render_type); map_add_engine_list (info, registered_engines, engine_type, render_type); } /** - * pango_map_get_entry: + * pango_map_get_engine: * @map: a #PangoMap - * @wc: an ISO-10646 codepoint + * @script: a #PangoScript * - * Returns the entry in the map for a given codepoint. The entry - * contains information about the engine that should be used for - * the codepoint and also whether the engine matches the language - * tag for which the map was created exactly or just approximately. + * Returns the best engine listed in the map for a given script * - * Return value: the #PangoMapEntry for the codepoint. This value - * is owned by the #PangoMap and should not be freed. + * Return value: the best engine, if one is listed for the script, + * or %NULL. The lookup may cause the engine to be loaded; + * once an engine is loaded, it won't be unloaded. If multiple + * engines are exact for the script, the choice of which is + * returned is arbitrary. **/ -PangoMapEntry * -pango_map_get_entry (PangoMap *map, - guint32 wc) +PangoEngine * +pango_map_get_engine (PangoMap *map, + PangoScript script) { - int i = wc / 256; - - if (i < map->n_submaps) - { - PangoSubmap *submap = &map->submaps[i]; - return submap->is_leaf ? &submap->d.entry : &submap->d.leaves[wc % 256]; - } + PangoMapEntry *entry = NULL; + PangoMapEntry *common_entry = NULL; + + if (script < map->entries->len) + entry = &g_array_index (map->entries, PangoMapEntry, script); + + if (PANGO_SCRIPT_COMMON < map->entries->len) + common_entry = &g_array_index (map->entries, PangoMapEntry, PANGO_SCRIPT_COMMON); + + if (entry && entry->exact) + return pango_engine_pair_get_engine (entry->exact->data); + else if (common_entry && common_entry->exact) + return pango_engine_pair_get_engine (common_entry->exact->data); + else if (entry && entry->fallback) + return pango_engine_pair_get_engine (entry->fallback->data); + else if (common_entry && common_entry->fallback) + return pango_engine_pair_get_engine (common_entry->fallback->data); else + return NULL; +} + +void +append_engines (GSList **engine_list, + GSList *pair_list) +{ + GSList *l; + + for (l = pair_list; l; l = l->next) { - static PangoMapEntry default_entry = { NULL, FALSE }; - return &default_entry; + PangoEngine *engine = pango_engine_pair_get_engine (l->data); + if (engine) + *engine_list = g_slist_append (*engine_list, engine); } } /** - * pango_map_get_engine: + * pango_map_get_engines: * @map: a #PangoMap - * @wc: an ISO-10646 codepoint - * - * Returns the engine listed in the map for a given codepoint. + * @script: a #PangoScript + * @exact_engines: location to store list of engines that exactly + * handle this script. + * @fallback_engines: location to store list of engines that approximately + * handle this script. * - * Return value: the engine, if one is listed for the codepoint, - * or %NULL. The lookup may cause the engine to be loaded; - * once an engine is loaded + * Finds engines in the map that handle the given script. The returned + * lists should be fred with g_slist_free, but the engines in the + * lists are owned by GLib and will be kept around permanently, so + * they should not be unref'ed. **/ -PangoEngine * -pango_map_get_engine (PangoMap *map, - guint32 wc) +void +pango_map_get_engines (PangoMap *map, + PangoScript script, + GSList **exact_engines, + GSList **fallback_engines) { - int i = wc / 256; + PangoMapEntry *entry = NULL; + PangoMapEntry *common_entry = NULL; + + if (script < map->entries->len) + entry = &g_array_index (map->entries, PangoMapEntry, script); + + if (PANGO_SCRIPT_COMMON < map->entries->len) + common_entry = &g_array_index (map->entries, PangoMapEntry, PANGO_SCRIPT_COMMON); - if (i < map->n_submaps) + if (exact_engines) { - PangoSubmap *submap = &map->submaps[i]; - PangoMapEntry *entry = submap->is_leaf ? &submap->d.entry : &submap->d.leaves[wc % 256]; - - if (entry->info) - return pango_engine_pair_get_engine ((PangoEnginePair *)entry->info); - else - return NULL; + *exact_engines = NULL; + if (entry && entry->exact) + append_engines (exact_engines, entry->exact); + else if (common_entry && common_entry->exact) + append_engines (exact_engines, common_entry->exact); + } + + if (fallback_engines) + { + *fallback_engines = NULL; + if (entry && entry->fallback) + append_engines (fallback_engines, entry->fallback); + else if (common_entry && common_entry->fallback) + append_engines (fallback_engines, common_entry->fallback); } - else - return NULL; } /** diff --git a/pango/pango-context.c b/pango/pango-context.c index 5c19adb9..d6cf6bc9 100644 --- a/pango/pango-context.c +++ b/pango/pango-context.c @@ -46,15 +46,6 @@ struct _PangoContextClass }; -static void add_engines (PangoContext *context, - const gchar *text, - gint start_index, - gint length, - PangoAttrList *attrs, - PangoAttrIterator *cached_iter, - gint n_chars, - PangoAnalysis *analyses); - static void pango_context_init (PangoContext *context); static void pango_context_class_init (PangoContextClass *klass); static void pango_context_finalize (GObject *object); @@ -360,299 +351,700 @@ pango_context_get_base_dir (PangoContext *context) return context->base_dir; } -/** - * pango_itemize: - * @context: a structure holding information that affects - the itemization process. - * @text: the text to itemize. - * @start_index: first byte in @text to process - * @length: the number of bytes (not characters) to process - * after @start_index. - * This must be >= 0. - * @attrs: the set of attributes that apply to @text. - * @cached_iter: Cached attribute iterator, or NULL - * - * Breaks a piece of text into segments with consistent - * directional level and shaping engine. Each byte of @text will - * be contained in exactly one of the items in the returned list; - * the generated list of items will be in logical order (the start - * offsets of the items are ascending). - * - * @cached_iter should be an iterator over @attrs currently positioned at a - * range before or containing @start_index; @cached_iter will be advanced to - * the range covering the position just after @start_index + @length. - * (i.e. if itemizing in a loop, just keep passing in the same @cached_iter). - * - * Return value: a GList of PangoItem structures. - */ -GList * -pango_itemize (PangoContext *context, - const char *text, - int start_index, - int length, - PangoAttrList *attrs, - PangoAttrIterator *cached_iter) +/**********************************************************************/ + +static gboolean +advance_attr_iterator_to (PangoAttrIterator *iterator, + int start_index) { - gunichar *text_ucs4; - long n_chars, i; - guint8 *embedding_levels; - PangoDirection base_dir; + int start_range, end_range; + + pango_attr_iterator_range (iterator, &start_range, &end_range); + + while (start_index >= end_range) + { + if (!pango_attr_iterator_next (iterator)) + return FALSE; + pango_attr_iterator_range (iterator, &start_range, &end_range); + } + + if (start_range > start_index) + g_warning ("In pango_itemize(), the cached iterator passed in " + "had already moved beyond the start_index"); + + return TRUE; +} + +/*************************************************************************** + * We cache the results of character,fontset => font,shaper in a hash table + ***************************************************************************/ + +typedef struct { + GHashTable *hash; +} ShaperFontCache; + +typedef struct { + PangoEngineShape *shape_engine; + PangoFont *font; +} ShaperFontElement; + +static void +shaper_font_cache_destroy (ShaperFontCache *cache) +{ + g_hash_table_destroy (cache->hash); + g_free (cache); +} + +static void +shaper_font_element_destroy (ShaperFontElement *element) +{ + if (element->font) + g_object_unref (element->font); + g_free (element); +} + +static ShaperFontCache * +get_shaper_font_cache (PangoFontset *fontset) +{ + ShaperFontCache *cache; + + static GQuark cache_quark = 0; + if (!cache_quark) + cache_quark = g_quark_from_static_string ("pango-shaper-font-cache"); + + cache = g_object_get_qdata (G_OBJECT (fontset), cache_quark); + if (!cache) + { + cache = g_new (ShaperFontCache, 1); + cache->hash = g_hash_table_new_full (g_direct_hash, NULL, + NULL, (GDestroyNotify)shaper_font_element_destroy); + + g_object_set_qdata_full (G_OBJECT (fontset), cache_quark, + cache, (GDestroyNotify)shaper_font_cache_destroy); + } + + return cache; +} + +static gboolean +shaper_font_cache_get (ShaperFontCache *cache, + gunichar wc, + PangoEngineShape **shape_engine, + PangoFont **font) +{ + ShaperFontElement *element; + + element = g_hash_table_lookup (cache->hash, GUINT_TO_POINTER (wc)); + if (element) + { + *shape_engine = element->shape_engine; + *font = element->font; + + return TRUE; + } + else + return FALSE; +} + +static void +shaper_font_cache_insert (ShaperFontCache *cache, + gunichar wc, + PangoEngineShape *shape_engine, + PangoFont *font) +{ + ShaperFontElement *element = g_new (ShaperFontElement, 1); + element->shape_engine = shape_engine; + element->font = font; + + g_hash_table_insert (cache->hash, GUINT_TO_POINTER (wc), element); +} + +/**********************************************************************/ + +typedef enum { + EMBEDDING_CHANGED = 1 << 0, + SCRIPT_CHANGED = 1 << 1, + LANG_CHANGED = 1 << 2, + FONT_CHANGED = 1 << 3, + DERIVED_LANG_CHANGED = 1 << 4 +} ChangedFlags; + +typedef struct _ItemizeState ItemizeState; + +struct _ItemizeState +{ + PangoContext *context; + const char *text; + const char *end; + + const char *run_start; + const char *run_end; + + GList *result; PangoItem *item; - const char *p; - const char *next; - GList *result = NULL; - PangoAnalysis *analyses; + guint8 *embedding_levels; + int embedding_end_offset; + const char *embedding_end; + guint8 embedding; - g_return_val_if_fail (context != NULL, NULL); - g_return_val_if_fail (start_index >= 0, NULL); - g_return_val_if_fail (length >= 0, NULL); - g_return_val_if_fail (length == 0 || text != NULL, NULL); + PangoAttrIterator *attr_iter; + gboolean free_attr_iter; + const char *attr_end; + PangoFontDescription *font_desc; + PangoLanguage *lang; + GSList *extra_attrs; + gboolean copy_extra_attrs; - if (length == 0) - return NULL; + ChangedFlags changed; + + PangoScriptIter *script_iter; + const char *script_end; + PangoScript script; - base_dir = context->base_dir; + PangoLanguage *derived_lang; + PangoEngineLang *lang_engine; + + PangoFontset *current_fonts; + ShaperFontCache *cache; + + GSList *exact_engines; + GSList *fallback_engines; +}; - if (length == 0) - return NULL; +static void +update_embedding_end (ItemizeState *state) +{ + state->embedding = state->embedding_levels[state->embedding_end_offset]; + while (state->embedding_end < state->end && + state->embedding_levels[state->embedding_end_offset] == state->embedding) + { + state->embedding_end_offset++; + state->embedding_end = g_utf8_next_char (state->embedding_end); + } + + state->changed |= EMBEDDING_CHANGED; +} + +static void +update_attr_iterator (ItemizeState *state) +{ + PangoLanguage *old_lang; + int end_index; + + pango_attr_iterator_range (state->attr_iter, NULL, &end_index); + if (end_index < state->end - state->text) + state->attr_end = state->text + end_index; + else + state->attr_end = state->end; + + old_lang = state->lang; + state->font_desc = pango_font_description_copy_static (state->context->font_desc); + pango_attr_iterator_get_font (state->attr_iter, state->font_desc, + &state->lang, &state->extra_attrs); + state->copy_extra_attrs = FALSE; + + state->changed |= FONT_CHANGED; + if (state->lang != old_lang) + state->changed |= LANG_CHANGED; +} +static void +update_end (ItemizeState *state) +{ + state->run_end = state->embedding_end; + if (state->attr_end < state->run_end) + state->run_end = state->attr_end; + if (state->script_end < state->run_end) + state->run_end = state->script_end; +} + +static void +itemize_state_init (ItemizeState *state, + PangoContext *context, + const char *text, + int start_index, + int length, + PangoAttrList *attrs, + PangoAttrIterator *cached_iter) +{ + PangoDirection base_dir; + gunichar *text_ucs4; + long n_chars; + + state->context = context; + state->text = text; + state->end = text + start_index + length; + + state->result = NULL; + state->item = NULL; + + state->run_start = text + start_index; + /* First, apply the bidirectional algorithm to break * the text into directional runs. */ - text_ucs4 = g_utf8_to_ucs4_fast (text + start_index, length, &n_chars); - - embedding_levels = g_new (guint8, n_chars); + base_dir = context->base_dir; + text_ucs4 = g_utf8_to_ucs4_fast (text + start_index, length, &n_chars); + state->embedding_levels = g_new (guint8, n_chars); pango_log2vis_get_embedding_levels (text_ucs4, n_chars, &base_dir, - embedding_levels); - - /* Storing ranges would be more efficient, but also more - * complicated... we take the simple approach for now. + state->embedding_levels); + g_free (text_ucs4); + + state->embedding_end_offset = 0; + state->embedding_end = text + start_index; + update_embedding_end (state); + + /* Initialize the attribute iterator */ + if (cached_iter) + { + state->attr_iter = cached_iter; + state->free_attr_iter = FALSE; + } + else + { + state->attr_iter = pango_attr_list_get_iterator (attrs); + state->free_attr_iter = TRUE; + } - analyses = g_new0 (PangoAnalysis, n_chars); + advance_attr_iterator_to (state->attr_iter, start_index); + update_attr_iterator (state); - /* Now, fill in the appropriate shapers, language engines and fonts for - * each character. + /* Initialize the script iterator */ + state->script_iter = pango_script_iter_new (text + start_index, length); + pango_script_iter_get_range (state->script_iter, NULL, + &state->script_end, &state->script); + + update_end (state); + + state->derived_lang = NULL; + state->lang_engine = NULL; + state->current_fonts = NULL; + state->cache = NULL; + state->exact_engines = NULL; + state->fallback_engines = NULL; + + state->changed = EMBEDDING_CHANGED | SCRIPT_CHANGED | LANG_CHANGED | FONT_CHANGED; +} - add_engines (context, text, start_index, length, attrs, - cached_iter, - n_chars, - analyses); +static gboolean +itemize_state_next (ItemizeState *state) +{ + if (state->run_end == state->end) + return FALSE; - /* Make a GList of PangoItems out of the above results - */ + state->changed = 0; + + state->run_start = state->run_end; - item = NULL; - p = text + start_index; - for (i=0; i<n_chars; i++) + if (state->run_end == state->embedding_end) { - PangoAnalysis *analysis = &analyses[i]; - PangoAnalysis *last_analysis = i > 0 ? &analyses[i-1] : 0; - - next = g_utf8_next_char (p); - - if (i == 0 || - text_ucs4[i] == '\t' || text_ucs4[i-1] == '\t' || - embedding_levels[i] != embedding_levels[i-1] || - analysis->shape_engine != last_analysis->shape_engine || - analysis->lang_engine != last_analysis->lang_engine || - analysis->font != last_analysis->font || - analysis->language != last_analysis->language || - analysis->extra_attrs != last_analysis->extra_attrs) + update_embedding_end (state); + } + + if (state->run_end == state->attr_end) + { + pango_attr_iterator_next (state->attr_iter); + update_attr_iterator (state); + } + + if (state->run_end == state->script_end) + { + pango_script_iter_next (state->script_iter); + pango_script_iter_get_range (state->script_iter, NULL, + &state->script_end, &state->script); + state->changed |= SCRIPT_CHANGED; + } + + update_end (state); + + return TRUE; +} + +static GSList * +copy_attr_slist (GSList *attr_slist) +{ + GSList *new_list = NULL; + GSList *l; + + for (l = attr_slist; l; l = l->next) + new_list = g_slist_prepend (new_list, pango_attribute_copy (l->data)); + + return g_slist_reverse (new_list); +} + +static void +itemize_state_fill_shaper (ItemizeState *state, + PangoEngineShape *shape_engine, + PangoFont *font) +{ + GList *l; + + for (l = state->result; l; l = l->next) + { + PangoItem *item = l->data; + if (item->analysis.shape_engine) + break; + item->analysis.font = g_object_ref (font); + item->analysis.shape_engine = shape_engine; + } +} + +static void +itemize_state_add_character (ItemizeState *state, + PangoEngineShape *shape_engine, + PangoFont *font, + gboolean force_break, + const char *pos) +{ + if (state->item) + { + if (!force_break && + state->item->analysis.lang_engine == state->lang_engine && + state->item->analysis.shape_engine == shape_engine && + state->item->analysis.font == font) { - /* assert that previous item got at least one char */ - g_assert (item == NULL || item->length > 0); - g_assert (item == NULL || item->num_chars > 0); - - item = pango_item_new (); - item->offset = p - text; - item->num_chars = 0; - item->analysis.level = embedding_levels[i]; - - item->analysis.shape_engine = analysis->shape_engine; - item->analysis.lang_engine = analysis->lang_engine; - - item->analysis.font = analysis->font; - item->analysis.language = analysis->language; - - /* Copy the extra attribute list if necessary */ - if (analysis->extra_attrs && i != 0 && analysis->extra_attrs == last_analysis->extra_attrs) - { - GSList *tmp_list = analysis->extra_attrs; - GSList *new_list = NULL; - while (tmp_list) - { - new_list = g_slist_prepend (new_list, - pango_attribute_copy (tmp_list->data)); - tmp_list = tmp_list->next; - } - item->analysis.extra_attrs = g_slist_reverse (new_list); - } - else - item->analysis.extra_attrs = analysis->extra_attrs; - - result = g_list_prepend (result, item); + state->item->num_chars++; + return; } - else - g_object_unref (analysis->font); - item->length = (next - text) - item->offset; - item->num_chars++; - p = next; - } + state->item->length = (pos - state->text) - state->item->offset; - g_free (analyses); - g_free (embedding_levels); - g_free (text_ucs4); + if (!state->item->analysis.shape_engine && shape_engine) + { + itemize_state_fill_shaper (state, shape_engine, font); + } + else if (state->item->analysis.shape_engine && !shape_engine) + { + font = state->item->analysis.font; + shape_engine = state->item->analysis.shape_engine; + } + } + + state->item = pango_item_new (); + state->item->offset = pos - state->text; + 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); + state->item->analysis.font = font; + + state->item->analysis.level = state->embedding; + state->item->analysis.language = state->derived_lang; - return g_list_reverse (result); + if (state->copy_extra_attrs) + { + state->item->analysis.extra_attrs = copy_attr_slist (state->extra_attrs); + } + else + { + state->item->analysis.extra_attrs = state->extra_attrs; + state->copy_extra_attrs = TRUE; + } + + state->result = g_list_prepend (state->result, state->item); +} + +static void +get_engines (PangoContext *context, + PangoLanguage *lang, + PangoScript script, + GSList **exact_engines, + GSList **fallback_engines) +{ + const char *engine_type = pango_font_map_get_shape_engine_type (context->font_map); + PangoMap *shaper_map = pango_find_map (lang, + g_quark_from_string (PANGO_ENGINE_TYPE_SHAPE), + g_quark_from_string (engine_type)); + pango_map_get_engines (shaper_map, script, + exact_engines, fallback_engines); } +typedef struct { + PangoLanguage *lang; + gunichar wc; + GSList *engines; + PangoEngineShape *shape_engine; + PangoFont *font; +} GetShaperFontInfo; + static gboolean -advance_iterator_to (PangoAttrIterator *iterator, - int start_index) +get_shaper_and_font_foreach (PangoFontset *fontset, + PangoFont *font, + gpointer data) { - int start_range, end_range; - - pango_attr_iterator_range (iterator, &start_range, &end_range); + GetShaperFontInfo *info = data; + GSList *l; - while (start_index >= end_range) + for (l = info->engines; l; l = l->next) { - if (!pango_attr_iterator_next (iterator)) - return FALSE; - pango_attr_iterator_range (iterator, &start_range, &end_range); + PangoEngineShape *engine = l->data; + PangoCoverageLevel level; + + level = _pango_engine_shape_covers (engine, font, + info->lang, info->wc); + if (level != PANGO_COVERAGE_NONE) + { + info->shape_engine = engine; + info->font = g_object_ref (font); + return TRUE; + } } - if (start_range > start_index) - g_warning ("In pango_itemize(), the cached iterator passed in " - "had already moved beyond the start_index"); + return FALSE; +} - return TRUE; +static gboolean +get_shaper_and_font (ItemizeState *state, + gunichar wc, + PangoEngineShape **shape_engine, + PangoFont **font) +{ + GetShaperFontInfo info; + + if (shaper_font_cache_get (state->cache, wc, shape_engine, font)) + return *shape_engine != NULL; + + if (!state->exact_engines && !state->fallback_engines) + get_engines (state->context, state->derived_lang, state->script, + &state->exact_engines, &state->fallback_engines); + + info.lang = state->derived_lang; + info.wc = wc; + info.shape_engine = NULL; + info.font = NULL; + + info.engines = state->exact_engines; + pango_fontset_foreach (state->current_fonts, get_shaper_and_font_foreach, &info); + if (info.shape_engine) + { + *shape_engine = info.shape_engine; + *font = info.font; + + shaper_font_cache_insert (state->cache, wc, *shape_engine, *font); + + return TRUE; + } + + info.engines = state->fallback_engines; + pango_fontset_foreach (state->current_fonts, get_shaper_and_font_foreach, &info); + + *shape_engine = info.shape_engine; + *font = info.font; + + shaper_font_cache_insert (state->cache, wc, *shape_engine, *font); + + return *shape_engine != NULL; } static void -add_engines (PangoContext *context, - const gchar *text, - gint start_index, - gint length, - PangoAttrList *attrs, - PangoAttrIterator *cached_iter, - gint n_chars, - PangoAnalysis *analyses) -{ - const char *pos; - PangoLanguage *language = NULL; - int next_index; - GSList *extra_attrs = NULL; - PangoMap *lang_map = NULL; - PangoFontDescription *current_desc = NULL; - PangoFontset *current_fonts = NULL; - PangoAttrIterator *iterator; - gboolean first_iteration = TRUE; - gunichar wc; - int i = 0; +itemize_state_reset_shape_engines (ItemizeState *state) +{ + g_slist_free (state->exact_engines); + state->exact_engines = NULL; + g_slist_free (state->fallback_engines); + state->fallback_engines = NULL; +} - if (cached_iter) - iterator = cached_iter; +static PangoLanguage * +compute_derived_language (PangoLanguage *lang, + PangoScript script) +{ + PangoLanguage *derived_lang; + + /* Make sure the language tag is consistent with the derived + * script. There is no point in marking up a section of + * Arabic text with the "en" language tag. + */ + if (lang && pango_language_includes_script (lang, script)) + derived_lang = lang; else - iterator = pango_attr_list_get_iterator (attrs); + { + derived_lang = pango_script_get_sample_language (script); + if (!derived_lang) + derived_lang = lang; + } - advance_iterator_to (iterator, start_index); - - pango_attr_iterator_range (iterator, NULL, &next_index); + return derived_lang; +} + +static PangoMap * +get_lang_map (PangoLanguage *lang) +{ + static guint engine_type_id = 0; + static guint render_type_id = 0; - pos = text + start_index; - for (i=0; i<n_chars; i++) + if (engine_type_id == 0) { - PangoAnalysis *analysis = &analyses[i]; - - if (first_iteration || pos - text == next_index) - { - PangoLanguage *next_language; - PangoFontDescription *next_desc = pango_font_description_copy_static (context->font_desc); - - first_iteration = FALSE; - - /* Only advance the iterator if we've exhausted a range, - * not on the first iteration. - */ - if (pos - text == next_index) - { - pango_attr_iterator_next (iterator); - pango_attr_iterator_range (iterator, NULL, &next_index); - } - - pango_attr_iterator_get_font (iterator, next_desc, &next_language, &extra_attrs); - - if (!next_language) - next_language = context->language; - - if (i == 0 || language != next_language) - { - static guint engine_type_id = 0; - static guint render_type_id = 0; - - if (engine_type_id == 0) - { - engine_type_id = g_quark_from_static_string (PANGO_ENGINE_TYPE_LANG); - render_type_id = g_quark_from_static_string (PANGO_RENDER_TYPE_NONE); - } + engine_type_id = g_quark_from_static_string (PANGO_ENGINE_TYPE_LANG); + render_type_id = g_quark_from_static_string (PANGO_RENDER_TYPE_NONE); + } - lang_map = pango_find_map (next_language, - engine_type_id, render_type_id); - } - - if (i == 0 || - language != next_language || - !pango_font_description_equal (current_desc, next_desc)) - { - pango_font_description_free (current_desc); - current_desc = next_desc; - language = next_language; - - if (current_fonts) - g_object_unref (current_fonts); - - current_fonts = pango_font_map_load_fontset (context->font_map, - context, - current_desc, - language); - } - else - pango_font_description_free (next_desc); - } - - wc = g_utf8_get_char (pos); - pos = g_utf8_next_char (pos); - - analysis->lang_engine = (PangoEngineLang *)pango_map_get_engine (lang_map, wc); - analysis->font = pango_fontset_get_font (current_fonts, wc); - analysis->language = language; + return pango_find_map (lang, engine_type_id, render_type_id); +} + +static void +itemize_state_update_for_new_run (ItemizeState *state) +{ + if (state->changed & (SCRIPT_CHANGED | LANG_CHANGED)) + { + PangoLanguage *old_derived_lang = state->derived_lang; + state->derived_lang = compute_derived_language (state->lang, state->script); + if (old_derived_lang != state->derived_lang) + state->changed |= DERIVED_LANG_CHANGED; + } - /* FIXME: handle reference counting properly on the shapers */ - if (analysis->font) - analysis->shape_engine = pango_font_find_shaper (analysis->font, language, wc); + if ((state->changed & DERIVED_LANG_CHANGED) || !state->lang_engine) + { + PangoMap *lang_map = get_lang_map (state->derived_lang); + state->lang_engine = (PangoEngineLang *)pango_map_get_engine (lang_map, state->script); + } + + if (state->changed & (SCRIPT_CHANGED | DERIVED_LANG_CHANGED)) + itemize_state_reset_shape_engines (state); + + if (state->changed & (FONT_CHANGED | DERIVED_LANG_CHANGED) && + state->current_fonts) + { + g_object_unref (state->current_fonts); + state->current_fonts = NULL; + state->cache = NULL; + } + + if (!state->current_fonts) + { + state->current_fonts = pango_font_map_load_fontset (state->context->font_map, + state->context, + state->font_desc, + state->derived_lang); + state->cache = get_shaper_font_cache (state->current_fonts); + } +} + +static void +itemize_state_process_run (ItemizeState *state) +{ + const char *p; + gboolean last_was_tab = FALSE; + + itemize_state_update_for_new_run (state); + + for (p = state->run_start; + p < state->run_end; + p = g_utf8_next_char (p)) + { + gunichar wc = g_utf8_get_char (p); + gboolean is_tab = wc == '\t'; + PangoEngineShape *shape_engine; + PangoFont *font; + + if (!g_unichar_isgraph (wc)) + { + shape_engine = NULL; + font = NULL; + } else - analysis->shape_engine = NULL; + get_shaper_and_font (state, wc, &shape_engine, &font); + + itemize_state_add_character (state, + shape_engine, font, + is_tab || last_was_tab, + p); - if (analysis->shape_engine == NULL) - analysis->shape_engine = _pango_get_fallback_shaper (); + last_was_tab = is_tab; + } + + /* Finish the final item from the current segment */ + state->item->length = (p - state->text) - state->item->offset; + if (!state->item->analysis.shape_engine) + { + PangoEngineShape *shape_engine; + PangoFont *font; - analysis->extra_attrs = extra_attrs; + if (!get_shaper_and_font (state, ' ', &shape_engine, &font)) + { + shape_engine = _pango_get_fallback_shaper (); + font = NULL; + } + + itemize_state_fill_shaper (state, shape_engine, font); } + state->item = NULL; +} + +static void +itemize_state_finish (ItemizeState *state) +{ + g_free (state->embedding_levels); + if (state->free_attr_iter) + pango_attr_iterator_destroy (state->attr_iter); + pango_script_iter_free (state->script_iter); + pango_font_description_free (state->font_desc); + + itemize_state_reset_shape_engines (state); + if (state->current_fonts) + g_object_unref (state->current_fonts); +} + +/** + * pango_itemize: + * @context: a structure holding information that affects + the itemization process. + * @text: the text to itemize. + * @start_index: first byte in @text to process + * @length: the number of bytes (not characters) to process + * after @start_index. + * This must be >= 0. + * @attrs: the set of attributes that apply to @text. + * @cached_iter: Cached attribute iterator, or NULL + * + * Breaks a piece of text into segments with consistent + * directional level and shaping engine. Each byte of @text will + * be contained in exactly one of the items in the returned list; + * the generated list of items will be in logical order (the start + * offsets of the items are ascending). + * + * @cached_iter should be an iterator over @attrs currently positioned at a + * range before or containing @start_index; @cached_iter will be advanced to + * the range covering the position just after @start_index + @length. + * (i.e. if itemizing in a loop, just keep passing in the same @cached_iter). + * + * Return value: a GList of PangoItem structures. + */ +GList * +pango_itemize (PangoContext *context, + const char *text, + int start_index, + int length, + PangoAttrList *attrs, + PangoAttrIterator *cached_iter) +{ + ItemizeState state; + + g_return_val_if_fail (context != NULL, NULL); + g_return_val_if_fail (start_index >= 0, NULL); + g_return_val_if_fail (length >= 0, NULL); + g_return_val_if_fail (length == 0 || text != NULL, NULL); - g_assert (pos - text == start_index + length); + if (length == 0) + return NULL; - if (current_desc) - pango_font_description_free (current_desc); - if (current_fonts) - g_object_unref (current_fonts); + itemize_state_init (&state, context, text, start_index, length, + attrs, cached_iter); - if (iterator != cached_iter) - pango_attr_iterator_destroy (iterator); + do + itemize_state_process_run (&state); + while (itemize_state_next (&state)); + + itemize_state_finish (&state); + + return g_list_reverse (state.result); } /** diff --git a/pango/pango-engine-private.h b/pango/pango-engine-private.h index 2e4a3573..d56a092f 100644 --- a/pango/pango-engine-private.h +++ b/pango/pango-engine-private.h @@ -27,15 +27,16 @@ G_BEGIN_DECLS -void _pango_engine_shape_shape (PangoEngineShape *engine, - PangoFont *font, - const char *text, - int length, - PangoAnalysis *analysis, - PangoGlyphString *glyphs); -PangoCoverage *_pango_engine_shape_get_coverage (PangoEngineShape *engine, - PangoFont *font, - PangoLanguage *language); +void _pango_engine_shape_shape (PangoEngineShape *engine, + PangoFont *font, + const char *text, + int length, + PangoAnalysis *analysis, + PangoGlyphString *glyphs); +PangoCoverageLevel _pango_engine_shape_covers (PangoEngineShape *engine, + PangoFont *font, + PangoLanguage *language, + gunichar wc); PangoEngineShape *_pango_get_fallback_shaper (void); diff --git a/pango/pango-engine.c b/pango/pango-engine.c index 844a534d..d421a1ac 100644 --- a/pango/pango-engine.c +++ b/pango/pango-engine.c @@ -31,18 +31,25 @@ PANGO_DEFINE_TYPE_ABSTRACT (PangoEngineLang, pango_engine_lang, NULL, NULL, PANGO_TYPE_ENGINE); -static PangoCoverage * -pango_engine_shape_real_get_coverage (PangoEngineShape *engine, - PangoFont *font, - PangoLanguage *language) +static PangoCoverageLevel +pango_engine_shape_real_covers (PangoEngineShape *engine, + PangoFont *font, + PangoLanguage *language, + gunichar wc) { - return pango_font_get_coverage (font, language); + + PangoCoverage *coverage = pango_font_get_coverage (font, language); + PangoCoverageLevel result = pango_coverage_get (coverage, wc); + + pango_coverage_unref (coverage); + + return result; } void pango_engine_shape_class_init (PangoEngineShapeClass *class) { - class->get_coverage = pango_engine_shape_real_get_coverage; + class->covers = pango_engine_shape_real_covers; } PANGO_DEFINE_TYPE_ABSTRACT (PangoEngineShape, pango_engine_shape, @@ -70,17 +77,19 @@ _pango_engine_shape_shape (PangoEngineShape *engine, glyphs); } -PangoCoverage * -_pango_engine_shape_get_coverage (PangoEngineShape *engine, - PangoFont *font, - PangoLanguage *language) +PangoCoverageLevel +_pango_engine_shape_covers (PangoEngineShape *engine, + PangoFont *font, + PangoLanguage *language, + gunichar wc) { - g_return_val_if_fail (PANGO_IS_ENGINE_SHAPE (engine), NULL); - g_return_val_if_fail (PANGO_IS_FONT (font), NULL); + g_return_val_if_fail (PANGO_IS_ENGINE_SHAPE (engine), PANGO_COVERAGE_NONE); + g_return_val_if_fail (PANGO_IS_FONT (font), PANGO_COVERAGE_NONE); - return PANGO_ENGINE_SHAPE_GET_CLASS (engine)->get_coverage (engine, - font, - language); + return PANGO_ENGINE_SHAPE_GET_CLASS (engine)->covers (engine, + font, + language, + wc); } /* No extra fields needed */ @@ -124,25 +133,19 @@ fallback_engine_shape (PangoEngineShape *engine, } } -static PangoCoverage* -fallback_engine_get_coverage (PangoEngineShape *engine, - PangoFont *font, - PangoLanguage *lang) +static PangoCoverageLevel +fallback_engine_covers (PangoEngineShape *engine, + PangoFont *font, + PangoLanguage *lang, + gunichar wc) { - PangoCoverage *result = pango_coverage_new (); - - /* We return an empty coverage (this function won't get - * called, but if it is, empty coverage will keep - * it from being used). - */ - - return result; + return PANGO_COVERAGE_NONE; } static void fallback_engine_class_init (PangoEngineShapeClass *class) { - class->get_coverage = fallback_engine_get_coverage; + class->covers = fallback_engine_covers; class->script_shape = fallback_engine_shape; } diff --git a/pango/pango-engine.h b/pango/pango-engine.h index 1aa429de..253d85c7 100644 --- a/pango/pango-engine.h +++ b/pango/pango-engine.h @@ -26,6 +26,7 @@ #include <pango/pango-item.h> #include <pango/pango-font.h> #include <pango/pango-glyph.h> +#include <pango/pango-script.h> G_BEGIN_DECLS @@ -182,20 +183,20 @@ struct _PangoEngineShapeClass int length, PangoAnalysis *analysis, PangoGlyphString *glyphs); - PangoCoverage *(*get_coverage) (PangoEngineShape *engine, + PangoCoverageLevel (*covers) (PangoEngineShape *engine, PangoFont *font, - PangoLanguage *language); + PangoLanguage *language, + gunichar wc); }; GType pango_engine_shape_get_type (void) G_GNUC_CONST; typedef struct _PangoEngineInfo PangoEngineInfo; -typedef struct _PangoEngineRange PangoEngineRange; +typedef struct _PangoEngineScriptInfo PangoEngineScriptInfo; -struct _PangoEngineRange +struct _PangoEngineScriptInfo { - guint32 start; - guint32 end; + PangoScript script; gchar *langs; }; @@ -204,8 +205,8 @@ struct _PangoEngineInfo gchar *id; gchar *engine_type; gchar *render_type; - PangoEngineRange *ranges; - gint n_ranges; + PangoEngineScriptInfo *scripts; + gint n_scripts; }; /** diff --git a/pango/pango-fontmap.c b/pango/pango-fontmap.c index c3b62694..ba373369 100644 --- a/pango/pango-fontmap.c +++ b/pango/pango-fontmap.c @@ -249,3 +249,24 @@ pango_font_map_real_load_fontset (PangoFontMap *fontmap, return PANGO_FONTSET (fonts); } + +/** + * pango_font_map_get_shape_engine_type: + * @fontmap: a #PangoFontmap + * + * Returns the render ID for shape engines for this fontmap. + * See the <structfield>render_type</structfield> field of + * #PangoEngineInfo. + * + * Return value: the ID string for shape engines for + * this fontmap. Owned by Pango, should not be modified + * or freed. + **/ +const char * +pango_font_map_get_shape_engine_type (PangoFontMap *fontmap) +{ + g_return_val_if_fail (PANGO_IS_FONT_MAP (fontmap), NULL); + + return PANGO_FONT_MAP_GET_CLASS (fontmap)->shape_engine_type; +} + diff --git a/pango/pango-fontmap.h b/pango/pango-fontmap.h index ddf7d173..5fc5d78f 100644 --- a/pango/pango-fontmap.h +++ b/pango/pango-fontmap.h @@ -46,7 +46,6 @@ void pango_font_map_list_families (PangoFontMap *fontma PangoFontFamily ***families, int *n_families); - #ifdef PANGO_ENABLE_BACKEND #define PANGO_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FONT_MAP, PangoFontMapClass)) @@ -76,6 +75,8 @@ struct _PangoFontMapClass PangoContext *context, const PangoFontDescription *desc, PangoLanguage *language); + + const char *shape_engine_type; /*< private >*/ @@ -86,6 +87,8 @@ struct _PangoFontMapClass void (*_pango_reserved4) (void); }; +const char *pango_font_map_get_shape_engine_type (PangoFontMap *fontmap); + #endif /* PANGO_ENABLE_BACKEND */ G_END_DECLS diff --git a/pango/pango-fontset.c b/pango/pango-fontset.c index 7ba883d1..1f639376 100644 --- a/pango/pango-fontset.c +++ b/pango/pango-fontset.c @@ -26,45 +26,20 @@ #include "pango-types.h" #include "pango-font.h" #include "pango-fontset.h" +#include "pango-impl-utils.h" #include "pango-utils.h" -static void pango_fontset_class_init (PangoFontsetClass *class); static PangoFontMetrics *pango_fontset_real_get_metrics (PangoFontset *fontset); -GType -pango_fontset_get_type (void) -{ - static GType object_type = 0; - - if (!object_type) - { - static const GTypeInfo object_info = - { - sizeof (PangoFontsetClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) pango_fontset_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (PangoFontset), - 0, /* n_preallocs */ - NULL /* init */ - }; - - object_type = g_type_register_static (G_TYPE_OBJECT, - "PangoFontset", - &object_info, 0); - } - - return object_type; -} - static void pango_fontset_class_init (PangoFontsetClass *class) { class->get_metrics = pango_fontset_real_get_metrics; } +PANGO_DEFINE_TYPE_ABSTRACT (PangoFontset, pango_fontset, + pango_fontset_class_init, NULL, G_TYPE_OBJECT); + /** * pango_fontset_get_font: * @fontset: a #PangoFontset @@ -81,7 +56,7 @@ pango_fontset_get_font (PangoFontset *fontset, guint wc) { - g_return_val_if_fail (fontset != NULL, NULL); + g_return_val_if_fail (PANGO_IS_FONTSET (fontset), NULL); return PANGO_FONTSET_GET_CLASS (fontset)->get_font (fontset, wc); } @@ -98,11 +73,30 @@ pango_fontset_get_font (PangoFontset *fontset, PangoFontMetrics * pango_fontset_get_metrics (PangoFontset *fontset) { - g_return_val_if_fail (fontset != NULL, NULL); + g_return_val_if_fail (PANGO_IS_FONTSET (fontset), NULL); return PANGO_FONTSET_GET_CLASS (fontset)->get_metrics (fontset); } +/** + * pango_fontset_foreach: + * @fontset: a #PangoFontset + * @func: Callback function + * @data: data to pass to the callback function + * + * Iterate through all the fonts in a fontset, calling @func for + * each one. If @func returns TRUE, that stops the iteration. + **/ +void +pango_fontset_foreach (PangoFontset *fontset, + PangoFontsetForeachFunc func, + gpointer data) +{ + g_return_if_fail (PANGO_IS_FONTSET (fontset)); + g_return_if_fail (func != NULL); + + PANGO_FONTSET_GET_CLASS (fontset)->foreach (fontset, func, data); +} static PangoFontMetrics * pango_fontset_real_get_metrics (PangoFontset *fontset) @@ -175,13 +169,15 @@ pango_fontset_real_get_metrics (PangoFontset *fontset) #define PANGO_IS_FONTSET_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FONTSET_SIMPLE)) #define PANGO_FONTSET_SIMPLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FONTSET_SIMPLE, PangoFontsetSimpleClass)) -static void pango_fontset_simple_class_init (PangoFontsetSimpleClass *class); static void pango_fontset_simple_finalize (GObject *object); static void pango_fontset_simple_init (PangoFontsetSimple *fontset); static PangoFontMetrics *pango_fontset_simple_get_metrics (PangoFontset *fontset); static PangoLanguage * pango_fontset_simple_get_language (PangoFontset *fontset); static PangoFont * pango_fontset_simple_get_font (PangoFontset *fontset, guint wc); +static void pango_fontset_simple_foreach (PangoFontset *fontset, + PangoFontsetForeachFunc func, + gpointer data); struct _PangoFontsetSimple { @@ -218,34 +214,6 @@ pango_fontset_simple_new (PangoLanguage *language) return fontset; } -GType -pango_fontset_simple_get_type (void) -{ - static GType object_type = 0; - - if (!object_type) - { - static const GTypeInfo object_info = - { - sizeof (PangoFontsetSimpleClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) pango_fontset_simple_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (PangoFontsetSimple), - 0, /* n_preallocs */ - (GInstanceInitFunc) pango_fontset_simple_init, - }; - - object_type = g_type_register_static (PANGO_TYPE_FONTSET, - "PangoFontsetSimple", - &object_info, 0); - } - - return object_type; -} - static void pango_fontset_simple_class_init (PangoFontsetSimpleClass *class) { @@ -258,6 +226,7 @@ pango_fontset_simple_class_init (PangoFontsetSimpleClass *class) fontset_class->get_font = pango_fontset_simple_get_font; fontset_class->get_metrics = pango_fontset_simple_get_metrics; fontset_class->get_language = pango_fontset_simple_get_language; + fontset_class->foreach = pango_fontset_simple_foreach; } static void @@ -268,6 +237,10 @@ pango_fontset_simple_init (PangoFontsetSimple *fontset) fontset->language = NULL; } +PANGO_DEFINE_TYPE (PangoFontsetSimple, pango_fontset_simple, + pango_fontset_simple_class_init, pango_fontset_simple_init, + PANGO_TYPE_FONTSET); + static void pango_fontset_simple_finalize (GObject *object) { @@ -379,3 +352,20 @@ pango_fontset_simple_get_font (PangoFontset *fontset, font = g_ptr_array_index(simple->fonts, result); return g_object_ref (font); } + +static void +pango_fontset_simple_foreach (PangoFontset *fontset, + PangoFontsetForeachFunc func, + gpointer data) +{ + PangoFontsetSimple *simple = PANGO_FONTSET_SIMPLE (fontset); + int i; + + for (i = 0; i < simple->fonts->len; i++) + { + if ((*func) (fontset, + g_ptr_array_index (simple->fonts, i), + data)) + return; + } +} diff --git a/pango/pango-fontset.h b/pango/pango-fontset.h index 8a118328..49cc6006 100644 --- a/pango/pango-fontset.h +++ b/pango/pango-fontset.h @@ -41,9 +41,27 @@ GType pango_fontset_get_type (void) G_GNUC_CONST; typedef struct _PangoFontset PangoFontset; -PangoFont * pango_fontset_get_font (PangoFontset *fontset, - guint wc); -PangoFontMetrics *pango_fontset_get_metrics (PangoFontset *fontset); +/** + * PangoFontsetForeachFunc + * @fontset: a #PangoFontset + * @font: a font from @fontset + * @data: callback data + * + * A callback function used by pango_fontset_foreach() when enumerating + * the fonts in a fontset. + * + * Returns: if %TRUE, stop iteration and return immediatlehy. + **/ +typedef gboolean (*PangoFontsetForeachFunc) (PangoFontset *fontset, + PangoFont *font, + gpointer data); + +PangoFont * pango_fontset_get_font (PangoFontset *fontset, + guint wc); +PangoFontMetrics *pango_fontset_get_metrics (PangoFontset *fontset); +void pango_fontset_foreach (PangoFontset *fontset, + PangoFontsetForeachFunc func, + gpointer data); #ifdef PANGO_ENABLE_BACKEND @@ -64,11 +82,14 @@ struct _PangoFontsetClass /*< public >*/ - PangoFont * (*get_font) (PangoFontset *fontset, - guint wc); - - PangoFontMetrics *(*get_metrics) (PangoFontset *fontset); - PangoLanguage * (*get_language) (PangoFontset *fontset); + PangoFont * (*get_font) (PangoFontset *fontset, + guint wc); + + PangoFontMetrics *(*get_metrics) (PangoFontset *fontset); + PangoLanguage * (*get_language) (PangoFontset *fontset); + void (*foreach) (PangoFontset *fontset, + PangoFontsetForeachFunc func, + gpointer data); /*< private >*/ diff --git a/pango/pango-modules.h b/pango/pango-modules.h index c0bb5c9a..5dbcfe9f 100644 --- a/pango/pango-modules.h +++ b/pango/pango-modules.h @@ -31,12 +31,6 @@ G_BEGIN_DECLS typedef struct _PangoMap PangoMap; typedef struct _PangoMapEntry PangoMapEntry; -struct _PangoMapEntry -{ - PangoEngineInfo *info; - gboolean is_exact; -}; - typedef struct _PangoIncludedModule PangoIncludedModule; struct _PangoIncludedModule @@ -51,10 +45,12 @@ struct _PangoIncludedModule PangoMap * pango_find_map (PangoLanguage *language, guint engine_type_id, guint render_type_id); -PangoMapEntry *pango_map_get_entry (PangoMap *map, - guint32 wc); PangoEngine * pango_map_get_engine (PangoMap *map, - guint32 wc); + PangoScript script); +void pango_map_get_engines (PangoMap *map, + PangoScript script, + GSList **exact_engines, + GSList **fallback_engines); void pango_module_register (PangoIncludedModule *module); #endif /* PANGO_ENABLE_BACKEND */ diff --git a/pango/pango-script-lang-table.h b/pango/pango-script-lang-table.h new file mode 100644 index 00000000..e3f0b783 --- /dev/null +++ b/pango/pango-script-lang-table.h @@ -0,0 +1,191 @@ +/* pango-script-lang-table.h: Generated by gen-script-for-lang.c + * + * Date: 15 September 2003 + * Source: fontconfig-2.2.0 + * + * Do not edit. + */ +typedef struct { + const char lang[6]; + PangoScript scripts[3]; +} PangoScriptForLang; + +PangoScriptForLang pango_script_for_lang[] = { + { "aa", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ab", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "af", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "am", { PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ar", { PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ast", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ava", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ay", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "az", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE } }, + { "ba", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "bam", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "be", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "bg", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "bh", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "bho", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "bi", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "bin", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "bn", { PANGO_SCRIPT_BENGALI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "bo", { PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "br", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "bs", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "bua", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ca", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ce", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ch", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "chm", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "chr", { PANGO_SCRIPT_CHEROKEE, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "co", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "cs", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "cu", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "cv", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE } }, + { "cy", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "da", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "de", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "dz", { PANGO_SCRIPT_TIBETAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "el", { PANGO_SCRIPT_GREEK, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "en", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "eo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "es", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "et", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "eu", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "fa", { PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "fi", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "fj", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "fo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "fr", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ful", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "fur", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "fy", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ga", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "gd", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "gez", { PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "gl", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "gn", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "gu", { PANGO_SCRIPT_GUJARATI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "gv", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ha", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "haw", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "he", { PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "hi", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ho", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "hr", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "hu", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "hy", { PANGO_SCRIPT_ARMENIAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ia", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ibo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "id", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ie", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ik", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "io", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "is", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "it", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "iu", { PANGO_SCRIPT_CANADIAN_ABORIGINAL, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ja", { PANGO_SCRIPT_HAN, PANGO_SCRIPT_HIRAGANA, PANGO_SCRIPT_KATAKANA } }, + { "ka", { PANGO_SCRIPT_GEORGIAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "kaa", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ki", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "kk", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "kl", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "km", { PANGO_SCRIPT_KHMER, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "kn", { PANGO_SCRIPT_KANNADA, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ko", { PANGO_SCRIPT_HANGUL, PANGO_SCRIPT_HAN, PANGO_SCRIPT_INVALID_CODE } }, + { "kok", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ks", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ku", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE } }, + { "kum", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "kv", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "kw", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ky", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "la", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "lb", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "lez", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "lo", { PANGO_SCRIPT_LAO, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "lt", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "lv", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "mg", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "mh", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "mi", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "mk", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ml", { PANGO_SCRIPT_MALAYALAM, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "mn", { PANGO_SCRIPT_MONGOLIAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "mo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE } }, + { "mr", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "mt", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "my", { PANGO_SCRIPT_MYANMAR, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "nb", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ne", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "nl", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "nn", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "no", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ny", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "oc", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "om", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "or", { PANGO_SCRIPT_ORIYA, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "os", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "pl", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "pt", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "rm", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ro", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ru", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "sa", { PANGO_SCRIPT_DEVANAGARI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "sah", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "sco", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "se", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "sel", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "sh", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "si", { PANGO_SCRIPT_SINHALA, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "sk", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "sl", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "sm", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "sma", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "smj", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "smn", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "sms", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "so", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "sq", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "sr", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "sv", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "sw", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "syr", { PANGO_SCRIPT_SYRIAC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ta", { PANGO_SCRIPT_TAMIL, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "te", { PANGO_SCRIPT_TELUGU, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "tg", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "th", { PANGO_SCRIPT_THAI, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ti-er", { PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ti-et", { PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "tig", { PANGO_SCRIPT_ETHIOPIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "tk", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "tl", { PANGO_SCRIPT_TAGALOG, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "tn", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "to", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "tr", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ts", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "tt", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "tw", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "tyv", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ug", { PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "uk", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ur", { PANGO_SCRIPT_ARABIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "uz", { PANGO_SCRIPT_CYRILLIC, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "ven", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "vi", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "vo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "vot", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "wa", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "wen", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "wo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "xh", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "yap", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "yi", { PANGO_SCRIPT_HEBREW, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "yo", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "zh-cn", { PANGO_SCRIPT_HAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "zh-hk", { PANGO_SCRIPT_HAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "zh-mo", { PANGO_SCRIPT_HAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "zh-sg", { PANGO_SCRIPT_HAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "zh-tw", { PANGO_SCRIPT_HAN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, + { "zu", { PANGO_SCRIPT_LATIN, PANGO_SCRIPT_INVALID_CODE, PANGO_SCRIPT_INVALID_CODE } }, +}; diff --git a/pango/pango-script.c b/pango/pango-script.c index 39a95641..10acfc90 100644 --- a/pango/pango-script.c +++ b/pango/pango-script.c @@ -341,3 +341,175 @@ pango_script_iter_next (PangoScriptIter *iter) return TRUE; } + +/********************************************************** + * End of code from ICU + **********************************************************/ + +#include "pango-script-lang-table.h" + +static int +script_for_lang_compare (gconstpointer key, + gconstpointer member) +{ + const char *lang = key; + const PangoScriptForLang *script_for_lang = member; + + return strcmp (lang, + pango_language_to_string (script_for_lang->lang)); +} + +/** + * pango_language_includes_script: + * @language: a PangoLanguage + * @script: a #PangoScript + * + * Determines if @script is one of the scripts used to + * write @language. The returned value is conservative; + * if nothing is known about the language tag @language, + * %TRUE will be returned, since, as far as Pango knows, + * @script might be used to write @language. + * + * This routine is used in Pango's itemization process when + * determining if a supplied language tag is relevant to + * a particular section of text. It probably is not useful for + * applications in most circumstances. + * + * Return value: %TRUE if @script is one of the scripts used + * to write @language, or if nothing is known about @language. + **/ +gboolean +pango_language_includes_script (PangoLanguage *language, + PangoScript script) +{ + PangoScriptForLang *script_for_lang; + int j; + + g_return_val_if_fail (language != NULL, FALSE); + + /* This bsearch could be optimized to occur only once if + * we store the pointer to the PangoScriptForLang in the + * same block as the string value for the PangoLanguage. + */ + script_for_lang = bsearch (pango_language_to_string (language), + pango_script_for_lang, + sizeof (PangoScriptForLang), + G_N_ELEMENTS (pango_script_for_lang), + script_for_lang_compare); + if (!script_for_lang) + return TRUE; + + for (j = 0; j < G_N_ELEMENTS (script_for_lang->scripts); j++) + if (script_for_lang->scripts[j] == script) + return TRUE; + + return FALSE; +} + +/** + * pango_script_get_sample_language: + * @script: a #PangoScript + * + * Given a script, finds a language tag that is reasonably + * representative of that script. This will usually be the + * most widely spoken or used language written in that script: + * for instance, the sample language for %PANGO_SCRIPT_CYRILLIC + * is <literal>ru</literal> (Russian), the sample lanugage + * for %PANGO_SCRIPT_ARABIC is <literal>ar</literal>. + * + * For some + * scripts, no sample language will be returned because there + * is no language that is sufficiently representative. The best + * example of this is %PANGO_SCRIPT_HAN, where various different + * variants of written Chinese, Japanese, and Korean all use + * significantly different sets of Han characters and forms + * of shared characters. No sample language can be provided + * for many historical scripts as well. + * + * Return value: a #PangoLanguage that is representative + * of the script, or %NULL if no such language exists. + **/ +PangoLanguage * +pango_script_get_sample_language (PangoScript script) +{ + /* Note that in the following, we want + * pango_language_includes_script() for the sample language + * to include the script, so alternate orthographies + * (Shavian for English, Osmanya for Somali, etc), typically + * have no sample language + */ + const char sample_languages[][4] = { + "", /* PANGO_SCRIPT_COMMON */ + "", /* PANGO_SCRIPT_INHERITED */ + "ar", /* PANGO_SCRIPT_ARABIC */ + "hy", /* PANGO_SCRIPT_ARMENIAN */ + "bn", /* PANGO_SCRIPT_BENGALI */ + /* Used primarily in Taiwan, but not part of the standard + * zh-tw orthography */ + "", /* PANGO_SCRIPT_BOPOMOFO */ + "chr", /* PANGO_SCRIPT_CHEROKEE */ + "cop", /* PANGO_SCRIPT_COPTIC */ + "ru", /* PANGO_SCRIPT_CYRILLIC */ + /* Deseret was used to write English */ + "", /* PANGO_SCRIPT_DESERET */ + "hi", /* PANGO_SCRIPT_DEVANAGARI */ + "am", /* PANGO_SCRIPT_ETHIOPIC */ + "ka", /* PANGO_SCRIPT_GEORGIAN */ + "", /* PANGO_SCRIPT_GOTHIC */ + "el", /* PANGO_SCRIPT_GREEK */ + "gu", /* PANGO_SCRIPT_GUJARATI */ + "pa", /* PANGO_SCRIPT_GURMUKHI */ + "", /* PANGO_SCRIPT_HAN */ + "ko", /* PANGO_SCRIPT_HANGUL */ + "he", /* PANGO_SCRIPT_HEBREW */ + "ja", /* PANGO_SCRIPT_HIRAGANA */ + "kn", /* PANGO_SCRIPT_KANNADA */ + "ja", /* PANGO_SCRIPT_KATAKANA */ + "km", /* PANGO_SCRIPT_KHMER */ + "lo", /* PANGO_SCRIPT_LAO */ + "en", /* PANGO_SCRIPT_LATIN */ + "ml", /* PANGO_SCRIPT_MALAYALAM */ + "mn", /* PANGO_SCRIPT_MONGOLIAN */ + "my", /* PANGO_SCRIPT_MYANMAR */ + /* Ogham was used to write old Irish */ + "", /* PANGO_SCRIPT_OGHAM */ + "", /* PANGO_SCRIPT_OLD_ITALIC */ + "or", /* PANGO_SCRIPT_ORIYA */ + "", /* PANGO_SCRIPT_RUNIC */ + "si", /* PANGO_SCRIPT_SINHALA */ + "syr", /* PANGO_SCRIPT_SYRIAC */ + "ta", /* PANGO_SCRIPT_TAMIL */ + "te", /* PANGO_SCRIPT_TELUGU */ + "dv", /* PANGO_SCRIPT_THAANA */ + "th", /* PANGO_SCRIPT_THAI */ + "bo", /* PANGO_SCRIPT_TIBETAN */ + "iu", /* PANGO_SCRIPT_CANADIAN_ABORIGINAL */ + "", /* PANGO_SCRIPT_YI */ + "tl", /* PANGO_SCRIPT_TAGALOG */ + /* There are no ISO-636 language codes for the following + * Phillipino languages/scripts */ + "", /* PANGO_SCRIPT_HANUNOO */ + "", /* PANGO_SCRIPT_BUHID */ + "", /* PANGO_SCRIPT_TAGBANWA */ + + "", /* PANGO_SCRIPT_BRAILLE */ + "", /* PANGO_SCRIPT_CYPRIOT */ + "", /* PANGO_SCRIPT_LIMBU */ + /* Used for Somali (so) in the past */ + "", /* PANGO_SCRIPT_OSMANYA */ + /* The Shavian alphabet was designed for English */ + "", /* PANGO_SCRIPT_SHAVIAN */ + "", /* PANGO_SCRIPT_LINEAR_B */ + "", /* PANGO_SCRIPT_TAI_LE */ + "uga", /* PANGO_SCRIPT_UGARITIC */ + }; + + g_return_val_if_fail (script >= 0, NULL); + g_return_val_if_fail (script < G_N_ELEMENTS (sample_languages), NULL); + const char *sample_language = sample_languages[script]; + + if (!sample_language[0]) + return NULL; + else + return pango_language_from_string (sample_language); +} diff --git a/pango/pango-script.h b/pango/pango-script.h index 6c03c89b..cc7e2c80 100644 --- a/pango/pango-script.h +++ b/pango/pango-script.h @@ -25,6 +25,8 @@ #include <glib.h> +#include <pango/pango-types.h> + G_BEGIN_DECLS /** @@ -106,6 +108,10 @@ void pango_script_iter_get_range (PangoScriptIter *iter, gboolean pango_script_iter_next (PangoScriptIter *iter); void pango_script_iter_free (PangoScriptIter *iter); +PangoLanguage *pango_script_get_sample_language (PangoScript script); +gboolean pango_language_includes_script (PangoLanguage *language, + PangoScript script); + G_END_DECLS #endif /* __PANGO_SCRIPT_H__ */ diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c index ab8837f1..7567a4ca 100644 --- a/pango/pangofc-fontmap.c +++ b/pango/pangofc-fontmap.c @@ -201,6 +201,7 @@ pango_fc_font_map_class_init (PangoFontMapClass *class) class->load_font = pango_fc_font_map_load_font; class->load_fontset = pango_fc_font_map_load_fontset; class->list_families = pango_fc_font_map_list_families; + class->shape_engine_type = PANGO_RENDER_TYPE_FC; #ifdef INSTANCE_PRIVATE_DATA_WORKS g_type_class_add_private (object_class, sizeof (PangoFontMapClass)); diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c index adcb6b97..fd6b05d5 100644 --- a/pango/pangowin32-fontmap.c +++ b/pango/pangowin32-fontmap.c @@ -187,7 +187,8 @@ pango_win32_font_map_class_init (PangoFontMapClass *class) object_class->finalize = pango_win32_font_map_finalize; class->load_font = pango_win32_font_map_load_font; class->list_families = pango_win32_font_map_list_families; - + class->shape_engine_type = PANGO_RENDER_TYPE_WIN32; + pango_win32_get_dc (); } diff --git a/pango/pangox-fontmap.c b/pango/pangox-fontmap.c index ca6615ec..09fbfcc9 100644 --- a/pango/pangox-fontmap.c +++ b/pango/pangox-fontmap.c @@ -220,6 +220,7 @@ pango_x_font_map_class_init (PangoFontMapClass *class) object_class->finalize = pango_x_font_map_finalize; class->load_font = pango_x_font_map_load_font; class->list_families = pango_x_font_map_list_families; + class->shape_engine_type = PANGO_RENDER_TYPE_X; } /* @@ -1527,7 +1528,6 @@ pango_x_face_get_coverage (PangoXFace *xface, PangoXFont *xfont; PangoXFontMap *xfontmap = NULL; /* Quiet gcc */ PangoCoverage *result = NULL; - GHashTable *coverage_hash; Atom atom = None; if (xface) @@ -1553,42 +1553,28 @@ pango_x_face_get_coverage (PangoXFace *xface, if (!result) { - guint32 ch; PangoMap *shape_map; - PangoCoverage *coverage; - PangoCoverageLevel font_level; - PangoMapEntry *map_entry; - + PangoEngineShape *engine; + gunichar wc; + result = pango_coverage_new (); - coverage_hash = g_hash_table_new (g_str_hash, g_str_equal); - shape_map = pango_x_get_shaper_map (language); + engine = (PangoEngineShape *)pango_map_get_engine (shape_map, PANGO_SCRIPT_COMMON); - for (ch = 0; ch < 65536; ch++) + for (wc = 0; wc < 65536; wc++) { - map_entry = pango_map_get_entry (shape_map, ch); - if (map_entry->info) - { - coverage = g_hash_table_lookup (coverage_hash, map_entry->info->id); - if (!coverage) - { - PangoEngineShape *engine = (PangoEngineShape *)pango_map_get_engine (shape_map, ch); - coverage = _pango_engine_shape_get_coverage (engine, font, language); - g_hash_table_insert (coverage_hash, map_entry->info->id, coverage); - } - - font_level = pango_coverage_get (coverage, ch); - if (font_level == PANGO_COVERAGE_EXACT && !map_entry->is_exact) - font_level = PANGO_COVERAGE_APPROXIMATE; - - if (font_level != PANGO_COVERAGE_NONE) - pango_coverage_set (result, ch, font_level); - } + PangoCoverageLevel level; + + level = _pango_engine_shape_covers (engine, font, language, wc); + if (level != PANGO_COVERAGE_NONE) + pango_coverage_set (result, wc, level); } - g_hash_table_foreach (coverage_hash, free_coverages_foreach, NULL); - g_hash_table_destroy (coverage_hash); + return result; + + + result = _pango_engine_shape_get_coverage (engine, font, language); if (atom) pango_x_store_cached_coverage (xfontmap, atom, result); diff --git a/pango/querymodules.c b/pango/querymodules.c index 0bec2a11..8ea48b7a 100644 --- a/pango/querymodules.c +++ b/pango/querymodules.c @@ -27,6 +27,7 @@ #include "pango-context.h" #include "pango-utils.h" #include "pango-engine.h" +#include "pango-enum-types.h" #include <errno.h> #include <string.h> @@ -98,6 +99,24 @@ escape_string (const char *str) g_module_symbol (module, name, (gpointer *)&location) #endif +static const char * +script_from_string (PangoScript script) +{ + static GEnumClass *class = NULL; + GEnumValue *value; + if (!class) + class = g_type_class_ref (PANGO_TYPE_SCRIPT); + + value = g_enum_get_value (class, script); + if (!value) + { + g_warning ("Engine reported invalid script value %d\n", script); + return script_from_string (PANGO_SCRIPT_INVALID_CODE); + } + + return value->value_nick; +} + void query_module (const char *dir, const char *name) { @@ -151,14 +170,13 @@ query_module (const char *dir, const char *name) engines[i].id, engines[i].engine_type, engines[i].render_type); g_free (quoted_path); - for (j=0; j < engines[i].n_ranges; j++) + for (j=0; j < engines[i].n_scripts; j++) { if (j != 0) g_printf (" "); - g_printf ("%d-%d:%s", - engines[i].ranges[j].start, - engines[i].ranges[j].end, - engines[i].ranges[j].langs); + g_printf ("%s:%s", + script_from_string (engines[i].scripts[j].script), + engines[i].scripts[j].langs); } g_printf ("\n"); } @@ -179,6 +197,8 @@ int main (int argc, char **argv) int i; char *path; + g_type_init (); + g_printf ("# Pango Modules file\n" "# Automatically generated file, do not edit\n" "#\n"); diff --git a/tools/gen-script-for-lang.c b/tools/gen-script-for-lang.c index 1f774ea7..0eb8e7ad 100644 --- a/tools/gen-script-for-lang.c +++ b/tools/gen-script-for-lang.c @@ -8,8 +8,16 @@ #include <pango/pango-types.h> #include <pango/pango-utils.h> -PangoScript script_for_file (const char *base_dir, - const char *file_part); +#define MAX_SCRIPTS 3 + +typedef struct { + PangoLanguage *lang; + PangoScript scripts[MAX_SCRIPTS]; +} LangInfo; + +static void scripts_for_file (const char *base_dir, + const char *file_part, + LangInfo *info); const char *get_script_name (PangoScript script) { @@ -55,14 +63,15 @@ void warn_mismatch (const char *file_part, file_part, get_script_name (script1), get_script_name (script2)); } -PangoScript script_for_line (const char *base_dir, - const char *file_part, - const char *str) +static void +scripts_for_line (const char *base_dir, + const char *file_part, + const char *str, + LangInfo *info) { gunichar start_char; gunichar end_char; gunichar ch; - PangoScript result = PANGO_SCRIPT_COMMON; const char *p = str; if (g_str_has_prefix (str, "include")) @@ -77,10 +86,10 @@ PangoScript script_for_line (const char *base_dir, pango_skip_space (&str)) goto err; - result = script_for_file (base_dir, file_part->str); + scripts_for_file (base_dir, file_part->str, info); g_string_free (file_part, TRUE); - return result; + return; } /* Format is HEX_DIGITS or HEX_DIGITS-HEX_DIGITS */ @@ -107,30 +116,39 @@ PangoScript script_for_line (const char *base_dir, if (script != PANGO_SCRIPT_COMMON && script != PANGO_SCRIPT_INHERITED) { - if (result != PANGO_SCRIPT_COMMON && script != result) + int j; + for (j = 0; j < MAX_SCRIPTS; j++) { - warn_mismatch (file_part, script, result); - return PANGO_SCRIPT_INVALID_CODE; + if (info->scripts[j] == script) + break; + if (info->scripts[j] == PANGO_SCRIPT_INVALID_CODE) + { + info->scripts[j] = script; + break; + } } - result = script; + + if (j == MAX_SCRIPTS) + fail ("More than %d scripts found for %s\n", MAX_SCRIPTS, file_part); } } - return result; + return; err: fail ("While processing '%s', cannot parse line: '%s'\n", file_part, str); - return PANGO_SCRIPT_INVALID_CODE; /* Not reached */ + return; /* Not reached */ } -PangoScript script_for_file (const char *base_dir, - const char *file_part) +static void +scripts_for_file (const char *base_dir, + const char *file_part, + LangInfo *info) { GError *error = NULL; char *filename = g_build_filename (base_dir, file_part, NULL); GIOChannel *channel = g_io_channel_new_file (filename, "r", &error); GIOStatus status = G_IO_STATUS_NORMAL; - PangoScript result = PANGO_SCRIPT_COMMON; if (!channel) fail ("Error opening '%s': %s\n", filename, error); @@ -155,21 +173,7 @@ PangoScript script_for_file (const char *base_dir, *comment = '\0'; g_strstrip (str); if (str[0] != '\0') /* Empty */ - { - PangoScript script = script_for_line (base_dir, file_part, str); - if (script != PANGO_SCRIPT_COMMON && - script != PANGO_SCRIPT_INHERITED) - { - if (result != PANGO_SCRIPT_COMMON && script != result) - { - warn_mismatch (file_part, script, result); - result = PANGO_SCRIPT_INVALID_CODE; - status = G_IO_STATUS_EOF; - } - else - result = script; - } - } + scripts_for_line (base_dir, file_part, str, info); g_free (str); break; case G_IO_STATUS_EOF: @@ -187,14 +191,47 @@ PangoScript script_for_file (const char *base_dir, fail ("Error closing '%s': %s\n", channel, error); g_free (filename); +} + +static void +do_file (GArray *script_array, + const char *base_dir, + const char *file_part) +{ + char *langpart; + LangInfo info; + int j; + + langpart = g_strndup (file_part, strlen (file_part) - strlen (".orth")); + info.lang = pango_language_from_string (langpart); + g_free (langpart); - return result; + for (j = 0; j < MAX_SCRIPTS; j++) + info.scripts[j] = PANGO_SCRIPT_INVALID_CODE; + + scripts_for_file (base_dir, file_part, &info); + + g_array_append_val (script_array, info); +} + +static int +compare_lang (gconstpointer a, + gconstpointer b) +{ + const LangInfo *info_a = a; + const LangInfo *info_b = a; + + return strcmp (pango_language_to_string (info_a->lang), + pango_language_to_string (info_b->lang)); } int main (int argc, char **argv) { GDir *dir; GError *error = NULL; + GArray *script_array; + int i, j; + int max_lang_len = 0; g_type_init (); @@ -205,6 +242,8 @@ int main (int argc, char **argv) if (!dir) fail ("%s\n", error->message); + script_array = g_array_new (FALSE, FALSE, sizeof (LangInfo)); + while (TRUE) { const char *name = g_dir_read_name (dir); @@ -212,22 +251,46 @@ int main (int argc, char **argv) break; if (g_str_has_suffix (name, ".orth")) + do_file (script_array, argv[1], name); + } + + g_array_sort (script_array, compare_lang); + + for (i = 0; i < script_array->len; i++) + { + LangInfo *info = &g_array_index (script_array, LangInfo, i); + + max_lang_len = MAX (max_lang_len, + 1 + strlen (pango_language_to_string (info->lang))); + } + + g_print ("typedef struct {\n" + " const char lang[%d];\n" + " PangoScript scripts[%d];\n" + "} PangoScriptForLang;\n" + "\n" + "PangoScriptForLang pango_script_for_lang[] = {\n", + max_lang_len, + MAX_SCRIPTS); + + for (i = 0; i < script_array->len; i++) + { + LangInfo *info = &g_array_index (script_array, LangInfo, i); + + g_print (" { \"%s\", { ", pango_language_to_string (info->lang)); + for (j = 0; j < MAX_SCRIPTS; j++) { - char *langpart = g_strndup (name, - strlen (name) - strlen (".orth")); - PangoLanguage *lang = pango_language_from_string (langpart); - PangoScript script; - - script = script_for_file (argv[1], name); - g_print ("%s - %s\n", - pango_language_to_string (lang), - get_script_name (script)); - g_free (langpart); + if (j != 0) + g_print (", "); + g_print ("%s", get_script_name (info->scripts[j])); } + g_print (" } },\n"); } + g_print ("};\n"); + + g_dir_close (dir); return 0; } - |