blob: f74b1bd57ac19895bf5fc123953383144d53d34d [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
reed39a9a502015-05-12 09:50:04 -07008#include "SkAdvancedTypefaceMetrics.h"
caryclark5fb6bd42014-06-23 11:25:00 -07009#include "SkBitmap.h"
10#include "SkCanvas.h"
Jim Van Verthaf78a942018-03-23 14:39:42 +000011#include "SkDescriptor.h"
Cary Clark992c7b02014-07-31 08:58:44 -040012#include "SkFontDescriptor.h"
caryclark5fb6bd42014-06-23 11:25:00 -070013#include "SkGlyph.h"
Jim Van Verthaf78a942018-03-23 14:39:42 +000014#include "SkMakeUnique.h"
15#include "SkMask.h"
Mike Kleincb6940b2017-11-09 13:45:10 -050016#include "SkOTUtils.h"
Mike Reed8be952a2017-02-13 20:44:33 -050017#include "SkPaintPriv.h"
caryclark5fb6bd42014-06-23 11:25:00 -070018#include "SkScalerContext.h"
Jim Van Verthaf78a942018-03-23 14:39:42 +000019#include "SkTestScalerContext.h"
20#include "SkTypefaceCache.h"
Mike Klein71a38d92017-11-10 13:42:29 -050021#include "SkUtils.h"
caryclark5fb6bd42014-06-23 11:25:00 -070022
Cary Clark992c7b02014-07-31 08:58:44 -040023SkTestFont::SkTestFont(const SkTestFontData& fontData)
24 : INHERITED()
25 , fCharCodes(fontData.fCharCodes)
jvanverthc7027ab2016-06-16 09:52:35 -070026 , fCharCodesCount(fontData.fCharCodes ? fontData.fCharCodesCount : 0)
Cary Clark992c7b02014-07-31 08:58:44 -040027 , fWidths(fontData.fWidths)
28 , fMetrics(fontData.fMetrics)
29 , fName(fontData.fName)
halcanary96fcdcc2015-08-27 07:41:13 -070030 , fPaths(nullptr)
Cary Clark992c7b02014-07-31 08:58:44 -040031{
32 init(fontData.fPoints, fontData.fVerbs);
Cary Clark992c7b02014-07-31 08:58:44 -040033}
34
35SkTestFont::~SkTestFont() {
36 for (unsigned index = 0; index < fCharCodesCount; ++index) {
halcanary385fe4d2015-08-26 13:07:48 -070037 delete fPaths[index];
caryclark5fb6bd42014-06-23 11:25:00 -070038 }
halcanary385fe4d2015-08-26 13:07:48 -070039 delete[] fPaths;
Cary Clark992c7b02014-07-31 08:58:44 -040040}
caryclark5fb6bd42014-06-23 11:25:00 -070041
Cary Clark992c7b02014-07-31 08:58:44 -040042int SkTestFont::codeToIndex(SkUnichar charCode) const {
Cary Clark992c7b02014-07-31 08:58:44 -040043 for (unsigned index = 0; index < fCharCodesCount; ++index) {
44 if (fCharCodes[index] == (unsigned) charCode) {
45 return (int) index;
46 }
caryclark5fb6bd42014-06-23 11:25:00 -070047 }
Cary Clark992c7b02014-07-31 08:58:44 -040048 return 0;
49}
caryclark5fb6bd42014-06-23 11:25:00 -070050
Cary Clark992c7b02014-07-31 08:58:44 -040051void SkTestFont::init(const SkScalar* pts, const unsigned char* verbs) {
halcanary385fe4d2015-08-26 13:07:48 -070052 fPaths = new SkPath* [fCharCodesCount];
Cary Clark992c7b02014-07-31 08:58:44 -040053 for (unsigned index = 0; index < fCharCodesCount; ++index) {
halcanary385fe4d2015-08-26 13:07:48 -070054 SkPath* path = new SkPath;
Cary Clark992c7b02014-07-31 08:58:44 -040055 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 }
mtklein6f6264f2015-10-05 07:29:22 -070082 // This should make SkPath::getBounds() queries threadsafe.
83 path->updateBoundsCache();
Cary Clark992c7b02014-07-31 08:58:44 -040084 fPaths[index] = path;
caryclark5fb6bd42014-06-23 11:25:00 -070085 }
Cary Clark992c7b02014-07-31 08:58:44 -040086}
bungemana4c4a2d2014-10-20 13:33:19 -070087
bungeman7cfd46a2016-10-20 16:06:52 -040088SkTestTypeface::SkTestTypeface(sk_sp<SkTestFont> testFont, const SkFontStyle& style)
bungemane3aea102016-07-13 05:16:58 -070089 : SkTypeface(style, false)
bungeman7cfd46a2016-10-20 16:06:52 -040090 , fTestFont(std::move(testFont)) {
Cary Clark992c7b02014-07-31 08:58:44 -040091}
caryclark5fb6bd42014-06-23 11:25:00 -070092
Cary Clark992c7b02014-07-31 08:58:44 -040093void SkTestTypeface::getAdvance(SkGlyph* glyph) {
benjaminwagner6b3eacb2016-03-24 19:07:58 -070094 // TODO(benjaminwagner): Update users to use floats.
95 glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyph->getGlyphID()]);
Cary Clark992c7b02014-07-31 08:58:44 -040096 glyph->fAdvanceY = 0;
97}
98
99void SkTestTypeface::getFontMetrics(SkPaint::FontMetrics* metrics) {
100 *metrics = fTestFont->fMetrics;
101}
102
103void SkTestTypeface::getMetrics(SkGlyph* glyph) {
Mike Kleincb6940b2017-11-09 13:45:10 -0500104 SkGlyphID glyphID = glyph->getGlyphID();
105 glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
106
benjaminwagner6b3eacb2016-03-24 19:07:58 -0700107 // TODO(benjaminwagner): Update users to use floats.
Mike Kleincb6940b2017-11-09 13:45:10 -0500108 glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyphID]);
Cary Clark992c7b02014-07-31 08:58:44 -0400109 glyph->fAdvanceY = 0;
110}
111
Mike Kleincb6940b2017-11-09 13:45:10 -0500112void SkTestTypeface::getPath(SkGlyphID glyphID, SkPath* path) {
113 glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
114 *path = *fTestFont->fPaths[glyphID];
Cary Clark992c7b02014-07-31 08:58:44 -0400115}
116
117void SkTestTypeface::onFilterRec(SkScalerContextRec* rec) const {
118 rec->setHinting(SkPaint::kNo_Hinting);
Cary Clark992c7b02014-07-31 08:58:44 -0400119}
120
Hal Canary209e4b12017-05-04 14:23:55 -0400121std::unique_ptr<SkAdvancedTypefaceMetrics> SkTestTypeface::onGetAdvancedMetrics() const { // pdf only
122 std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics);
caryclark0edd9652015-06-11 06:46:21 -0700123 info->fFontName.set(fTestFont->fName);
halcanary3d01c622016-08-31 12:52:35 -0700124 int glyphCount = this->onCountGlyphs();
halcanary3d01c622016-08-31 12:52:35 -0700125
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 }
Cary Clark992c7b02014-07-31 08:58:44 -0400132 return info;
133}
134
135void SkTestTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
136 desc->setFamilyName(fTestFont->fName);
bungemanb8113782016-07-25 16:54:59 -0700137 desc->setStyle(this->fontStyle());
Cary Clark992c7b02014-07-31 08:58:44 -0400138 *isLocal = false;
139}
140
141int SkTestTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
Hal Canary58d2a722017-01-11 13:26:43 -0500142 uint16_t glyphs[], int glyphCount) const {
Mike Klein71a38d92017-11-10 13:42:29 -0500143 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 }
Brian Salomon0c1c2b32017-11-20 13:13:01 -0500154 if (glyphs) {
155 glyphs[i] = fTestFont->codeToIndex(ch);
156 }
caryclark5fb6bd42014-06-23 11:25:00 -0700157 }
Cary Clark992c7b02014-07-31 08:58:44 -0400158 return glyphCount;
159}
caryclark5fb6bd42014-06-23 11:25:00 -0700160
bungemanb374d6a2014-09-17 07:48:59 -0700161void SkTestTypeface::onGetFamilyName(SkString* familyName) const {
162 *familyName = fTestFont->fName;
163}
164
Cary Clark992c7b02014-07-31 08:58:44 -0400165SkTypeface::LocalizedStrings* SkTestTypeface::onCreateFamilyNameIterator() const {
166 SkString familyName(fTestFont->fName);
167 SkString language("und"); //undetermined
Mike Kleincb6940b2017-11-09 13:45:10 -0500168 return new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
caryclark5fb6bd42014-06-23 11:25:00 -0700169}
170
171class SkTestScalerContext : public SkScalerContext {
172public:
bungeman7cfd46a2016-10-20 16:06:52 -0400173 SkTestScalerContext(sk_sp<SkTestTypeface> face, const SkScalerContextEffects& effects,
reeda9322c22016-04-12 06:47:05 -0700174 const SkDescriptor* desc)
bungeman7cfd46a2016-10-20 16:06:52 -0400175 : SkScalerContext(std::move(face), effects, desc)
caryclark5fb6bd42014-06-23 11:25:00 -0700176 {
177 fRec.getSingleMatrix(&fMatrix);
178 this->forceGenerateImageFromPath();
179 }
180
bungeman7cfd46a2016-10-20 16:06:52 -0400181protected:
182 SkTestTypeface* getTestTypeface() const {
183 return static_cast<SkTestTypeface*>(this->getTypeface());
caryclark5fb6bd42014-06-23 11:25:00 -0700184 }
185
mtklein36352bf2015-03-25 18:17:31 -0700186 unsigned generateGlyphCount() override {
bungeman7cfd46a2016-10-20 16:06:52 -0400187 return this->getTestTypeface()->onCountGlyphs();
caryclark5fb6bd42014-06-23 11:25:00 -0700188 }
189
mtklein36352bf2015-03-25 18:17:31 -0700190 uint16_t generateCharToGlyph(SkUnichar uni) override {
caryclark5fb6bd42014-06-23 11:25:00 -0700191 uint16_t glyph;
bungeman7cfd46a2016-10-20 16:06:52 -0400192 (void) this->getTestTypeface()->onCharsToGlyphs((const void *) &uni,
Hal Canary58d2a722017-01-11 13:26:43 -0500193 SkTypeface::kUTF32_Encoding, &glyph, 1);
caryclark5fb6bd42014-06-23 11:25:00 -0700194 return glyph;
195 }
196
mtklein36352bf2015-03-25 18:17:31 -0700197 void generateAdvance(SkGlyph* glyph) override {
bungeman7cfd46a2016-10-20 16:06:52 -0400198 this->getTestTypeface()->getAdvance(glyph);
caryclark5fb6bd42014-06-23 11:25:00 -0700199
benjaminwagner6b3eacb2016-03-24 19:07:58 -0700200 const SkVector advance = fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX),
201 SkFloatToScalar(glyph->fAdvanceY));
202 glyph->fAdvanceX = SkScalarToFloat(advance.fX);
203 glyph->fAdvanceY = SkScalarToFloat(advance.fY);
caryclark5fb6bd42014-06-23 11:25:00 -0700204 }
205
mtklein36352bf2015-03-25 18:17:31 -0700206 void generateMetrics(SkGlyph* glyph) override {
bungeman7cfd46a2016-10-20 16:06:52 -0400207 this->getTestTypeface()->getMetrics(glyph);
caryclark5fb6bd42014-06-23 11:25:00 -0700208
benjaminwagner6b3eacb2016-03-24 19:07:58 -0700209 const SkVector advance = fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX),
210 SkFloatToScalar(glyph->fAdvanceY));
211 glyph->fAdvanceX = SkScalarToFloat(advance.fX);
212 glyph->fAdvanceY = SkScalarToFloat(advance.fY);
caryclark5fb6bd42014-06-23 11:25:00 -0700213
214 SkPath path;
Ben Wagner6e9ac122016-11-11 14:31:06 -0500215 this->getTestTypeface()->getPath(glyph->getGlyphID(), &path);
caryclark5fb6bd42014-06-23 11:25:00 -0700216 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();
caryclark5fb6bd42014-06-23 11:25:00 -0700229 }
230
mtklein36352bf2015-03-25 18:17:31 -0700231 void generateImage(const SkGlyph& glyph) override {
caryclark5fb6bd42014-06-23 11:25:00 -0700232 SkPath path;
Ben Wagner6e9ac122016-11-11 14:31:06 -0500233 this->getTestTypeface()->getPath(glyph.getGlyphID(), &path);
caryclark5fb6bd42014-06-23 11:25:00 -0700234
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
Ben Wagner6e9ac122016-11-11 14:31:06 -0500249 void generatePath(SkGlyphID glyph, SkPath* path) override {
bungeman7cfd46a2016-10-20 16:06:52 -0400250 this->getTestTypeface()->getPath(glyph, path);
caryclark5fb6bd42014-06-23 11:25:00 -0700251 path->transform(fMatrix);
252 }
253
mtklein36352bf2015-03-25 18:17:31 -0700254 void generateFontMetrics(SkPaint::FontMetrics* metrics) override {
bungeman7cfd46a2016-10-20 16:06:52 -0400255 this->getTestTypeface()->getFontMetrics(metrics);
Mike Reed8be952a2017-02-13 20:44:33 -0500256 SkPaintPriv::ScaleFontMetrics(metrics, fMatrix.getScaleY());
caryclark5fb6bd42014-06-23 11:25:00 -0700257 }
258
259private:
caryclark5fb6bd42014-06-23 11:25:00 -0700260 SkMatrix fMatrix;
261};
262
bungeman7cfd46a2016-10-20 16:06:52 -0400263SkScalerContext* SkTestTypeface::onCreateScalerContext(
264 const SkScalerContextEffects& effects, const SkDescriptor* desc) const
265{
266 return new SkTestScalerContext(sk_ref_sp(const_cast<SkTestTypeface*>(this)), effects, desc);
caryclark5fb6bd42014-06-23 11:25:00 -0700267}