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