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 "SkFontDescriptor.h"
     12 #include "SkFontMetrics.h"
     13 #include "SkFontPriv.h"
     14 #include "SkGlyph.h"
     15 #include "SkImageInfo.h"
     16 #include "SkMatrix.h"
     17 #include "SkOTUtils.h"
     18 #include "SkPaintPriv.h"
     19 #include "SkPath.h"
     20 #include "SkPoint.h"
     21 #include "SkRect.h"
     22 #include "SkScalerContext.h"
     23 #include "SkString.h"
     24 #include "SkTDArray.h"
     25 #include "SkTestTypeface.h"
     26 #include "SkTo.h"
     27 #include "SkUtils.h"
     28 
     29 #include <utility>
     30 
     31 class SkDescriptor;
     32 
     33 SkTestFont::SkTestFont(const SkTestFontData& fontData)
     34     : INHERITED()
     35     , fCharCodes(fontData.fCharCodes)
     36     , fCharCodesCount(fontData.fCharCodes ? fontData.fCharCodesCount : 0)
     37     , fWidths(fontData.fWidths)
     38     , fMetrics(fontData.fMetrics)
     39     , fName(fontData.fName)
     40     , fPaths(nullptr)
     41 {
     42     init(fontData.fPoints, fontData.fVerbs);
     43 }
     44 
     45 SkTestFont::~SkTestFont() {
     46     for (unsigned index = 0; index < fCharCodesCount; ++index) {
     47         delete fPaths[index];
     48     }
     49     delete[] fPaths;
     50 }
     51 
     52 SkGlyphID SkTestFont::glyphForUnichar(SkUnichar charCode) const {
     53     for (size_t index = 0; index < fCharCodesCount; ++index) {
     54         if (fCharCodes[index] == charCode) {
     55             return SkTo<SkGlyphID>(index);
     56         }
     57     }
     58     return 0;
     59 }
     60 
     61 void SkTestFont::init(const SkScalar* pts, const unsigned char* verbs) {
     62     fPaths = new SkPath* [fCharCodesCount];
     63     for (unsigned index = 0; index < fCharCodesCount; ++index) {
     64         SkPath* path = new SkPath;
     65         SkPath::Verb verb;
     66         while ((verb = (SkPath::Verb) *verbs++) != SkPath::kDone_Verb) {
     67             switch (verb) {
     68                 case SkPath::kMove_Verb:
     69                     path->moveTo(pts[0], pts[1]);
     70                     pts += 2;
     71                     break;
     72                 case SkPath::kLine_Verb:
     73                     path->lineTo(pts[0], pts[1]);
     74                     pts += 2;
     75                     break;
     76                 case SkPath::kQuad_Verb:
     77                     path->quadTo(pts[0], pts[1], pts[2], pts[3]);
     78                     pts += 4;
     79                     break;
     80                 case SkPath::kCubic_Verb:
     81                     path->cubicTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]);
     82                     pts += 6;
     83                     break;
     84                 case SkPath::kClose_Verb:
     85                     path->close();
     86                     break;
     87                 default:
     88                     SkDEBUGFAIL("bad verb");
     89                     return;
     90             }
     91         }
     92         // This should make SkPath::getBounds() queries threadsafe.
     93         path->updateBoundsCache();
     94         fPaths[index] = path;
     95     }
     96 }
     97 
     98 SkTestTypeface::SkTestTypeface(sk_sp<SkTestFont> testFont, const SkFontStyle& style)
     99     : SkTypeface(style, false)
    100     , fTestFont(std::move(testFont)) {
    101 }
    102 
    103 void SkTestTypeface::getAdvance(SkGlyph* glyph) {
    104     SkGlyphID glyphID = glyph->getGlyphID();
    105     glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
    106 
    107     // TODO(benjaminwagner): Update users to use floats.
    108     glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyphID]);
    109     glyph->fAdvanceY = 0;
    110 }
    111 
    112 void SkTestTypeface::getFontMetrics(SkFontMetrics* metrics) {
    113     *metrics = fTestFont->fMetrics;
    114 }
    115 
    116 void SkTestTypeface::getPath(SkGlyphID glyphID, SkPath* path) {
    117     glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
    118     *path = *fTestFont->fPaths[glyphID];
    119 }
    120 
    121 void SkTestTypeface::onFilterRec(SkScalerContextRec* rec) const {
    122     rec->setHinting(kNo_SkFontHinting);
    123 }
    124 
    125 void SkTestTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const {
    126     unsigned glyphCount = fTestFont->fCharCodesCount;
    127     for (unsigned gid = 0; gid < glyphCount; ++gid) {
    128         glyphToUnicode[gid] = SkTo<SkUnichar>(fTestFont->fCharCodes[gid]);
    129     }
    130 }
    131 
    132 std::unique_ptr<SkAdvancedTypefaceMetrics> SkTestTypeface::onGetAdvancedMetrics() const { // pdf only
    133     std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics);
    134     info->fFontName.set(fTestFont->fName);
    135     return info;
    136 }
    137 
    138 void SkTestTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
    139     desc->setFamilyName(fTestFont->fName);
    140     desc->setStyle(this->fontStyle());
    141     *isLocal = false;
    142 }
    143 
    144 int SkTestTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
    145                                     SkGlyphID glyphs[], int glyphCount) const {
    146     auto utf8  = (const      char*)chars;
    147     auto utf16 = (const  uint16_t*)chars;
    148     auto utf32 = (const SkUnichar*)chars;
    149 
    150     for (int i = 0; i < glyphCount; ++i) {
    151         SkUnichar ch;
    152         switch (encoding) {
    153             case kUTF8_Encoding:  ch =  SkUTF8_NextUnichar(&utf8 ); break;
    154             case kUTF16_Encoding: ch = SkUTF16_NextUnichar(&utf16); break;
    155             case kUTF32_Encoding: ch =                    *utf32++; break;
    156         }
    157         if (glyphs) {
    158             glyphs[i] = fTestFont->glyphForUnichar(ch);
    159         }
    160     }
    161     return glyphCount;
    162 }
    163 
    164 void SkTestTypeface::onGetFamilyName(SkString* familyName) const {
    165     *familyName = fTestFont->fName;
    166 }
    167 
    168 SkTypeface::LocalizedStrings* SkTestTypeface::onCreateFamilyNameIterator() const {
    169     SkString familyName(fTestFont->fName);
    170     SkString language("und"); //undetermined
    171     return new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
    172 }
    173 
    174 class SkTestScalerContext : public SkScalerContext {
    175 public:
    176     SkTestScalerContext(sk_sp<SkTestTypeface> face, const SkScalerContextEffects& effects,
    177                         const SkDescriptor* desc)
    178         : SkScalerContext(std::move(face), effects, desc)
    179     {
    180         fRec.getSingleMatrix(&fMatrix);
    181         this->forceGenerateImageFromPath();
    182     }
    183 
    184 protected:
    185     SkTestTypeface* getTestTypeface() const {
    186         return static_cast<SkTestTypeface*>(this->getTypeface());
    187     }
    188 
    189     unsigned generateGlyphCount() override {
    190         return this->getTestTypeface()->onCountGlyphs();
    191     }
    192 
    193     uint16_t generateCharToGlyph(SkUnichar uni) override {
    194         uint16_t glyph;
    195         (void) this->getTestTypeface()->onCharsToGlyphs((const void *) &uni,
    196                                                         SkTypeface::kUTF32_Encoding, &glyph, 1);
    197         return glyph;
    198     }
    199 
    200     bool generateAdvance(SkGlyph* glyph) override {
    201         this->getTestTypeface()->getAdvance(glyph);
    202 
    203         const SkVector advance = fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX),
    204                                                SkFloatToScalar(glyph->fAdvanceY));
    205         glyph->fAdvanceX = SkScalarToFloat(advance.fX);
    206         glyph->fAdvanceY = SkScalarToFloat(advance.fY);
    207         return true;
    208     }
    209 
    210     void generateMetrics(SkGlyph* glyph) override {
    211         glyph->zeroMetrics();
    212         this->generateAdvance(glyph);
    213         // Always generates from paths, so SkScalerContext::getMetrics will figure the bounds.
    214     }
    215 
    216     void generateImage(const SkGlyph&) override {
    217         SK_ABORT("Should have generated from path.");
    218     }
    219 
    220     bool generatePath(SkGlyphID glyph, SkPath* path) override {
    221         this->getTestTypeface()->getPath(glyph, path);
    222         path->transform(fMatrix);
    223         return true;
    224     }
    225 
    226     void generateFontMetrics(SkFontMetrics* metrics) override {
    227         this->getTestTypeface()->getFontMetrics(metrics);
    228         SkFontPriv::ScaleFontMetrics(metrics, fMatrix.getScaleY());
    229     }
    230 
    231 private:
    232     SkMatrix         fMatrix;
    233 };
    234 
    235 SkScalerContext* SkTestTypeface::onCreateScalerContext(
    236     const SkScalerContextEffects& effects, const SkDescriptor* desc) const
    237 {
    238     return new SkTestScalerContext(sk_ref_sp(const_cast<SkTestTypeface*>(this)), effects, desc);
    239 }
    240