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 "include/core/SkBitmap.h"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkFontMetrics.h"
11 #include "include/core/SkImageInfo.h"
12 #include "include/core/SkMatrix.h"
13 #include "include/core/SkPathBuilder.h"
14 #include "include/core/SkPoint.h"
15 #include "include/core/SkRect.h"
16 #include "include/core/SkString.h"
17 #include "include/private/base/SkTDArray.h"
18 #include "include/private/base/SkTo.h"
19 #include "src/base/SkUtils.h"
20 #include "src/core/SkAdvancedTypefaceMetrics.h"
21 #include "src/core/SkFontDescriptor.h"
22 #include "src/core/SkFontPriv.h"
23 #include "src/core/SkGlyph.h"
24 #include "src/core/SkPaintPriv.h"
25 #include "src/core/SkScalerContext.h"
26 #include "src/sfnt/SkOTUtils.h"
27 #include "tools/fonts/TestTypeface.h"
28
29 #include <utility>
30
31 namespace {
32
33 #include "tools/fonts/test_font_monospace.inc"
34 #include "tools/fonts/test_font_sans_serif.inc"
35 #include "tools/fonts/test_font_serif.inc"
36
37 #include "tools/fonts/test_font_index.inc"
38
39 } // namespace
40
41 class SkDescriptor;
42
Typefaces()43 const TestTypeface::List& TestTypeface::Typefaces() {
44 static List list = []() -> List {
45 TestTypeface::List list;
46 for (const auto& sub : gSubFonts) {
47 List::Family* existingFamily = nullptr;
48 for (auto& family : list.families) {
49 if (strcmp(family.name, sub.fFamilyName) == 0) {
50 existingFamily = &family;
51 break;
52 }
53 }
54 if (!existingFamily) {
55 existingFamily = &list.families.emplace_back();
56 existingFamily->name = sub.fFamilyName;
57 }
58
59 auto font = sk_make_sp<SkTestFont>(sub.fFont);
60 sk_sp<SkTypeface> typeface(new TestTypeface(std::move(font), sub.fStyle));
61 bool isDefault = (&sub - gSubFonts == gDefaultFontIndex);
62 existingFamily->faces.emplace_back(
63 List::Family::Face{std::move(typeface), sub.fStyleName, isDefault});
64 }
65 return list;
66 }();
67 return list;
68 }
69
SkTestFont(const SkTestFontData & fontData)70 SkTestFont::SkTestFont(const SkTestFontData& fontData)
71 : INHERITED()
72 , fCharCodes(fontData.fCharCodes)
73 , fCharCodesCount(fontData.fCharCodes ? fontData.fCharCodesCount : 0)
74 , fWidths(fontData.fWidths)
75 , fMetrics(fontData.fMetrics)
76 , fName(fontData.fName)
77 , fPaths(nullptr) {
78 init(fontData.fPoints, fontData.fVerbs);
79 }
80
~SkTestFont()81 SkTestFont::~SkTestFont() {
82 delete[] fPaths;
83 }
84
glyphForUnichar(SkUnichar charCode) const85 SkGlyphID SkTestFont::glyphForUnichar(SkUnichar charCode) const {
86 for (size_t index = 0; index < fCharCodesCount; ++index) {
87 if (fCharCodes[index] == charCode) {
88 return SkTo<SkGlyphID>(index);
89 }
90 }
91 return 0;
92 }
93
init(const SkScalar * pts,const unsigned char * verbs)94 void SkTestFont::init(const SkScalar* pts, const unsigned char* verbs) {
95 fPaths = new SkPath[fCharCodesCount];
96 for (unsigned index = 0; index < fCharCodesCount; ++index) {
97 SkPathBuilder b;
98 SkPath::Verb verb;
99 while ((verb = (SkPath::Verb)*verbs++) != SkPath::kDone_Verb) {
100 switch (verb) {
101 case SkPath::kMove_Verb:
102 b.moveTo(pts[0], pts[1]);
103 pts += 2;
104 break;
105 case SkPath::kLine_Verb:
106 b.lineTo(pts[0], pts[1]);
107 pts += 2;
108 break;
109 case SkPath::kQuad_Verb:
110 b.quadTo(pts[0], pts[1], pts[2], pts[3]);
111 pts += 4;
112 break;
113 case SkPath::kCubic_Verb:
114 b.cubicTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]);
115 pts += 6;
116 break;
117 case SkPath::kClose_Verb:
118 b.close();
119 break;
120 default:
121 SK_ABORT("bad verb");
122 }
123 }
124 fPaths[index] = b.detach();
125 }
126 }
127
TestTypeface(sk_sp<SkTestFont> testFont,const SkFontStyle & style)128 TestTypeface::TestTypeface(sk_sp<SkTestFont> testFont, const SkFontStyle& style)
129 : SkTypeface(style, false), fTestFont(std::move(testFont)) {}
130
getAdvance(SkGlyphID glyphID) const131 SkVector TestTypeface::getAdvance(SkGlyphID glyphID) const {
132 glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
133
134 // TODO(benjaminwagner): Update users to use floats.
135 return {SkFixedToFloat(fTestFont->fWidths[glyphID]), 0};
136 }
137
getFontMetrics(SkFontMetrics * metrics)138 void TestTypeface::getFontMetrics(SkFontMetrics* metrics) { *metrics = fTestFont->fMetrics; }
139
getPath(SkGlyphID glyphID)140 SkPath TestTypeface::getPath(SkGlyphID glyphID) {
141 glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
142 return fTestFont->fPaths[glyphID];
143 }
144
onFilterRec(SkScalerContextRec * rec) const145 void TestTypeface::onFilterRec(SkScalerContextRec* rec) const {
146 rec->setHinting(SkFontHinting::kNone);
147 }
148
getGlyphToUnicodeMap(SkUnichar * glyphToUnicode) const149 void TestTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const {
150 unsigned glyphCount = fTestFont->fCharCodesCount;
151 for (unsigned gid = 0; gid < glyphCount; ++gid) {
152 glyphToUnicode[gid] = SkTo<SkUnichar>(fTestFont->fCharCodes[gid]);
153 }
154 }
155
onGetAdvancedMetrics() const156 std::unique_ptr<SkAdvancedTypefaceMetrics> TestTypeface::onGetAdvancedMetrics() const { // pdf only
157 std::unique_ptr<SkAdvancedTypefaceMetrics>info(new SkAdvancedTypefaceMetrics);
158 info->fPostScriptName.set(fTestFont->fName);
159 return info;
160 }
161
162 static constexpr const char gHeaderString[] = "SkTestTypeface01";
163 static constexpr const size_t kHeaderSize = sizeof(gHeaderString);
164
onOpenStream(int * ttcIndex) const165 std::unique_ptr<SkStreamAsset> TestTypeface::onOpenStream(int* ttcIndex) const {
166 SkDynamicMemoryWStream wstream;
167 wstream.write(gHeaderString, kHeaderSize);
168
169 SkString name;
170 this->getFamilyName(&name);
171 SkFontStyle style = this->fontStyle();
172
173 wstream.writePackedUInt(name.size());
174 wstream.write(name.c_str(), name.size());
175 wstream.writeScalar(style.weight());
176 wstream.writeScalar(style.width());
177 wstream.writePackedUInt(style.slant());
178
179 *ttcIndex = 0;
180 return wstream.detachAsStream();
181 }
182
MakeFromStream(std::unique_ptr<SkStreamAsset> stream,const SkFontArguments &)183 sk_sp<SkTypeface> TestTypeface::MakeFromStream(std::unique_ptr<SkStreamAsset> stream,
184 const SkFontArguments&) {
185 char header[kHeaderSize];
186 if (stream->read(header, kHeaderSize) != kHeaderSize ||
187 0 != memcmp(header, gHeaderString, kHeaderSize))
188 {
189 return nullptr;
190 }
191
192 size_t familyNameSize;
193 SkString familyName;
194 if (!stream->readPackedUInt(&familyNameSize)) { return nullptr; }
195 familyName.resize(familyNameSize);
196 if (!stream->read(familyName.data(), familyNameSize)) { return nullptr; }
197
198 SkScalar weight;
199 SkScalar width;
200 size_t slant;
201 if (!stream->readScalar(&weight)) { return nullptr; }
202 if (!stream->readScalar(&width)) { return nullptr; }
203 if (!stream->readPackedUInt(&slant)) { return nullptr; }
204 SkFontStyle style(weight, width, (SkFontStyle::Slant)slant);
205
206 auto&& list = TestTypeface::Typefaces();
207 for (auto&& family : list.families) {
208 if (familyName.equals(family.name)) {
209 for (auto&& face : family.faces) {
210 if (face.typeface->fontStyle() == style) {
211 return face.typeface;
212 }
213 }
214 }
215 }
216 return nullptr;
217 }
218
onGetFontDescriptor(SkFontDescriptor * desc,bool * serialize) const219 void TestTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const {
220 desc->setFamilyName(fTestFont->fName);
221 desc->setStyle(this->fontStyle());
222 desc->setFactoryId(FactoryId);
223 *serialize = true;
224 }
225
Register()226 TestTypeface::Register::Register() {
227 SkTypeface::Register(TestTypeface::FactoryId, &TestTypeface::MakeFromStream);
228 }
229 static TestTypeface::Register registerer;
230
onCharsToGlyphs(const SkUnichar * uni,int count,SkGlyphID glyphs[]) const231 void TestTypeface::onCharsToGlyphs(const SkUnichar* uni, int count, SkGlyphID glyphs[]) const {
232 for (int i = 0; i < count; ++i) {
233 glyphs[i] = fTestFont->glyphForUnichar(uni[i]);
234 }
235 }
236
onGetFamilyName(SkString * familyName) const237 void TestTypeface::onGetFamilyName(SkString* familyName) const { *familyName = fTestFont->fName; }
238
onGetPostScriptName(SkString *) const239 bool TestTypeface::onGetPostScriptName(SkString*) const { return false; }
240
onCreateFamilyNameIterator() const241 SkTypeface::LocalizedStrings* TestTypeface::onCreateFamilyNameIterator() const {
242 SkString familyName(fTestFont->fName);
243 SkString language("und"); // undetermined
244 return new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
245 }
246
247 class SkTestScalerContext : public SkScalerContext {
248 public:
SkTestScalerContext(sk_sp<TestTypeface> face,const SkScalerContextEffects & effects,const SkDescriptor * desc)249 SkTestScalerContext(sk_sp<TestTypeface> face,
250 const SkScalerContextEffects& effects,
251 const SkDescriptor* desc)
252 : SkScalerContext(std::move(face), effects, desc) {
253 fRec.getSingleMatrix(&fMatrix);
254 this->forceGenerateImageFromPath();
255 }
256
257 protected:
getTestTypeface() const258 TestTypeface* getTestTypeface() const {
259 return static_cast<TestTypeface*>(this->getTypeface());
260 }
261
generateMetrics(const SkGlyph & glyph,SkArenaAlloc *)262 GlyphMetrics generateMetrics(const SkGlyph& glyph, SkArenaAlloc*) override {
263 GlyphMetrics mx(glyph.maskFormat());
264
265 auto advance = this->getTestTypeface()->getAdvance(glyph.getGlyphID());
266
267 mx.advance = fMatrix.mapXY(advance.fX, advance.fY);
268 return mx;
269
270 // Always generates from paths, so SkScalerContext::makeGlyph will figure the bounds.
271 }
272
generateImage(const SkGlyph &,void *)273 void generateImage(const SkGlyph&, void*) override {
274 SK_ABORT("Should have generated from path.");
275 }
276
generatePath(const SkGlyph & glyph,SkPath * path)277 bool generatePath(const SkGlyph& glyph, SkPath* path) override {
278 *path = this->getTestTypeface()->getPath(glyph.getGlyphID()).makeTransform(fMatrix);
279 return true;
280 }
281
generateFontMetrics(SkFontMetrics * metrics)282 void generateFontMetrics(SkFontMetrics* metrics) override {
283 this->getTestTypeface()->getFontMetrics(metrics);
284 SkFontPriv::ScaleFontMetrics(metrics, fMatrix.getScaleY());
285 }
286
287 private:
288 SkMatrix fMatrix;
289 };
290
onCreateScalerContext(const SkScalerContextEffects & effects,const SkDescriptor * desc) const291 std::unique_ptr<SkScalerContext> TestTypeface::onCreateScalerContext(
292 const SkScalerContextEffects& effects, const SkDescriptor* desc) const
293 {
294 return std::make_unique<SkTestScalerContext>(
295 sk_ref_sp(const_cast<TestTypeface*>(this)), effects, desc);
296 }
297