blob: c9cb87c03ccf0f21a0a21dde4c4b9adc971e75d5 [file] [log] [blame]
joshualittaa2f6582015-07-29 10:14:58 -07001/*
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 "SkRandomScalerContext.h"
9#include "SkGlyph.h"
10#include "SkPath.h"
11#include "SkCanvas.h"
joshualitt65e96b42015-07-31 11:45:22 -070012#include "SkRasterizer.h"
joshualittaa2f6582015-07-29 10:14:58 -070013
14class SkRandomScalerContext : public SkScalerContext {
15public:
reeda9322c22016-04-12 06:47:05 -070016 SkRandomScalerContext(SkRandomTypeface*, const SkScalerContextEffects&,
17 const SkDescriptor*, bool fFakeIt);
joshualittaa2f6582015-07-29 10:14:58 -070018 virtual ~SkRandomScalerContext();
19
20protected:
21 unsigned generateGlyphCount() override;
22 uint16_t generateCharToGlyph(SkUnichar) override;
23 void generateAdvance(SkGlyph*) override;
24 void generateMetrics(SkGlyph*) override;
25 void generateImage(const SkGlyph&) override;
26 void generatePath(const SkGlyph&, SkPath*) override;
27 void generateFontMetrics(SkPaint::FontMetrics*) override;
28
29private:
30 SkRandomTypeface* fFace;
31 SkScalerContext* fProxy;
joshualitt65e96b42015-07-31 11:45:22 -070032 bool fFakeIt;
joshualittaa2f6582015-07-29 10:14:58 -070033};
34
35#define STD_SIZE 1
36
37#include "SkDescriptor.h"
38
reeda9322c22016-04-12 06:47:05 -070039SkRandomScalerContext::SkRandomScalerContext(SkRandomTypeface* face,
40 const SkScalerContextEffects& effects,
41 const SkDescriptor* desc,
joshualitt65e96b42015-07-31 11:45:22 -070042 bool fakeIt)
reeda9322c22016-04-12 06:47:05 -070043 : SkScalerContext(face, effects, desc)
joshualitt65e96b42015-07-31 11:45:22 -070044 , fFace(face)
45 , fFakeIt(fakeIt) {
reeda9322c22016-04-12 06:47:05 -070046 fProxy = face->proxy()->createScalerContext(effects, desc);
joshualittaa2f6582015-07-29 10:14:58 -070047}
48
halcanary385fe4d2015-08-26 13:07:48 -070049SkRandomScalerContext::~SkRandomScalerContext() { delete fProxy; }
joshualittaa2f6582015-07-29 10:14:58 -070050
51unsigned SkRandomScalerContext::generateGlyphCount() {
52 return fProxy->getGlyphCount();
53}
54
55uint16_t SkRandomScalerContext::generateCharToGlyph(SkUnichar uni) {
56 return fProxy->charToGlyphID(uni);
57}
58
59void SkRandomScalerContext::generateAdvance(SkGlyph* glyph) {
60 fProxy->getAdvance(glyph);
joshualittaa2f6582015-07-29 10:14:58 -070061}
62
63void SkRandomScalerContext::generateMetrics(SkGlyph* glyph) {
joshualittaa2f6582015-07-29 10:14:58 -070064 // Here we will change the mask format of the glyph
65 // NOTE this is being overridden by the base class
robertphillips52b88cc2016-04-05 16:55:41 -070066 SkMask::Format format = SkMask::kARGB32_Format; // init to handle defective compilers
joshualittd45fb5a2015-08-01 10:33:40 -070067 switch (glyph->getGlyphID() % 4) {
joshualittaa2f6582015-07-29 10:14:58 -070068 case 0:
69 format = SkMask::kLCD16_Format;
70 break;
71 case 1:
72 format = SkMask::kA8_Format;
73 break;
74 case 2:
75 format = SkMask::kARGB32_Format;
76 break;
joshualittd45fb5a2015-08-01 10:33:40 -070077 case 3:
78 format = SkMask::kBW_Format;
79 break;
joshualittaa2f6582015-07-29 10:14:58 -070080 }
81
joshualitt65e96b42015-07-31 11:45:22 -070082 fProxy->getMetrics(glyph);
83
joshualittaa2f6582015-07-29 10:14:58 -070084 glyph->fMaskFormat = format;
joshualitt65e96b42015-07-31 11:45:22 -070085 if (fFakeIt) {
86 return;
87 }
88 if (SkMask::kARGB32_Format == format) {
joshualitt65e96b42015-07-31 11:45:22 -070089 SkPath path;
90 fProxy->getPath(*glyph, &path);
joshualitt65e96b42015-07-31 11:45:22 -070091
92 SkRect storage;
93 const SkPaint& paint = fFace->paint();
94 const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
95 &storage,
96 SkPaint::kFill_Style);
97 SkIRect ibounds;
98 newBounds.roundOut(&ibounds);
99 glyph->fLeft = ibounds.fLeft;
100 glyph->fTop = ibounds.fTop;
101 glyph->fWidth = ibounds.width();
102 glyph->fHeight = ibounds.height();
103 } else {
104 SkPath devPath, fillPath;
105 SkMatrix fillToDevMatrix;
106
107 this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
108
109 // just use devPath
110 const SkIRect ir = devPath.getBounds().roundOut();
111
112 if (ir.isEmpty() || !ir.is16Bit()) {
113 glyph->fLeft = 0;
114 glyph->fTop = 0;
115 glyph->fWidth = 0;
116 glyph->fHeight = 0;
117 return;
118 }
119 glyph->fLeft = ir.fLeft;
120 glyph->fTop = ir.fTop;
121 glyph->fWidth = SkToU16(ir.width());
122 glyph->fHeight = SkToU16(ir.height());
123
124 if (glyph->fWidth > 0) {
125 switch (glyph->fMaskFormat) {
126 case SkMask::kLCD16_Format:
127 glyph->fWidth += 2;
128 glyph->fLeft -= 1;
129 break;
130 default:
131 break;
132 }
133 }
134 }
joshualittaa2f6582015-07-29 10:14:58 -0700135}
136
137void SkRandomScalerContext::generateImage(const SkGlyph& glyph) {
138 SkMask::Format format = (SkMask::Format)glyph.fMaskFormat;
joshualittd45fb5a2015-08-01 10:33:40 -0700139 switch (glyph.getGlyphID() % 4) {
joshualittaa2f6582015-07-29 10:14:58 -0700140 case 0:
joshualittaa2f6582015-07-29 10:14:58 -0700141 format = SkMask::kLCD16_Format;
142 break;
joshualitt65e96b42015-07-31 11:45:22 -0700143 case 1:
joshualittaa2f6582015-07-29 10:14:58 -0700144 format = SkMask::kA8_Format;
145 break;
joshualitt65e96b42015-07-31 11:45:22 -0700146 case 2:
joshualittaa2f6582015-07-29 10:14:58 -0700147 format = SkMask::kARGB32_Format;
148 break;
joshualittd45fb5a2015-08-01 10:33:40 -0700149 case 3:
150 format = SkMask::kBW_Format;
151 break;
joshualittaa2f6582015-07-29 10:14:58 -0700152 }
153 const_cast<SkGlyph&>(glyph).fMaskFormat = format;
154
155 // if the format is ARGB, we just draw the glyph from path ourselves. Otherwise, we force
156 // our proxy context to generate the image from paths.
joshualitt65e96b42015-07-31 11:45:22 -0700157 if (!fFakeIt) {
158 if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
159 SkPath path;
160 fProxy->getPath(glyph, &path);
joshualittaa2f6582015-07-29 10:14:58 -0700161
joshualitt65e96b42015-07-31 11:45:22 -0700162 SkBitmap bm;
163 bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
164 glyph.fImage, glyph.rowBytes());
165 bm.eraseColor(0);
joshualittaa2f6582015-07-29 10:14:58 -0700166
joshualitt65e96b42015-07-31 11:45:22 -0700167 SkCanvas canvas(bm);
168 canvas.translate(-SkIntToScalar(glyph.fLeft),
169 -SkIntToScalar(glyph.fTop));
joshualitt65e96b42015-07-31 11:45:22 -0700170 canvas.drawPath(path, fFace->paint());
171 } else {
172 fProxy->forceGenerateImageFromPath();
173 fProxy->getImage(glyph);
174 fProxy->forceOffGenerateImageFromPath();
175 }
joshualittaa2f6582015-07-29 10:14:58 -0700176 } else {
joshualitt65e96b42015-07-31 11:45:22 -0700177 sk_bzero(glyph.fImage, glyph.computeImageSize());
joshualittaa2f6582015-07-29 10:14:58 -0700178 }
179}
180
181void SkRandomScalerContext::generatePath(const SkGlyph& glyph, SkPath* path) {
182 fProxy->getPath(glyph, path);
joshualittaa2f6582015-07-29 10:14:58 -0700183}
184
185void SkRandomScalerContext::generateFontMetrics(SkPaint::FontMetrics* metrics) {
186 fProxy->getFontMetrics(metrics);
joshualittaa2f6582015-07-29 10:14:58 -0700187}
188
189///////////////////////////////////////////////////////////////////////////////
190
191#include "SkTypefaceCache.h"
192
bungeman13b9c952016-05-12 10:09:30 -0700193SkRandomTypeface::SkRandomTypeface(sk_sp<SkTypeface> proxy, const SkPaint& paint, bool fakeIt)
bungemane3aea102016-07-13 05:16:58 -0700194 : SkTypeface(proxy->fontStyle(), false)
bungeman13b9c952016-05-12 10:09:30 -0700195 , fProxy(std::move(proxy))
joshualitt65e96b42015-07-31 11:45:22 -0700196 , fPaint(paint)
197 , fFakeIt(fakeIt) {}
joshualittaa2f6582015-07-29 10:14:58 -0700198
reeda9322c22016-04-12 06:47:05 -0700199SkScalerContext* SkRandomTypeface::onCreateScalerContext(const SkScalerContextEffects& effects,
200 const SkDescriptor* desc) const {
201 return new SkRandomScalerContext(const_cast<SkRandomTypeface*>(this), effects, desc, fFakeIt);
joshualittaa2f6582015-07-29 10:14:58 -0700202}
203
204void SkRandomTypeface::onFilterRec(SkScalerContextRec* rec) const {
205 fProxy->filterRec(rec);
206 rec->setHinting(SkPaint::kNo_Hinting);
207 rec->fMaskFormat = SkMask::kARGB32_Format;
208}
209
210SkAdvancedTypefaceMetrics* SkRandomTypeface::onGetAdvancedTypefaceMetrics(
211 PerGlyphInfo info,
212 const uint32_t* glyphIDs,
213 uint32_t glyphIDsCount) const {
214 return fProxy->getAdvancedTypefaceMetrics(info, glyphIDs, glyphIDsCount);
215}
216
217SkStreamAsset* SkRandomTypeface::onOpenStream(int* ttcIndex) const {
218 return fProxy->openStream(ttcIndex);
219}
220
221void SkRandomTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
222 bool* isLocal) const {
223 fProxy->getFontDescriptor(desc, isLocal);
224}
225
226int SkRandomTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
227 uint16_t glyphs[], int glyphCount) const {
228 return fProxy->charsToGlyphs(chars, encoding, glyphs, glyphCount);
229}
230
231int SkRandomTypeface::onCountGlyphs() const {
232 return fProxy->countGlyphs();
233}
234
235int SkRandomTypeface::onGetUPEM() const {
236 return fProxy->getUnitsPerEm();
237}
238
239void SkRandomTypeface::onGetFamilyName(SkString* familyName) const {
240 fProxy->getFamilyName(familyName);
241}
242
243SkTypeface::LocalizedStrings* SkRandomTypeface::onCreateFamilyNameIterator() const {
244 return fProxy->createFamilyNameIterator();
245}
246
247int SkRandomTypeface::onGetTableTags(SkFontTableTag tags[]) const {
248 return fProxy->getTableTags(tags);
249}
250
251size_t SkRandomTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
252 size_t length, void* data) const {
253 return fProxy->getTableData(tag, offset, length, data);
254}
255