Index: src/fonts/SkTestScalerContext.cpp |
diff --git a/src/fonts/SkTestScalerContext.cpp b/src/fonts/SkTestScalerContext.cpp |
index 7d311cdbc0d91a337efd6858a8599d0dca0a05bc..854c98090488c3e8c53e8b99e03c0ccc3fa7883b 100644 |
--- a/src/fonts/SkTestScalerContext.cpp |
+++ b/src/fonts/SkTestScalerContext.cpp |
@@ -8,6 +8,7 @@ |
#include "SkBitmap.h" |
#include "SkCanvas.h" |
#include "SkDescriptor.h" |
+#include "SkFontDescriptor.h" |
#include "SkGlyph.h" |
#include "SkMask.h" |
// #include "SkOTUtils.h" |
@@ -15,126 +16,171 @@ |
#include "SkTestScalerContext.h" |
#include "SkTypefaceCache.h" |
-class SkTestTypeface : public SkTypeface { |
-public: |
- SkTestTypeface(SkPaint::FontMetrics (*funct)(SkTDArray<SkPath*>& , SkTDArray<SkFixed>& ), |
- SkTypeface::Style style) |
- : SkTypeface(style, SkTypefaceCache::NewFontID(), false) { |
- fMetrics = (*funct)(fPaths, fWidths); |
- } |
+SkTestFont::SkTestFont(const SkTestFontData& fontData) |
+ : INHERITED() |
+ , fCharCodes(fontData.fCharCodes) |
+ , fCharCodesCount(fontData.fCharCodesCount) |
+ , fWidths(fontData.fWidths) |
+ , fMetrics(fontData.fMetrics) |
+ , fName(fontData.fName) |
+ , fPaths(NULL) |
+{ |
+ init(fontData.fPoints, fontData.fVerbs); |
+#ifdef SK_DEBUG |
+ sk_bzero(fDebugBits, sizeof(fDebugBits)); |
+ sk_bzero(fDebugOverage, sizeof(fDebugOverage)); |
+#endif |
+} |
- virtual ~SkTestTypeface() { |
- fPaths.deleteAll(); |
+SkTestFont::~SkTestFont() { |
+ for (unsigned index = 0; index < fCharCodesCount; ++index) { |
+ SkDELETE(fPaths[index]); |
} |
+ SkDELETE_ARRAY(fPaths); |
+} |
- void getAdvance(SkGlyph* glyph) { |
- glyph->fAdvanceX = fWidths[SkGlyph::ID2Code(glyph->fID)]; |
- glyph->fAdvanceY = 0; |
- } |
+#ifdef SK_DEBUG |
- void getFontMetrics(SkPaint::FontMetrics* metrics) { |
- *metrics = fMetrics; |
- } |
+#include "SkThread.h" |
+SK_DECLARE_STATIC_MUTEX(gUsedCharsMutex); |
- void getMetrics(SkGlyph* glyph) { |
- glyph->fAdvanceX = fWidths[SkGlyph::ID2Code(glyph->fID)]; |
- glyph->fAdvanceY = 0; |
- } |
+#endif |
- void getPath(const SkGlyph& glyph, SkPath* path) { |
- *path = *fPaths[SkGlyph::ID2Code(glyph.fID)]; |
+int SkTestFont::codeToIndex(SkUnichar charCode) const { |
+#ifdef SK_DEBUG // detect missing test font data |
+ { |
+ SkAutoMutexAcquire ac(gUsedCharsMutex); |
+ if (charCode >= ' ' && charCode <= '~') { |
+ int bitOffset = charCode - ' '; |
+ fDebugBits[bitOffset >> 3] |= 1 << (bitOffset & 7); |
+ } else { |
+ int index = 0; |
+ while (fDebugOverage[index] != 0 && fDebugOverage[index] != charCode |
+ && index < (int) sizeof(fDebugOverage)) { |
+ ++index; |
+ } |
+ SkASSERT(index < (int) sizeof(fDebugOverage)); |
+ if (fDebugOverage[index] == 0) { |
+ fDebugOverage[index] = charCode; |
+ } |
+ } |
} |
- |
-protected: |
- virtual SkScalerContext* onCreateScalerContext(const SkDescriptor* desc) const SK_OVERRIDE; |
- |
- virtual void onFilterRec(SkScalerContextRec* rec) const SK_OVERRIDE { |
- rec->setHinting(SkPaint::kNo_Hinting); |
- rec->fMaskFormat = SkMask::kA8_Format; |
+#endif |
+ for (unsigned index = 0; index < fCharCodesCount; ++index) { |
+ if (fCharCodes[index] == (unsigned) charCode) { |
+ return (int) index; |
+ } |
} |
+ SkDEBUGF(("missing '%c' (%d) from %s %d\n", (char) charCode, charCode, |
+ fDebugName, fDebugStyle)); |
+ return 0; |
+} |
- virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( |
- SkAdvancedTypefaceMetrics::PerGlyphInfo , |
- const uint32_t* glyphIDs, |
- uint32_t glyphIDsCount) const SK_OVERRIDE { |
- // pdf only |
- SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics; |
- info->fEmSize = 0; |
- info->fLastGlyphID = SkToU16(onCountGlyphs() - 1); |
- info->fStyle = 0; |
- info->fFontName.set("SkiaTest"); |
- info->fType = SkAdvancedTypefaceMetrics::kOther_Font; |
- info->fItalicAngle = 0; |
- info->fAscent = 0; |
- info->fDescent = 0; |
- info->fStemV = 0; |
- info->fCapHeight = 0; |
- info->fBBox = SkIRect::MakeEmpty(); |
- return info; |
+void SkTestFont::init(const SkScalar* pts, const unsigned char* verbs) { |
+ fPaths = SkNEW_ARRAY(SkPath*, fCharCodesCount); |
+ for (unsigned index = 0; index < fCharCodesCount; ++index) { |
+ SkPath* path = SkNEW(SkPath); |
+ SkPath::Verb verb; |
+ while ((verb = (SkPath::Verb) *verbs++) != SkPath::kDone_Verb) { |
+ switch (verb) { |
+ case SkPath::kMove_Verb: |
+ path->moveTo(pts[0], pts[1]); |
+ pts += 2; |
+ break; |
+ case SkPath::kLine_Verb: |
+ path->lineTo(pts[0], pts[1]); |
+ pts += 2; |
+ break; |
+ case SkPath::kQuad_Verb: |
+ path->quadTo(pts[0], pts[1], pts[2], pts[3]); |
+ pts += 4; |
+ break; |
+ case SkPath::kCubic_Verb: |
+ path->cubicTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]); |
+ pts += 6; |
+ break; |
+ case SkPath::kClose_Verb: |
+ path->close(); |
+ break; |
+ default: |
+ SkDEBUGFAIL("bad verb"); |
+ return; |
+ } |
+ } |
+ fPaths[index] = path; |
} |
+} |
+ |
+SkTestTypeface::SkTestTypeface(SkTestFont* testFont, SkTypeface::Style style) |
+ : SkTypeface(style, SkTypefaceCache::NewFontID(), false) |
+ , fTestFont(testFont) { |
+} |
- virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { |
- SkASSERT(0); // don't expect to get here |
- return NULL; |
- } |
+void SkTestTypeface::getAdvance(SkGlyph* glyph) { |
+ glyph->fAdvanceX = fTestFont->fWidths[SkGlyph::ID2Code(glyph->fID)]; |
+ glyph->fAdvanceY = 0; |
+} |
- virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const SK_OVERRIDE { |
- SkASSERT(0); // don't expect to get here |
- } |
+void SkTestTypeface::getFontMetrics(SkPaint::FontMetrics* metrics) { |
+ *metrics = fTestFont->fMetrics; |
+} |
- virtual int onCharsToGlyphs(const void* chars, Encoding encoding, |
- uint16_t glyphs[], int glyphCount) const SK_OVERRIDE { |
- SkASSERT(encoding == kUTF8_Encoding); |
- for (int index = 0; index < glyphCount; ++index) { |
- int ch = ((unsigned char*) chars)[index]; |
- SkASSERT(ch < 0x7F); |
- if (ch < 0x20) { |
- glyphs[index] = 0; |
- } else { |
- glyphs[index] = ch - 0x20; |
- } |
- } |
- return glyphCount; |
- } |
+void SkTestTypeface::getMetrics(SkGlyph* glyph) { |
+ glyph->fAdvanceX = fTestFont->fWidths[SkGlyph::ID2Code(glyph->fID)]; |
+ glyph->fAdvanceY = 0; |
+} |
- virtual int onCountGlyphs() const SK_OVERRIDE { |
- return fPaths.count(); |
- } |
+void SkTestTypeface::getPath(const SkGlyph& glyph, SkPath* path) { |
+ *path = *fTestFont->fPaths[SkGlyph::ID2Code(glyph.fID)]; |
+} |
- virtual int onGetUPEM() const SK_OVERRIDE { |
- SkASSERT(0); // don't expect to get here |
- return 1; |
- } |
+void SkTestTypeface::onFilterRec(SkScalerContextRec* rec) const { |
+ rec->setHinting(SkPaint::kNo_Hinting); |
+ rec->fMaskFormat = SkMask::kA8_Format; |
+} |
- virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE { |
- SkString familyName("SkiaTest"); |
- SkString language("und"); //undetermined |
- SkASSERT(0); // incomplete |
- return NULL; |
- // return new SkOTUtils::LocalizedStrings_SingleName(familyName, language); |
- } |
+SkAdvancedTypefaceMetrics* SkTestTypeface::onGetAdvancedTypefaceMetrics( |
+ SkAdvancedTypefaceMetrics::PerGlyphInfo , |
+ const uint32_t* glyphIDs, |
+ uint32_t glyphIDsCount) const { |
+// pdf only |
+ SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics; |
+ info->fEmSize = 0; |
+ info->fLastGlyphID = SkToU16(onCountGlyphs() - 1); |
+ info->fStyle = 0; |
+ info->fFontName.set(fTestFont->fName); |
+ info->fType = SkAdvancedTypefaceMetrics::kOther_Font; |
+ info->fItalicAngle = 0; |
+ info->fAscent = 0; |
+ info->fDescent = 0; |
+ info->fStemV = 0; |
+ info->fCapHeight = 0; |
+ info->fBBox = SkIRect::MakeEmpty(); |
+ return info; |
+} |
- virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE { |
- return 0; |
- } |
+void SkTestTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const { |
+ desc->setFamilyName(fTestFont->fName); |
+ desc->setFontFileName(fTestFont->fName); |
+ *isLocal = false; |
+} |
- virtual size_t onGetTableData(SkFontTableTag tag, size_t offset, |
- size_t length, void* data) const SK_OVERRIDE { |
- return 0; |
+int SkTestTypeface::onCharsToGlyphs(const void* chars, Encoding encoding, |
+ uint16_t glyphs[], int glyphCount) const { |
+ SkASSERT(encoding == kUTF16_Encoding); |
+ for (int index = 0; index < glyphCount; ++index) { |
+ SkUnichar ch = ((SkUnichar*) chars)[index]; |
+ glyphs[index] = fTestFont->codeToIndex(ch); |
} |
+ return glyphCount; |
+} |
-private: |
- SkTDArray<SkPath* > fPaths; |
- SkTDArray<SkFixed> fWidths; |
- SkPaint::FontMetrics fMetrics; |
- friend class SkTestScalerContext; |
-}; |
- |
-SkTypeface* CreateTestTypeface(SkPaint::FontMetrics (*funct)(SkTDArray<SkPath*>& pathArray, |
- SkTDArray<SkFixed>& widthArray), |
- SkTypeface::Style style) { |
- SkTypeface* test = SkNEW_ARGS(SkTestTypeface, (funct, style)); |
- return test; |
+SkTypeface::LocalizedStrings* SkTestTypeface::onCreateFamilyNameIterator() const { |
+ SkString familyName(fTestFont->fName); |
+ SkString language("und"); //undetermined |
+SkASSERT(0); // incomplete |
+ return NULL; |
+// return new SkOTUtils::LocalizedStrings_SingleName(familyName, language); |
} |
class SkTestScalerContext : public SkScalerContext { |
@@ -156,10 +202,8 @@ protected: |
} |
virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE { |
- uint8_t ch = (uint8_t) uni; |
- SkASSERT(ch < 0x7f); |
uint16_t glyph; |
- (void) fFace->onCharsToGlyphs((const void *) &ch, SkTypeface::kUTF8_Encoding, &glyph, 1); |
+ (void) fFace->onCharsToGlyphs((const void *) &uni, SkTypeface::kUTF16_Encoding, &glyph, 1); |
return glyph; |
} |