From f4f708456a78383a8d1498445cd2963a493b4867 Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Thu, 11 Nov 2010 11:25:59 +1300 Subject: [PATCH] b=597147 part 15: set up PangoAnalysis for Pango shaping r=jfkthame --HG-- extra : rebase_source : 89c6d15adbf7d82672939889aad64a80a36f945a --- config/system-headers | 5 +- gfx/thebes/gfxPangoFonts.cpp | 182 +++++++++++++++++++++++++++++++++-- js/src/config/system-headers | 5 +- 3 files changed, 177 insertions(+), 15 deletions(-) diff --git a/config/system-headers b/config/system-headers index 41cccb8b47e1..d06abaae7e41 100644 --- a/config/system-headers +++ b/config/system-headers @@ -552,9 +552,7 @@ OSUtils.h Packages.h Palettes.h PALM_CMN.H -pango-engine.h -pango-glyph.h -pango-modules.h +pango/pango-modules.h pango/pangocairo.h pango/pangofc-decoder.h pango/pangofc-font.h @@ -564,7 +562,6 @@ pango/pango-fontmap.h pango/pango.h pango/pangoxft.h pango/pango-utils.h -pango-types.h pascal.h Patches.h Path.h diff --git a/gfx/thebes/gfxPangoFonts.cpp b/gfx/thebes/gfxPangoFonts.cpp index 4e145ae7875f..77d4398b786e 100644 --- a/gfx/thebes/gfxPangoFonts.cpp +++ b/gfx/thebes/gfxPangoFonts.cpp @@ -43,6 +43,7 @@ * ***** END LICENSE BLOCK ***** */ #define PANGO_ENABLE_BACKEND +#define PANGO_ENABLE_ENGINE #include "prtypes.h" #include "prlink.h" @@ -62,6 +63,7 @@ #include "gfxFT2FontBase.h" #include "gfxFT2Utils.h" #include "harfbuzz/hb-unicode.h" +#include "harfbuzz/hb-ot-tag.h" #include "gfxUnicodeProperties.h" #include "gfxFontconfigUtils.h" #include "gfxUserFontSet.h" @@ -74,6 +76,7 @@ #include #include +#include #include #ifdef MOZ_WIDGET_GTK2 @@ -535,6 +538,11 @@ public: nsresult InitGlyphRunFast(gfxTextRun *aTextRun, const PRUnichar *aString, PRUint32 aLength); #endif + PRBool InitGlyphRunWithPango(gfxTextRun *aTextRun, + const PRUnichar *aString, + PRUint32 aRunStart, PRUint32 aRunLength, + PangoScript aScript); + // The PangoFont returned is owned by the gfxFcFont PangoFont *GetPangoFont() { if (!mPangoFont) { @@ -3199,11 +3207,11 @@ SetMissingGlyphs(gfxTextRun *aTextRun, const gchar *aUTF8, } static void -InitGlyphRunWithPango(gfxTextRun *aTextRun, - const gchar *aUTF8, PRUint32 aUTF8Length, - PRUint32 *aUTF16Offset, - PangoAnalysis *aAnalysis, - PangoGlyphUnit aOverrideSpaceWidth) +InitGlyphRunWithPangoAnalysis(gfxTextRun *aTextRun, + const gchar *aUTF8, PRUint32 aUTF8Length, + PRUint32 *aUTF16Offset, + PangoAnalysis *aAnalysis, + PangoGlyphUnit aOverrideSpaceWidth) { PRUint32 utf16Offset = *aUTF16Offset; PangoGlyphString *glyphString = pango_glyph_string_new(); @@ -3236,6 +3244,165 @@ InitGlyphRunWithPango(gfxTextRun *aTextRun, *aUTF16Offset = utf16Offset; } +// PangoAnalysis is part of Pango's ABI but over time extra fields have been +// inserted into padding. This union is used so that the code here can be +// compiled against older Pango versions but run against newer versions. +typedef union { + PangoAnalysis pango; + // This struct matches PangoAnalysis from Pango version + // 1.16.5 to 1.28.1 (at least). + struct { + PangoEngineShape *shape_engine; + PangoEngineLang *lang_engine; + PangoFont *font; + guint8 level; + guint8 gravity; /* PangoGravity */ + guint8 flags; + guint8 script; /* PangoScript */ + PangoLanguage *language; + GSList *extra_attrs; + } local; +} PangoAnalysisUnion; + +PRBool +gfxFcFont::InitGlyphRunWithPango(gfxTextRun *aTextRun, + const PRUnichar *aString, + PRUint32 aRunStart, PRUint32 aRunLength, + PangoScript aScript) +{ + NS_ConvertUTF16toUTF8 utf8(aString + aRunStart, aRunLength); + + PangoFont *font = GetPangoFont(); + gfxPangoFontGroup *fontGroup = + static_cast(aTextRun->GetFontGroup()); + + hb_language_t languageOverride = NULL; + if (fontGroup->GetStyle()->languageOverride) { + languageOverride = + hb_ot_tag_to_language(fontGroup->GetStyle()->languageOverride); + } else if (GetFontEntry()->mLanguageOverride) { + languageOverride = + hb_ot_tag_to_language(GetFontEntry()->mLanguageOverride); + } + + PangoLanguage *language; + if (languageOverride) { + language = + pango_language_from_string(hb_language_to_string(languageOverride)); + } else { + language = fontGroup->GetPangoLanguage(); + // The language that we have here is often not as good an indicator for + // the run as the script. This is not so important for the PangoMaps + // here as all the default Pango shape and lang engines are selected + // by script only (not language) anyway, but may be important in the + // PangoAnalysis as the shaper sometimes accesses language-specific + // tables. + const PangoScript script = static_cast(aScript); + PangoLanguage *scriptLang; + if ((!language || + !pango_language_includes_script(language, script)) && + (scriptLang = pango_script_get_sample_language(script))) { + language = scriptLang; + } + } + + static GQuark engineLangId = + g_quark_from_static_string(PANGO_ENGINE_TYPE_LANG); + static GQuark renderNoneId = + g_quark_from_static_string(PANGO_RENDER_TYPE_NONE); + PangoMap *langMap = pango_find_map(language, engineLangId, renderNoneId); + + static GQuark engineShapeId = + g_quark_from_static_string(PANGO_ENGINE_TYPE_SHAPE); + static GQuark renderFcId = + g_quark_from_static_string(PANGO_RENDER_TYPE_FC); + PangoMap *shapeMap = pango_find_map(language, engineShapeId, renderFcId); + if (!shapeMap) { + return PR_FALSE; + } + + // The preferred shape engine for language and script + PangoEngineShape *shapeEngine = + PANGO_ENGINE_SHAPE(pango_map_get_engine(shapeMap, aScript)); + if (!shapeEngine) { + return PR_FALSE; + } + + PangoEngineShapeClass *shapeClass = static_cast + (g_type_class_peek(PANGO_TYPE_ENGINE_SHAPE)); + + // The |covers| method in the PangoEngineShape base class, which is the + // method used by Pango shapers, merely copies the fontconfig coverage map + // to a PangoCoverage and checks that the character is supported. We've + // already checked for character support, so we can avoid this copy for + // these shapers. + // + // With SIL Graphite shapers, however, |covers| also checks that the font + // is a Graphite font. (bug 397860) + if (!shapeClass || + PANGO_ENGINE_SHAPE_GET_CLASS(shapeEngine)->covers != shapeClass->covers) + { + GSList *exact_engines; + GSList *fallback_engines; + pango_map_get_engines(shapeMap, aScript, + &exact_engines, &fallback_engines); + + GSList *engines = g_slist_concat(exact_engines, fallback_engines); + for (GSList *link = engines; link; link = link->next) { + PangoEngineShape *engine = PANGO_ENGINE_SHAPE(link->data); + PangoCoverageLevel (*covers)(PangoEngineShape*, PangoFont*, + PangoLanguage*, gunichar) = + PANGO_ENGINE_SHAPE_GET_CLASS(shapeEngine)->covers; + + if ((shapeClass && covers == shapeClass->covers) || + covers(engine, font, language, ' ') != PANGO_COVERAGE_NONE) + { + shapeEngine = engine; + break; + } + } + g_slist_free(engines); // Frees exact and fallback links + } + + PangoAnalysisUnion analysis; + memset(&analysis, 0, sizeof(analysis)); + + // For pango_shape + analysis.local.shape_engine = shapeEngine; + // For pango_break + analysis.local.lang_engine = + PANGO_ENGINE_LANG(pango_map_get_engine(langMap, aScript)); + + analysis.local.font = font; + analysis.local.level = aTextRun->IsRightToLeft() ? 1 : 0; + // gravity and flags are used in Pango 1.14.10 and newer. + // + // PANGO_GRAVITY_SOUTH is what we want for upright horizontal text. The + // constant is not available when compiling with older Pango versions, but + // is zero so the zero memset initialization is sufficient. + // + // Pango uses non-zero flags for vertical gravities only + // (up to version 1.28 at least), so using zero is fine for flags too. +#if 0 + analysis.local.gravity = PANGO_GRAVITY_SOUTH; + analysis.local.flags = 0; +#endif + // Only used in Pango 1.16.5 and newer. + analysis.local.script = aScript; + + analysis.local.language = language; + // Non-font attributes. Not used here. + analysis.local.extra_attrs = NULL; + + PangoGlyphUnit spaceWidth = + moz_pango_units_from_double(GetMetrics().spaceWidth); + + PRUint32 utf16Offset = aRunStart; + InitGlyphRunWithPangoAnalysis(aTextRun, utf8.get(), utf8.Length(), + &utf16Offset, &analysis.pango, spaceWidth); + return PR_TRUE; +} + #if defined(ENABLE_FAST_PATH_8BIT) nsresult gfxPangoFontGroup::CreateGlyphRunsFast(gfxTextRun *aTextRun, @@ -3368,8 +3535,9 @@ gfxPangoFontGroup::CreateGlyphRunsItemizing(gfxTextRun *aTextRun, PRUint32 spaceWidth = moz_pango_units_from_double(font->GetMetrics().spaceWidth); - InitGlyphRunWithPango(aTextRun, utf8.get() + offset, length, - &utf16Offset, &item->analysis, spaceWidth); + InitGlyphRunWithPangoAnalysis(aTextRun, utf8.get() + offset, length, + &utf16Offset, &item->analysis, + spaceWidth); } out: diff --git a/js/src/config/system-headers b/js/src/config/system-headers index 41cccb8b47e1..d06abaae7e41 100644 --- a/js/src/config/system-headers +++ b/js/src/config/system-headers @@ -552,9 +552,7 @@ OSUtils.h Packages.h Palettes.h PALM_CMN.H -pango-engine.h -pango-glyph.h -pango-modules.h +pango/pango-modules.h pango/pangocairo.h pango/pangofc-decoder.h pango/pangofc-font.h @@ -564,7 +562,6 @@ pango/pango-fontmap.h pango/pango.h pango/pangoxft.h pango/pango-utils.h -pango-types.h pascal.h Patches.h Path.h