aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/SkPaint.cpp16
-rw-r--r--src/core/SkScalerContext.cpp8
-rw-r--r--src/ports/FontHostConfiguration_android.cpp53
-rw-r--r--src/ports/FontHostConfiguration_android.h17
-rw-r--r--src/ports/SkFontHost_android.cpp266
5 files changed, 132 insertions, 228 deletions
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.
}
+