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 "SkMakeUnique.h"
15 #include "SkMask.h"
16 #include "SkOTUtils.h"
17 #include "SkPaintPriv.h"
18 #include "SkScalerContext.h"
19 #include "SkTestScalerContext.h"
20 #include "SkTypefaceCache.h"
21 #include "SkUtils.h"
22 
SkTestFont(const SkTestFontData & fontData)23 SkTestFont::SkTestFont(const SkTestFontData& fontData)
24     : INHERITED()
25     , fCharCodes(fontData.fCharCodes)
26     , fCharCodesCount(fontData.fCharCodes ? fontData.fCharCodesCount : 0)
27     , fWidths(fontData.fWidths)
28     , fMetrics(fontData.fMetrics)
29     , fName(fontData.fName)
30     , fPaths(nullptr)
31 {
32     init(fontData.fPoints, fontData.fVerbs);
33 }
34 
~SkTestFont()35 SkTestFont::~SkTestFont() {
36     for (unsigned index = 0; index < fCharCodesCount; ++index) {
37         delete fPaths[index];
38     }
39     delete[] fPaths;
40 }
41 
codeToIndex(SkUnichar charCode) const42 int SkTestFont::codeToIndex(SkUnichar charCode) const {
43     for (unsigned index = 0; index < fCharCodesCount; ++index) {
44         if (fCharCodes[index] == (unsigned) charCode) {
45             return (int) index;
46         }
47     }
48     return 0;
49 }
50 
init(const SkScalar * pts,const unsigned char * verbs)51 void SkTestFont::init(const SkScalar* pts, const unsigned char* verbs) {
52     fPaths = new SkPath* [fCharCodesCount];
53     for (unsigned index = 0; index < fCharCodesCount; ++index) {
54         SkPath* path = new SkPath;
55         SkPath::Verb verb;
56         while ((verb = (SkPath::Verb) *verbs++) != SkPath::kDone_Verb) {
57             switch (verb) {
58                 case SkPath::kMove_Verb:
59                     path->moveTo(pts[0], pts[1]);
60                     pts += 2;
61                     break;
62                 case SkPath::kLine_Verb:
63                     path->lineTo(pts[0], pts[1]);
64                     pts += 2;
65                     break;
66                 case SkPath::kQuad_Verb:
67                     path->quadTo(pts[0], pts[1], pts[2], pts[3]);
68                     pts += 4;
69                     break;
70                 case SkPath::kCubic_Verb:
71                     path->cubicTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]);
72                     pts += 6;
73                     break;
74                 case SkPath::kClose_Verb:
75                     path->close();
76                     break;
77                 default:
78                     SkDEBUGFAIL("bad verb");
79                     return;
80             }
81         }
82         // This should make SkPath::getBounds() queries threadsafe.
83         path->updateBoundsCache();
84         fPaths[index] = path;
85     }
86 }
87 
SkTestTypeface(sk_sp<SkTestFont> testFont,const SkFontStyle & style)88 SkTestTypeface::SkTestTypeface(sk_sp<SkTestFont> testFont, const SkFontStyle& style)
89     : SkTypeface(style, false)
90     , fTestFont(std::move(testFont)) {
91 }
92 
getAdvance(SkGlyph * glyph)93 void SkTestTypeface::getAdvance(SkGlyph* glyph) {
94     // TODO(benjaminwagner): Update users to use floats.
95     glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyph->getGlyphID()]);
96     glyph->fAdvanceY = 0;
97 }
98 
getFontMetrics(SkPaint::FontMetrics * metrics)99 void SkTestTypeface::getFontMetrics(SkPaint::FontMetrics* metrics) {
100     *metrics = fTestFont->fMetrics;
101 }
102 
getMetrics(SkGlyph * glyph)103 void SkTestTypeface::getMetrics(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 
getPath(SkGlyphID glyphID,SkPath * path)112 void SkTestTypeface::getPath(SkGlyphID glyphID, SkPath* path) {
113     glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
114     *path = *fTestFont->fPaths[glyphID];
115 }
116 
onFilterRec(SkScalerContextRec * rec) const117 void SkTestTypeface::onFilterRec(SkScalerContextRec* rec) const {
118     rec->setHinting(SkPaint::kNo_Hinting);
119 }
120 
onGetAdvancedMetrics() const121 std::unique_ptr<SkAdvancedTypefaceMetrics> SkTestTypeface::onGetAdvancedMetrics() const { // pdf only
122     std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics);
123     info->fFontName.set(fTestFont->fName);
124     int glyphCount = this->onCountGlyphs();
125 
126     SkTDArray<SkUnichar>& toUnicode = info->fGlyphToUnicode;
127     toUnicode.setCount(glyphCount);
128     SkASSERT(glyphCount == SkToInt(fTestFont->fCharCodesCount));
129     for (int gid = 0; gid < glyphCount; ++gid) {
130         toUnicode[gid] = SkToS32(fTestFont->fCharCodes[gid]);
131     }
132     return info;
133 }
134 
onGetFontDescriptor(SkFontDescriptor * desc,bool * isLocal) const135 void SkTestTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
136     desc->setFamilyName(fTestFont->fName);
137     desc->setStyle(this->fontStyle());
138     *isLocal = false;
139 }
140 
onCharsToGlyphs(const void * chars,Encoding encoding,uint16_t glyphs[],int glyphCount) const141 int SkTestTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
142                                     uint16_t glyphs[], int glyphCount) const {
143     auto utf8  = (const      char*)chars;
144     auto utf16 = (const  uint16_t*)chars;
145     auto utf32 = (const SkUnichar*)chars;
146 
147     for (int i = 0; i < glyphCount; i++) {
148         SkUnichar ch;
149         switch (encoding) {
150             case kUTF8_Encoding:  ch =  SkUTF8_NextUnichar(&utf8 ); break;
151             case kUTF16_Encoding: ch = SkUTF16_NextUnichar(&utf16); break;
152             case kUTF32_Encoding: ch =                    *utf32++; break;
153         }
154         if (glyphs) {
155             glyphs[i] = fTestFont->codeToIndex(ch);
156         }
157     }
158     return glyphCount;
159 }
160 
onGetFamilyName(SkString * familyName) const161 void SkTestTypeface::onGetFamilyName(SkString* familyName) const {
162     *familyName = fTestFont->fName;
163 }
164 
onCreateFamilyNameIterator() const165 SkTypeface::LocalizedStrings* SkTestTypeface::onCreateFamilyNameIterator() const {
166     SkString familyName(fTestFont->fName);
167     SkString language("und"); //undetermined
168     return new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
169 }
170 
171 class SkTestScalerContext : public SkScalerContext {
172 public:
SkTestScalerContext(sk_sp<SkTestTypeface> face,const SkScalerContextEffects & effects,const SkDescriptor * desc)173     SkTestScalerContext(sk_sp<SkTestTypeface> face, const SkScalerContextEffects& effects,
174                         const SkDescriptor* desc)
175         : SkScalerContext(std::move(face), effects, desc)
176     {
177         fRec.getSingleMatrix(&fMatrix);
178         this->forceGenerateImageFromPath();
179     }
180 
181 protected:
getTestTypeface() const182     SkTestTypeface* getTestTypeface() const {
183         return static_cast<SkTestTypeface*>(this->getTypeface());
184     }
185 
generateGlyphCount()186     unsigned generateGlyphCount() override {
187         return this->getTestTypeface()->onCountGlyphs();
188     }
189 
generateCharToGlyph(SkUnichar uni)190     uint16_t generateCharToGlyph(SkUnichar uni) override {
191         uint16_t glyph;
192         (void) this->getTestTypeface()->onCharsToGlyphs((const void *) &uni,
193                                                         SkTypeface::kUTF32_Encoding, &glyph, 1);
194         return glyph;
195     }
196 
generateAdvance(SkGlyph * glyph)197     void generateAdvance(SkGlyph* glyph) override {
198         this->getTestTypeface()->getAdvance(glyph);
199 
200         const SkVector advance = fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX),
201                                                SkFloatToScalar(glyph->fAdvanceY));
202         glyph->fAdvanceX = SkScalarToFloat(advance.fX);
203         glyph->fAdvanceY = SkScalarToFloat(advance.fY);
204     }
205 
generateMetrics(SkGlyph * glyph)206     void generateMetrics(SkGlyph* glyph) override {
207         this->getTestTypeface()->getMetrics(glyph);
208 
209         const SkVector advance = fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX),
210                                                SkFloatToScalar(glyph->fAdvanceY));
211         glyph->fAdvanceX = SkScalarToFloat(advance.fX);
212         glyph->fAdvanceY = SkScalarToFloat(advance.fY);
213 
214         SkPath path;
215         this->getTestTypeface()->getPath(glyph->getGlyphID(), &path);
216         path.transform(fMatrix);
217 
218         SkRect storage;
219         const SkPaint paint;
220         const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
221                                                             &storage,
222                                                             SkPaint::kFill_Style);
223         SkIRect ibounds;
224         newBounds.roundOut(&ibounds);
225         glyph->fLeft = ibounds.fLeft;
226         glyph->fTop = ibounds.fTop;
227         glyph->fWidth = ibounds.width();
228         glyph->fHeight = ibounds.height();
229     }
230 
generateImage(const SkGlyph & glyph)231     void generateImage(const SkGlyph& glyph) override {
232         SkPath path;
233         this->getTestTypeface()->getPath(glyph.getGlyphID(), &path);
234 
235         SkBitmap bm;
236         bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
237                             glyph.fImage, glyph.rowBytes());
238         bm.eraseColor(0);
239 
240         SkCanvas canvas(bm);
241         canvas.translate(-SkIntToScalar(glyph.fLeft),
242                             -SkIntToScalar(glyph.fTop));
243         canvas.concat(fMatrix);
244         SkPaint paint;
245         paint.setAntiAlias(true);
246         canvas.drawPath(path, paint);
247     }
248 
generatePath(SkGlyphID glyph,SkPath * path)249     void generatePath(SkGlyphID glyph, SkPath* path) override {
250         this->getTestTypeface()->getPath(glyph, path);
251         path->transform(fMatrix);
252     }
253 
generateFontMetrics(SkPaint::FontMetrics * metrics)254     void generateFontMetrics(SkPaint::FontMetrics* metrics) override {
255         this->getTestTypeface()->getFontMetrics(metrics);
256         SkPaintPriv::ScaleFontMetrics(metrics, fMatrix.getScaleY());
257     }
258 
259 private:
260     SkMatrix         fMatrix;
261 };
262 
onCreateScalerContext(const SkScalerContextEffects & effects,const SkDescriptor * desc) const263 SkScalerContext* SkTestTypeface::onCreateScalerContext(
264     const SkScalerContextEffects& effects, const SkDescriptor* desc) const
265 {
266     return new SkTestScalerContext(sk_ref_sp(const_cast<SkTestTypeface*>(this)), effects, desc);
267 }
268