blob: 551b01c961100a425de458accd9e7ff32220440c [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;
25 virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
26 SkPaint::FontMetrics* mY) SK_OVERRIDE;
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +000027
reed@google.com7edec142013-05-31 20:17:57 +000028private:
29 SkGTypeface* fFace;
30 SkScalerContext* fProxy;
31 SkMatrix fMatrix;
32};
33
34#define STD_SIZE 1
35
36#include "SkDescriptor.h"
37
38SkGScalerContext::SkGScalerContext(SkGTypeface* face, const SkDescriptor* desc)
39 : SkScalerContext(face, desc)
40 , fFace(face)
41{
42
43 size_t descSize = SkDescriptor::ComputeOverhead(1) + sizeof(SkScalerContext::Rec);
44 SkAutoDescriptor ad(descSize);
45 SkDescriptor* newDesc = ad.getDesc();
46
47 newDesc->init();
48 void* entry = newDesc->addEntry(kRec_SkDescriptorTag,
49 sizeof(SkScalerContext::Rec), &fRec);
50 {
51 SkScalerContext::Rec* rec = (SkScalerContext::Rec*)entry;
52 rec->fTextSize = STD_SIZE;
53 rec->fPreScaleX = SK_Scalar1;
54 rec->fPreSkewX = 0;
55 rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
56 rec->fPost2x2[1][0] = rec->fPost2x2[0][1] = 0;
57 }
58 SkASSERT(descSize == newDesc->getLength());
59 newDesc->computeChecksum();
60
61 fProxy = face->proxy()->createScalerContext(newDesc);
62
63 fRec.getSingleMatrix(&fMatrix);
64 fMatrix.preScale(SK_Scalar1 / STD_SIZE, SK_Scalar1 / STD_SIZE);
65}
66
67SkGScalerContext::~SkGScalerContext() {
68 SkDELETE(fProxy);
69}
70
71unsigned SkGScalerContext::generateGlyphCount() {
72 return fProxy->getGlyphCount();
73}
74
75uint16_t SkGScalerContext::generateCharToGlyph(SkUnichar uni) {
76 return fProxy->charToGlyphID(uni);
77}
78
79void SkGScalerContext::generateAdvance(SkGlyph* glyph) {
80 fProxy->getAdvance(glyph);
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +000081
reed@google.com7edec142013-05-31 20:17:57 +000082 SkVector advance;
83 fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX),
84 SkFixedToScalar(glyph->fAdvanceY), &advance);
85 glyph->fAdvanceX = SkScalarToFixed(advance.fX);
86 glyph->fAdvanceY = SkScalarToFixed(advance.fY);
87}
88
89void SkGScalerContext::generateMetrics(SkGlyph* glyph) {
90 fProxy->getMetrics(glyph);
91
92 SkVector advance;
93 fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX),
94 SkFixedToScalar(glyph->fAdvanceY), &advance);
95 glyph->fAdvanceX = SkScalarToFixed(advance.fX);
96 glyph->fAdvanceY = SkScalarToFixed(advance.fY);
97
98 SkPath path;
99 fProxy->getPath(*glyph, &path);
100 path.transform(fMatrix);
101
102 SkRect storage;
103 const SkPaint& paint = fFace->paint();
104 const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
105 &storage,
106 SkPaint::kFill_Style);
107 SkIRect ibounds;
108 newBounds.roundOut(&ibounds);
109 glyph->fLeft = ibounds.fLeft;
110 glyph->fTop = ibounds.fTop;
111 glyph->fWidth = ibounds.width();
112 glyph->fHeight = ibounds.height();
113 glyph->fMaskFormat = SkMask::kARGB32_Format;
114}
115
116void SkGScalerContext::generateImage(const SkGlyph& glyph) {
117 if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
118 SkPath path;
119 fProxy->getPath(glyph, &path);
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000120
reed@google.com7edec142013-05-31 20:17:57 +0000121 SkBitmap bm;
122 bm.setConfig(SkBitmap::kARGB_8888_Config, glyph.fWidth, glyph.fHeight,
123 glyph.rowBytes());
124 bm.setPixels(glyph.fImage);
125 bm.eraseColor(0);
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000126
reed@google.com7edec142013-05-31 20:17:57 +0000127 SkCanvas canvas(bm);
reed@google.com1b6a04f2013-05-31 21:06:03 +0000128 canvas.translate(-SkIntToScalar(glyph.fLeft),
129 -SkIntToScalar(glyph.fTop));
reed@google.com7edec142013-05-31 20:17:57 +0000130 canvas.concat(fMatrix);
131 canvas.drawPath(path, fFace->paint());
132 } else {
133 fProxy->getImage(glyph);
134 }
135}
136
137void SkGScalerContext::generatePath(const SkGlyph& glyph, SkPath* path) {
138 fProxy->getPath(glyph, path);
139 path->transform(fMatrix);
140}
141
142void SkGScalerContext::generateFontMetrics(SkPaint::FontMetrics*,
143 SkPaint::FontMetrics* metrics) {
144 fProxy->getFontMetrics(metrics);
145 if (metrics) {
146 SkScalar scale = fMatrix.getScaleY();
147 metrics->fTop = SkScalarMul(metrics->fTop, scale);
148 metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
149 metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
150 metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
151 metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
152 metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
153 metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
154 metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
155 metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
156 }
157}
158
159///////////////////////////////////////////////////////////////////////////////
160
161#include "SkTypefaceCache.h"
162
163SkGTypeface::SkGTypeface(SkTypeface* proxy, const SkPaint& paint)
164 : SkTypeface(proxy->style(), SkTypefaceCache::NewFontID(), false)
165 , fProxy(SkRef(proxy))
166 , fPaint(paint) {}
167
168SkGTypeface::~SkGTypeface() {
169 fProxy->unref();
170}
171
172SkScalerContext* SkGTypeface::onCreateScalerContext(
173 const SkDescriptor* desc) const {
174 return SkNEW_ARGS(SkGScalerContext, (const_cast<SkGTypeface*>(this), desc));
175}
176
177void SkGTypeface::onFilterRec(SkScalerContextRec* rec) const {
178 fProxy->filterRec(rec);
rmistry@google.comd6bab022013-12-02 13:50:38 +0000179 rec->setHinting(SkPaint::kNo_Hinting);
180 rec->fMaskFormat = SkMask::kARGB32_Format;
reed@google.com7edec142013-05-31 20:17:57 +0000181}
182
183SkAdvancedTypefaceMetrics* SkGTypeface::onGetAdvancedTypefaceMetrics(
184 SkAdvancedTypefaceMetrics::PerGlyphInfo info,
185 const uint32_t* glyphIDs,
186 uint32_t glyphIDsCount) const {
187 return fProxy->getAdvancedTypefaceMetrics(info, glyphIDs, glyphIDsCount);
188}
189
190SkStream* SkGTypeface::onOpenStream(int* ttcIndex) const {
191 return fProxy->openStream(ttcIndex);
192}
193
194void SkGTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
195 bool* isLocal) const {
196 fProxy->getFontDescriptor(desc, isLocal);
197}
198
bungeman@google.com3c996f82013-10-24 21:39:35 +0000199int SkGTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
200 uint16_t glyphs[], int glyphCount) const {
201 return fProxy->charsToGlyphs(chars, encoding, glyphs, glyphCount);
202}
203
bungeman@google.come05e75e2013-07-15 19:52:13 +0000204int SkGTypeface::onCountGlyphs() const {
205 return fProxy->countGlyphs();
206}
207
reed@google.com7edec142013-05-31 20:17:57 +0000208int SkGTypeface::onGetUPEM() const {
209 return fProxy->getUnitsPerEm();
210}
211
bungeman@google.com839702b2013-08-07 17:09:22 +0000212SkTypeface::LocalizedStrings* SkGTypeface::onCreateFamilyNameIterator() const {
213 return fProxy->createFamilyNameIterator();
bungeman@google.coma9802692013-08-07 02:45:25 +0000214}
215
reed@google.com7edec142013-05-31 20:17:57 +0000216int SkGTypeface::onGetTableTags(SkFontTableTag tags[]) const {
217 return fProxy->getTableTags(tags);
218}
219
220size_t SkGTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
221 size_t length, void* data) const {
222 return fProxy->getTableData(tag, offset, length, data);
223}
224
225///////////////////////////////////////////////////////////////////////////////
226
227#if 0
228// under construction -- defining a font purely in terms of skia primitives
229// ala an SVG-font.
230class SkGFont : public SkRefCnt {
231public:
232 virtual ~SkGFont();
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000233
reed@google.com7edec142013-05-31 20:17:57 +0000234 int unicharToGlyph(SkUnichar) const;
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000235
reed@google.com7edec142013-05-31 20:17:57 +0000236 int countGlyphs() const { return fCount; }
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000237
reed@google.com7edec142013-05-31 20:17:57 +0000238 float getAdvance(int index) const {
239 SkASSERT((unsigned)index < (unsigned)fCount);
240 return fGlyphs[index].fAdvance;
241 }
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000242
reed@google.com7edec142013-05-31 20:17:57 +0000243 const SkPath& getPath(int index) const {
244 SkASSERT((unsigned)index < (unsigned)fCount);
245 return fGlyphs[index].fPath;
246 }
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000247
reed@google.com7edec142013-05-31 20:17:57 +0000248private:
249 struct Glyph {
250 SkUnichar fUni;
251 float fAdvance;
252 SkPath fPath;
253 };
254 int fCount;
255 Glyph* fGlyphs;
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000256
reed@google.com7edec142013-05-31 20:17:57 +0000257 friend class SkGFontBuilder;
258 SkGFont(int count, Glyph* array);
259};
260
261class SkGFontBuilder {
262public:
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000263
reed@google.com7edec142013-05-31 20:17:57 +0000264};
265#endif