• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SkTestFont(const SkTestFontData & fontData)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(nullptr)
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 
~SkTestFont()36 SkTestFont::~SkTestFont() {
37     for (unsigned index = 0; index < fCharCodesCount; ++index) {
38         delete fPaths[index];
39     }
40     delete[] fPaths;
41 }
42 
43 #ifdef SK_DEBUG
44 
45 #include "SkMutex.h"
46 SK_DECLARE_STATIC_MUTEX(gUsedCharsMutex);
47 
48 #endif
49 
codeToIndex(SkUnichar charCode) const50 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 
init(const SkScalar * pts,const unsigned char * verbs)80 void SkTestFont::init(const SkScalar* pts, const unsigned char* verbs) {
81     fPaths = new SkPath* [fCharCodesCount];
82     for (unsigned index = 0; index < fCharCodesCount; ++index) {
83         SkPath* path = new 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         // This should make SkPath::getBounds() queries threadsafe.
112         path->updateBoundsCache();
113         fPaths[index] = path;
114     }
115 }
116 
SkTestTypeface(SkTestFont * testFont,const SkFontStyle & style)117 SkTestTypeface::SkTestTypeface(SkTestFont* testFont, const SkFontStyle& style)
118     : SkTypeface(style, SkTypefaceCache::NewFontID(), false)
119     , fTestFont(testFont) {
120 }
121 
getAdvance(SkGlyph * glyph)122 void SkTestTypeface::getAdvance(SkGlyph* glyph) {
123     glyph->fAdvanceX = fTestFont->fWidths[glyph->getGlyphID()];
124     glyph->fAdvanceY = 0;
125 }
126 
getFontMetrics(SkPaint::FontMetrics * metrics)127 void SkTestTypeface::getFontMetrics(SkPaint::FontMetrics* metrics) {
128     *metrics = fTestFont->fMetrics;
129 }
130 
getMetrics(SkGlyph * glyph)131 void SkTestTypeface::getMetrics(SkGlyph* glyph) {
132     glyph->fAdvanceX = fTestFont->fWidths[glyph->getGlyphID()];
133     glyph->fAdvanceY = 0;
134 }
135 
getPath(const SkGlyph & glyph,SkPath * path)136 void SkTestTypeface::getPath(const SkGlyph& glyph, SkPath* path) {
137     *path = *fTestFont->fPaths[glyph.getGlyphID()];
138 }
139 
onFilterRec(SkScalerContextRec * rec) const140 void SkTestTypeface::onFilterRec(SkScalerContextRec* rec) const {
141     rec->setHinting(SkPaint::kNo_Hinting);
142 }
143 
onGetAdvancedTypefaceMetrics(PerGlyphInfo,const uint32_t * glyphIDs,uint32_t glyphIDsCount) const144 SkAdvancedTypefaceMetrics* SkTestTypeface::onGetAdvancedTypefaceMetrics(
145                                 PerGlyphInfo ,
146                                 const uint32_t* glyphIDs,
147                                 uint32_t glyphIDsCount) const {
148 // pdf only
149     SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics;
150     info->fFontName.set(fTestFont->fName);
151     info->fLastGlyphID = SkToU16(onCountGlyphs() - 1);
152     return info;
153 }
154 
onGetFontDescriptor(SkFontDescriptor * desc,bool * isLocal) const155 void SkTestTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
156     desc->setFamilyName(fTestFont->fName);
157     *isLocal = false;
158 }
159 
onCharsToGlyphs(const void * chars,Encoding encoding,uint16_t glyphs[],int glyphCount) const160 int SkTestTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
161                             uint16_t glyphs[], int glyphCount) const {
162     SkASSERT(encoding == kUTF16_Encoding);
163     for (int index = 0; index < glyphCount; ++index) {
164         SkUnichar ch = ((SkUnichar*) chars)[index];
165         glyphs[index] = fTestFont->codeToIndex(ch);
166     }
167     return glyphCount;
168 }
169 
onGetFamilyName(SkString * familyName) const170 void SkTestTypeface::onGetFamilyName(SkString* familyName) const {
171     *familyName = fTestFont->fName;
172 }
173 
onCreateFamilyNameIterator() const174 SkTypeface::LocalizedStrings* SkTestTypeface::onCreateFamilyNameIterator() const {
175     SkString familyName(fTestFont->fName);
176     SkString language("und"); //undetermined
177 SkASSERT(0);  // incomplete
178     return nullptr;
179 //     return new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
180 }
181 
182 class SkTestScalerContext : public SkScalerContext {
183 public:
SkTestScalerContext(SkTestTypeface * face,const SkDescriptor * desc)184     SkTestScalerContext(SkTestTypeface* face, const SkDescriptor* desc)
185         : SkScalerContext(face, desc)
186         , fFace(face)
187     {
188         fRec.getSingleMatrix(&fMatrix);
189         this->forceGenerateImageFromPath();
190     }
191 
~SkTestScalerContext()192     virtual ~SkTestScalerContext() {
193     }
194 
195 protected:
generateGlyphCount()196     unsigned generateGlyphCount() override {
197         return fFace->onCountGlyphs();
198     }
199 
generateCharToGlyph(SkUnichar uni)200     uint16_t generateCharToGlyph(SkUnichar uni) override {
201         uint16_t glyph;
202         (void) fFace->onCharsToGlyphs((const void *) &uni, SkTypeface::kUTF16_Encoding, &glyph, 1);
203         return glyph;
204     }
205 
generateAdvance(SkGlyph * glyph)206     void generateAdvance(SkGlyph* glyph) override {
207         fFace->getAdvance(glyph);
208 
209         const SkVector advance = fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX),
210                                                SkFixedToScalar(glyph->fAdvanceY));
211         glyph->fAdvanceX = SkScalarToFixed(advance.fX);
212         glyph->fAdvanceY = SkScalarToFixed(advance.fY);
213     }
214 
generateMetrics(SkGlyph * glyph)215     void generateMetrics(SkGlyph* glyph) override {
216         fFace->getMetrics(glyph);
217 
218         const SkVector advance = fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX),
219                                                SkFixedToScalar(glyph->fAdvanceY));
220         glyph->fAdvanceX = SkScalarToFixed(advance.fX);
221         glyph->fAdvanceY = SkScalarToFixed(advance.fY);
222 
223         SkPath path;
224         fFace->getPath(*glyph, &path);
225         path.transform(fMatrix);
226 
227         SkRect storage;
228         const SkPaint paint;
229         const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
230                                                             &storage,
231                                                             SkPaint::kFill_Style);
232         SkIRect ibounds;
233         newBounds.roundOut(&ibounds);
234         glyph->fLeft = ibounds.fLeft;
235         glyph->fTop = ibounds.fTop;
236         glyph->fWidth = ibounds.width();
237         glyph->fHeight = ibounds.height();
238     }
239 
generateImage(const SkGlyph & glyph)240     void generateImage(const SkGlyph& glyph) override {
241         SkPath path;
242         fFace->getPath(glyph, &path);
243 
244         SkBitmap bm;
245         bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
246                             glyph.fImage, glyph.rowBytes());
247         bm.eraseColor(0);
248 
249         SkCanvas canvas(bm);
250         canvas.translate(-SkIntToScalar(glyph.fLeft),
251                             -SkIntToScalar(glyph.fTop));
252         canvas.concat(fMatrix);
253         SkPaint paint;
254         paint.setAntiAlias(true);
255         canvas.drawPath(path, paint);
256     }
257 
generatePath(const SkGlyph & glyph,SkPath * path)258     void generatePath(const SkGlyph& glyph, SkPath* path) override {
259         fFace->getPath(glyph, path);
260         path->transform(fMatrix);
261     }
262 
generateFontMetrics(SkPaint::FontMetrics * metrics)263     void generateFontMetrics(SkPaint::FontMetrics* metrics) override {
264         fFace->getFontMetrics(metrics);
265         if (metrics) {
266             SkScalar scale = fMatrix.getScaleY();
267             metrics->fTop = SkScalarMul(metrics->fTop, scale);
268             metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
269             metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
270             metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
271             metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
272             metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
273             metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
274             metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
275             metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
276         }
277     }
278 
279 private:
280     SkTestTypeface*  fFace;
281     SkMatrix         fMatrix;
282 };
283 
onCreateScalerContext(const SkDescriptor * desc) const284 SkScalerContext* SkTestTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
285     return new SkTestScalerContext(const_cast<SkTestTypeface*>(this), desc);
286 }
287