blob: 568f09563ff513d3d1a223fdc4b0833451aa9831 [file] [log] [blame]
jvanverth@google.comd830d132013-11-11 20:54:09 +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 "GrDistanceFieldTextContext.h"
9#include "GrAtlas.h"
10#include "GrDrawTarget.h"
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +000011#include "GrDrawTargetCaps.h"
jvanverth@google.comd830d132013-11-11 20:54:09 +000012#include "GrFontScaler.h"
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +000013#include "SkGlyphCache.h"
jvanverth@google.comd830d132013-11-11 20:54:09 +000014#include "GrIndexBuffer.h"
15#include "GrTextStrike.h"
16#include "GrTextStrike_impl.h"
commit-bot@chromium.org9f94b912014-01-30 15:22:54 +000017#include "SkDraw.h"
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +000018#include "SkGpuDevice.h"
jvanverth@google.comd830d132013-11-11 20:54:09 +000019#include "SkPath.h"
20#include "SkRTConf.h"
21#include "SkStrokeRec.h"
22#include "effects/GrDistanceFieldTextureEffect.h"
23
24static const int kGlyphCoordsAttributeIndex = 1;
25
commit-bot@chromium.orgdc5cd852014-04-02 19:24:32 +000026static const int kSmallDFFontSize = 32;
27static const int kSmallDFFontLimit = 32;
28static const int kMediumDFFontSize = 64;
29static const int kMediumDFFontLimit = 64;
30static const int kLargeDFFontSize = 128;
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +000031
jvanverth@google.comd830d132013-11-11 20:54:09 +000032SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
33 "Dump the contents of the font cache before every purge.");
34
commit-bot@chromium.orgae796122014-03-12 17:05:46 +000035#if SK_FORCE_DISTANCEFIELD_FONTS
36static const bool kForceDistanceFieldFonts = true;
37#else
38static const bool kForceDistanceFieldFonts = false;
39#endif
40
skia.committer@gmail.come5d70152014-01-29 07:01:48 +000041GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +000042 const SkDeviceProperties& properties)
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +000043 : GrTextContext(context, properties) {
jvanverth@google.comd830d132013-11-11 20:54:09 +000044 fStrike = NULL;
45
46 fCurrTexture = NULL;
47 fCurrVertex = 0;
48
49 fVertices = NULL;
50 fMaxVertices = 0;
51}
52
53GrDistanceFieldTextContext::~GrDistanceFieldTextContext() {
54 this->flushGlyphs();
55}
56
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +000057bool GrDistanceFieldTextContext::canDraw(const SkPaint& paint) {
commit-bot@chromium.orgeefd8a02014-04-08 20:14:32 +000058 if (!kForceDistanceFieldFonts && !paint.isDistanceFieldTextTEMP()) {
59 return false;
60 }
61
skia.committer@gmail.come1d94432014-04-09 03:04:11 +000062 // rasterizers and mask filters modify alpha, which doesn't
commit-bot@chromium.orgeefd8a02014-04-08 20:14:32 +000063 // translate well to distance
64 if (paint.getRasterizer() || paint.getMaskFilter() ||
65 !fContext->getTextTarget()->caps()->shaderDerivativeSupport()) {
66 return false;
67 }
68
69 // TODO: add some stroking support
70 if (paint.getStyle() != SkPaint::kFill_Style) {
71 return false;
72 }
73
74 // TODO: choose an appropriate maximum scale for distance fields and
75 // enable perspective
76 if (SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix())) {
77 return false;
78 }
79
80 // distance fields cannot represent color fonts
81 SkScalerContext::Rec rec;
82 SkScalerContext::MakeRec(paint, &fDeviceProperties, NULL, &rec);
83 return rec.getFormat() != SkMask::kARGB32_Format;
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +000084}
85
jvanverth@google.comd830d132013-11-11 20:54:09 +000086static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
87 unsigned r = SkColorGetR(c);
88 unsigned g = SkColorGetG(c);
89 unsigned b = SkColorGetB(c);
90 return GrColorPackRGBA(r, g, b, 0xff);
91}
92
93void GrDistanceFieldTextContext::flushGlyphs() {
94 if (NULL == fDrawTarget) {
95 return;
96 }
97
98 GrDrawState* drawState = fDrawTarget->drawState();
99 GrDrawState::AutoRestoreEffects are(drawState);
100 drawState->setFromPaint(fPaint, fContext->getMatrix(), fContext->getRenderTarget());
101
102 if (fCurrVertex > 0) {
103 // setup our sampler state for our text texture/atlas
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000104 SkASSERT(SkIsAlign4(fCurrVertex));
jvanverth@google.comd830d132013-11-11 20:54:09 +0000105 SkASSERT(fCurrTexture);
106 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode);
107
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000108 // Effects could be stored with one of the cache objects (atlas?)
109 if (fUseLCDText) {
110 bool useBGR = SkDeviceProperties::Geometry::kBGR_Layout ==
111 fDeviceProperties.fGeometry.getLayout();
112 drawState->addCoverageEffect(GrDistanceFieldLCDTextureEffect::Create(
113 fCurrTexture,
114 params,
115 fContext->getMatrix().rectStaysRect() &&
116 fContext->getMatrix().isSimilarity(),
117 useBGR),
118 kGlyphCoordsAttributeIndex)->unref();
jvanverth@google.comd830d132013-11-11 20:54:09 +0000119
jvanverth@google.comd830d132013-11-11 20:54:09 +0000120 if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
121 kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
122 fPaint.numColorStages()) {
123 GrPrintf("LCD Text will not draw correctly.\n");
124 }
125 // We don't use the GrPaint's color in this case because it's been premultiplied by
126 // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
127 // the mask texture color. The end result is that we get
128 // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000129 int a = SkColorGetA(fSkPaint.getColor());
jvanverth@google.comd830d132013-11-11 20:54:09 +0000130 // paintAlpha
131 drawState->setColor(SkColorSetARGB(a, a, a, a));
132 // paintColor
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000133 drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor()));
jvanverth@google.comd830d132013-11-11 20:54:09 +0000134 drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
135 } else {
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000136 drawState->addCoverageEffect(GrDistanceFieldTextureEffect::Create(fCurrTexture, params,
137 fContext->getMatrix().isSimilarity()),
138 kGlyphCoordsAttributeIndex)->unref();
139
jvanverth@google.comd830d132013-11-11 20:54:09 +0000140 // set back to normal in case we took LCD path previously.
141 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
142 drawState->setColor(fPaint.getColor());
143 }
144
145 int nGlyphs = fCurrVertex / 4;
146 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
147 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
148 nGlyphs,
149 4, 6);
150 fDrawTarget->resetVertexSource();
151 fVertices = NULL;
152 fMaxVertices = 0;
153 fCurrVertex = 0;
154 SkSafeSetNull(fCurrTexture);
155 }
156}
157
158namespace {
159
160// position + texture coord
161extern const GrVertexAttrib gTextVertexAttribs[] = {
162 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000163 {kVec2f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding}
jvanverth@google.comd830d132013-11-11 20:54:09 +0000164};
165
166};
167
168void GrDistanceFieldTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000169 SkFixed vx, SkFixed vy,
jvanverth@google.comd830d132013-11-11 20:54:09 +0000170 GrFontScaler* scaler) {
171 if (NULL == fDrawTarget) {
172 return;
173 }
174 if (NULL == fStrike) {
175 fStrike = fContext->getFontCache()->getStrike(scaler, true);
176 }
177
178 GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
179 if (NULL == glyph || glyph->fBounds.isEmpty()) {
180 return;
181 }
182
183 SkScalar sx = SkFixedToScalar(vx);
184 SkScalar sy = SkFixedToScalar(vy);
185/*
186 // not valid, need to find a different solution for this
187 vx += SkIntToFixed(glyph->fBounds.fLeft);
188 vy += SkIntToFixed(glyph->fBounds.fTop);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000189
jvanverth@google.comd830d132013-11-11 20:54:09 +0000190 // keep them as ints until we've done the clip-test
191 GrFixed width = glyph->fBounds.width();
192 GrFixed height = glyph->fBounds.height();
193
194 // check if we clipped out
195 if (true || NULL == glyph->fPlot) {
196 int x = vx >> 16;
197 int y = vy >> 16;
198 if (fClipRect.quickReject(x, y, x + width, y + height)) {
199// SkCLZ(3); // so we can set a break-point in the debugger
200 return;
201 }
202 }
203*/
204 if (NULL == glyph->fPlot) {
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000205 if (fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comd830d132013-11-11 20:54:09 +0000206 goto HAS_ATLAS;
207 }
208
209 // try to clear out an unused plot before we flush
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000210 if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
211 fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comd830d132013-11-11 20:54:09 +0000212 goto HAS_ATLAS;
213 }
214
215 if (c_DumpFontCache) {
216#ifdef SK_DEVELOPER
217 fContext->getFontCache()->dump();
218#endif
219 }
220
221 // before we purge the cache, we must flush any accumulated draws
222 this->flushGlyphs();
223 fContext->flush();
224
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000225 // we should have an unused plot now
226 if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
227 fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comd830d132013-11-11 20:54:09 +0000228 goto HAS_ATLAS;
229 }
230
231 if (NULL == glyph->fPath) {
232 SkPath* path = SkNEW(SkPath);
233 if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
234 // flag the glyph as being dead?
235 delete path;
236 return;
237 }
238 glyph->fPath = path;
239 }
240
241 GrContext::AutoMatrix am;
242 SkMatrix translate;
243 translate.setTranslate(sx, sy);
244 GrPaint tmpPaint(fPaint);
245 am.setPreConcat(fContext, translate, &tmpPaint);
246 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
247 fContext->drawPath(tmpPaint, *glyph->fPath, stroke);
248 return;
249 }
250
251HAS_ATLAS:
252 SkASSERT(glyph->fPlot);
253 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken();
254 glyph->fPlot->setDrawToken(drawToken);
255
256 GrTexture* texture = glyph->fPlot->texture();
257 SkASSERT(texture);
258
259 if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) {
260 this->flushGlyphs();
261 fCurrTexture = texture;
262 fCurrTexture->ref();
263 }
264
265 if (NULL == fVertices) {
266 // If we need to reserve vertices allow the draw target to suggest
267 // a number of verts to reserve and whether to perform a flush.
268 fMaxVertices = kMinRequestedVerts;
269 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
270 SK_ARRAY_COUNT(gTextVertexAttribs));
271 bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL);
272 if (flush) {
273 this->flushGlyphs();
274 fContext->flush();
275 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
276 SK_ARRAY_COUNT(gTextVertexAttribs));
277 }
278 fMaxVertices = kDefaultRequestedVerts;
279 // ignore return, no point in flushing again.
280 fDrawTarget->geometryHints(&fMaxVertices, NULL);
281
282 int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads();
283 if (fMaxVertices < kMinRequestedVerts) {
284 fMaxVertices = kDefaultRequestedVerts;
285 } else if (fMaxVertices > maxQuadVertices) {
286 // don't exceed the limit of the index buffer
287 fMaxVertices = maxQuadVertices;
288 }
289 bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices,
290 0,
291 GrTCast<void**>(&fVertices),
292 NULL);
293 GrAlwaysAssert(success);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000294 SkASSERT(2*sizeof(SkPoint) == fDrawTarget->getDrawState().getVertexSize());
jvanverth@google.comd830d132013-11-11 20:54:09 +0000295 }
296
297 SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft);
298 SkScalar dy = SkIntToScalar(glyph->fBounds.fTop);
299 SkScalar width = SkIntToScalar(glyph->fBounds.width());
300 SkScalar height = SkIntToScalar(glyph->fBounds.height());
301
302 SkScalar scale = fTextRatio;
303 dx *= scale;
304 dy *= scale;
305 sx += dx;
306 sy += dy;
307 width *= scale;
308 height *= scale;
skia.committer@gmail.coma3b53272014-02-15 03:02:15 +0000309
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000310 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX);
311 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY);
312 SkFixed tw = SkIntToFixed(glyph->fBounds.width());
313 SkFixed th = SkIntToFixed(glyph->fBounds.height());
jvanverth@google.comd830d132013-11-11 20:54:09 +0000314
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000315 static const size_t kVertexSize = 2 * sizeof(SkPoint);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000316 fVertices[2*fCurrVertex].setRectFan(sx,
317 sy,
318 sx + width,
319 sy + height,
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000320 kVertexSize);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000321 fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)),
322 SkFixedToFloat(texture->normalizeFixedY(ty)),
323 SkFixedToFloat(texture->normalizeFixedX(tx + tw)),
324 SkFixedToFloat(texture->normalizeFixedY(ty + th)),
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000325 kVertexSize);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000326 fCurrVertex += 4;
327}
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000328
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000329inline void GrDistanceFieldTextContext::init(const GrPaint& paint, const SkPaint& skPaint) {
330 GrTextContext::init(paint, skPaint);
331
332 fStrike = NULL;
333
334 fCurrTexture = NULL;
335 fCurrVertex = 0;
336
337 fVertices = NULL;
338 fMaxVertices = 0;
339
commit-bot@chromium.orgdc5cd852014-04-02 19:24:32 +0000340 if (fSkPaint.getTextSize() <= kSmallDFFontLimit) {
341 fTextRatio = fSkPaint.getTextSize()/kSmallDFFontSize;
342 fSkPaint.setTextSize(SkIntToScalar(kSmallDFFontSize));
343 } else if (fSkPaint.getTextSize() <= kMediumDFFontLimit) {
344 fTextRatio = fSkPaint.getTextSize()/kMediumDFFontSize;
345 fSkPaint.setTextSize(SkIntToScalar(kMediumDFFontSize));
346 } else {
347 fTextRatio = fSkPaint.getTextSize()/kLargeDFFontSize;
348 fSkPaint.setTextSize(SkIntToScalar(kLargeDFFontSize));
349 }
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000350
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000351 fUseLCDText = fSkPaint.isLCDRenderText();
skia.committer@gmail.com221b9112014-04-04 03:04:32 +0000352
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000353 fSkPaint.setLCDRenderText(false);
354 fSkPaint.setAutohinted(false);
commit-bot@chromium.org0bed43c2014-03-14 21:22:38 +0000355 fSkPaint.setSubpixelText(true);
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000356}
357
358inline void GrDistanceFieldTextContext::finish() {
359 flushGlyphs();
360
361 GrTextContext::finish();
362}
363
364void GrDistanceFieldTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
365 const char text[], size_t byteLength,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000366 SkScalar x, SkScalar y) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000367 SkASSERT(byteLength == 0 || text != NULL);
368
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000369 // nothing to draw or can't draw
370 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/
371 || fSkPaint.getRasterizer()) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000372 return;
373 }
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000374
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000375 this->init(paint, skPaint);
376
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000377 SkScalar sizeRatio = fTextRatio;
378
379 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
380
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000381 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, NULL);
382 SkGlyphCache* cache = autoCache.getCache();
383 GrFontScaler* fontScaler = GetGrFontScaler(cache);
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000384
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000385 // need to measure first
386 // TODO - generate positions and pre-load cache as well?
387 const char* stop = text + byteLength;
388 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
389 SkFixed stopX = 0;
390 SkFixed stopY = 0;
391
392 const char* textPtr = text;
393 while (textPtr < stop) {
394 // don't need x, y here, since all subpixel variants will have the
395 // same advance
396 const SkGlyph& glyph = glyphCacheProc(cache, &textPtr, 0, 0);
397
398 stopX += glyph.fAdvanceX;
399 stopY += glyph.fAdvanceY;
400 }
401 SkASSERT(textPtr == stop);
402
403 SkScalar alignX = SkFixedToScalar(stopX)*sizeRatio;
404 SkScalar alignY = SkFixedToScalar(stopY)*sizeRatio;
405
406 if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
407 alignX = SkScalarHalf(alignX);
408 alignY = SkScalarHalf(alignY);
409 }
410
411 x -= alignX;
412 y -= alignY;
413 }
414
415 SkFixed fx = SkScalarToFixed(x) + SK_FixedHalf;
416 SkFixed fy = SkScalarToFixed(y) + SK_FixedHalf;
417 SkFixed fixedScale = SkScalarToFixed(sizeRatio);
418 while (text < stop) {
commit-bot@chromium.orga9dae712014-03-24 18:34:04 +0000419 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000420
421 if (glyph.fWidth) {
422 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
423 glyph.getSubXFixed(),
424 glyph.getSubYFixed()),
425 SkFixedFloorToFixed(fx),
426 SkFixedFloorToFixed(fy),
427 fontScaler);
428 }
429
430 fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale);
431 fy += SkFixedMul_portable(glyph.fAdvanceY, fixedScale);
432 }
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000433
434 this->finish();
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000435}
436
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000437void GrDistanceFieldTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPaint,
438 const char text[], size_t byteLength,
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000439 const SkScalar pos[], SkScalar constY,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000440 int scalarsPerPosition) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000441
442 SkASSERT(byteLength == 0 || text != NULL);
443 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
444
445 // nothing to draw
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000446 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000447 return;
448 }
449
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000450 this->init(paint, skPaint);
451
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000452 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
453
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000454 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, NULL);
455 SkGlyphCache* cache = autoCache.getCache();
456 GrFontScaler* fontScaler = GetGrFontScaler(cache);
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000457
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000458 const char* stop = text + byteLength;
459
460 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
461 while (text < stop) {
462 // the last 2 parameters are ignored
463 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
464
465 if (glyph.fWidth) {
466 SkScalar x = pos[0];
467 SkScalar y = scalarsPerPosition == 1 ? constY : pos[1];
468
469 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
470 glyph.getSubXFixed(),
471 glyph.getSubYFixed()),
472 SkScalarToFixed(x) + SK_FixedHalf, //d1g.fHalfSampleX,
473 SkScalarToFixed(y) + SK_FixedHalf, //d1g.fHalfSampleY,
474 fontScaler);
475 }
476 pos += scalarsPerPosition;
477 }
478 } else {
479 int alignShift = SkPaint::kCenter_Align == fSkPaint.getTextAlign() ? 1 : 0;
480 while (text < stop) {
481 // the last 2 parameters are ignored
482 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
483
484 if (glyph.fWidth) {
485 SkScalar x = pos[0];
486 SkScalar y = scalarsPerPosition == 1 ? constY : pos[1];
skia.committer@gmail.com22e96722013-12-20 07:01:36 +0000487
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000488 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
489 glyph.getSubXFixed(),
490 glyph.getSubYFixed()),
491 SkScalarToFixed(x) - (glyph.fAdvanceX >> alignShift)
492 + SK_FixedHalf, //d1g.fHalfSampleX,
493 SkScalarToFixed(y) - (glyph.fAdvanceY >> alignShift)
494 + SK_FixedHalf, //d1g.fHalfSampleY,
495 fontScaler);
496 }
497 pos += scalarsPerPosition;
498 }
499 }
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000500
501 this->finish();
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000502}