• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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: SkDEBUGFAIL("bad verb"); return;
121             }
122         }
123         fPaths[index] = b.detach();
124     }
125 }
126 
TestTypeface(sk_sp<SkTestFont> testFont,const SkFontStyle & style)127 TestTypeface::TestTypeface(sk_sp<SkTestFont> testFont, const SkFontStyle& style)
128         : SkTypeface(style, false), fTestFont(std::move(testFont)) {}
129 
getAdvance(SkGlyph * glyph)130 void TestTypeface::getAdvance(SkGlyph* glyph) {
131     SkGlyphID glyphID = glyph->getGlyphID();
132     glyphID           = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
133 
134     // TODO(benjaminwagner): Update users to use floats.
135     glyph->fAdvanceX = SkFixedToFloat(fTestFont->fWidths[glyphID]);
136     glyph->fAdvanceY = 0;
137 }
138 
getFontMetrics(SkFontMetrics * metrics)139 void TestTypeface::getFontMetrics(SkFontMetrics* metrics) { *metrics = fTestFont->fMetrics; }
140 
getPath(SkGlyphID glyphID)141 SkPath TestTypeface::getPath(SkGlyphID glyphID) {
142     glyphID = glyphID < fTestFont->fCharCodesCount ? glyphID : 0;
143     return fTestFont->fPaths[glyphID];
144 }
145 
onFilterRec(SkScalerContextRec * rec) const146 void TestTypeface::onFilterRec(SkScalerContextRec* rec) const {
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->fFontName.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 
generateAdvance(SkGlyph * glyph)263     bool generateAdvance(SkGlyph* glyph) override {
264         this->getTestTypeface()->getAdvance(glyph);
265 
266         const SkVector advance =
267                 fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX), SkFloatToScalar(glyph->fAdvanceY));
268         glyph->fAdvanceX = SkScalarToFloat(advance.fX);
269         glyph->fAdvanceY = SkScalarToFloat(advance.fY);
270         return true;
271     }
272 
generateMetrics(SkGlyph * glyph,SkArenaAlloc *)273     void generateMetrics(SkGlyph* glyph, SkArenaAlloc*) override {
274         glyph->zeroMetrics();
275         this->generateAdvance(glyph);
276         // Always generates from paths, so SkScalerContext::makeGlyph will figure the bounds.
277     }
278 
generateImage(const SkGlyph &)279     void generateImage(const SkGlyph&) override { SK_ABORT("Should have generated from path."); }
280 
generatePath(const SkGlyph & glyph,SkPath * path)281     bool generatePath(const SkGlyph& glyph, SkPath* path) override {
282         *path = this->getTestTypeface()->getPath(glyph.getGlyphID()).makeTransform(fMatrix);
283         return true;
284     }
285 
generateFontMetrics(SkFontMetrics * metrics)286     void generateFontMetrics(SkFontMetrics* metrics) override {
287         this->getTestTypeface()->getFontMetrics(metrics);
288         SkFontPriv::ScaleFontMetrics(metrics, fMatrix.getScaleY());
289     }
290 
291 private:
292     SkMatrix fMatrix;
293 };
294 
onCreateScalerContext(const SkScalerContextEffects & effects,const SkDescriptor * desc) const295 std::unique_ptr<SkScalerContext> TestTypeface::onCreateScalerContext(
296     const SkScalerContextEffects& effects, const SkDescriptor* desc) const
297 {
298     return std::make_unique<SkTestScalerContext>(
299             sk_ref_sp(const_cast<TestTypeface*>(this)), effects, desc);
300 }
301