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 "SkPaintPriv.h"
17 #include "SkScalerContext.h"
18 #include "SkTestScalerContext.h"
19 #include "SkTypefaceCache.h"
20
SkTestFont(const SkTestFontData & fontData)21 SkTestFont::SkTestFont(const SkTestFontData& fontData)
22 : INHERITED()
23 , fCharCodes(fontData.fCharCodes)
24 , fCharCodesCount(fontData.fCharCodes ? fontData.fCharCodesCount : 0)
25 , fWidths(fontData.fWidths)
26 , fMetrics(fontData.fMetrics)
27 , fName(fontData.fName)
28 , fPaths(nullptr)
29 {
30 init(fontData.fPoints, fontData.fVerbs);
31 #ifdef SK_DEBUG
32 sk_bzero(fDebugBits, sizeof(fDebugBits));
33 sk_bzero(fDebugOverage, sizeof(fDebugOverage));
34 #endif
35 }
36
~SkTestFont()37 SkTestFont::~SkTestFont() {
38 for (unsigned index = 0; index < fCharCodesCount; ++index) {
39 delete fPaths[index];
40 }
41 delete[] fPaths;
42 }
43
44 #ifdef SK_DEBUG
45
46 #include "SkMutex.h"
47 SK_DECLARE_STATIC_MUTEX(gUsedCharsMutex);
48
49 #endif
50
codeToIndex(SkUnichar charCode) const51 int SkTestFont::codeToIndex(SkUnichar charCode) const {
52 #ifdef SK_DEBUG // detect missing test font data
53 {
54 SkAutoMutexAcquire ac(gUsedCharsMutex);
55 if (charCode >= ' ' && charCode <= '~') {
56 int bitOffset = charCode - ' ';
57 fDebugBits[bitOffset >> 3] |= 1 << (bitOffset & 7);
58 } else {
59 int index = 0;
60 while (fDebugOverage[index] != 0 && fDebugOverage[index] != charCode
61 && index < (int) sizeof(fDebugOverage)) {
62 ++index;
63 }
64 SkASSERT(index < (int) sizeof(fDebugOverage));
65 if (fDebugOverage[index] == 0) {
66 fDebugOverage[index] = charCode;
67 }
68 }
69 }
70 #endif
71 for (unsigned index = 0; index < fCharCodesCount; ++index) {
72 if (fCharCodes[index] == (unsigned) charCode) {
73 return (int) index;
74 }
75 }
76
77 SkDEBUGF(("missing '%c' (%d) from %s (weight %d, width %d, slant %d)\n",
78 (char) charCode, charCode, fDebugName,
79 fDebugStyle.weight(), fDebugStyle.width(), fDebugStyle.slant()));
80 return 0;
81 }
82
init(const SkScalar * pts,const unsigned char * verbs)83 void SkTestFont::init(const SkScalar* pts, const unsigned char* verbs) {
84 fPaths = new SkPath* [fCharCodesCount];
85 for (unsigned index = 0; index < fCharCodesCount; ++index) {
86 SkPath* path = new SkPath;
87 SkPath::Verb verb;
88 while ((verb = (SkPath::Verb) *verbs++) != SkPath::kDone_Verb) {
89 switch (verb) {
90 case SkPath::kMove_Verb:
91 path->moveTo(pts[0], pts[1]);
92 pts += 2;
93 break;
94 case SkPath::kLine_Verb:
95 path->lineTo(pts[0], pts[1]);
96 pts += 2;
97 break;
98 case SkPath::kQuad_Verb:
99 path->quadTo(pts[0], pts[1], pts[2], pts[3]);
100 pts += 4;
101 break;
102 case SkPath::kCubic_Verb:
103 path->cubicTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]);
104 pts += 6;
105 break;
106 case SkPath::kClose_Verb:
107 path->close();
108 break;
109 default:
110 SkDEBUGFAIL("bad verb");
111 return;
112 }
113 }
114 // This should make SkPath::getBounds() queries threadsafe.
115 path->updateBoundsCache();
116 fPaths[index] = path;
117 }
118 }
119
SkTestTypeface(sk_sp<SkTestFont> testFont,const SkFontStyle & style)120 SkTestTypeface::SkTestTypeface(sk_sp<SkTestFont> testFont, const SkFontStyle& style)
121 : SkTypeface(style, false)
122 , fTestFont(std::move(testFont)) {
123 }
124
getAdvance(SkGlyph * glyph)125 void SkTestTypeface::getAdvance(SkGlyph* glyph) {
126 // TODO(benjaminwagner): Update users to use floats.
127 glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyph->getGlyphID()]);
128 glyph->fAdvanceY = 0;
129 }
130
getFontMetrics(SkPaint::FontMetrics * metrics)131 void SkTestTypeface::getFontMetrics(SkPaint::FontMetrics* metrics) {
132 *metrics = fTestFont->fMetrics;
133 }
134
getMetrics(SkGlyph * glyph)135 void SkTestTypeface::getMetrics(SkGlyph* glyph) {
136 // TODO(benjaminwagner): Update users to use floats.
137 glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyph->getGlyphID()]);
138 glyph->fAdvanceY = 0;
139 }
140
getPath(SkGlyphID glyph,SkPath * path)141 void SkTestTypeface::getPath(SkGlyphID glyph, SkPath* path) {
142 *path = *fTestFont->fPaths[glyph];
143 }
144
onFilterRec(SkScalerContextRec * rec) const145 void SkTestTypeface::onFilterRec(SkScalerContextRec* rec) const {
146 rec->setHinting(SkPaint::kNo_Hinting);
147 }
148
onGetAdvancedMetrics() const149 std::unique_ptr<SkAdvancedTypefaceMetrics> SkTestTypeface::onGetAdvancedMetrics() const { // pdf only
150 std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics);
151 info->fFontName.set(fTestFont->fName);
152 int glyphCount = this->onCountGlyphs();
153
154 SkTDArray<SkUnichar>& toUnicode = info->fGlyphToUnicode;
155 toUnicode.setCount(glyphCount);
156 SkASSERT(glyphCount == SkToInt(fTestFont->fCharCodesCount));
157 for (int gid = 0; gid < glyphCount; ++gid) {
158 toUnicode[gid] = SkToS32(fTestFont->fCharCodes[gid]);
159 }
160 return info;
161 }
162
onGetFontDescriptor(SkFontDescriptor * desc,bool * isLocal) const163 void SkTestTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
164 desc->setFamilyName(fTestFont->fName);
165 desc->setStyle(this->fontStyle());
166 *isLocal = false;
167 }
168
onCharsToGlyphs(const void * chars,Encoding encoding,uint16_t glyphs[],int glyphCount) const169 int SkTestTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
170 uint16_t glyphs[], int glyphCount) const {
171 SkASSERT(encoding == kUTF32_Encoding);
172 for (int index = 0; index < glyphCount; ++index) {
173 SkUnichar ch = ((SkUnichar*) chars)[index];
174 glyphs[index] = fTestFont->codeToIndex(ch);
175 }
176 return glyphCount;
177 }
178
onGetFamilyName(SkString * familyName) const179 void SkTestTypeface::onGetFamilyName(SkString* familyName) const {
180 *familyName = fTestFont->fName;
181 }
182
onCreateFamilyNameIterator() const183 SkTypeface::LocalizedStrings* SkTestTypeface::onCreateFamilyNameIterator() const {
184 SkString familyName(fTestFont->fName);
185 SkString language("und"); //undetermined
186 //SkASSERT(0); // incomplete
187 return nullptr;
188 // return new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
189 }
190
191 class SkTestScalerContext : public SkScalerContext {
192 public:
SkTestScalerContext(sk_sp<SkTestTypeface> face,const SkScalerContextEffects & effects,const SkDescriptor * desc)193 SkTestScalerContext(sk_sp<SkTestTypeface> face, const SkScalerContextEffects& effects,
194 const SkDescriptor* desc)
195 : SkScalerContext(std::move(face), effects, desc)
196 {
197 fRec.getSingleMatrix(&fMatrix);
198 this->forceGenerateImageFromPath();
199 }
200
201 protected:
getTestTypeface() const202 SkTestTypeface* getTestTypeface() const {
203 return static_cast<SkTestTypeface*>(this->getTypeface());
204 }
205
generateGlyphCount()206 unsigned generateGlyphCount() override {
207 return this->getTestTypeface()->onCountGlyphs();
208 }
209
generateCharToGlyph(SkUnichar uni)210 uint16_t generateCharToGlyph(SkUnichar uni) override {
211 uint16_t glyph;
212 (void) this->getTestTypeface()->onCharsToGlyphs((const void *) &uni,
213 SkTypeface::kUTF32_Encoding, &glyph, 1);
214 return glyph;
215 }
216
generateAdvance(SkGlyph * glyph)217 void generateAdvance(SkGlyph* glyph) override {
218 this->getTestTypeface()->getAdvance(glyph);
219
220 const SkVector advance = fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX),
221 SkFloatToScalar(glyph->fAdvanceY));
222 glyph->fAdvanceX = SkScalarToFloat(advance.fX);
223 glyph->fAdvanceY = SkScalarToFloat(advance.fY);
224 }
225
generateMetrics(SkGlyph * glyph)226 void generateMetrics(SkGlyph* glyph) override {
227 this->getTestTypeface()->getMetrics(glyph);
228
229 const SkVector advance = fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX),
230 SkFloatToScalar(glyph->fAdvanceY));
231 glyph->fAdvanceX = SkScalarToFloat(advance.fX);
232 glyph->fAdvanceY = SkScalarToFloat(advance.fY);
233
234 SkPath path;
235 this->getTestTypeface()->getPath(glyph->getGlyphID(), &path);
236 path.transform(fMatrix);
237
238 SkRect storage;
239 const SkPaint paint;
240 const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
241 &storage,
242 SkPaint::kFill_Style);
243 SkIRect ibounds;
244 newBounds.roundOut(&ibounds);
245 glyph->fLeft = ibounds.fLeft;
246 glyph->fTop = ibounds.fTop;
247 glyph->fWidth = ibounds.width();
248 glyph->fHeight = ibounds.height();
249 }
250
generateImage(const SkGlyph & glyph)251 void generateImage(const SkGlyph& glyph) override {
252 SkPath path;
253 this->getTestTypeface()->getPath(glyph.getGlyphID(), &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
generatePath(SkGlyphID glyph,SkPath * path)269 void generatePath(SkGlyphID glyph, SkPath* path) override {
270 this->getTestTypeface()->getPath(glyph, path);
271 path->transform(fMatrix);
272 }
273
generateFontMetrics(SkPaint::FontMetrics * metrics)274 void generateFontMetrics(SkPaint::FontMetrics* metrics) override {
275 this->getTestTypeface()->getFontMetrics(metrics);
276 SkPaintPriv::ScaleFontMetrics(metrics, fMatrix.getScaleY());
277 }
278
279 private:
280 SkMatrix fMatrix;
281 };
282
onCreateScalerContext(const SkScalerContextEffects & effects,const SkDescriptor * desc) const283 SkScalerContext* SkTestTypeface::onCreateScalerContext(
284 const SkScalerContextEffects& effects, const SkDescriptor* desc) const
285 {
286 return new SkTestScalerContext(sk_ref_sp(const_cast<SkTestTypeface*>(this)), effects, desc);
287 }
288