blob: d2d0cacd0e1d25791fb2b28f7fa001101f2a1f27 [file] [log] [blame]
reed@google.com7edec142013-05-31 20:17:57 +00001/*
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 "SkGScalerContext.h"
9#include "SkGlyph.h"
10#include "SkPath.h"
11#include "SkCanvas.h"
12
13class SkGScalerContext : public SkScalerContext {
14public:
15 SkGScalerContext(SkGTypeface*, const SkDescriptor*);
16 virtual ~SkGScalerContext();
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +000017
reed@google.com7edec142013-05-31 20:17:57 +000018protected:
mtklein36352bf2015-03-25 18:17:31 -070019 unsigned generateGlyphCount() override;
20 uint16_t generateCharToGlyph(SkUnichar) override;
21 void generateAdvance(SkGlyph*) override;
22 void generateMetrics(SkGlyph*) override;
23 void generateImage(const SkGlyph&) override;
24 void generatePath(const SkGlyph&, SkPath*) override;
25 void generateFontMetrics(SkPaint::FontMetrics*) override;
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +000026
reed@google.com7edec142013-05-31 20:17:57 +000027private:
28 SkGTypeface* fFace;
29 SkScalerContext* fProxy;
30 SkMatrix fMatrix;
31};
32
33#define STD_SIZE 1
34
35#include "SkDescriptor.h"
36
37SkGScalerContext::SkGScalerContext(SkGTypeface* face, const SkDescriptor* desc)
38 : SkScalerContext(face, desc)
39 , fFace(face)
40{
41
42 size_t descSize = SkDescriptor::ComputeOverhead(1) + sizeof(SkScalerContext::Rec);
43 SkAutoDescriptor ad(descSize);
44 SkDescriptor* newDesc = ad.getDesc();
45
46 newDesc->init();
47 void* entry = newDesc->addEntry(kRec_SkDescriptorTag,
48 sizeof(SkScalerContext::Rec), &fRec);
49 {
50 SkScalerContext::Rec* rec = (SkScalerContext::Rec*)entry;
51 rec->fTextSize = STD_SIZE;
52 rec->fPreScaleX = SK_Scalar1;
53 rec->fPreSkewX = 0;
54 rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
55 rec->fPost2x2[1][0] = rec->fPost2x2[0][1] = 0;
56 }
57 SkASSERT(descSize == newDesc->getLength());
58 newDesc->computeChecksum();
59
60 fProxy = face->proxy()->createScalerContext(newDesc);
61
62 fRec.getSingleMatrix(&fMatrix);
63 fMatrix.preScale(SK_Scalar1 / STD_SIZE, SK_Scalar1 / STD_SIZE);
64}
65
halcanary385fe4d2015-08-26 13:07:48 -070066SkGScalerContext::~SkGScalerContext() { delete fProxy; }
reed@google.com7edec142013-05-31 20:17:57 +000067
68unsigned SkGScalerContext::generateGlyphCount() {
69 return fProxy->getGlyphCount();
70}
71
72uint16_t SkGScalerContext::generateCharToGlyph(SkUnichar uni) {
73 return fProxy->charToGlyphID(uni);
74}
75
76void SkGScalerContext::generateAdvance(SkGlyph* glyph) {
77 fProxy->getAdvance(glyph);
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +000078
reed@google.com7edec142013-05-31 20:17:57 +000079 SkVector advance;
80 fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX),
81 SkFixedToScalar(glyph->fAdvanceY), &advance);
82 glyph->fAdvanceX = SkScalarToFixed(advance.fX);
83 glyph->fAdvanceY = SkScalarToFixed(advance.fY);
84}
85
86void SkGScalerContext::generateMetrics(SkGlyph* glyph) {
87 fProxy->getMetrics(glyph);
88
89 SkVector advance;
90 fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX),
91 SkFixedToScalar(glyph->fAdvanceY), &advance);
92 glyph->fAdvanceX = SkScalarToFixed(advance.fX);
93 glyph->fAdvanceY = SkScalarToFixed(advance.fY);
94
95 SkPath path;
96 fProxy->getPath(*glyph, &path);
97 path.transform(fMatrix);
98
99 SkRect storage;
100 const SkPaint& paint = fFace->paint();
101 const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
102 &storage,
103 SkPaint::kFill_Style);
104 SkIRect ibounds;
105 newBounds.roundOut(&ibounds);
106 glyph->fLeft = ibounds.fLeft;
107 glyph->fTop = ibounds.fTop;
108 glyph->fWidth = ibounds.width();
109 glyph->fHeight = ibounds.height();
110 glyph->fMaskFormat = SkMask::kARGB32_Format;
111}
112
113void SkGScalerContext::generateImage(const SkGlyph& glyph) {
114 if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
115 SkPath path;
116 fProxy->getPath(glyph, &path);
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000117
reed@google.com7edec142013-05-31 20:17:57 +0000118 SkBitmap bm;
reed6c225732014-06-09 19:52:07 -0700119 bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
120 glyph.fImage, glyph.rowBytes());
reed@google.com7edec142013-05-31 20:17:57 +0000121 bm.eraseColor(0);
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000122
reed@google.com7edec142013-05-31 20:17:57 +0000123 SkCanvas canvas(bm);
reed@google.com1b6a04f2013-05-31 21:06:03 +0000124 canvas.translate(-SkIntToScalar(glyph.fLeft),
125 -SkIntToScalar(glyph.fTop));
reed@google.com7edec142013-05-31 20:17:57 +0000126 canvas.concat(fMatrix);
127 canvas.drawPath(path, fFace->paint());
128 } else {
129 fProxy->getImage(glyph);
130 }
131}
132
133void SkGScalerContext::generatePath(const SkGlyph& glyph, SkPath* path) {
134 fProxy->getPath(glyph, path);
135 path->transform(fMatrix);
136}
137
bungeman41078062014-07-07 08:16:37 -0700138void SkGScalerContext::generateFontMetrics(SkPaint::FontMetrics* metrics) {
reed@google.com7edec142013-05-31 20:17:57 +0000139 fProxy->getFontMetrics(metrics);
140 if (metrics) {
141 SkScalar scale = fMatrix.getScaleY();
142 metrics->fTop = SkScalarMul(metrics->fTop, scale);
143 metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
144 metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
145 metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
146 metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
147 metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
148 metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
149 metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
150 metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
151 }
152}
153
154///////////////////////////////////////////////////////////////////////////////
155
156#include "SkTypefaceCache.h"
157
158SkGTypeface::SkGTypeface(SkTypeface* proxy, const SkPaint& paint)
bungemana4c4a2d2014-10-20 13:33:19 -0700159 : SkTypeface(proxy->fontStyle(), SkTypefaceCache::NewFontID(), false)
reed@google.com7edec142013-05-31 20:17:57 +0000160 , fProxy(SkRef(proxy))
161 , fPaint(paint) {}
162
163SkGTypeface::~SkGTypeface() {
164 fProxy->unref();
165}
166
167SkScalerContext* SkGTypeface::onCreateScalerContext(
168 const SkDescriptor* desc) const {
halcanary385fe4d2015-08-26 13:07:48 -0700169 return new SkGScalerContext(const_cast<SkGTypeface*>(this), desc);
reed@google.com7edec142013-05-31 20:17:57 +0000170}
171
172void SkGTypeface::onFilterRec(SkScalerContextRec* rec) const {
173 fProxy->filterRec(rec);
rmistry@google.comd6bab022013-12-02 13:50:38 +0000174 rec->setHinting(SkPaint::kNo_Hinting);
175 rec->fMaskFormat = SkMask::kARGB32_Format;
reed@google.com7edec142013-05-31 20:17:57 +0000176}
177
178SkAdvancedTypefaceMetrics* SkGTypeface::onGetAdvancedTypefaceMetrics(
reed39a9a502015-05-12 09:50:04 -0700179 PerGlyphInfo info,
reed@google.com7edec142013-05-31 20:17:57 +0000180 const uint32_t* glyphIDs,
181 uint32_t glyphIDsCount) const {
182 return fProxy->getAdvancedTypefaceMetrics(info, glyphIDs, glyphIDsCount);
183}
184
bungeman5f213d92015-01-27 05:39:10 -0800185SkStreamAsset* SkGTypeface::onOpenStream(int* ttcIndex) const {
reed@google.com7edec142013-05-31 20:17:57 +0000186 return fProxy->openStream(ttcIndex);
187}
188
189void SkGTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
190 bool* isLocal) const {
191 fProxy->getFontDescriptor(desc, isLocal);
192}
193
bungeman@google.com3c996f82013-10-24 21:39:35 +0000194int SkGTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
195 uint16_t glyphs[], int glyphCount) const {
196 return fProxy->charsToGlyphs(chars, encoding, glyphs, glyphCount);
197}
198
bungeman@google.come05e75e2013-07-15 19:52:13 +0000199int SkGTypeface::onCountGlyphs() const {
200 return fProxy->countGlyphs();
201}
202
reed@google.com7edec142013-05-31 20:17:57 +0000203int SkGTypeface::onGetUPEM() const {
204 return fProxy->getUnitsPerEm();
205}
206
bungemanb374d6a2014-09-17 07:48:59 -0700207void SkGTypeface::onGetFamilyName(SkString* familyName) const {
208 fProxy->getFamilyName(familyName);
209}
210
bungeman@google.com839702b2013-08-07 17:09:22 +0000211SkTypeface::LocalizedStrings* SkGTypeface::onCreateFamilyNameIterator() const {
212 return fProxy->createFamilyNameIterator();
bungeman@google.coma9802692013-08-07 02:45:25 +0000213}
214
reed@google.com7edec142013-05-31 20:17:57 +0000215int SkGTypeface::onGetTableTags(SkFontTableTag tags[]) const {
216 return fProxy->getTableTags(tags);
217}
218
219size_t SkGTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
220 size_t length, void* data) const {
221 return fProxy->getTableData(tag, offset, length, data);
222}
223
224///////////////////////////////////////////////////////////////////////////////
225
226#if 0
227// under construction -- defining a font purely in terms of skia primitives
228// ala an SVG-font.
229class SkGFont : public SkRefCnt {
230public:
231 virtual ~SkGFont();
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000232
reed@google.com7edec142013-05-31 20:17:57 +0000233 int unicharToGlyph(SkUnichar) const;
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000234
reed@google.com7edec142013-05-31 20:17:57 +0000235 int countGlyphs() const { return fCount; }
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000236
reed@google.com7edec142013-05-31 20:17:57 +0000237 float getAdvance(int index) const {
238 SkASSERT((unsigned)index < (unsigned)fCount);
239 return fGlyphs[index].fAdvance;
240 }
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000241
reed@google.com7edec142013-05-31 20:17:57 +0000242 const SkPath& getPath(int index) const {
243 SkASSERT((unsigned)index < (unsigned)fCount);
244 return fGlyphs[index].fPath;
245 }
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000246
reed@google.com7edec142013-05-31 20:17:57 +0000247private:
248 struct Glyph {
249 SkUnichar fUni;
250 float fAdvance;
251 SkPath fPath;
252 };
253 int fCount;
254 Glyph* fGlyphs;
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000255
reed@google.com7edec142013-05-31 20:17:57 +0000256 friend class SkGFontBuilder;
257 SkGFont(int count, Glyph* array);
258};
259
260class SkGFontBuilder {
261public:
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000262
reed@google.com7edec142013-05-31 20:17:57 +0000263};
264#endif