diff options
author | Billy Hewlett <billyh@google.com> | 2012-06-21 09:49:26 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-06-21 09:49:26 -0700 |
commit | 02edd722321b71c9ab900c4188a912b8363f3727 (patch) | |
tree | 513ecd82d2a8e3430628a98164b0366ffcc1c7e2 | |
parent | 4fb14ab43a7aac5cd51550a404b8b8c6144e37d3 (diff) | |
parent | 81957ccb58db76c172e195dc3e31eba85d3e4ac9 (diff) | |
download | external_skia-02edd722321b71c9ab900c4188a912b8363f3727.zip external_skia-02edd722321b71c9ab900c4188a912b8363f3727.tar.gz external_skia-02edd722321b71c9ab900c4188a912b8363f3727.tar.bz2 |
Merge "Revert "Use Elegant fonts for Webkit, Compact fonts for Textview""
-rw-r--r-- | include/core/SkFontHost.h | 9 | ||||
-rw-r--r-- | include/core/SkPaint.h | 20 | ||||
-rw-r--r-- | include/core/SkScalerContext.h | 4 | ||||
-rw-r--r-- | include/ports/SkTypeface_android.h | 45 | ||||
-rw-r--r-- | src/core/SkPaint.cpp | 16 | ||||
-rw-r--r-- | src/core/SkScalerContext.cpp | 8 | ||||
-rw-r--r-- | src/ports/FontHostConfiguration_android.cpp | 53 | ||||
-rw-r--r-- | src/ports/FontHostConfiguration_android.h | 17 | ||||
-rw-r--r-- | src/ports/SkFontHost_android.cpp | 266 |
9 files changed, 169 insertions, 269 deletions
diff --git a/include/core/SkFontHost.h b/include/core/SkFontHost.h index ace08d8..25c9ecb 100644 --- a/include/core/SkFontHost.h +++ b/include/core/SkFontHost.h @@ -154,15 +154,6 @@ public: */ static SkFontID NextLogicalFont(SkFontID currFontID, SkFontID origFontID); -#ifdef SK_BUILD_FOR_ANDROID - /* - * This Android-only version of NextLogicalFont allows us to pass in an - * entire Rec structure so that a caller can change fallback behavior - */ - static SkFontID NextLogicalFont(const SkScalerContext::Rec& rec); -#endif - - /////////////////////////////////////////////////////////////////////////// /** Given a filled-out rec, the fonthost may decide to modify it to reflect diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h index 1715013..30ff663 100644 --- a/include/core/SkPaint.h +++ b/include/core/SkPaint.h @@ -665,25 +665,6 @@ public: @param locale set the paint's locale value for drawing text. */ void setTextLocale(const SkString& locale); - - - enum FontVariant { - kDefault_Variant, // Currently setting yourself to Default gives you Compact Variant - kCompact_Variant, - kElegant_Variant, - kLast_Variant = kElegant_Variant, - }; - - /** Return the font variant - @return the font variant used by this paint object - */ - FontVariant getFontVariant() const { return fFontVariant; } - - - /** Set the font variant - @param fontVariant set the paint's font variant for choosing fonts - */ - void setFontVariant(FontVariant fontVariant); #endif /** Return the paint's text size. @@ -925,7 +906,6 @@ private: unsigned fHinting : 2; #ifdef SK_BUILD_FOR_ANDROID SkString fTextLocale; - FontVariant fFontVariant; #endif SkDrawCacheProc getDrawCacheProc() const; diff --git a/include/core/SkScalerContext.h b/include/core/SkScalerContext.h index 33c3c3d..9bcf601 100644 --- a/include/core/SkScalerContext.h +++ b/include/core/SkScalerContext.h @@ -210,9 +210,6 @@ public: #ifdef SK_USE_COLOR_LUMINANCE uint32_t fLumBits; #endif -#ifdef SK_BUILD_FOR_ANDROID - SkPaint::FontVariant fFontVariant; -#endif uint8_t fMaskFormat; uint8_t fStrokeJoin; uint16_t fFlags; @@ -237,6 +234,7 @@ public: SkMask::Format getFormat() const { return static_cast<SkMask::Format>(fMaskFormat); } + #ifdef SK_USE_COLOR_LUMINANCE SkColor getLuminanceColor() const { return fLumBits; diff --git a/include/ports/SkTypeface_android.h b/include/ports/SkTypeface_android.h index c3eb3d1..3471a94 100644 --- a/include/ports/SkTypeface_android.h +++ b/include/ports/SkTypeface_android.h @@ -10,20 +10,47 @@ #define SkTypeface_android_DEFINED #include "SkTypeface.h" -#include "SkPaint.h" -#include "../harfbuzz/src/harfbuzz-shaper.h" +enum FallbackScripts { + kArabic_FallbackScript, + kArmenian_FallbackScript, + kBengali_FallbackScript, + kDevanagari_FallbackScript, + kEthiopic_FallbackScript, + kGeorgian_FallbackScript, + kHebrewRegular_FallbackScript, + kHebrewBold_FallbackScript, + kKannada_FallbackScript, + kMalayalam_FallbackScript, + kTamilRegular_FallbackScript, + kTamilBold_FallbackScript, + kThai_FallbackScript, + kTelugu_FallbackScript, + kFallbackScriptNumber +}; + +#define SkTypeface_ValidScript(s) (s >= 0 && s < kFallbackScriptNumber) /** * Return a new typeface for a fallback script. If the script is * not valid, or can not map to a font, returns null. - * @param script The harfbuzz script id. - * @param style The font style, for example bold - * @param elegant true if we want the web friendly elegant version of the font - * @return reference to the matching typeface. Caller must call - * unref() when they are done. + * @param script The script id. + * @return reference to the matching typeface. Caller must call + * unref() when they are done. + */ +SK_API SkTypeface* SkCreateTypefaceForScript(FallbackScripts script); + +/** + * Return the string representation for the fallback script on Android. + * If the script is not valid, returns null. + */ +SK_API const char* SkGetFallbackScriptID(FallbackScripts script); + +/** + * Return the fallback script enum for the ID on Android. + * If the ID is not valid, or can not map to a fallback + * script, returns kFallbackScriptNumber. */ -SK_API SkTypeface* SkCreateTypefaceForScript(HB_Script script, SkTypeface::Style style, - SkPaint::FontVariant fontVariant = SkPaint::kDefault_Variant); +SK_API FallbackScripts SkGetFallbackScriptFromID(const char* id); #endif diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp index 412ab2b..e1932a7 100644 --- a/src/core/SkPaint.cpp +++ b/src/core/SkPaint.cpp @@ -72,7 +72,6 @@ SkPaint::SkPaint() { fHinting = SkPaintDefaults_Hinting; #ifdef SK_BUILD_FOR_ANDROID new(&fTextLocale) SkString(); - fFontVariant = kDefault_Variant; fGenerationID = 0; #endif } @@ -373,18 +372,6 @@ void SkPaint::setTextLocale(const SkString& locale) { GEN_ID_INC; } } - -void SkPaint::setFontVariant(FontVariant fontVariant) { - if ((unsigned)fontVariant <= kLast_Variant) { - GEN_ID_INC_EVAL((unsigned)fontVariant != fFontVariant); - fFontVariant = fontVariant; - } else { -#ifdef SK_REPORT_API_RANGE_CHECK - SkDebugf("SkPaint::setFontVariant(%d) out of range\n", fontVariant); -#endif - } -} - #endif /////////////////////////////////////////////////////////////////////////////// @@ -1574,9 +1561,6 @@ void SkScalerContext::MakeRec(const SkPaint& paint, #else rec->setLuminanceBits(computeLuminance(paint)); #endif -#ifdef SK_BUILD_FOR_ANDROID - rec->fFontVariant = paint.getFontVariant(); -#endif //SK_BUILD_FOR_ANDROID /* Allow the fonthost to modify our rec before we use it as a key into the cache. This way if we're asking for something that they will ignore, diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp index e33ad7a..2921b1e 100644 --- a/src/core/SkScalerContext.cpp +++ b/src/core/SkScalerContext.cpp @@ -118,13 +118,7 @@ static SkScalerContext* allocNextContext(const SkScalerContext::Rec& rec) { // fonthost will determine the next possible font to search, based // on the current font in fRec. It will return NULL if ctx is our // last font that can be searched (i.e. ultimate fallback font) -#ifdef SK_BUILD_FOR_ANDROID - // On Android, pass entire rec structure so that clients can change fallback behavior - uint32_t newFontID = SkFontHost::NextLogicalFont(rec); -#else - uint32_t newFontID = SkFontHost::NextLogicalFont(rec.fFontID, rec.fOrigFontID); -#endif - + uint32_t newFontID = SkFontHost::NextLogicalFont(rec.fFontID, rec.fOrigFontID); if (0 == newFontID) { return NULL; } diff --git a/src/ports/FontHostConfiguration_android.cpp b/src/ports/FontHostConfiguration_android.cpp index 9296769..d1164c8 100644 --- a/src/ports/FontHostConfiguration_android.cpp +++ b/src/ports/FontHostConfiguration_android.cpp @@ -18,7 +18,6 @@ #include "FontHostConfiguration_android.h" #include "SkString.h" #include "SkTDArray.h" -#include "SkTypeface.h" #include <expat.h> #if !defined(SK_BUILD_FOR_ANDROID_NDK) #include <cutils/properties.h> @@ -47,13 +46,12 @@ struct FamilyData { XML_Parser *parser; // The expat parser doing the work SkTDArray<FontFamily*> &families; // The array that each family is put into as it is parsed FontFamily *currentFamily; // The current family being created - FontFileInfo *currentFontInfo; // The current fontInfo being created int currentTag; // A flag to indicate whether we're in nameset/fileset tags }; /** * Handler for arbitrary text. This is used to parse the text inside each name - * or file tag. The resulting strings are put into the fNames or FontFileInfo arrays. + * or file tag. The resulting strings are put into the fNames or fFileNames arrays. */ void textHandler(void *data, const char *s, int len) { FamilyData *familyData = (FamilyData*) data; @@ -70,9 +68,7 @@ void textHandler(void *data, const char *s, int len) { *(familyData->currentFamily->fNames.append()) = buff; break; case FILESET_TAG: - if (familyData->currentFontInfo) { - familyData->currentFontInfo->fFileName = buff; - } + *(familyData->currentFamily->fFileNames.append()) = buff; break; default: // Noop - don't care about any text that's not in the Fonts or Names list @@ -82,39 +78,6 @@ void textHandler(void *data, const char *s, int len) { } /** - * Handler for font files. This processes the attributes for language and variants - * then lets textHandler handle the actual file name - */ -void fontFileElementHandler(FamilyData *familyData, const char **attributes) { - FontFileInfo* newFileInfo = new FontFileInfo(); - if (attributes) { - int currentAttributeIndex = 0; - while (attributes[currentAttributeIndex]) { - const char* attributeName = attributes[currentAttributeIndex]; - const char* attributeValue = attributes[currentAttributeIndex+1]; - int nameLength = strlen(attributeName); - int valueLength = strlen(attributeValue); - if (strncmp(attributeName, "variant", nameLength) == 0) { - if (strncmp(attributeValue, "elegant", valueLength) == 0) { - newFileInfo->fVariant = SkPaint::kElegant_Variant; - } else if (strncmp(attributeValue, "compact", valueLength) == 0) { - newFileInfo->fVariant = SkPaint::kCompact_Variant; - } - } else if (strncmp(attributeName, "language", nameLength) == 0) { - if (strncmp(attributeValue, "ja", valueLength) == 0) { - newFileInfo->fLanguage = "ja"; - } //else if (other languages) - } - //each element is a pair of attributeName/attributeValue string pairs - currentAttributeIndex += 2; - } - } - *(familyData->currentFamily->fFontFileArray.append()) = newFileInfo; - familyData->currentFontInfo = newFileInfo; - XML_SetCharacterDataHandler(*familyData->parser, textHandler); -} - -/** * Handler for the start of a tag. The only tags we expect are family, nameset, * fileset, name, and file. */ @@ -135,16 +98,14 @@ void startElementHandler(void *data, const char *tag, const char **atts) { familyData->currentFamily->order = value; } } - } else if (len == 7 && strncmp(tag, "nameset", len) == 0) { + } else if (len == 7 && strncmp(tag, "nameset", len)== 0) { familyData->currentTag = NAMESET_TAG; } else if (len == 7 && strncmp(tag, "fileset", len) == 0) { familyData->currentTag = FILESET_TAG; - } else if (strncmp(tag, "name", len) == 0 && familyData->currentTag == NAMESET_TAG) { + } else if ((strncmp(tag, "name", len) == 0 && familyData->currentTag == NAMESET_TAG) || + (strncmp(tag, "file", len) == 0 && familyData->currentTag == FILESET_TAG)) { // If it's a Name, parse the text inside XML_SetCharacterDataHandler(*familyData->parser, textHandler); - } else if (strncmp(tag, "file", len) == 0 && familyData->currentTag == FILESET_TAG) { - // If it's a file, parse the attributes, then parse the text inside - fontFileElementHandler(familyData, atts); } } @@ -159,9 +120,9 @@ void endElementHandler(void *data, const char *tag) { // Done parsing a Family - store the created currentFamily in the families array *familyData->families.append() = familyData->currentFamily; familyData->currentFamily = NULL; - } else if (len == 7 && strncmp(tag, "nameset", len) == 0) { + } else if (len == 7 && strncmp(tag, "nameset", len)== 0) { familyData->currentTag = NO_TAG; - } else if (len == 7 && strncmp(tag, "fileset", len) == 0) { + } else if (len == 7 && strncmp(tag, "fileset", len)== 0) { familyData->currentTag = NO_TAG; } else if ((strncmp(tag, "name", len) == 0 && familyData->currentTag == NAMESET_TAG) || (strncmp(tag, "file", len) == 0 && familyData->currentTag == FILESET_TAG)) { diff --git a/src/ports/FontHostConfiguration_android.h b/src/ports/FontHostConfiguration_android.h index c8a70e3..2441f0e 100644 --- a/src/ports/FontHostConfiguration_android.h +++ b/src/ports/FontHostConfiguration_android.h @@ -18,27 +18,18 @@ #define FONTHOSTCONFIGURATION_ANDROID_H_ #include "SkTDArray.h" -#include "SkPaint.h" - -struct FontFileInfo { - FontFileInfo() : fVariant(SkPaint::kDefault_Variant), fLanguage(NULL), fFileName(NULL) {} - const char* fFileName; - SkPaint::FontVariant fVariant; - const char* fLanguage; // We may eventually use a enum for this -}; - /** * The FontFamily data structure is created during parsing and handed back to * Skia to fold into its representation of font families. fNames is the list of - * font names that alias to a font family. fontFileArray is the list of information - * about each file. Order is the priority order for the font. This is + * font names that alias to a font family. fFileNames is the list of font + * filenames for the family. Order is the priority order for the font. This is * used internally to determine the order in which to place fallback fonts as * they are read from the configuration files. */ struct FontFamily { - SkTDArray<const char*> fNames; - SkTDArray<FontFileInfo*> fFontFileArray; + SkTDArray<const char*> fNames; + SkTDArray<const char*> fFileNames; int order; }; diff --git a/src/ports/SkFontHost_android.cpp b/src/ports/SkFontHost_android.cpp index 0a9cced..afd0ebe 100644 --- a/src/ports/SkFontHost_android.cpp +++ b/src/ports/SkFontHost_android.cpp @@ -29,7 +29,7 @@ #include <string.h> #include "SkGlyphCache.h" #include "SkTypeface_android.h" -#include "SkTSearch.h" + //#define SkDEBUGF(args ) SkDebugf args @@ -76,7 +76,7 @@ static SkTypeface* createTypefaceLocked(const SkTypeface* familyFace, SkTypeface::Style style); static SkStream* openStreamLocked(uint32_t fontID); static size_t getFileNameLocked(SkFontID fontID, char path[], size_t length, int32_t* index); -static SkFontID nextLogicalFontLocked(const SkScalerContext::Rec& rec); +static SkFontID nextLogicalFontLocked(SkFontID currFontID, SkFontID origFontID); static SkTypeface* createTypefaceFromStreamLocked(SkStream* stream); /////////////////////////////////////////////////////////////////////////////// @@ -150,12 +150,6 @@ static SkTypeface* findBestFaceLocked(const FamilyRec* family, return NULL; } -static SkTypeface* FindBestFace(const FamilyRec* family, - SkTypeface::Style style) { - SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); - return findBestFaceLocked(family, style); -} - static FamilyRec* findFamilyLocked(const SkTypeface* member) { FamilyRec* curr = gFamilyHead; while (curr != NULL) { @@ -186,14 +180,6 @@ static SkTypeface* findFromUniqueIDLocked(uint32_t uniqueID) { return NULL; } -/* Returns the matching typeface, or NULL. If a typeface is found, its refcnt - is not modified. - */ -static SkTypeface* FindFromUniqueID(uint32_t uniqueID) { - SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); - return findFromUniqueIDLocked(uniqueID); -} - /* Remove reference to this face from its family. If the resulting family is empty (has no faces), return that family, otherwise return NULL */ @@ -411,15 +397,8 @@ private: // used to record our notion of the pre-existing fonts struct FontInitRec { - const char* fFileName; - const char* const* fNames; // null-terminated list - SkPaint::FontVariant fVariant; -}; - -//used to record information about the fallback fonts -struct FallbackFontRec { - SkFontID fFontID; - SkPaint::FontVariant fVariant; + const char* fFileName; + const char* const* fNames; // null-terminated list }; // deliberately empty, but we use the address to identify fallback fonts @@ -431,7 +410,7 @@ static const char* gFBNames[] = { NULL }; null for the list. The names list must be NULL-terminated. */ static SkTDArray<FontInitRec> gSystemFonts; -static SkTDArray<FallbackFontRec> gFallbackFonts; +static SkTDArray<SkFontID> gFallbackFonts; // these globals are assigned (once) by loadSystemFontsLocked() static FamilyRec* gDefaultFamily = NULL; @@ -514,8 +493,8 @@ static void loadFontInfoLocked() { for (int i = 0; i < fontFamilies.count(); ++i) { FontFamily *family = fontFamilies[i]; - for (int j = 0; j < family->fFontFileArray.count(); ++j) { - const char* filename = family->fFontFileArray[j]->fFileName; + for (int j = 0; j < family->fFileNames.count(); ++j) { + const char* filename = family->fFileNames[j]; if (haveSystemFont(filename)) { SkDebugf("---- system font and fallback font files specify a duplicate " "font %s, skipping the second occurrence", filename); @@ -524,7 +503,6 @@ static void loadFontInfoLocked() { FontInitRec fontInfoRecord; fontInfoRecord.fFileName = filename; - fontInfoRecord.fVariant = family->fFontFileArray[j]->fVariant; if (j == 0) { if (family->fNames.count() == 0) { // Fallback font @@ -617,10 +595,7 @@ static void initSystemFontsLocked() { if (names == gFBNames) { SkDEBUGF(("---- adding %s as fallback[%d] fontID %d\n", gSystemFonts[i].fFileName, gFallbackFonts.count(), tf->uniqueID())); - FallbackFontRec newFallbackRec; - newFallbackRec.fFontID = tf->uniqueID(); - newFallbackRec.fVariant = gSystemFonts[i].fVariant; - *gFallbackFonts.append() = newFallbackRec; + *gFallbackFonts.append() = tf->uniqueID(); } firstInFamily = tf; @@ -659,7 +634,7 @@ static SkFontID findUniqueIDLocked(const char* filename) { static int findFallbackFontIndex(SkFontID fontId) { for (int i = 0; i < gFallbackFonts.count(); i++) { - if (gFallbackFonts[i].fFontID == fontId) { + if (gFallbackFonts[i] == fontId) { return i; } } @@ -677,8 +652,8 @@ static void reloadFallbackFontsLocked() { for (int i = 0; i < fallbackFamilies.count(); ++i) { FontFamily *family = fallbackFamilies[i]; - for (int j = 0; j < family->fFontFileArray.count(); ++j) { - const char* filename = family->fFontFileArray[j]->fFileName; + for (int j = 0; j < family->fFileNames.count(); ++j) { + const char* filename = family->fFileNames[j]; if (filename) { if (!haveSystemFont(filename)) { SkDebugf("---- skipping fallback font %s because it was not " @@ -705,10 +680,8 @@ static void reloadFallbackFontsLocked() { SkDEBUGF(("---- reload %s as fallback[%d] fontID %d\n", filename, gFallbackFonts.count(), uniqueID)); - FallbackFontRec newFallbackFont; - newFallbackFont.fFontID = uniqueID; - newFallbackFont.fVariant = family->fFontFileArray[j]->fVariant; - *gFallbackFonts.append() = newFallbackFont; + + *gFallbackFonts.append() = uniqueID; break; // The fallback set contains only the first font of each family } } @@ -913,16 +886,16 @@ static size_t getFileNameLocked(SkFontID fontID, char path[], size_t length, int } } -SkFontID SkFontHost::NextLogicalFont(const SkScalerContext::Rec& rec) { +SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) { SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); - return nextLogicalFontLocked(rec); + return nextLogicalFontLocked(currFontID, origFontID); } -static SkFontID nextLogicalFontLocked(const SkScalerContext::Rec& rec) { +static SkFontID nextLogicalFontLocked(SkFontID currFontID, SkFontID origFontID) { loadSystemFontsLocked(); - const SkTypeface* origTypeface = findFromUniqueIDLocked(rec.fOrigFontID); - const SkTypeface* currTypeface = findFromUniqueIDLocked(rec.fFontID); + const SkTypeface* origTypeface = findFromUniqueIDLocked(origFontID); + const SkTypeface* currTypeface = findFromUniqueIDLocked(currFontID); SkASSERT(origTypeface != 0); SkASSERT(currTypeface != 0); @@ -938,30 +911,17 @@ static SkFontID nextLogicalFontLocked(const SkScalerContext::Rec& rec) { */ int plainFallbackFontIndex = findFallbackFontIndex(plainFontID); int nextFallbackFontIndex = plainFallbackFontIndex + 1; - - // If a rec object is set to prefer "kDefault_Variant" it means they have no preference - // In this case, we set the value to "kCompact_Variant" - SkPaint::FontVariant recPreference = rec.fFontVariant; - if (recPreference == SkPaint::kDefault_Variant) { - recPreference = SkPaint::kCompact_Variant; - } - SkFontID nextFontID = 0; - while (nextFallbackFontIndex < gFallbackFonts.count()) { - bool normalFont = - (gFallbackFonts[nextFallbackFontIndex].fVariant == SkPaint::kDefault_Variant); - bool fontChosen = (gFallbackFonts[nextFallbackFontIndex].fVariant == recPreference); - if (normalFont || fontChosen) { - const SkTypeface* nextTypeface = - findFromUniqueIDLocked(gFallbackFonts[nextFallbackFontIndex].fFontID); - nextFontID = findTypefaceLocked(nextTypeface, origTypeface->style())->uniqueID(); - break; - } - nextFallbackFontIndex++; + SkFontID nextFontID; + if (nextFallbackFontIndex == gFallbackFonts.count()) { + nextFontID = 0; // no more fallbacks + } else { + const SkTypeface* nextTypeface = findFromUniqueIDLocked(gFallbackFonts[nextFallbackFontIndex]); + nextFontID = findTypefaceLocked(nextTypeface, origTypeface->style())->uniqueID(); } SkDEBUGF(("---- nextLogicalFont: currFontID=%d, origFontID=%d, plainFontID=%d, " "plainFallbackFontIndex=%d, nextFallbackFontIndex=%d " - "=> nextFontID=%d", rec.fFontID, rec.fOrigFontID, plainFontID, + "=> nextFontID=%d", currFontID, origFontID, plainFontID, plainFallbackFontIndex, nextFallbackFontIndex, nextFontID)); return nextFontID; } @@ -1006,9 +966,46 @@ SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { // Function from SkTypeface_android.h /////////////////////////////////////////////////////////////////////////////// -static SkFontID findFontIDForChar(SkUnichar uni, SkTypeface::Style style, - SkPaint::FontVariant fontVariant) { - SkTypeface* face = FindBestFace(gDefaultFamily, style); +struct FBScriptInfo { + const FallbackScripts fScript; + const char* fScriptID; + const SkTypeface::Style fStyle; + const SkUnichar fChar; // representative character for that script type + SkFontID fFontID; +}; + +#define SK_DEFINE_SCRIPT_ENTRY(script, style, unichar) \ + { script, #script, style, unichar, 0 } + +static FBScriptInfo gFBScriptInfo[] = { + SK_DEFINE_SCRIPT_ENTRY(kArabic_FallbackScript, SkTypeface::kNormal, 0x0600), + SK_DEFINE_SCRIPT_ENTRY(kArmenian_FallbackScript, SkTypeface::kNormal, 0x0531), + SK_DEFINE_SCRIPT_ENTRY(kBengali_FallbackScript, SkTypeface::kNormal, 0x0981), + SK_DEFINE_SCRIPT_ENTRY(kDevanagari_FallbackScript, SkTypeface::kNormal, 0x0901), + SK_DEFINE_SCRIPT_ENTRY(kEthiopic_FallbackScript, SkTypeface::kNormal, 0x1200), + SK_DEFINE_SCRIPT_ENTRY(kGeorgian_FallbackScript, SkTypeface::kNormal, 0x10A0), + SK_DEFINE_SCRIPT_ENTRY(kHebrewRegular_FallbackScript, SkTypeface::kNormal, 0x0591), + SK_DEFINE_SCRIPT_ENTRY(kHebrewBold_FallbackScript, SkTypeface::kBold, 0x0591), + SK_DEFINE_SCRIPT_ENTRY(kKannada_FallbackScript, SkTypeface::kNormal, 0x0C90), + SK_DEFINE_SCRIPT_ENTRY(kMalayalam_FallbackScript, SkTypeface::kNormal, 0x0D10), + SK_DEFINE_SCRIPT_ENTRY(kTamilRegular_FallbackScript, SkTypeface::kNormal, 0x0B82), + SK_DEFINE_SCRIPT_ENTRY(kTamilBold_FallbackScript, SkTypeface::kBold, 0x0B82), + SK_DEFINE_SCRIPT_ENTRY(kThai_FallbackScript, SkTypeface::kNormal, 0x0E01), + SK_DEFINE_SCRIPT_ENTRY(kTelugu_FallbackScript, SkTypeface::kNormal, 0x0C10), +}; + +static bool gFBScriptInitialized = false; +static const int gFBScriptInfoCount = sizeof(gFBScriptInfo) / sizeof(FBScriptInfo); + +// ensure that if any value is added to the public enum it is also added here +SK_COMPILE_ASSERT(gFBScriptInfoCount == kFallbackScriptNumber, FBScript_count_mismatch); + + +// this function can't be called if the gFamilyHeadAndNameListMutex is already locked +static SkFontID findFontIDForChar(SkUnichar uni, SkTypeface::Style style) { + gFamilyHeadAndNameListMutex.acquire(); + SkTypeface* face = findBestFaceLocked(gDefaultFamily, style); + gFamilyHeadAndNameListMutex.release(); if (!face) { return 0; } @@ -1016,7 +1013,6 @@ static SkFontID findFontIDForChar(SkUnichar uni, SkTypeface::Style style, SkPaint paint; paint.setTypeface(face); paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); - paint.setFontVariant(fontVariant); SkAutoGlyphCache autoCache(paint, NULL); SkGlyphCache* cache = autoCache.getCache(); @@ -1029,93 +1025,71 @@ static SkFontID findFontIDForChar(SkUnichar uni, SkTypeface::Style style, return 0; } -struct HB_UnicodeMapping { - HB_Script script; - const SkUnichar unicode; -}; - -static HB_UnicodeMapping HB_UnicodeMappingArray[] { - {HB_Script_Arabic, 0x0600}, - {HB_Script_Armenian, 0x0531}, - {HB_Script_Bengali, 0x0981}, - {HB_Script_Devanagari, 0x0901}, - // we don't currently support HB_Script_Ethiopic, it is a placeholder for an upstream merge - //{HB_Script_Ethiopic, 0x1200}, - {HB_Script_Georgian, 0x10A0}, - {HB_Script_Hebrew, 0x0591}, - {HB_Script_Kannada, 0x0C90}, - {HB_Script_Malayalam, 0x0D10}, - {HB_Script_Tamil, 0x0B82}, - {HB_Script_Thai, 0x0E01}, - {HB_Script_Telugu, 0x0C10}, -}; +// this function can't be called if the gFamilyHeadAndNameListMutex is already locked +static void initFBScriptInfo() { + if (gFBScriptInitialized) { + return; + } -// returns 0 for "Not Found" -static SkUnichar getUnicodeFromHBScript(HB_Script script) { - SkUnichar unichar = 0; - int numSupportedFonts = sizeof(HB_UnicodeMappingArray) / sizeof(HB_UnicodeMapping); - for (int i = 0; i < numSupportedFonts; i++) { - if (script == HB_UnicodeMappingArray[i].script) { - unichar = HB_UnicodeMappingArray[i].unicode; - break; - } + // ensure the system fonts are loaded + gFamilyHeadAndNameListMutex.acquire(); + loadSystemFontsLocked(); + gFamilyHeadAndNameListMutex.release(); + + for (int i = 0; i < gFBScriptInfoCount; i++) { + FBScriptInfo& scriptInfo = gFBScriptInfo[i]; + // selects the best available style for the desired font. However, if + // bold is requested and no bold font exists for the typeface containing + // the character the next best style is chosen (e.g. normal). + scriptInfo.fFontID = findFontIDForChar(scriptInfo.fChar, scriptInfo.fStyle); + SkDEBUGF(("gFBScriptInfo[%s] --> %d", scriptInfo.fScriptID, scriptInfo.fFontID)); } - return unichar; + // mark the value as initialized so we don't repeat our work unnecessarily + gFBScriptInitialized = true; } -struct TypefaceLookupStruct { - HB_Script script; - SkTypeface::Style style; - SkPaint::FontVariant fontVariant; - SkTypeface* typeface; -}; +SkTypeface* SkCreateTypefaceForScript(FallbackScripts script) { + if (!SkTypeface_ValidScript(script)) { + return NULL; + } -SK_DECLARE_STATIC_MUTEX(gTypefaceTableMutex); // This is the mutex for gTypefaceTable -static SkTDArray<TypefaceLookupStruct> gTypefaceTable; // This is protected by gTypefaceTableMutex + // ensure that our table is populated + initFBScriptInfo(); -static int typefaceLookupCompare(const TypefaceLookupStruct& first, - const TypefaceLookupStruct& second) { - if (first.script != second.script) { - return (first.script > second.script) ? 1 : -1; - } - if (first.style != second.style) { - return (first.style > second.style) ? 1 : -1; - } - if (first.fontVariant != second.fontVariant) { - return (first.fontVariant > second.fontVariant) ? 1 : -1; + FBScriptInfo& scriptInfo = gFBScriptInfo[script]; + + // ensure the element with that index actually maps to the correct script + SkASSERT(scriptInfo.fScript == script); + + // if a suitable script could not be found then return NULL + if (scriptInfo.fFontID == 0) { + return NULL; } - return 0; + + SkAutoMutexAcquire ac(gFamilyHeadAndNameListMutex); + + // retrieve the typeface the corresponds to this fontID + SkTypeface* tf = findFromUniqueIDLocked(scriptInfo.fFontID); + // we ref(), since the semantic is to return a new instance + tf->ref(); + return tf; } -SK_API SkTypeface* SkCreateTypefaceForScript(HB_Script script, SkTypeface::Style style, - SkPaint::FontVariant fontVariant) { - SkTypeface* retTypeface = NULL; - - SkAutoMutexAcquire ac(gTypefaceTableMutex); // Note: NOT gFamilyHeadAndNameListMutex - TypefaceLookupStruct key; - key.script = script; - key.style = style; - key.fontVariant = fontVariant; - int index = SkTSearch<TypefaceLookupStruct>( - (const TypefaceLookupStruct*) gTypefaceTable.begin(), - gTypefaceTable.count(), key, sizeof(TypefaceLookupStruct), - &typefaceLookupCompare); - if (index >= 0) { - retTypeface = gTypefaceTable[index].typeface; +const char* SkGetFallbackScriptID(FallbackScripts script) { + for (int i = 0; i < gFBScriptInfoCount; i++) { + if (gFBScriptInfo[i].fScript == script) { + return gFBScriptInfo[i].fScriptID; + } } - else { - SkUnichar unichar = getUnicodeFromHBScript(script); - if (!unichar) { - return NULL; + return NULL; +} + +FallbackScripts SkGetFallbackScriptFromID(const char* id) { + for (int i = 0; i < gFBScriptInfoCount; i++) { + if (strcmp(gFBScriptInfo[i].fScriptID, id) == 0) { + return gFBScriptInfo[i].fScript; } - SkFontID newFontID = findFontIDForChar(unichar, style, fontVariant); - // retrieve the typeface that corresponds to this fontID - retTypeface = FindFromUniqueID(newFontID); - // we ref(), since the semantic is to return a new instance - retTypeface->ref(); - key.typeface = retTypeface; - index = ~index; - *gTypefaceTable.insert(index) = key; } - return retTypeface; + return kFallbackScriptNumber; // Use kFallbackScriptNumber as an invalid value. } + |