1 /*
2  * Copyright 2015 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 "SkAdvancedTypefaceMetrics.h"
9 #include "SkBitmap.h"
10 #include "SkCanvas.h"
11 #include "SkGlyph.h"
12 #include "SkMakeUnique.h"
13 #include "SkPath.h"
14 #include "SkRandomScalerContext.h"
15 #include "SkRectPriv.h"
16 
17 class SkDescriptor;
18 
19 class SkRandomScalerContext : public SkScalerContext {
20 public:
21     SkRandomScalerContext(sk_sp<SkRandomTypeface>, const SkScalerContextEffects&,
22                           const SkDescriptor*, bool fFakeIt);
23 
24 protected:
25     unsigned generateGlyphCount() override;
26     uint16_t generateCharToGlyph(SkUnichar) override;
27     bool generateAdvance(SkGlyph*) override;
28     void generateMetrics(SkGlyph*) override;
29     void generateImage(const SkGlyph&) override;
30     bool generatePath(SkGlyphID, SkPath*) override;
31     void generateFontMetrics(SkFontMetrics*) override;
32 
33 private:
getRandomTypeface() const34     SkRandomTypeface* getRandomTypeface() const {
35         return static_cast<SkRandomTypeface*>(this->getTypeface());
36     }
37     std::unique_ptr<SkScalerContext> fProxy;
38     bool fFakeIt;
39 };
40 
SkRandomScalerContext(sk_sp<SkRandomTypeface> face,const SkScalerContextEffects & effects,const SkDescriptor * desc,bool fakeIt)41 SkRandomScalerContext::SkRandomScalerContext(sk_sp<SkRandomTypeface> face,
42                                              const SkScalerContextEffects& effects,
43                                              const SkDescriptor* desc,
44                                              bool fakeIt)
45         : SkScalerContext(std::move(face), effects, desc)
46         , fProxy(getRandomTypeface()->proxy()->createScalerContext(SkScalerContextEffects(), desc))
47         , fFakeIt(fakeIt)
48 {
49     fProxy->forceGenerateImageFromPath();
50 }
51 
generateGlyphCount()52 unsigned SkRandomScalerContext::generateGlyphCount() {
53     return fProxy->getGlyphCount();
54 }
55 
generateCharToGlyph(SkUnichar uni)56 uint16_t SkRandomScalerContext::generateCharToGlyph(SkUnichar uni) {
57     return fProxy->charToGlyphID(uni);
58 }
59 
generateAdvance(SkGlyph * glyph)60 bool SkRandomScalerContext::generateAdvance(SkGlyph* glyph) {
61     return fProxy->generateAdvance(glyph);
62 }
63 
generateMetrics(SkGlyph * glyph)64 void SkRandomScalerContext::generateMetrics(SkGlyph* glyph) {
65     // Here we will change the mask format of the glyph
66     // NOTE: this may be overridden by the base class (e.g. if a mask filter is applied).
67     switch (glyph->getGlyphID() % 4) {
68         case 0: glyph->fMaskFormat = SkMask::kLCD16_Format; break;
69         case 1: glyph->fMaskFormat = SkMask::kA8_Format; break;
70         case 2: glyph->fMaskFormat = SkMask::kARGB32_Format; break;
71         case 3: glyph->fMaskFormat = SkMask::kBW_Format; break;
72     }
73 
74     fProxy->getMetrics(glyph);
75 
76     if (fFakeIt || (glyph->getGlyphID() % 4) != 2) {
77         return;
78     }
79 
80     SkPath path;
81     if (!fProxy->getPath(glyph->getPackedID(), &path)) {
82         return;
83     }
84     glyph->fMaskFormat = SkMask::kARGB32_Format;
85 
86     SkRect storage;
87     const SkPaint& paint = this->getRandomTypeface()->paint();
88     const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
89                                                         &storage,
90                                                         SkPaint::kFill_Style);
91     SkIRect ibounds;
92     newBounds.roundOut(&ibounds);
93     glyph->fLeft = ibounds.fLeft;
94     glyph->fTop = ibounds.fTop;
95     glyph->fWidth = ibounds.width();
96     glyph->fHeight = ibounds.height();
97 }
98 
generateImage(const SkGlyph & glyph)99 void SkRandomScalerContext::generateImage(const SkGlyph& glyph) {
100     // TODO: can force down but not up
101     /*
102     SkMask::Format format = (SkMask::Format)glyph.fMaskFormat;
103     switch (glyph.getGlyphID() % 4) {
104         case 0: format = SkMask::kLCD16_Format; break;
105         case 1: format = SkMask::kA8_Format; break;
106         case 2: format = SkMask::kARGB32_Format; break;
107         case 3: format = SkMask::kBW_Format; break;
108     }
109     const_cast<SkGlyph&>(glyph).fMaskFormat = format;
110     */
111 
112     if (fFakeIt) {
113         sk_bzero(glyph.fImage, glyph.computeImageSize());
114         return;
115     }
116 
117     if (SkMask::kARGB32_Format != glyph.fMaskFormat) {
118         fProxy->getImage(glyph);
119         return;
120     }
121 
122     // If the format is ARGB, just draw the glyph from path.
123     SkPath path;
124     if (!fProxy->getPath(glyph.getPackedID(), &path)) {
125         fProxy->getImage(glyph);
126         return;
127     }
128 
129     SkBitmap bm;
130     bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
131                      glyph.fImage, glyph.rowBytes());
132     bm.eraseColor(0);
133 
134     SkCanvas canvas(bm);
135     canvas.translate(-SkIntToScalar(glyph.fLeft), -SkIntToScalar(glyph.fTop));
136     canvas.drawPath(path, this->getRandomTypeface()->paint());
137 }
138 
generatePath(SkGlyphID glyph,SkPath * path)139 bool SkRandomScalerContext::generatePath(SkGlyphID glyph, SkPath* path) {
140     return fProxy->generatePath(glyph, path);
141 }
142 
generateFontMetrics(SkFontMetrics * metrics)143 void SkRandomScalerContext::generateFontMetrics(SkFontMetrics* metrics) {
144     fProxy->getFontMetrics(metrics);
145 }
146 
147 ///////////////////////////////////////////////////////////////////////////////
148 
SkRandomTypeface(sk_sp<SkTypeface> proxy,const SkPaint & paint,bool fakeIt)149 SkRandomTypeface::SkRandomTypeface(sk_sp<SkTypeface> proxy, const SkPaint& paint, bool fakeIt)
150     : SkTypeface(proxy->fontStyle(), false)
151     , fProxy(std::move(proxy))
152     , fPaint(paint)
153     , fFakeIt(fakeIt) {}
154 
onCreateScalerContext(const SkScalerContextEffects & effects,const SkDescriptor * desc) const155 SkScalerContext* SkRandomTypeface::onCreateScalerContext(const SkScalerContextEffects& effects,
156                                                          const SkDescriptor* desc) const {
157     return new SkRandomScalerContext(sk_ref_sp(const_cast<SkRandomTypeface*>(this)),
158                                      effects, desc, fFakeIt);
159 }
160 
onFilterRec(SkScalerContextRec * rec) const161 void SkRandomTypeface::onFilterRec(SkScalerContextRec* rec) const {
162     fProxy->filterRec(rec);
163     rec->setHinting(kNo_SkFontHinting);
164     rec->fMaskFormat = SkMask::kARGB32_Format;
165 }
166 
getGlyphToUnicodeMap(SkUnichar * glyphToUnicode) const167 void SkRandomTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const {
168     fProxy->getGlyphToUnicodeMap(glyphToUnicode);
169 }
170 
onGetAdvancedMetrics() const171 std::unique_ptr<SkAdvancedTypefaceMetrics> SkRandomTypeface::onGetAdvancedMetrics() const {
172     return fProxy->getAdvancedMetrics();
173 }
174 
onOpenStream(int * ttcIndex) const175 SkStreamAsset* SkRandomTypeface::onOpenStream(int* ttcIndex) const {
176     return fProxy->openStream(ttcIndex);
177 }
178 
onMakeClone(const SkFontArguments & args) const179 sk_sp<SkTypeface> SkRandomTypeface::onMakeClone(const SkFontArguments& args) const {
180     sk_sp<SkTypeface> proxy = fProxy->makeClone(args);
181     if (!proxy) {
182         return nullptr;
183     }
184     return sk_make_sp<SkRandomTypeface>(proxy, fPaint, fFakeIt);
185 }
186 
onGetFontDescriptor(SkFontDescriptor * desc,bool * isLocal) const187 void SkRandomTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
188     // TODO: anything that uses this typeface isn't correctly serializable, since this typeface
189     // cannot be deserialized.
190     fProxy->getFontDescriptor(desc, isLocal);
191 }
192 
onCharsToGlyphs(const void * chars,Encoding encoding,uint16_t glyphs[],int glyphCount) const193 int SkRandomTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
194                                  uint16_t glyphs[], int glyphCount) const {
195     return fProxy->charsToGlyphs(chars, encoding, glyphs, glyphCount);
196 }
197 
onCountGlyphs() const198 int SkRandomTypeface::onCountGlyphs() const {
199     return fProxy->countGlyphs();
200 }
201 
onGetUPEM() const202 int SkRandomTypeface::onGetUPEM() const {
203     return fProxy->getUnitsPerEm();
204 }
205 
onGetFamilyName(SkString * familyName) const206 void SkRandomTypeface::onGetFamilyName(SkString* familyName) const {
207     fProxy->getFamilyName(familyName);
208 }
209 
onCreateFamilyNameIterator() const210 SkTypeface::LocalizedStrings* SkRandomTypeface::onCreateFamilyNameIterator() const {
211     return fProxy->createFamilyNameIterator();
212 }
213 
onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],int coordinateCount) const214 int SkRandomTypeface::onGetVariationDesignPosition(
215         SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const
216 {
217     return fProxy->onGetVariationDesignPosition(coordinates, coordinateCount);
218 }
219 
onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],int parameterCount) const220 int SkRandomTypeface::onGetVariationDesignParameters(
221         SkFontParameters::Variation::Axis parameters[], int parameterCount) const
222 {
223     return fProxy->onGetVariationDesignParameters(parameters, parameterCount);
224 }
225 
onGetTableTags(SkFontTableTag tags[]) const226 int SkRandomTypeface::onGetTableTags(SkFontTableTag tags[]) const {
227     return fProxy->getTableTags(tags);
228 }
229 
onGetTableData(SkFontTableTag tag,size_t offset,size_t length,void * data) const230 size_t SkRandomTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
231                                     size_t length, void* data) const {
232     return fProxy->getTableData(tag, offset, length, data);
233 }
234 
235