bug 603879 - part 2 - update harfbuzz integration to support arabic etc shaping. r=jdaggett a=blocking2.0
--- a/gfx/thebes/gfxHarfBuzzShaper.cpp
+++ b/gfx/thebes/gfxHarfBuzzShaper.cpp
@@ -200,22 +200,23 @@ struct HLongMetric {
struct HMetrics {
HLongMetric metrics[1]; // actually numberOfHMetrics
// the variable-length metrics[] array is immediately followed by:
// AutoSwap_PRUint16 leftSideBearing[];
};
void
-gfxHarfBuzzShaper::GetGlyphMetrics(gfxContext *aContext,
+gfxHarfBuzzShaper::GetGlyphAdvance(gfxContext *aContext,
hb_codepoint_t glyph,
- hb_glyph_metrics_t *metrics) const
+ hb_position_t *x_advance,
+ hb_position_t *y_advance) const
{
if (mUseHintedWidths) {
- metrics->x_advance = mFont->GetHintedGlyphWidth(aContext, glyph);
+ *x_advance = mFont->GetHintedGlyphWidth(aContext, glyph);
return;
}
// font did not implement GetHintedGlyphWidth, so get an unhinted value
// directly from the font tables
NS_ASSERTION((mNumLongMetrics > 0) && mHmtxTable != nsnull,
"font is lacking metrics, we shouldn't be here");
@@ -224,31 +225,30 @@ gfxHarfBuzzShaper::GetGlyphMetrics(gfxCo
glyph = mNumLongMetrics - 1;
}
// glyph must be valid now, because we checked during initialization
// that mNumLongMetrics is > 0, and that the hmtx table is large enough
// to contain mNumLongMetrics records
const HMetrics* hmtx =
reinterpret_cast<const HMetrics*>(hb_blob_lock(mHmtxTable));
- metrics->x_advance =
+ *x_advance =
FloatToFixed(mFont->FUnitsToDevUnitsFactor() *
PRUint16(hmtx->metrics[glyph].advanceWidth));
hb_blob_unlock(mHmtxTable);
-
- // TODO: set additional metrics if/when harfbuzz needs them
}
static void
-HBGetGlyphMetrics(hb_font_t *font, hb_face_t *face, const void *user_data,
- hb_codepoint_t glyph, hb_glyph_metrics_t *metrics)
+HBGetGlyphAdvance(hb_font_t *font, hb_face_t *face, const void *user_data,
+ hb_codepoint_t glyph,
+ hb_position_t *x_advance, hb_position_t *y_advance)
{
const FontCallbackData *fcd =
static_cast<const FontCallbackData*>(user_data);
- fcd->mShaper->GetGlyphMetrics(fcd->mContext, glyph, metrics);
+ fcd->mShaper->GetGlyphAdvance(fcd->mContext, glyph, x_advance, y_advance);
}
static hb_bool_t
HBGetContourPoint(hb_font_t *font, hb_face_t *face, const void *user_data,
unsigned int point_index, hb_codepoint_t glyph,
hb_position_t *x, hb_position_t *y)
{
/* not yet implemented - no support for used of hinted contour points
@@ -706,18 +706,18 @@ gfxHarfBuzzShaper::InitTextRun(gfxContex
if (!mHBFace) {
// set up the harfbuzz face etc the first time we use the font
if (!sHBFontFuncs) {
// static function callback pointers, initialized by the first
// harfbuzz shaper used
sHBFontFuncs = hb_font_funcs_copy(hb_font_funcs_create());
hb_font_funcs_set_glyph_func(sHBFontFuncs, HBGetGlyph);
- hb_font_funcs_set_glyph_metrics_func(sHBFontFuncs,
- HBGetGlyphMetrics);
+ hb_font_funcs_set_glyph_advance_func(sHBFontFuncs,
+ HBGetGlyphAdvance);
hb_font_funcs_set_contour_point_func(sHBFontFuncs,
HBGetContourPoint);
hb_font_funcs_set_kerning_func(sHBFontFuncs, HBGetKerning);
sHBUnicodeFuncs = hb_unicode_funcs_copy(hb_unicode_funcs_create());
hb_unicode_funcs_set_mirroring_func(sHBUnicodeFuncs,
HBGetMirroring);
hb_unicode_funcs_set_script_func(sHBUnicodeFuncs, HBGetScript);
--- a/gfx/thebes/gfxHarfBuzzShaper.h
+++ b/gfx/thebes/gfxHarfBuzzShaper.h
@@ -59,20 +59,21 @@ public:
// get a given font table in harfbuzz blob form
hb_blob_t * GetFontTable(hb_tag_t aTag) const;
// map unicode character to glyph ID
hb_codepoint_t GetGlyph(hb_codepoint_t unicode,
hb_codepoint_t variation_selector) const;
- // get harfbuzz glyph metrics, in font design units
- void GetGlyphMetrics(gfxContext *aContext,
+ // get harfbuzz glyph advance, in font design units
+ void GetGlyphAdvance(gfxContext *aContext,
hb_codepoint_t glyph,
- hb_glyph_metrics_t *metrics) const;
+ hb_position_t *x_advance,
+ hb_position_t *y_advance) const;
hb_position_t GetKerning(PRUint16 aFirstGlyph,
PRUint16 aSecondGlyph) const;
protected:
// extract glyphs from HarfBuzz buffer and store into the gfxTextRun
nsresult SetGlyphsFromRun(gfxContext *aContext,
gfxTextRun *aTextRun,
--- a/gfx/thebes/gfxMacPlatformFontList.mm
+++ b/gfx/thebes/gfxMacPlatformFontList.mm
@@ -188,17 +188,17 @@ enum eComplexScript {
struct ScriptRange {
eComplexScript script;
PRUint32 rangeStart;
PRUint32 rangeEnd;
};
const ScriptRange gScriptsThatRequireShaping[] = {
- { eComplexScriptArabic, 0x0600, 0x077F }, // Basic Arabic and Arabic Supplement
+ { eComplexScriptArabic, 0x0600, 0x077F }, // Basic Arabic, Syriac, Arabic Supplement
{ eComplexScriptIndic, 0x0900, 0x0D7F }, // Indic scripts - Devanagari, Bengali, ..., Malayalam
{ eComplexScriptTibetan, 0x0F00, 0x0FFF } // Tibetan
// Thai seems to be "renderable" without AAT morphing tables
// xxx - Lao, Khmer?
};
nsresult
MacOSFontEntry::ReadCMAP()
@@ -256,18 +256,20 @@ MacOSFontEntry::ReadCMAP()
gScriptsThatRequireShaping[s].rangeEnd)) {
PRBool omitRange = PR_TRUE;
if (hasAATLayout) {
omitRange = PR_FALSE;
} else if (whichScript == eComplexScriptArabic) {
// special-case for Arabic:
// even if there's no morph table, CoreText can shape Arabic
- // using OpenType layout
- if (hasOTLayout) {
+ // using OpenType layout; or if it's a downloaded font,
+ // assume the site knows what it's doing (as harfbuzz will
+ // be able to shape even though the font itself lacks tables)
+ if (hasOTLayout || (mIsUserFont && !mIsLocalUserFont)) {
// TODO: to be really thorough, we could check that the
// GSUB table actually supports the 'arab' script tag.
omitRange = PR_FALSE;
}
}
if (omitRange) {
mCharacterMap.ClearRange(gScriptsThatRequireShaping[s].rangeStart,
--- a/gfx/thebes/gfxUnicodeProperties.cpp
+++ b/gfx/thebes/gfxUnicodeProperties.cpp
@@ -147,28 +147,50 @@ gfxUnicodeProperties::GetScriptCode(PRUi
// TODO: replace this with a properties file or similar;
// expect this to evolve as harfbuzz shaping support matures.
//
// The "shaping level" of each script run, as returned by this
// function, is compared to the gfx.font_rendering.harfbuzz.level
// preference to decide whether to use the harfbuzz shaper.
//
-// Currently, we only distinguish "simple" (level 1) scripts
-// and "the rest" (level 2), but may subdivide this further in
-// the future.
+// Currently, we only distinguish "simple" (level 1) scripts,
+// Arabic-style cursive scripts (level 2),
+// and "Indic or other complex scripts" (level 3),
+// but may subdivide this further in the future.
PRInt32
gfxUnicodeProperties::ScriptShapingLevel(PRInt32 aScriptCode)
{
switch (aScriptCode) {
- case HB_SCRIPT_LATIN:
- case HB_SCRIPT_CYRILLIC:
- case HB_SCRIPT_HAN:
- case HB_SCRIPT_HIRAGANA:
- case HB_SCRIPT_KATAKANA:
- case HB_SCRIPT_COMMON:
- case HB_SCRIPT_INHERITED:
- case HB_SCRIPT_UNKNOWN:
- return 1; // level 1: common scripts that can use "generic" shaping
+ default:
+ return 1; // scripts not explicitly listed here are considered
+ // level 1: default shaping behavior is adequate
+
+ case HB_SCRIPT_ARABIC:
+ case HB_SCRIPT_SYRIAC:
+ case HB_SCRIPT_NKO:
+ return 2; // level 2: bidi scripts with Arabic-style shaping
+
+ case HB_SCRIPT_HEBREW:
+ case HB_SCRIPT_HANGUL:
+ case HB_SCRIPT_BENGALI:
+ case HB_SCRIPT_DEVANAGARI:
+ case HB_SCRIPT_GUJARATI:
+ case HB_SCRIPT_GURMUKHI:
+ case HB_SCRIPT_KANNADA:
+ case HB_SCRIPT_MALAYALAM:
+ case HB_SCRIPT_ORIYA:
+ case HB_SCRIPT_TAMIL:
+ case HB_SCRIPT_TELUGU:
+ case HB_SCRIPT_KHMER:
+ case HB_SCRIPT_THAI:
+ case HB_SCRIPT_LAO:
+ case HB_SCRIPT_TIBETAN:
+ case HB_SCRIPT_NEW_TAI_LUE:
+ case HB_SCRIPT_TAI_LE:
+ case HB_SCRIPT_MONGOLIAN:
+ case HB_SCRIPT_MYANMAR:
+ case HB_SCRIPT_PHAGS_PA:
+ case HB_SCRIPT_BATAK:
+ case HB_SCRIPT_BRAHMI:
+ return 3; // scripts that require Indic or other "special" shaping
}
-
- return 2; // all others are considered level 2
}
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -194,17 +194,17 @@ pref("gfx.3d_video.enabled", false);
pref("gfx.downloadable_fonts.enabled", true);
pref("gfx.downloadable_fonts.sanitize", true);
#ifdef XP_MACOSX
pref("gfx.downloadable_fonts.sanitize.preserve_otl_tables", false);
#else
pref("gfx.downloadable_fonts.sanitize.preserve_otl_tables", true);
#endif
-pref("gfx.font_rendering.harfbuzz.level", 1);
+pref("gfx.font_rendering.harfbuzz.level", 2);
#ifdef XP_WIN
#ifndef WINCE
pref("gfx.font_rendering.directwrite.enabled", false);
#endif
#endif
pref("accessibility.browsewithcaret", false);