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 "SkRasterizer.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 void generateAdvance(SkGlyph*) override;
28 void generateMetrics(SkGlyph*) override;
29 void generateImage(const SkGlyph&) override;
30 void generatePath(SkGlyphID, SkPath*) override;
31 void generateFontMetrics(SkPaint::FontMetrics*) 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 , fFakeIt(fakeIt) {
47 fProxy = this->getRandomTypeface()->proxy()->createScalerContext(effects, desc);
48 }
49
generateGlyphCount()50 unsigned SkRandomScalerContext::generateGlyphCount() {
51 return fProxy->getGlyphCount();
52 }
53
generateCharToGlyph(SkUnichar uni)54 uint16_t SkRandomScalerContext::generateCharToGlyph(SkUnichar uni) {
55 return fProxy->charToGlyphID(uni);
56 }
57
generateAdvance(SkGlyph * glyph)58 void SkRandomScalerContext::generateAdvance(SkGlyph* glyph) {
59 fProxy->getAdvance(glyph);
60 }
61
generateMetrics(SkGlyph * glyph)62 void SkRandomScalerContext::generateMetrics(SkGlyph* glyph) {
63 // Here we will change the mask format of the glyph
64 // NOTE this is being overridden by the base class
65 SkMask::Format format = SkMask::kARGB32_Format; // init to handle defective compilers
66 switch (glyph->getGlyphID() % 4) {
67 case 0:
68 format = SkMask::kLCD16_Format;
69 break;
70 case 1:
71 format = SkMask::kA8_Format;
72 break;
73 case 2:
74 format = SkMask::kARGB32_Format;
75 break;
76 case 3:
77 format = SkMask::kBW_Format;
78 break;
79 }
80
81 fProxy->getMetrics(glyph);
82
83 glyph->fMaskFormat = format;
84 if (fFakeIt) {
85 return;
86 }
87 if (SkMask::kARGB32_Format == format) {
88 SkPath path;
89 fProxy->getPath(glyph->getPackedID(), &path);
90
91 SkRect storage;
92 const SkPaint& paint = this->getRandomTypeface()->paint();
93 const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
94 &storage,
95 SkPaint::kFill_Style);
96 SkIRect ibounds;
97 newBounds.roundOut(&ibounds);
98 glyph->fLeft = ibounds.fLeft;
99 glyph->fTop = ibounds.fTop;
100 glyph->fWidth = ibounds.width();
101 glyph->fHeight = ibounds.height();
102 } else {
103 SkPath devPath, fillPath;
104 SkMatrix fillToDevMatrix;
105
106 this->internalGetPath(glyph->getPackedID(), &fillPath, &devPath, &fillToDevMatrix);
107
108 // just use devPath
109 const SkIRect ir = devPath.getBounds().roundOut();
110
111 if (ir.isEmpty() || !ir.is16Bit()) {
112 glyph->fLeft = 0;
113 glyph->fTop = 0;
114 glyph->fWidth = 0;
115 glyph->fHeight = 0;
116 return;
117 }
118 glyph->fLeft = ir.fLeft;
119 glyph->fTop = ir.fTop;
120 glyph->fWidth = SkToU16(ir.width());
121 glyph->fHeight = SkToU16(ir.height());
122
123 if (glyph->fWidth > 0) {
124 switch (glyph->fMaskFormat) {
125 case SkMask::kLCD16_Format:
126 glyph->fWidth += 2;
127 glyph->fLeft -= 1;
128 break;
129 default:
130 break;
131 }
132 }
133 }
134 }
135
generateImage(const SkGlyph & glyph)136 void SkRandomScalerContext::generateImage(const SkGlyph& glyph) {
137 SkMask::Format format = (SkMask::Format)glyph.fMaskFormat;
138 switch (glyph.getGlyphID() % 4) {
139 case 0:
140 format = SkMask::kLCD16_Format;
141 break;
142 case 1:
143 format = SkMask::kA8_Format;
144 break;
145 case 2:
146 format = SkMask::kARGB32_Format;
147 break;
148 case 3:
149 format = SkMask::kBW_Format;
150 break;
151 }
152 const_cast<SkGlyph&>(glyph).fMaskFormat = format;
153
154 // if the format is ARGB, we just draw the glyph from path ourselves. Otherwise, we force
155 // our proxy context to generate the image from paths.
156 if (!fFakeIt) {
157 if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
158 SkPath path;
159 fProxy->getPath(glyph.getPackedID(), &path);
160
161 SkBitmap bm;
162 bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
163 glyph.fImage, glyph.rowBytes());
164 bm.eraseColor(0);
165
166 SkCanvas canvas(bm);
167 canvas.translate(-SkIntToScalar(glyph.fLeft),
168 -SkIntToScalar(glyph.fTop));
169 canvas.drawPath(path, this->getRandomTypeface()->paint());
170 } else {
171 fProxy->forceGenerateImageFromPath();
172 fProxy->getImage(glyph);
173 fProxy->forceOffGenerateImageFromPath();
174 }
175 } else {
176 sk_bzero(glyph.fImage, glyph.computeImageSize());
177 }
178 }
179
generatePath(SkGlyphID glyph,SkPath * path)180 void SkRandomScalerContext::generatePath(SkGlyphID glyph, SkPath* path) {
181 fProxy->generatePath(glyph, path);
182 }
183
generateFontMetrics(SkPaint::FontMetrics * metrics)184 void SkRandomScalerContext::generateFontMetrics(SkPaint::FontMetrics* metrics) {
185 fProxy->getFontMetrics(metrics);
186 }
187
188 ///////////////////////////////////////////////////////////////////////////////
189
190 #include "SkTypefaceCache.h"
191
SkRandomTypeface(sk_sp<SkTypeface> proxy,const SkPaint & paint,bool fakeIt)192 SkRandomTypeface::SkRandomTypeface(sk_sp<SkTypeface> proxy, const SkPaint& paint, bool fakeIt)
193 : SkTypeface(proxy->fontStyle(), false)
194 , fProxy(std::move(proxy))
195 , fPaint(paint)
196 , fFakeIt(fakeIt) {}
197
onCreateScalerContext(const SkScalerContextEffects & effects,const SkDescriptor * desc) const198 SkScalerContext* SkRandomTypeface::onCreateScalerContext(const SkScalerContextEffects& effects,
199 const SkDescriptor* desc) const {
200 return new SkRandomScalerContext(sk_ref_sp(const_cast<SkRandomTypeface*>(this)),
201 effects, desc, fFakeIt);
202 }
203
onFilterRec(SkScalerContextRec * rec) const204 void SkRandomTypeface::onFilterRec(SkScalerContextRec* rec) const {
205 fProxy->filterRec(rec);
206 rec->setHinting(SkPaint::kNo_Hinting);
207 rec->fMaskFormat = SkMask::kARGB32_Format;
208 }
209
onGetAdvancedMetrics() const210 std::unique_ptr<SkAdvancedTypefaceMetrics> SkRandomTypeface::onGetAdvancedMetrics() const {
211 return fProxy->getAdvancedMetrics();
212 }
213
onOpenStream(int * ttcIndex) const214 SkStreamAsset* SkRandomTypeface::onOpenStream(int* ttcIndex) const {
215 return fProxy->openStream(ttcIndex);
216 }
217
onGetFontDescriptor(SkFontDescriptor * desc,bool * isLocal) const218 void SkRandomTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
219 bool* isLocal) const {
220 fProxy->getFontDescriptor(desc, isLocal);
221 }
222
onCharsToGlyphs(const void * chars,Encoding encoding,uint16_t glyphs[],int glyphCount) const223 int SkRandomTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
224 uint16_t glyphs[], int glyphCount) const {
225 return fProxy->charsToGlyphs(chars, encoding, glyphs, glyphCount);
226 }
227
onCountGlyphs() const228 int SkRandomTypeface::onCountGlyphs() const {
229 return fProxy->countGlyphs();
230 }
231
onGetUPEM() const232 int SkRandomTypeface::onGetUPEM() const {
233 return fProxy->getUnitsPerEm();
234 }
235
onGetFamilyName(SkString * familyName) const236 void SkRandomTypeface::onGetFamilyName(SkString* familyName) const {
237 fProxy->getFamilyName(familyName);
238 }
239
onCreateFamilyNameIterator() const240 SkTypeface::LocalizedStrings* SkRandomTypeface::onCreateFamilyNameIterator() const {
241 return fProxy->createFamilyNameIterator();
242 }
243
onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],int coordinateCount) const244 int SkRandomTypeface::onGetVariationDesignPosition(
245 SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const
246 {
247 return fProxy->onGetVariationDesignPosition(coordinates, coordinateCount);
248 }
249
onGetTableTags(SkFontTableTag tags[]) const250 int SkRandomTypeface::onGetTableTags(SkFontTableTag tags[]) const {
251 return fProxy->getTableTags(tags);
252 }
253
onGetTableData(SkFontTableTag tag,size_t offset,size_t length,void * data) const254 size_t SkRandomTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
255 size_t length, void* data) const {
256 return fProxy->getTableData(tag, offset, length, data);
257 }
258
259