1 /*
2 * Copyright 2013 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 "SkCanvas.h"
9 #include "SkDescriptor.h"
10 #include "SkGScalerContext.h"
11 #include "SkGlyph.h"
12 #include "SkPaintPriv.h"
13 #include "SkPath.h"
14 #include "SkMakeUnique.h"
15
16 #define STD_SIZE 1
17
18 class SkGScalerContext : public SkScalerContext {
19 public:
SkGScalerContext(sk_sp<SkGTypeface> face,const SkScalerContextEffects & effects,const SkDescriptor * desc)20 SkGScalerContext(sk_sp<SkGTypeface> face, const SkScalerContextEffects& effects,
21 const SkDescriptor* desc)
22 : SkScalerContext(std::move(face), effects, desc)
23 {
24
25 size_t descSize = SkDescriptor::ComputeOverhead(1) + sizeof(SkScalerContext::Rec);
26 SkAutoDescriptor ad(descSize);
27 SkDescriptor* newDesc = ad.getDesc();
28
29 newDesc->init();
30 void* entry = newDesc->addEntry(kRec_SkDescriptorTag,
31 sizeof(SkScalerContext::Rec), &fRec);
32 {
33 SkScalerContext::Rec* rec = (SkScalerContext::Rec*)entry;
34 rec->fTextSize = STD_SIZE;
35 rec->fPreScaleX = SK_Scalar1;
36 rec->fPreSkewX = 0;
37 rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
38 rec->fPost2x2[1][0] = rec->fPost2x2[0][1] = 0;
39 }
40 SkASSERT(descSize == newDesc->getLength());
41 newDesc->computeChecksum();
42
43 fProxy = this->getGTypeface()->proxy()->createScalerContext(effects, newDesc);
44
45 fRec.getSingleMatrix(&fMatrix);
46 fMatrix.preScale(SK_Scalar1 / STD_SIZE, SK_Scalar1 / STD_SIZE);
47 }
48
49 protected:
getGTypeface()50 SkGTypeface* getGTypeface() { return static_cast<SkGTypeface*>(this->getTypeface()); }
51
52 unsigned generateGlyphCount() override;
53 uint16_t generateCharToGlyph(SkUnichar) override;
54 void generateAdvance(SkGlyph*) override;
55 void generateMetrics(SkGlyph*) override;
56 void generateImage(const SkGlyph&) override;
57 void generatePath(SkGlyphID, SkPath*) override;
58 void generateFontMetrics(SkPaint::FontMetrics*) override;
59
60 private:
61 std::unique_ptr<SkScalerContext> fProxy;
62 SkMatrix fMatrix;
63 };
64
generateGlyphCount()65 unsigned SkGScalerContext::generateGlyphCount() {
66 return fProxy->getGlyphCount();
67 }
68
generateCharToGlyph(SkUnichar uni)69 uint16_t SkGScalerContext::generateCharToGlyph(SkUnichar uni) {
70 return fProxy->charToGlyphID(uni);
71 }
72
generateAdvance(SkGlyph * glyph)73 void SkGScalerContext::generateAdvance(SkGlyph* glyph) {
74 fProxy->getAdvance(glyph);
75
76 SkVector advance;
77 fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX),
78 SkFloatToScalar(glyph->fAdvanceY), &advance);
79 glyph->fAdvanceX = SkScalarToFloat(advance.fX);
80 glyph->fAdvanceY = SkScalarToFloat(advance.fY);
81 }
82
generateMetrics(SkGlyph * glyph)83 void SkGScalerContext::generateMetrics(SkGlyph* glyph) {
84 fProxy->getMetrics(glyph);
85
86 SkVector advance;
87 fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX),
88 SkFloatToScalar(glyph->fAdvanceY), &advance);
89 glyph->fAdvanceX = SkScalarToFloat(advance.fX);
90 glyph->fAdvanceY = SkScalarToFloat(advance.fY);
91
92 SkPath path;
93 fProxy->getPath(glyph->getPackedID(), &path);
94 path.transform(fMatrix);
95
96 SkRect storage;
97 const SkPaint& paint = this->getGTypeface()->paint();
98 const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
99 &storage,
100 SkPaint::kFill_Style);
101 SkIRect ibounds;
102 newBounds.roundOut(&ibounds);
103 glyph->fLeft = ibounds.fLeft;
104 glyph->fTop = ibounds.fTop;
105 glyph->fWidth = ibounds.width();
106 glyph->fHeight = ibounds.height();
107 glyph->fMaskFormat = SkMask::kARGB32_Format;
108 }
109
generateImage(const SkGlyph & glyph)110 void SkGScalerContext::generateImage(const SkGlyph& glyph) {
111 if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
112 SkPath path;
113 fProxy->getPath(glyph.getPackedID(), &path);
114
115 SkBitmap bm;
116 bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
117 glyph.fImage, glyph.rowBytes());
118 bm.eraseColor(0);
119
120 SkCanvas canvas(bm);
121 canvas.translate(-SkIntToScalar(glyph.fLeft),
122 -SkIntToScalar(glyph.fTop));
123 canvas.concat(fMatrix);
124 canvas.drawPath(path, this->getGTypeface()->paint());
125 } else {
126 fProxy->getImage(glyph);
127 }
128 }
129
generatePath(SkGlyphID glyph,SkPath * path)130 void SkGScalerContext::generatePath(SkGlyphID glyph, SkPath* path) {
131 fProxy->getPath(SkPackedGlyphID(glyph), path);
132 path->transform(fMatrix);
133 }
134
generateFontMetrics(SkPaint::FontMetrics * metrics)135 void SkGScalerContext::generateFontMetrics(SkPaint::FontMetrics* metrics) {
136 fProxy->getFontMetrics(metrics);
137 SkPaintPriv::ScaleFontMetrics(metrics, fMatrix.getScaleY());
138 }
139
140 ///////////////////////////////////////////////////////////////////////////////
141
142 #include "SkTypefaceCache.h"
143
SkGTypeface(sk_sp<SkTypeface> proxy,const SkPaint & paint)144 SkGTypeface::SkGTypeface(sk_sp<SkTypeface> proxy, const SkPaint& paint)
145 : SkTypeface(proxy->fontStyle(), false)
146 , fProxy(std::move(proxy))
147 , fPaint(paint)
148 {}
149
onCreateScalerContext(const SkScalerContextEffects & effects,const SkDescriptor * desc) const150 SkScalerContext* SkGTypeface::onCreateScalerContext(const SkScalerContextEffects& effects,
151 const SkDescriptor* desc) const {
152 return new SkGScalerContext(sk_ref_sp(const_cast<SkGTypeface*>(this)), effects, desc);
153 }
154
onFilterRec(SkScalerContextRec * rec) const155 void SkGTypeface::onFilterRec(SkScalerContextRec* rec) const {
156 fProxy->filterRec(rec);
157 rec->setHinting(SkPaint::kNo_Hinting);
158 rec->fMaskFormat = SkMask::kARGB32_Format;
159 }
160
onGetAdvancedTypefaceMetrics(PerGlyphInfo info,const uint32_t * glyphIDs,uint32_t glyphIDsCount) const161 SkAdvancedTypefaceMetrics* SkGTypeface::onGetAdvancedTypefaceMetrics(
162 PerGlyphInfo info,
163 const uint32_t* glyphIDs,
164 uint32_t glyphIDsCount) const {
165 return fProxy->getAdvancedTypefaceMetrics(info, glyphIDs, glyphIDsCount);
166 }
167
onOpenStream(int * ttcIndex) const168 SkStreamAsset* SkGTypeface::onOpenStream(int* ttcIndex) const {
169 return fProxy->openStream(ttcIndex);
170 }
171
onGetFontDescriptor(SkFontDescriptor * desc,bool * isLocal) const172 void SkGTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
173 bool* isLocal) const {
174 fProxy->getFontDescriptor(desc, isLocal);
175 }
176
onCharsToGlyphs(const void * chars,Encoding encoding,uint16_t glyphs[],int glyphCount) const177 int SkGTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
178 uint16_t glyphs[], int glyphCount) const {
179 return fProxy->charsToGlyphs(chars, encoding, glyphs, glyphCount);
180 }
181
onCountGlyphs() const182 int SkGTypeface::onCountGlyphs() const {
183 return fProxy->countGlyphs();
184 }
185
onGetUPEM() const186 int SkGTypeface::onGetUPEM() const {
187 return fProxy->getUnitsPerEm();
188 }
189
onGetFamilyName(SkString * familyName) const190 void SkGTypeface::onGetFamilyName(SkString* familyName) const {
191 fProxy->getFamilyName(familyName);
192 }
193
onCreateFamilyNameIterator() const194 SkTypeface::LocalizedStrings* SkGTypeface::onCreateFamilyNameIterator() const {
195 return fProxy->createFamilyNameIterator();
196 }
197
onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],int coordinateCount) const198 int SkGTypeface::onGetVariationDesignPosition(
199 SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const
200 {
201 return fProxy->onGetVariationDesignPosition(coordinates, coordinateCount);
202 }
203
onGetTableTags(SkFontTableTag tags[]) const204 int SkGTypeface::onGetTableTags(SkFontTableTag tags[]) const {
205 return fProxy->getTableTags(tags);
206 }
207
onGetTableData(SkFontTableTag tag,size_t offset,size_t length,void * data) const208 size_t SkGTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
209 size_t length, void* data) const {
210 return fProxy->getTableData(tag, offset, length, data);
211 }
212
213 ///////////////////////////////////////////////////////////////////////////////
214
215 #if 0
216 // under construction -- defining a font purely in terms of skia primitives
217 // ala an SVG-font.
218 class SkGFont : public SkRefCnt {
219 public:
220 virtual ~SkGFont();
221
222 int unicharToGlyph(SkUnichar) const;
223
224 int countGlyphs() const { return fCount; }
225
226 float getAdvance(int index) const {
227 SkASSERT((unsigned)index < (unsigned)fCount);
228 return fGlyphs[index].fAdvance;
229 }
230
231 const SkPath& getPath(int index) const {
232 SkASSERT((unsigned)index < (unsigned)fCount);
233 return fGlyphs[index].fPath;
234 }
235
236 private:
237 struct Glyph {
238 SkUnichar fUni;
239 float fAdvance;
240 SkPath fPath;
241 };
242 int fCount;
243 Glyph* fGlyphs;
244
245 friend class SkGFontBuilder;
246 SkGFont(int count, Glyph* array);
247 };
248
249 class SkGFontBuilder {
250 public:
251
252 };
253 #endif
254