blob: 854c98090488c3e8c53e8b99e03c0ccc3fa7883b [file] [log] [blame]
caryclark5fb6bd42014-06-23 11:25:00 -07001/*
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"
Cary Clark992c7b02014-07-31 08:58:44 -040011#include "SkFontDescriptor.h"
caryclark5fb6bd42014-06-23 11:25:00 -070012#include "SkGlyph.h"
13#include "SkMask.h"
14// #include "SkOTUtils.h"
15#include "SkScalerContext.h"
16#include "SkTestScalerContext.h"
17#include "SkTypefaceCache.h"
18
Cary Clark992c7b02014-07-31 08:58:44 -040019SkTestFont::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
35SkTestFont::~SkTestFont() {
36 for (unsigned index = 0; index < fCharCodesCount; ++index) {
37 SkDELETE(fPaths[index]);
caryclark5fb6bd42014-06-23 11:25:00 -070038 }
Cary Clark992c7b02014-07-31 08:58:44 -040039 SkDELETE_ARRAY(fPaths);
40}
caryclark5fb6bd42014-06-23 11:25:00 -070041
Cary Clark992c7b02014-07-31 08:58:44 -040042#ifdef SK_DEBUG
caryclark5fb6bd42014-06-23 11:25:00 -070043
Cary Clark992c7b02014-07-31 08:58:44 -040044#include "SkThread.h"
45SK_DECLARE_STATIC_MUTEX(gUsedCharsMutex);
caryclark5fb6bd42014-06-23 11:25:00 -070046
Cary Clark992c7b02014-07-31 08:58:44 -040047#endif
caryclark5fb6bd42014-06-23 11:25:00 -070048
Cary Clark992c7b02014-07-31 08:58:44 -040049int 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;
caryclark5fb6bd42014-06-23 11:25:00 -070065 }
66 }
caryclark5fb6bd42014-06-23 11:25:00 -070067 }
Cary Clark992c7b02014-07-31 08:58:44 -040068#endif
69 for (unsigned index = 0; index < fCharCodesCount; ++index) {
70 if (fCharCodes[index] == (unsigned) charCode) {
71 return (int) index;
72 }
caryclark5fb6bd42014-06-23 11:25:00 -070073 }
Cary Clark992c7b02014-07-31 08:58:44 -040074 SkDEBUGF(("missing '%c' (%d) from %s %d\n", (char) charCode, charCode,
75 fDebugName, fDebugStyle));
76 return 0;
77}
caryclark5fb6bd42014-06-23 11:25:00 -070078
Cary Clark992c7b02014-07-31 08:58:44 -040079void 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;
caryclark5fb6bd42014-06-23 11:25:00 -0700111 }
Cary Clark992c7b02014-07-31 08:58:44 -0400112}
113
114SkTestTypeface::SkTestTypeface(SkTestFont* testFont, SkTypeface::Style style)
115 : SkTypeface(style, SkTypefaceCache::NewFontID(), false)
116 , fTestFont(testFont) {
117}
caryclark5fb6bd42014-06-23 11:25:00 -0700118
Cary Clark992c7b02014-07-31 08:58:44 -0400119void SkTestTypeface::getAdvance(SkGlyph* glyph) {
120 glyph->fAdvanceX = fTestFont->fWidths[SkGlyph::ID2Code(glyph->fID)];
121 glyph->fAdvanceY = 0;
122}
123
124void SkTestTypeface::getFontMetrics(SkPaint::FontMetrics* metrics) {
125 *metrics = fTestFont->fMetrics;
126}
127
128void SkTestTypeface::getMetrics(SkGlyph* glyph) {
129 glyph->fAdvanceX = fTestFont->fWidths[SkGlyph::ID2Code(glyph->fID)];
130 glyph->fAdvanceY = 0;
131}
132
133void SkTestTypeface::getPath(const SkGlyph& glyph, SkPath* path) {
134 *path = *fTestFont->fPaths[SkGlyph::ID2Code(glyph.fID)];
135}
136
137void SkTestTypeface::onFilterRec(SkScalerContextRec* rec) const {
138 rec->setHinting(SkPaint::kNo_Hinting);
139 rec->fMaskFormat = SkMask::kA8_Format;
140}
141
142SkAdvancedTypefaceMetrics* 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
162void SkTestTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
163 desc->setFamilyName(fTestFont->fName);
164 desc->setFontFileName(fTestFont->fName);
165 *isLocal = false;
166}
167
168int 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);
caryclark5fb6bd42014-06-23 11:25:00 -0700174 }
Cary Clark992c7b02014-07-31 08:58:44 -0400175 return glyphCount;
176}
caryclark5fb6bd42014-06-23 11:25:00 -0700177
Cary Clark992c7b02014-07-31 08:58:44 -0400178SkTypeface::LocalizedStrings* SkTestTypeface::onCreateFamilyNameIterator() const {
179 SkString familyName(fTestFont->fName);
180 SkString language("und"); //undetermined
181SkASSERT(0); // incomplete
182 return NULL;
183// return new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
caryclark5fb6bd42014-06-23 11:25:00 -0700184}
185
186class SkTestScalerContext : public SkScalerContext {
187public:
188 SkTestScalerContext(SkTestTypeface* face, const SkDescriptor* desc)
189 : SkScalerContext(face, desc)
190 , fFace(face)
191 {
192 fRec.getSingleMatrix(&fMatrix);
193 this->forceGenerateImageFromPath();
194 }
195
196 virtual ~SkTestScalerContext() {
197 }
198
199protected:
200 virtual unsigned generateGlyphCount() SK_OVERRIDE {
201 return fFace->onCountGlyphs();
202 }
203
204 virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE {
caryclark5fb6bd42014-06-23 11:25:00 -0700205 uint16_t glyph;
Cary Clark992c7b02014-07-31 08:58:44 -0400206 (void) fFace->onCharsToGlyphs((const void *) &uni, SkTypeface::kUTF16_Encoding, &glyph, 1);
caryclark5fb6bd42014-06-23 11:25:00 -0700207 return glyph;
208 }
209
210 virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE {
211 fFace->getAdvance(glyph);
212
213 SkVector advance;
214 fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX),
215 SkFixedToScalar(glyph->fAdvanceY), &advance);
216 glyph->fAdvanceX = SkScalarToFixed(advance.fX);
217 glyph->fAdvanceY = SkScalarToFixed(advance.fY);
218 }
219
220 virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE {
221 fFace->getMetrics(glyph);
222
223 SkVector advance;
224 fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX),
225 SkFixedToScalar(glyph->fAdvanceY), &advance);
226 glyph->fAdvanceX = SkScalarToFixed(advance.fX);
227 glyph->fAdvanceY = SkScalarToFixed(advance.fY);
228
229 SkPath path;
230 fFace->getPath(*glyph, &path);
231 path.transform(fMatrix);
232
233 SkRect storage;
234 const SkPaint paint;
235 const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
236 &storage,
237 SkPaint::kFill_Style);
238 SkIRect ibounds;
239 newBounds.roundOut(&ibounds);
240 glyph->fLeft = ibounds.fLeft;
241 glyph->fTop = ibounds.fTop;
242 glyph->fWidth = ibounds.width();
243 glyph->fHeight = ibounds.height();
244 glyph->fMaskFormat = SkMask::kARGB32_Format;
245 }
246
247 virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE {
248 SkPath path;
249 fFace->getPath(glyph, &path);
250
251 SkBitmap bm;
252 bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
253 glyph.fImage, glyph.rowBytes());
254 bm.eraseColor(0);
255
256 SkCanvas canvas(bm);
257 canvas.translate(-SkIntToScalar(glyph.fLeft),
258 -SkIntToScalar(glyph.fTop));
259 canvas.concat(fMatrix);
260 SkPaint paint;
261 paint.setAntiAlias(true);
262 canvas.drawPath(path, paint);
263 }
264
265 virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE {
266 fFace->getPath(glyph, path);
267 path->transform(fMatrix);
268 }
269
bungeman41078062014-07-07 08:16:37 -0700270 virtual void generateFontMetrics(SkPaint::FontMetrics* metrics) SK_OVERRIDE {
caryclark5fb6bd42014-06-23 11:25:00 -0700271 fFace->getFontMetrics(metrics);
272 if (metrics) {
273 SkScalar scale = fMatrix.getScaleY();
274 metrics->fTop = SkScalarMul(metrics->fTop, scale);
275 metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
276 metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
277 metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
278 metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
279 metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
280 metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
281 metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
282 metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
283 }
284 }
285
286private:
287 SkTestTypeface* fFace;
288 SkMatrix fMatrix;
289};
290
291SkScalerContext* SkTestTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
292 return SkNEW_ARGS(SkTestScalerContext, (const_cast<SkTestTypeface*>(this), desc));
293}