diff options
author | Russell Brenner <russellbrenner@google.com> | 2011-08-18 13:39:43 -0700 |
---|---|---|
committer | Russell Brenner <russellbrenner@google.com> | 2011-08-23 13:16:00 -0700 |
commit | 6afb175cd4fceab68383533f7f8539100067c5c9 (patch) | |
tree | 5bc9241bd6f51577eaa37d74e2ca8e97a57d2ee2 /Source/WebCore/platform/graphics/android | |
parent | 55488a4e70941dc7d313c02041395e9a75d8b150 (diff) | |
download | external_webkit-6afb175cd4fceab68383533f7f8539100067c5c9.zip external_webkit-6afb175cd4fceab68383533f7f8539100067c5c9.tar.gz external_webkit-6afb175cd4fceab68383533f7f8539100067c5c9.tar.bz2 |
Add Harfbuzz support for fallback fonts (redux)
When Skia resorts to fallback fonts for non-latin characters, it
retains the font ID of originally requested font, concealing the
fact that a fallback was invoked. Harfbuzz needs to know the fallback
font ID to read the correct GSUB/GPOS tables from the fallback font
file so that these complex languages can be properly rendered.
This change uses the script recognized by Harfbuzz as a means to
surmise the fallback font that would be used by Skia and then injects
that font file as a replacement for the originally requested font.
Fallback fonts are loaded once and reused multiple times. An earlier
implementation did not cache fonts in this way, causing large pages
to run out of files for mmap streaming.
Bug: 5087744
Change-Id: I61222829209d9bd6df465d37923ccff3681c2c54
Diffstat (limited to 'Source/WebCore/platform/graphics/android')
3 files changed, 90 insertions, 5 deletions
diff --git a/Source/WebCore/platform/graphics/android/FontAndroid.cpp b/Source/WebCore/platform/graphics/android/FontAndroid.cpp index b56e37c..31589e3 100644 --- a/Source/WebCore/platform/graphics/android/FontAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/FontAndroid.cpp @@ -426,7 +426,21 @@ public: } private: + enum CustomScript { + Hindi, + Thai, + Naskh, + Hebrew, + HebrewBold, + NUM_SCRIPTS + }; + + static const char* paths[NUM_SCRIPTS]; + static const FontPlatformData* s_fallbackPlatformData[NUM_SCRIPTS]; + void setupFontForScriptRun(); + const FontPlatformData* setupComplexFont(CustomScript script, + const FontPlatformData& platformData); HB_FontRec* allocHarfbuzzFont(); void deleteGlyphArrays(); void createGlyphArrays(int); @@ -468,6 +482,18 @@ private: }; +// Indexed using enum CustomScript +const char* TextRunWalker::paths[] = { + "/system/fonts/Lohit_Hindi.ttf", + "/system/fonts/DroidSansThai.ttf", + "/system/fonts/DroidNaskh-Regular.ttf", + "/system/fonts/DroidSansHebrew-Regular.ttf", + "/system/fonts/DroidSansHebrew-Bold.ttf" +}; + +// Indexed using enum CustomScript +const FontPlatformData* TextRunWalker::s_fallbackPlatformData[] = {}; + TextRunWalker::TextRunWalker(const TextRun& run, unsigned startingX, const Font* font) : m_font(font) , m_startingX(startingX) @@ -620,15 +646,60 @@ void TextRunWalker::setWordAndLetterSpacing(int wordSpacingAdjustment, setLetterSpacingAdjustment(letterSpacingAdjustment); } +const FontPlatformData* TextRunWalker::setupComplexFont( + CustomScript script, + const FontPlatformData& platformData) +{ + if (!s_fallbackPlatformData[script]) { + SkTypeface* typeface = SkTypeface::CreateFromFile(paths[script]); + s_fallbackPlatformData[script] = new FontPlatformData(platformData, typeface); + SkSafeUnref(typeface); + } + + // If we couldn't allocate a new FontPlatformData, revert to the one passed + if (!s_fallbackPlatformData[script]) + return &platformData; + + return s_fallbackPlatformData[script]; +} + void TextRunWalker::setupFontForScriptRun() { - const FontData* fontData = m_font->glyphDataForCharacter( - m_item.string[m_item.item.pos], false).fontData; + const FontData* fontData = m_font->glyphDataForCharacter(m_run[0], false).fontData; const FontPlatformData& platformData = fontData->fontDataForCharacter(' ')->platformData(); - m_item.face = platformData.harfbuzzFace(); - void* opaquePlatformData = const_cast<FontPlatformData*>(&platformData); - m_item.font->userData = opaquePlatformData; + const FontPlatformData* complexPlatformData = &platformData; + + switch (m_item.item.script) { + case HB_Script_Devanagari: + complexPlatformData = setupComplexFont(Hindi, platformData); + break; + case HB_Script_Thai: + complexPlatformData = setupComplexFont(Thai, platformData); + break; + case HB_Script_Arabic: + complexPlatformData = setupComplexFont(Naskh, platformData); + break; + case HB_Script_Hebrew: + switch (platformData.typeface()->style()) { + case SkTypeface::kBold: + case SkTypeface::kBoldItalic: + complexPlatformData = setupComplexFont(HebrewBold, platformData); + break; + case SkTypeface::kNormal: + case SkTypeface::kItalic: + default: + complexPlatformData = setupComplexFont(Hebrew, platformData); + break; + } + break; + default: + // HB_Script_Common; includes Ethiopic + complexPlatformData = &platformData; + break; + } + m_item.face = complexPlatformData->harfbuzzFace(); + m_item.font->userData = const_cast<FontPlatformData*>(complexPlatformData); } HB_FontRec* TextRunWalker::allocHarfbuzzFont() diff --git a/Source/WebCore/platform/graphics/android/FontPlatformData.h b/Source/WebCore/platform/graphics/android/FontPlatformData.h index 3313aca..56ce6e9 100644 --- a/Source/WebCore/platform/graphics/android/FontPlatformData.h +++ b/Source/WebCore/platform/graphics/android/FontPlatformData.h @@ -55,6 +55,7 @@ public: FontPlatformData(SkTypeface*, float textSize, bool fakeBold, bool fakeItalic); FontPlatformData(const FontPlatformData& src, float textSize); FontPlatformData(float size, bool syntheticBold, bool syntheticOblique); + FontPlatformData(const FontPlatformData& src, SkTypeface* typeface); ~FontPlatformData(); @@ -87,6 +88,7 @@ public: #endif HB_FaceRec_* harfbuzzFace() const; + SkTypeface* typeface() const { return mTypeface; } private: class RefCountedHarfbuzzFace : public RefCounted<RefCountedHarfbuzzFace> { diff --git a/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp b/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp index 337a94d..8e77b5b 100644 --- a/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp @@ -127,6 +127,18 @@ FontPlatformData::FontPlatformData(float size, bool bold, bool oblique) trace(5); } +FontPlatformData::FontPlatformData(const FontPlatformData& src, SkTypeface* tf) + : mTypeface(tf), mTextSize(src.mTextSize), mFakeBold(src.mFakeBold), + mFakeItalic(src.mFakeItalic) +{ + if (hashTableDeletedFontValue() != mTypeface) { + SkSafeRef(mTypeface); + } + + inc_count(); + trace(6); +} + FontPlatformData::~FontPlatformData() { dec_count(); |