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