diff options
author | Cary Clark <caryclark@google.com> | 2014-07-31 08:58:44 -0400 |
---|---|---|
committer | Cary Clark <caryclark@google.com> | 2014-07-31 08:58:44 -0400 |
commit | 992c7b03ef7914a18bfd78e965b0b4c99a5f5672 (patch) | |
tree | 2158c7f9db5da4989dc591f0aabe4a6302f3bb63 /src | |
parent | 3f22e8c44a16d93377c0a3881f936e692b5b3320 (diff) |
Add standard fonts to all GMs.
Allow GM results to be compared across machines and platforms by
standardizing the fonts used by all tests.
This adds runtime flags to DM to use either the system font context (the
default), the fonts in the resources directory ( --resourceFonts ) or a set
of canonical paths generated from the fonts ( --portableFonts ).
This CL should leave the current DM results unchanged by default.
If the portable font data or resource font is missing when DM is run, it
falls back to using the system font context.
The create_test_font tool generates the paths and metrics read by DM
with the --portableFonts flag set, and generates the font substitution
tables read by DM with the --resourceFonts flag set.
If DM is run in SkDebug mode with the --reportUsedChars flag set, it
generates the corresponding data compiled into the create_test_font tool.
All GM tests set their typeface information by calling either
sk_tool_utils::set_portable_typeface or
sk_tool_utils::portable_typeface .
(The former takes the paint, the latter returns a SkTypeface.) These calls
can be removed in the future when the Font Manager can be superceded.
BUG=skia:2687
R=mtklein@google.com
Review URL: https://codereview.chromium.org/407183003
Diffstat (limited to 'src')
-rw-r--r-- | src/fonts/SkTestScalerContext.cpp | 250 | ||||
-rw-r--r-- | src/fonts/SkTestScalerContext.h | 98 |
2 files changed, 242 insertions, 106 deletions
diff --git a/src/fonts/SkTestScalerContext.cpp b/src/fonts/SkTestScalerContext.cpp index 7d311cdbc0..854c980904 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; } diff --git a/src/fonts/SkTestScalerContext.h b/src/fonts/SkTestScalerContext.h index fa44defbfb..aed64e7e43 100644 --- a/src/fonts/SkTestScalerContext.h +++ b/src/fonts/SkTestScalerContext.h @@ -10,11 +10,103 @@ #include "SkPaint.h" #include "SkPath.h" +#include "SkRefCnt.h" #include "SkTDArray.h" #include "SkTypeface.h" -SkTypeface* CreateTestTypeface(SkPaint::FontMetrics (*funct)(SkTDArray<SkPath*>& pathArray, - SkTDArray<SkFixed>& widthArray), - SkTypeface::Style style); +class SkTestFont; + +struct SkTestFontData { + const SkScalar* fPoints; + const unsigned char* fVerbs; + const unsigned* fCharCodes; + const size_t fCharCodesCount; + const SkFixed* fWidths; + const SkPaint::FontMetrics& fMetrics; + const char* fName; + SkTypeface::Style fStyle; + SkTestFont* fFontCache; +}; + +class SkTestFont : public SkRefCnt { +public: + SK_DECLARE_INST_COUNT(SkTestFont) + + SkTestFont(const SkTestFontData& ); + virtual ~SkTestFont(); + int codeToIndex(SkUnichar charCode) const; + void init(const SkScalar* pts, const unsigned char* verbs); +#ifdef SK_DEBUG // detect missing test font data + mutable unsigned char fDebugBits[16]; + mutable SkUnichar fDebugOverage[8]; + const char* fDebugName; + SkTypeface::Style fDebugStyle; + const char* debugFontName() const { return fName; } +#endif +private: + const unsigned* fCharCodes; + const size_t fCharCodesCount; + const SkFixed* fWidths; + const SkPaint::FontMetrics& fMetrics; + const char* fName; + SkPath** fPaths; + friend class SkTestTypeface; + typedef SkRefCnt INHERITED; +}; + + +class SkTestTypeface : public SkTypeface { +public: + SkTestTypeface(SkTestFont* , SkTypeface::Style style); + virtual ~SkTestTypeface() { + SkSafeUnref(fTestFont); + } + void getAdvance(SkGlyph* glyph); + void getFontMetrics(SkPaint::FontMetrics* metrics); + void getMetrics(SkGlyph* glyph); + void getPath(const SkGlyph& glyph, SkPath* path); +protected: + virtual SkScalerContext* onCreateScalerContext(const SkDescriptor* desc) const SK_OVERRIDE; + virtual void onFilterRec(SkScalerContextRec* rec) const SK_OVERRIDE; + virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( + SkAdvancedTypefaceMetrics::PerGlyphInfo , + const uint32_t* glyphIDs, + uint32_t glyphIDsCount) const SK_OVERRIDE; + + virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { + SkASSERT(0); // don't expect to get here + return NULL; + } + + virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const SK_OVERRIDE; + + virtual int onCharsToGlyphs(const void* chars, Encoding encoding, + uint16_t glyphs[], int glyphCount) const SK_OVERRIDE; + + virtual int onCountGlyphs() const SK_OVERRIDE { + return (int) fTestFont->fCharCodesCount; + } + + virtual int onGetUPEM() const SK_OVERRIDE { + SkASSERT(0); // don't expect to get here + return 1; + } + + virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE; + + virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE { + return 0; + } + + virtual size_t onGetTableData(SkFontTableTag tag, size_t offset, + size_t length, void* data) const SK_OVERRIDE { + return 0; + } +private: + SkTestFont* fTestFont; + friend class SkTestScalerContext; +}; + +SkTypeface* CreateTestTypeface(const char* name, SkTypeface::Style style); #endif |