• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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