blob: e543fdbd0a395a5b670203519b5f74e34a9b1857 [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:
19 virtual unsigned generateGlyphCount() SK_OVERRIDE;
20 virtual uint16_t generateCharToGlyph(SkUnichar) SK_OVERRIDE;
21 virtual void generateAdvance(SkGlyph*) SK_OVERRIDE;
22 virtual void generateMetrics(SkGlyph*) SK_OVERRIDE;
23 virtual void generateImage(const SkGlyph&) SK_OVERRIDE;
24 virtual void generatePath(const SkGlyph&, SkPath*) SK_OVERRIDE;
bungeman41078062014-07-07 08:16:37 -070025 virtual void generateFontMetrics(SkPaint::FontMetrics*) SK_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
66SkGScalerContext::~SkGScalerContext() {
67 SkDELETE(fProxy);
68}
69
70unsigned SkGScalerContext::generateGlyphCount() {
71 return fProxy->getGlyphCount();
72}
73
74uint16_t SkGScalerContext::generateCharToGlyph(SkUnichar uni) {
75 return fProxy->charToGlyphID(uni);
76}
77
78void SkGScalerContext::generateAdvance(SkGlyph* glyph) {
79 fProxy->getAdvance(glyph);
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +000080
reed@google.com7edec142013-05-31 20:17:57 +000081 SkVector advance;
82 fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX),
83 SkFixedToScalar(glyph->fAdvanceY), &advance);
84 glyph->fAdvanceX = SkScalarToFixed(advance.fX);
85 glyph->fAdvanceY = SkScalarToFixed(advance.fY);
86}
87
88void SkGScalerContext::generateMetrics(SkGlyph* glyph) {
89 fProxy->getMetrics(glyph);
90
91 SkVector advance;
92 fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX),
93 SkFixedToScalar(glyph->fAdvanceY), &advance);
94 glyph->fAdvanceX = SkScalarToFixed(advance.fX);
95 glyph->fAdvanceY = SkScalarToFixed(advance.fY);
96
97 SkPath path;
98 fProxy->getPath(*glyph, &path);
99 path.transform(fMatrix);
100
101 SkRect storage;
102 const SkPaint& paint = fFace->paint();
103 const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
104 &storage,
105 SkPaint::kFill_Style);
106 SkIRect ibounds;
107 newBounds.roundOut(&ibounds);
108 glyph->fLeft = ibounds.fLeft;
109 glyph->fTop = ibounds.fTop;
110 glyph->fWidth = ibounds.width();
111 glyph->fHeight = ibounds.height();
112 glyph->fMaskFormat = SkMask::kARGB32_Format;
113}
114
115void SkGScalerContext::generateImage(const SkGlyph& glyph) {
116 if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
117 SkPath path;
118 fProxy->getPath(glyph, &path);
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000119
reed@google.com7edec142013-05-31 20:17:57 +0000120 SkBitmap bm;
reed6c225732014-06-09 19:52:07 -0700121 bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
122 glyph.fImage, glyph.rowBytes());
reed@google.com7edec142013-05-31 20:17:57 +0000123 bm.eraseColor(0);
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000124
reed@google.com7edec142013-05-31 20:17:57 +0000125 SkCanvas canvas(bm);
reed@google.com1b6a04f2013-05-31 21:06:03 +0000126 canvas.translate(-SkIntToScalar(glyph.fLeft),
127 -SkIntToScalar(glyph.fTop));
reed@google.com7edec142013-05-31 20:17:57 +0000128 canvas.concat(fMatrix);
129 canvas.drawPath(path, fFace->paint());
130 } else {
131 fProxy->getImage(glyph);
132 }
133}
134
135void SkGScalerContext::generatePath(const SkGlyph& glyph, SkPath* path) {
136 fProxy->getPath(glyph, path);
137 path->transform(fMatrix);
138}
139
bungeman41078062014-07-07 08:16:37 -0700140void SkGScalerContext::generateFontMetrics(SkPaint::FontMetrics* metrics) {
reed@google.com7edec142013-05-31 20:17:57 +0000141 fProxy->getFontMetrics(metrics);
142 if (metrics) {
143 SkScalar scale = fMatrix.getScaleY();
144 metrics->fTop = SkScalarMul(metrics->fTop, scale);
145 metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
146 metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
147 metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
148 metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
149 metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
150 metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
151 metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
152 metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
153 }
154}
155
156///////////////////////////////////////////////////////////////////////////////
157
158#include "SkTypefaceCache.h"
159
160SkGTypeface::SkGTypeface(SkTypeface* proxy, const SkPaint& paint)
161 : SkTypeface(proxy->style(), SkTypefaceCache::NewFontID(), false)
162 , fProxy(SkRef(proxy))
163 , fPaint(paint) {}
164
165SkGTypeface::~SkGTypeface() {
166 fProxy->unref();
167}
168
169SkScalerContext* SkGTypeface::onCreateScalerContext(
170 const SkDescriptor* desc) const {
171 return SkNEW_ARGS(SkGScalerContext, (const_cast<SkGTypeface*>(this), desc));
172}
173
174void SkGTypeface::onFilterRec(SkScalerContextRec* rec) const {
175 fProxy->filterRec(rec);
rmistry@google.comd6bab022013-12-02 13:50:38 +0000176 rec->setHinting(SkPaint::kNo_Hinting);
177 rec->fMaskFormat = SkMask::kARGB32_Format;
reed@google.com7edec142013-05-31 20:17:57 +0000178}
179
180SkAdvancedTypefaceMetrics* SkGTypeface::onGetAdvancedTypefaceMetrics(
181 SkAdvancedTypefaceMetrics::PerGlyphInfo info,
182 const uint32_t* glyphIDs,
183 uint32_t glyphIDsCount) const {
184 return fProxy->getAdvancedTypefaceMetrics(info, glyphIDs, glyphIDsCount);
185}
186
187SkStream* SkGTypeface::onOpenStream(int* ttcIndex) const {
188 return fProxy->openStream(ttcIndex);
189}
190
191void SkGTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
192 bool* isLocal) const {
193 fProxy->getFontDescriptor(desc, isLocal);
194}
195
bungeman@google.com3c996f82013-10-24 21:39:35 +0000196int SkGTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
197 uint16_t glyphs[], int glyphCount) const {
198 return fProxy->charsToGlyphs(chars, encoding, glyphs, glyphCount);
199}
200
bungeman@google.come05e75e2013-07-15 19:52:13 +0000201int SkGTypeface::onCountGlyphs() const {
202 return fProxy->countGlyphs();
203}
204
reed@google.com7edec142013-05-31 20:17:57 +0000205int SkGTypeface::onGetUPEM() const {
206 return fProxy->getUnitsPerEm();
207}
208
bungeman@google.com839702b2013-08-07 17:09:22 +0000209SkTypeface::LocalizedStrings* SkGTypeface::onCreateFamilyNameIterator() const {
210 return fProxy->createFamilyNameIterator();
bungeman@google.coma9802692013-08-07 02:45:25 +0000211}
212
reed@google.com7edec142013-05-31 20:17:57 +0000213int SkGTypeface::onGetTableTags(SkFontTableTag tags[]) const {
214 return fProxy->getTableTags(tags);
215}
216
217size_t SkGTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
218 size_t length, void* data) const {
219 return fProxy->getTableData(tag, offset, length, data);
220}
221
222///////////////////////////////////////////////////////////////////////////////
223
224#if 0
225// under construction -- defining a font purely in terms of skia primitives
226// ala an SVG-font.
227class SkGFont : public SkRefCnt {
228public:
229 virtual ~SkGFont();
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000230
reed@google.com7edec142013-05-31 20:17:57 +0000231 int unicharToGlyph(SkUnichar) const;
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000232
reed@google.com7edec142013-05-31 20:17:57 +0000233 int countGlyphs() const { return fCount; }
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000234
reed@google.com7edec142013-05-31 20:17:57 +0000235 float getAdvance(int index) const {
236 SkASSERT((unsigned)index < (unsigned)fCount);
237 return fGlyphs[index].fAdvance;
238 }
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000239
reed@google.com7edec142013-05-31 20:17:57 +0000240 const SkPath& getPath(int index) const {
241 SkASSERT((unsigned)index < (unsigned)fCount);
242 return fGlyphs[index].fPath;
243 }
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000244
reed@google.com7edec142013-05-31 20:17:57 +0000245private:
246 struct Glyph {
247 SkUnichar fUni;
248 float fAdvance;
249 SkPath fPath;
250 };
251 int fCount;
252 Glyph* fGlyphs;
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000253
reed@google.com7edec142013-05-31 20:17:57 +0000254 friend class SkGFontBuilder;
255 SkGFont(int count, Glyph* array);
256};
257
258class SkGFontBuilder {
259public:
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000260
reed@google.com7edec142013-05-31 20:17:57 +0000261};
262#endif