Home | History | Annotate | Download | only in fonts
      1 /*
      2  * Copyright 2014 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkAdvancedTypefaceMetrics.h"
      9 #include "SkBitmap.h"
     10 #include "SkCanvas.h"
     11 #include "SkDescriptor.h"
     12 #include "SkFontDescriptor.h"
     13 #include "SkGlyph.h"
     14 #include "SkMask.h"
     15 // #include "SkOTUtils.h"
     16 #include "SkScalerContext.h"
     17 #include "SkTestScalerContext.h"
     18 #include "SkTypefaceCache.h"
     19 
     20 SkTestFont::SkTestFont(const SkTestFontData& fontData)
     21     : INHERITED()
     22     , fCharCodes(fontData.fCharCodes)
     23     , fCharCodesCount(fontData.fCharCodesCount)
     24     , fWidths(fontData.fWidths)
     25     , fMetrics(fontData.fMetrics)
     26     , fName(fontData.fName)
     27     , fPaths(NULL)
     28 {
     29     init(fontData.fPoints, fontData.fVerbs);
     30 #ifdef SK_DEBUG
     31     sk_bzero(fDebugBits, sizeof(fDebugBits));
     32     sk_bzero(fDebugOverage, sizeof(fDebugOverage));
     33 #endif
     34 }
     35 
     36 SkTestFont::~SkTestFont() {
     37     for (unsigned index = 0; index < fCharCodesCount; ++index) {
     38         SkDELETE(fPaths[index]);
     39     }
     40     SkDELETE_ARRAY(fPaths);
     41 }
     42 
     43 #ifdef SK_DEBUG
     44 
     45 #include "SkThread.h"
     46 SK_DECLARE_STATIC_MUTEX(gUsedCharsMutex);
     47 
     48 #endif
     49 
     50 int SkTestFont::codeToIndex(SkUnichar charCode) const {
     51 #ifdef SK_DEBUG  // detect missing test font data
     52     {
     53         SkAutoMutexAcquire ac(gUsedCharsMutex);
     54         if (charCode >= ' ' && charCode <= '~') {
     55             int bitOffset = charCode - ' ';
     56             fDebugBits[bitOffset >> 3] |= 1 << (bitOffset & 7);
     57         } else {
     58             int index = 0;
     59             while (fDebugOverage[index] != 0 && fDebugOverage[index] != charCode
     60                     && index < (int) sizeof(fDebugOverage)) {
     61                 ++index;
     62             }
     63             SkASSERT(index < (int) sizeof(fDebugOverage));
     64             if (fDebugOverage[index] == 0) {
     65                 fDebugOverage[index] = charCode;
     66             }
     67         }
     68     }
     69 #endif
     70     for (unsigned index = 0; index < fCharCodesCount; ++index) {
     71         if (fCharCodes[index] == (unsigned) charCode) {
     72             return (int) index;
     73         }
     74     }
     75     SkDEBUGF(("missing '%c' (%d) from %s %d\n", (char) charCode, charCode,
     76             fDebugName, fDebugStyle));
     77     return 0;
     78 }
     79 
     80 void SkTestFont::init(const SkScalar* pts, const unsigned char* verbs) {
     81     fPaths = SkNEW_ARRAY(SkPath*, fCharCodesCount);
     82     for (unsigned index = 0; index < fCharCodesCount; ++index) {
     83         SkPath* path = SkNEW(SkPath);
     84         SkPath::Verb verb;
     85         while ((verb = (SkPath::Verb) *verbs++) != SkPath::kDone_Verb) {
     86             switch (verb) {
     87                 case SkPath::kMove_Verb:
     88                     path->moveTo(pts[0], pts[1]);
     89                     pts += 2;
     90                     break;
     91                 case SkPath::kLine_Verb:
     92                     path->lineTo(pts[0], pts[1]);
     93                     pts += 2;
     94                     break;
     95                 case SkPath::kQuad_Verb:
     96                     path->quadTo(pts[0], pts[1], pts[2], pts[3]);
     97                     pts += 4;
     98                     break;
     99                 case SkPath::kCubic_Verb:
    100                     path->cubicTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]);
    101                     pts += 6;
    102                     break;
    103                 case SkPath::kClose_Verb:
    104                     path->close();
    105                     break;
    106                 default:
    107                     SkDEBUGFAIL("bad verb");
    108                     return;
    109             }
    110         }
    111         fPaths[index] = path;
    112     }
    113 }
    114 
    115 SkTestTypeface::SkTestTypeface(SkTestFont* testFont, const SkFontStyle& style)
    116     : SkTypeface(style, SkTypefaceCache::NewFontID(), false)
    117     , fTestFont(testFont) {
    118 }
    119 
    120 void SkTestTypeface::getAdvance(SkGlyph* glyph) {
    121     glyph->fAdvanceX = fTestFont->fWidths[glyph->getGlyphID()];
    122     glyph->fAdvanceY = 0;
    123 }
    124 
    125 void SkTestTypeface::getFontMetrics(SkPaint::FontMetrics* metrics) {
    126     *metrics = fTestFont->fMetrics;
    127 }
    128 
    129 void SkTestTypeface::getMetrics(SkGlyph* glyph) {
    130     glyph->fAdvanceX = fTestFont->fWidths[glyph->getGlyphID()];
    131     glyph->fAdvanceY = 0;
    132 }
    133 
    134 void SkTestTypeface::getPath(const SkGlyph& glyph, SkPath* path) {
    135     *path = *fTestFont->fPaths[glyph.getGlyphID()];
    136 }
    137 
    138 void SkTestTypeface::onFilterRec(SkScalerContextRec* rec) const {
    139     rec->setHinting(SkPaint::kNo_Hinting);
    140     rec->fMaskFormat = SkMask::kA8_Format;
    141 }
    142 
    143 SkAdvancedTypefaceMetrics* SkTestTypeface::onGetAdvancedTypefaceMetrics(
    144                                 PerGlyphInfo ,
    145                                 const uint32_t* glyphIDs,
    146                                 uint32_t glyphIDsCount) const {
    147 // pdf only
    148     SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics;
    149     info->fEmSize = 0;
    150     info->fLastGlyphID = SkToU16(onCountGlyphs() - 1);
    151     info->fStyle = 0;
    152     info->fFontName.set(fTestFont->fName);
    153     info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
    154     info->fItalicAngle = 0;
    155     info->fAscent = 0;
    156     info->fDescent = 0;
    157     info->fStemV = 0;
    158     info->fCapHeight = 0;
    159     info->fBBox = SkIRect::MakeEmpty();
    160     return info;
    161 }
    162 
    163 void SkTestTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
    164     desc->setFamilyName(fTestFont->fName);
    165     *isLocal = false;
    166 }
    167 
    168 int SkTestTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
    169                             uint16_t glyphs[], int glyphCount) const {
    170     SkASSERT(encoding == kUTF16_Encoding);
    171     for (int index = 0; index < glyphCount; ++index) {
    172         SkUnichar ch = ((SkUnichar*) chars)[index];
    173         glyphs[index] = fTestFont->codeToIndex(ch);
    174     }
    175     return glyphCount;
    176 }
    177 
    178 void SkTestTypeface::onGetFamilyName(SkString* familyName) const {
    179     *familyName = fTestFont->fName;
    180 }
    181 
    182 SkTypeface::LocalizedStrings* SkTestTypeface::onCreateFamilyNameIterator() const {
    183     SkString familyName(fTestFont->fName);
    184     SkString language("und"); //undetermined
    185 SkASSERT(0);  // incomplete
    186     return NULL;
    187 //     return new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
    188 }
    189 
    190 class SkTestScalerContext : public SkScalerContext {
    191 public:
    192     SkTestScalerContext(SkTestTypeface* face, const SkDescriptor* desc)
    193         : SkScalerContext(face, desc)
    194         , fFace(face)
    195     {
    196         fRec.getSingleMatrix(&fMatrix);
    197         this->forceGenerateImageFromPath();
    198     }
    199 
    200     virtual ~SkTestScalerContext() {
    201     }
    202 
    203 protected:
    204     unsigned generateGlyphCount() override {
    205         return fFace->onCountGlyphs();
    206     }
    207 
    208     uint16_t generateCharToGlyph(SkUnichar uni) override {
    209         uint16_t glyph;
    210         (void) fFace->onCharsToGlyphs((const void *) &uni, SkTypeface::kUTF16_Encoding, &glyph, 1);
    211         return glyph;
    212     }
    213 
    214     void generateAdvance(SkGlyph* glyph) override {
    215         fFace->getAdvance(glyph);
    216 
    217         const SkVector advance = fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX),
    218                                                SkFixedToScalar(glyph->fAdvanceY));
    219         glyph->fAdvanceX = SkScalarToFixed(advance.fX);
    220         glyph->fAdvanceY = SkScalarToFixed(advance.fY);
    221     }
    222 
    223     void generateMetrics(SkGlyph* glyph) override {
    224         fFace->getMetrics(glyph);
    225 
    226         const SkVector advance = fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX),
    227                                                SkFixedToScalar(glyph->fAdvanceY));
    228         glyph->fAdvanceX = SkScalarToFixed(advance.fX);
    229         glyph->fAdvanceY = SkScalarToFixed(advance.fY);
    230 
    231         SkPath path;
    232         fFace->getPath(*glyph, &path);
    233         path.transform(fMatrix);
    234 
    235         SkRect storage;
    236         const SkPaint paint;
    237         const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
    238                                                             &storage,
    239                                                             SkPaint::kFill_Style);
    240         SkIRect ibounds;
    241         newBounds.roundOut(&ibounds);
    242         glyph->fLeft = ibounds.fLeft;
    243         glyph->fTop = ibounds.fTop;
    244         glyph->fWidth = ibounds.width();
    245         glyph->fHeight = ibounds.height();
    246         glyph->fMaskFormat = SkMask::kARGB32_Format;
    247     }
    248 
    249     void generateImage(const SkGlyph& glyph) override {
    250         SkPath path;
    251         fFace->getPath(glyph, &path);
    252 
    253         SkBitmap bm;
    254         bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
    255                             glyph.fImage, glyph.rowBytes());
    256         bm.eraseColor(0);
    257 
    258         SkCanvas canvas(bm);
    259         canvas.translate(-SkIntToScalar(glyph.fLeft),
    260                             -SkIntToScalar(glyph.fTop));
    261         canvas.concat(fMatrix);
    262         SkPaint paint;
    263         paint.setAntiAlias(true);
    264         canvas.drawPath(path, paint);
    265     }
    266 
    267     void generatePath(const SkGlyph& glyph, SkPath* path) override {
    268         fFace->getPath(glyph, path);
    269         path->transform(fMatrix);
    270     }
    271 
    272     void generateFontMetrics(SkPaint::FontMetrics* metrics) override {
    273         fFace->getFontMetrics(metrics);
    274         if (metrics) {
    275             SkScalar scale = fMatrix.getScaleY();
    276             metrics->fTop = SkScalarMul(metrics->fTop, scale);
    277             metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
    278             metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
    279             metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
    280             metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
    281             metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
    282             metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
    283             metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
    284             metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
    285         }
    286     }
    287 
    288 private:
    289     SkTestTypeface*  fFace;
    290     SkMatrix         fMatrix;
    291 };
    292 
    293 SkScalerContext* SkTestTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
    294     return SkNEW_ARGS(SkTestScalerContext, (const_cast<SkTestTypeface*>(this), desc));
    295 }
    296