blob: 9da05492e6ce2d64ca7b43b0d283881de59404c6 [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
bungeman7cfd46a2016-10-20 16:06:52 -04008#include "SkCanvas.h"
reeda9322c22016-04-12 06:47:05 -07009#include "SkDescriptor.h"
reed@google.com7edec142013-05-31 20:17:57 +000010#include "SkGScalerContext.h"
11#include "SkGlyph.h"
12#include "SkPath.h"
bungeman7cfd46a2016-10-20 16:06:52 -040013#include "SkMakeUnique.h"
reed@google.com7edec142013-05-31 20:17:57 +000014
reeda9322c22016-04-12 06:47:05 -070015#define STD_SIZE 1
16
reed@google.com7edec142013-05-31 20:17:57 +000017class SkGScalerContext : public SkScalerContext {
18public:
bungeman7cfd46a2016-10-20 16:06:52 -040019 SkGScalerContext(sk_sp<SkGTypeface> face, const SkScalerContextEffects& effects,
reeda9322c22016-04-12 06:47:05 -070020 const SkDescriptor* desc)
bungeman7cfd46a2016-10-20 16:06:52 -040021 : SkScalerContext(std::move(face), effects, desc)
reeda9322c22016-04-12 06:47:05 -070022 {
bungeman7cfd46a2016-10-20 16:06:52 -040023
reeda9322c22016-04-12 06:47:05 -070024 size_t descSize = SkDescriptor::ComputeOverhead(1) + sizeof(SkScalerContext::Rec);
25 SkAutoDescriptor ad(descSize);
26 SkDescriptor* newDesc = ad.getDesc();
bungeman7cfd46a2016-10-20 16:06:52 -040027
reeda9322c22016-04-12 06:47:05 -070028 newDesc->init();
29 void* entry = newDesc->addEntry(kRec_SkDescriptorTag,
30 sizeof(SkScalerContext::Rec), &fRec);
31 {
32 SkScalerContext::Rec* rec = (SkScalerContext::Rec*)entry;
33 rec->fTextSize = STD_SIZE;
34 rec->fPreScaleX = SK_Scalar1;
35 rec->fPreSkewX = 0;
36 rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
37 rec->fPost2x2[1][0] = rec->fPost2x2[0][1] = 0;
38 }
39 SkASSERT(descSize == newDesc->getLength());
40 newDesc->computeChecksum();
bungeman7cfd46a2016-10-20 16:06:52 -040041
42 fProxy = this->getGTypeface()->proxy()->createScalerContext(effects, newDesc);
43
reeda9322c22016-04-12 06:47:05 -070044 fRec.getSingleMatrix(&fMatrix);
45 fMatrix.preScale(SK_Scalar1 / STD_SIZE, SK_Scalar1 / STD_SIZE);
46 }
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +000047
reed@google.com7edec142013-05-31 20:17:57 +000048protected:
bungeman7cfd46a2016-10-20 16:06:52 -040049 SkGTypeface* getGTypeface() { return static_cast<SkGTypeface*>(this->getTypeface()); }
50
mtklein36352bf2015-03-25 18:17:31 -070051 unsigned generateGlyphCount() override;
52 uint16_t generateCharToGlyph(SkUnichar) override;
53 void generateAdvance(SkGlyph*) override;
54 void generateMetrics(SkGlyph*) override;
55 void generateImage(const SkGlyph&) override;
Ben Wagner6e9ac122016-11-11 14:31:06 -050056 void generatePath(SkGlyphID, SkPath*) override;
mtklein36352bf2015-03-25 18:17:31 -070057 void generateFontMetrics(SkPaint::FontMetrics*) override;
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +000058
reed@google.com7edec142013-05-31 20:17:57 +000059private:
bungeman7cfd46a2016-10-20 16:06:52 -040060 std::unique_ptr<SkScalerContext> fProxy;
reed@google.com7edec142013-05-31 20:17:57 +000061 SkMatrix fMatrix;
62};
63
reed@google.com7edec142013-05-31 20:17:57 +000064unsigned SkGScalerContext::generateGlyphCount() {
65 return fProxy->getGlyphCount();
66}
67
68uint16_t SkGScalerContext::generateCharToGlyph(SkUnichar uni) {
69 return fProxy->charToGlyphID(uni);
70}
71
72void SkGScalerContext::generateAdvance(SkGlyph* glyph) {
73 fProxy->getAdvance(glyph);
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +000074
reed@google.com7edec142013-05-31 20:17:57 +000075 SkVector advance;
benjaminwagner6b3eacb2016-03-24 19:07:58 -070076 fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX),
77 SkFloatToScalar(glyph->fAdvanceY), &advance);
78 glyph->fAdvanceX = SkScalarToFloat(advance.fX);
79 glyph->fAdvanceY = SkScalarToFloat(advance.fY);
reed@google.com7edec142013-05-31 20:17:57 +000080}
81
82void SkGScalerContext::generateMetrics(SkGlyph* glyph) {
83 fProxy->getMetrics(glyph);
84
85 SkVector advance;
benjaminwagner6b3eacb2016-03-24 19:07:58 -070086 fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX),
87 SkFloatToScalar(glyph->fAdvanceY), &advance);
88 glyph->fAdvanceX = SkScalarToFloat(advance.fX);
89 glyph->fAdvanceY = SkScalarToFloat(advance.fY);
reed@google.com7edec142013-05-31 20:17:57 +000090
91 SkPath path;
Ben Wagner6e9ac122016-11-11 14:31:06 -050092 fProxy->getPath(glyph->getPackedID(), &path);
reed@google.com7edec142013-05-31 20:17:57 +000093 path.transform(fMatrix);
94
95 SkRect storage;
bungeman7cfd46a2016-10-20 16:06:52 -040096 const SkPaint& paint = this->getGTypeface()->paint();
reed@google.com7edec142013-05-31 20:17:57 +000097 const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
98 &storage,
99 SkPaint::kFill_Style);
100 SkIRect ibounds;
101 newBounds.roundOut(&ibounds);
102 glyph->fLeft = ibounds.fLeft;
103 glyph->fTop = ibounds.fTop;
104 glyph->fWidth = ibounds.width();
105 glyph->fHeight = ibounds.height();
106 glyph->fMaskFormat = SkMask::kARGB32_Format;
107}
108
109void SkGScalerContext::generateImage(const SkGlyph& glyph) {
110 if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
111 SkPath path;
Ben Wagner6e9ac122016-11-11 14:31:06 -0500112 fProxy->getPath(glyph.getPackedID(), &path);
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000113
reed@google.com7edec142013-05-31 20:17:57 +0000114 SkBitmap bm;
reed6c225732014-06-09 19:52:07 -0700115 bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
116 glyph.fImage, glyph.rowBytes());
reed@google.com7edec142013-05-31 20:17:57 +0000117 bm.eraseColor(0);
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000118
reed@google.com7edec142013-05-31 20:17:57 +0000119 SkCanvas canvas(bm);
reed@google.com1b6a04f2013-05-31 21:06:03 +0000120 canvas.translate(-SkIntToScalar(glyph.fLeft),
121 -SkIntToScalar(glyph.fTop));
reed@google.com7edec142013-05-31 20:17:57 +0000122 canvas.concat(fMatrix);
bungeman7cfd46a2016-10-20 16:06:52 -0400123 canvas.drawPath(path, this->getGTypeface()->paint());
reed@google.com7edec142013-05-31 20:17:57 +0000124 } else {
125 fProxy->getImage(glyph);
126 }
127}
128
Ben Wagner6e9ac122016-11-11 14:31:06 -0500129void SkGScalerContext::generatePath(SkGlyphID glyph, SkPath* path) {
130 fProxy->getPath(SkPackedGlyphID(glyph), path);
reed@google.com7edec142013-05-31 20:17:57 +0000131 path->transform(fMatrix);
132}
133
bungeman41078062014-07-07 08:16:37 -0700134void SkGScalerContext::generateFontMetrics(SkPaint::FontMetrics* metrics) {
reed@google.com7edec142013-05-31 20:17:57 +0000135 fProxy->getFontMetrics(metrics);
136 if (metrics) {
137 SkScalar scale = fMatrix.getScaleY();
138 metrics->fTop = SkScalarMul(metrics->fTop, scale);
139 metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
140 metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
141 metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
142 metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
143 metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
144 metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
145 metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
146 metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
147 }
148}
149
150///////////////////////////////////////////////////////////////////////////////
151
152#include "SkTypefaceCache.h"
153
bungeman13b9c952016-05-12 10:09:30 -0700154SkGTypeface::SkGTypeface(sk_sp<SkTypeface> proxy, const SkPaint& paint)
bungemane3aea102016-07-13 05:16:58 -0700155 : SkTypeface(proxy->fontStyle(), false)
bungeman13b9c952016-05-12 10:09:30 -0700156 , fProxy(std::move(proxy))
157 , fPaint(paint)
158{}
reed@google.com7edec142013-05-31 20:17:57 +0000159
reeda9322c22016-04-12 06:47:05 -0700160SkScalerContext* SkGTypeface::onCreateScalerContext(const SkScalerContextEffects& effects,
161 const SkDescriptor* desc) const {
bungeman7cfd46a2016-10-20 16:06:52 -0400162 return new SkGScalerContext(sk_ref_sp(const_cast<SkGTypeface*>(this)), effects, desc);
reed@google.com7edec142013-05-31 20:17:57 +0000163}
164
165void SkGTypeface::onFilterRec(SkScalerContextRec* rec) const {
166 fProxy->filterRec(rec);
rmistry@google.comd6bab022013-12-02 13:50:38 +0000167 rec->setHinting(SkPaint::kNo_Hinting);
168 rec->fMaskFormat = SkMask::kARGB32_Format;
reed@google.com7edec142013-05-31 20:17:57 +0000169}
170
171SkAdvancedTypefaceMetrics* SkGTypeface::onGetAdvancedTypefaceMetrics(
reed39a9a502015-05-12 09:50:04 -0700172 PerGlyphInfo info,
reed@google.com7edec142013-05-31 20:17:57 +0000173 const uint32_t* glyphIDs,
174 uint32_t glyphIDsCount) const {
175 return fProxy->getAdvancedTypefaceMetrics(info, glyphIDs, glyphIDsCount);
176}
177
bungeman5f213d92015-01-27 05:39:10 -0800178SkStreamAsset* SkGTypeface::onOpenStream(int* ttcIndex) const {
reed@google.com7edec142013-05-31 20:17:57 +0000179 return fProxy->openStream(ttcIndex);
180}
181
182void SkGTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
183 bool* isLocal) const {
184 fProxy->getFontDescriptor(desc, isLocal);
185}
186
bungeman@google.com3c996f82013-10-24 21:39:35 +0000187int SkGTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
188 uint16_t glyphs[], int glyphCount) const {
189 return fProxy->charsToGlyphs(chars, encoding, glyphs, glyphCount);
190}
191
bungeman@google.come05e75e2013-07-15 19:52:13 +0000192int SkGTypeface::onCountGlyphs() const {
193 return fProxy->countGlyphs();
194}
195
reed@google.com7edec142013-05-31 20:17:57 +0000196int SkGTypeface::onGetUPEM() const {
197 return fProxy->getUnitsPerEm();
198}
199
bungemanb374d6a2014-09-17 07:48:59 -0700200void SkGTypeface::onGetFamilyName(SkString* familyName) const {
201 fProxy->getFamilyName(familyName);
202}
203
bungeman@google.com839702b2013-08-07 17:09:22 +0000204SkTypeface::LocalizedStrings* SkGTypeface::onCreateFamilyNameIterator() const {
205 return fProxy->createFamilyNameIterator();
bungeman@google.coma9802692013-08-07 02:45:25 +0000206}
207
reed@google.com7edec142013-05-31 20:17:57 +0000208int SkGTypeface::onGetTableTags(SkFontTableTag tags[]) const {
209 return fProxy->getTableTags(tags);
210}
211
212size_t SkGTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
213 size_t length, void* data) const {
214 return fProxy->getTableData(tag, offset, length, data);
215}
216
217///////////////////////////////////////////////////////////////////////////////
218
219#if 0
220// under construction -- defining a font purely in terms of skia primitives
221// ala an SVG-font.
222class SkGFont : public SkRefCnt {
223public:
224 virtual ~SkGFont();
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000225
reed@google.com7edec142013-05-31 20:17:57 +0000226 int unicharToGlyph(SkUnichar) const;
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000227
reed@google.com7edec142013-05-31 20:17:57 +0000228 int countGlyphs() const { return fCount; }
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000229
reed@google.com7edec142013-05-31 20:17:57 +0000230 float getAdvance(int index) const {
231 SkASSERT((unsigned)index < (unsigned)fCount);
232 return fGlyphs[index].fAdvance;
233 }
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000234
reed@google.com7edec142013-05-31 20:17:57 +0000235 const SkPath& getPath(int index) const {
236 SkASSERT((unsigned)index < (unsigned)fCount);
237 return fGlyphs[index].fPath;
238 }
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000239
reed@google.com7edec142013-05-31 20:17:57 +0000240private:
241 struct Glyph {
242 SkUnichar fUni;
243 float fAdvance;
244 SkPath fPath;
245 };
246 int fCount;
247 Glyph* fGlyphs;
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000248
reed@google.com7edec142013-05-31 20:17:57 +0000249 friend class SkGFontBuilder;
250 SkGFont(int count, Glyph* array);
251};
252
253class SkGFontBuilder {
254public:
skia.committer@gmail.com26da7f02013-06-01 07:01:39 +0000255
reed@google.com7edec142013-05-31 20:17:57 +0000256};
257#endif