xref: /aosp_15_r20/external/skia/tools/fonts/TestTypeface.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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->useStrokeForFakeBold();
147     rec->setHinting(SkFontHinting::kNone);
148 }
149 
getGlyphToUnicodeMap(SkUnichar * glyphToUnicode) const150 void TestTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const {
151     unsigned glyphCount = fTestFont->fCharCodesCount;
152     for (unsigned gid = 0; gid < glyphCount; ++gid) {
153         glyphToUnicode[gid] = SkTo<SkUnichar>(fTestFont->fCharCodes[gid]);
154     }
155 }
156 
onGetAdvancedMetrics() const157 std::unique_ptr<SkAdvancedTypefaceMetrics> TestTypeface::onGetAdvancedMetrics() const {  // pdf only
158     std::unique_ptr<SkAdvancedTypefaceMetrics>info(new SkAdvancedTypefaceMetrics);
159     info->fPostScriptName.set(fTestFont->fName);
160     return info;
161 }
162 
163 static constexpr const char gHeaderString[] = "SkTestTypeface01";
164 static constexpr const size_t kHeaderSize = sizeof(gHeaderString);
165 
onOpenStream(int * ttcIndex) const166 std::unique_ptr<SkStreamAsset> TestTypeface::onOpenStream(int* ttcIndex) const {
167     SkDynamicMemoryWStream wstream;
168     wstream.write(gHeaderString, kHeaderSize);
169 
170     SkString name;
171     this->getFamilyName(&name);
172     SkFontStyle style = this->fontStyle();
173 
174     wstream.writePackedUInt(name.size());
175     wstream.write(name.c_str(), name.size());
176     wstream.writeScalar(style.weight());
177     wstream.writeScalar(style.width());
178     wstream.writePackedUInt(style.slant());
179 
180     *ttcIndex = 0;
181     return wstream.detachAsStream();
182 }
183 
MakeFromStream(std::unique_ptr<SkStreamAsset> stream,const SkFontArguments &)184 sk_sp<SkTypeface> TestTypeface::MakeFromStream(std::unique_ptr<SkStreamAsset> stream,
185                                                const SkFontArguments&) {
186     char header[kHeaderSize];
187     if (stream->read(header, kHeaderSize) != kHeaderSize ||
188         0 != memcmp(header, gHeaderString, kHeaderSize))
189     {
190         return nullptr;
191     }
192 
193     size_t familyNameSize;
194     SkString familyName;
195     if (!stream->readPackedUInt(&familyNameSize)) { return nullptr; }
196     familyName.resize(familyNameSize);
197     if (!stream->read(familyName.data(), familyNameSize)) { return nullptr; }
198 
199     SkScalar weight;
200     SkScalar width;
201     size_t slant;
202     if (!stream->readScalar(&weight)) { return nullptr; }
203     if (!stream->readScalar(&width)) { return nullptr; }
204     if (!stream->readPackedUInt(&slant)) { return nullptr; }
205     SkFontStyle style(weight, width, (SkFontStyle::Slant)slant);
206 
207     auto&& list = TestTypeface::Typefaces();
208     for (auto&& family : list.families) {
209         if (familyName.equals(family.name)) {
210             for (auto&& face : family.faces) {
211                 if (face.typeface->fontStyle() == style) {
212                     return face.typeface;
213                 }
214             }
215         }
216     }
217     return nullptr;
218 }
219 
onGetFontDescriptor(SkFontDescriptor * desc,bool * serialize) const220 void TestTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* serialize) const {
221     desc->setFamilyName(fTestFont->fName);
222     desc->setStyle(this->fontStyle());
223     desc->setFactoryId(FactoryId);
224     *serialize = true;
225 }
226 
Register()227 TestTypeface::Register::Register() {
228     SkTypeface::Register(TestTypeface::FactoryId, &TestTypeface::MakeFromStream);
229 }
230 static TestTypeface::Register registerer;
231 
onCharsToGlyphs(const SkUnichar * uni,int count,SkGlyphID glyphs[]) const232 void TestTypeface::onCharsToGlyphs(const SkUnichar* uni, int count, SkGlyphID glyphs[]) const {
233     for (int i = 0; i < count; ++i) {
234         glyphs[i] = fTestFont->glyphForUnichar(uni[i]);
235     }
236 }
237 
onGetFamilyName(SkString * familyName) const238 void TestTypeface::onGetFamilyName(SkString* familyName) const { *familyName = fTestFont->fName; }
239 
onGetPostScriptName(SkString *) const240 bool TestTypeface::onGetPostScriptName(SkString*) const { return false; }
241 
onCreateFamilyNameIterator() const242 SkTypeface::LocalizedStrings* TestTypeface::onCreateFamilyNameIterator() const {
243     SkString familyName(fTestFont->fName);
244     SkString language("und");  // undetermined
245     return new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
246 }
247 
248 class SkTestScalerContext : public SkScalerContext {
249 public:
SkTestScalerContext(sk_sp<TestTypeface> face,const SkScalerContextEffects & effects,const SkDescriptor * desc)250     SkTestScalerContext(sk_sp<TestTypeface>           face,
251                         const SkScalerContextEffects& effects,
252                         const SkDescriptor*           desc)
253             : SkScalerContext(std::move(face), effects, desc) {
254         fRec.getSingleMatrix(&fMatrix);
255         this->forceGenerateImageFromPath();
256     }
257 
258 protected:
getTestTypeface() const259     TestTypeface* getTestTypeface() const {
260         return static_cast<TestTypeface*>(this->getTypeface());
261     }
262 
generateMetrics(const SkGlyph & glyph,SkArenaAlloc *)263     GlyphMetrics generateMetrics(const SkGlyph& glyph, SkArenaAlloc*) override {
264         GlyphMetrics mx(glyph.maskFormat());
265 
266         auto advance = this->getTestTypeface()->getAdvance(glyph.getGlyphID());
267 
268         mx.advance = fMatrix.mapXY(advance.fX, advance.fY);
269         return mx;
270 
271         // Always generates from paths, so SkScalerContext::makeGlyph will figure the bounds.
272     }
273 
generateImage(const SkGlyph &,void *)274     void generateImage(const SkGlyph&, void*) override {
275         SK_ABORT("Should have generated from path.");
276     }
277 
generatePath(const SkGlyph & glyph,SkPath * path,bool * modified)278     bool generatePath(const SkGlyph& glyph, SkPath* path, bool* modified) override {
279         *path = this->getTestTypeface()->getPath(glyph.getGlyphID()).makeTransform(fMatrix);
280         return true;
281     }
282 
generateFontMetrics(SkFontMetrics * metrics)283     void generateFontMetrics(SkFontMetrics* metrics) override {
284         this->getTestTypeface()->getFontMetrics(metrics);
285         SkFontPriv::ScaleFontMetrics(metrics, fMatrix.getScaleY());
286     }
287 
288 private:
289     SkMatrix fMatrix;
290 };
291 
onCreateScalerContext(const SkScalerContextEffects & effects,const SkDescriptor * desc) const292 std::unique_ptr<SkScalerContext> TestTypeface::onCreateScalerContext(
293     const SkScalerContextEffects& effects, const SkDescriptor* desc) const
294 {
295     return std::make_unique<SkTestScalerContext>(
296             sk_ref_sp(const_cast<TestTypeface*>(this)), effects, desc);
297 }
298