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