blob: 71e5d0f16c7b5294252c70825b52e74d578cfa43 [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.orgae796122014-03-12 17:05:46 +000058 return (kForceDistanceFieldFonts || paint.isDistanceFieldTextTEMP()) &&
commit-bot@chromium.orgb97c3ff2014-03-11 17:07:15 +000059 !paint.getRasterizer() && !paint.getMaskFilter() &&
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +000060 paint.getStyle() == SkPaint::kFill_Style &&
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +000061 fContext->getTextTarget()->caps()->shaderDerivativeSupport() &&
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +000062 !SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix());
63}
64
jvanverth@google.comd830d132013-11-11 20:54:09 +000065static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
66 unsigned r = SkColorGetR(c);
67 unsigned g = SkColorGetG(c);
68 unsigned b = SkColorGetB(c);
69 return GrColorPackRGBA(r, g, b, 0xff);
70}
71
72void GrDistanceFieldTextContext::flushGlyphs() {
73 if (NULL == fDrawTarget) {
74 return;
75 }
76
77 GrDrawState* drawState = fDrawTarget->drawState();
78 GrDrawState::AutoRestoreEffects are(drawState);
79 drawState->setFromPaint(fPaint, fContext->getMatrix(), fContext->getRenderTarget());
80
81 if (fCurrVertex > 0) {
82 // setup our sampler state for our text texture/atlas
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000083 SkASSERT(SkIsAlign4(fCurrVertex));
jvanverth@google.comd830d132013-11-11 20:54:09 +000084 SkASSERT(fCurrTexture);
85 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode);
86
87 // This effect could be stored with one of the cache objects (atlas?)
88 drawState->addCoverageEffect(
commit-bot@chromium.org4362a382014-03-26 19:49:03 +000089 GrDistanceFieldTextureEffect::Create(fCurrTexture, params,
90 fContext->getMatrix().isSimilarity()),
91 kGlyphCoordsAttributeIndex)->unref();
jvanverth@google.comd830d132013-11-11 20:54:09 +000092
93 if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) {
94 if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
95 kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
96 fPaint.numColorStages()) {
97 GrPrintf("LCD Text will not draw correctly.\n");
98 }
99 // We don't use the GrPaint's color in this case because it's been premultiplied by
100 // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
101 // the mask texture color. The end result is that we get
102 // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000103 int a = SkColorGetA(fSkPaint.getColor());
jvanverth@google.comd830d132013-11-11 20:54:09 +0000104 // paintAlpha
105 drawState->setColor(SkColorSetARGB(a, a, a, a));
106 // paintColor
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000107 drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor()));
jvanverth@google.comd830d132013-11-11 20:54:09 +0000108 drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
109 } else {
110 // set back to normal in case we took LCD path previously.
111 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
112 drawState->setColor(fPaint.getColor());
113 }
114
115 int nGlyphs = fCurrVertex / 4;
116 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
117 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
118 nGlyphs,
119 4, 6);
120 fDrawTarget->resetVertexSource();
121 fVertices = NULL;
122 fMaxVertices = 0;
123 fCurrVertex = 0;
124 SkSafeSetNull(fCurrTexture);
125 }
126}
127
128namespace {
129
130// position + texture coord
131extern const GrVertexAttrib gTextVertexAttribs[] = {
132 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000133 {kVec2f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding}
jvanverth@google.comd830d132013-11-11 20:54:09 +0000134};
135
136};
137
138void GrDistanceFieldTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000139 SkFixed vx, SkFixed vy,
jvanverth@google.comd830d132013-11-11 20:54:09 +0000140 GrFontScaler* scaler) {
141 if (NULL == fDrawTarget) {
142 return;
143 }
144 if (NULL == fStrike) {
145 fStrike = fContext->getFontCache()->getStrike(scaler, true);
146 }
147
148 GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
149 if (NULL == glyph || glyph->fBounds.isEmpty()) {
150 return;
151 }
152
153 SkScalar sx = SkFixedToScalar(vx);
154 SkScalar sy = SkFixedToScalar(vy);
155/*
156 // not valid, need to find a different solution for this
157 vx += SkIntToFixed(glyph->fBounds.fLeft);
158 vy += SkIntToFixed(glyph->fBounds.fTop);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000159
jvanverth@google.comd830d132013-11-11 20:54:09 +0000160 // keep them as ints until we've done the clip-test
161 GrFixed width = glyph->fBounds.width();
162 GrFixed height = glyph->fBounds.height();
163
164 // check if we clipped out
165 if (true || NULL == glyph->fPlot) {
166 int x = vx >> 16;
167 int y = vy >> 16;
168 if (fClipRect.quickReject(x, y, x + width, y + height)) {
169// SkCLZ(3); // so we can set a break-point in the debugger
170 return;
171 }
172 }
173*/
174 if (NULL == glyph->fPlot) {
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000175 if (fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comd830d132013-11-11 20:54:09 +0000176 goto HAS_ATLAS;
177 }
178
179 // try to clear out an unused plot before we flush
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000180 if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
181 fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comd830d132013-11-11 20:54:09 +0000182 goto HAS_ATLAS;
183 }
184
185 if (c_DumpFontCache) {
186#ifdef SK_DEVELOPER
187 fContext->getFontCache()->dump();
188#endif
189 }
190
191 // before we purge the cache, we must flush any accumulated draws
192 this->flushGlyphs();
193 fContext->flush();
194
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000195 // we should have an unused plot now
196 if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
197 fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comd830d132013-11-11 20:54:09 +0000198 goto HAS_ATLAS;
199 }
200
201 if (NULL == glyph->fPath) {
202 SkPath* path = SkNEW(SkPath);
203 if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
204 // flag the glyph as being dead?
205 delete path;
206 return;
207 }
208 glyph->fPath = path;
209 }
210
211 GrContext::AutoMatrix am;
212 SkMatrix translate;
213 translate.setTranslate(sx, sy);
214 GrPaint tmpPaint(fPaint);
215 am.setPreConcat(fContext, translate, &tmpPaint);
216 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
217 fContext->drawPath(tmpPaint, *glyph->fPath, stroke);
218 return;
219 }
220
221HAS_ATLAS:
222 SkASSERT(glyph->fPlot);
223 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken();
224 glyph->fPlot->setDrawToken(drawToken);
225
226 GrTexture* texture = glyph->fPlot->texture();
227 SkASSERT(texture);
228
229 if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) {
230 this->flushGlyphs();
231 fCurrTexture = texture;
232 fCurrTexture->ref();
233 }
234
235 if (NULL == fVertices) {
236 // If we need to reserve vertices allow the draw target to suggest
237 // a number of verts to reserve and whether to perform a flush.
238 fMaxVertices = kMinRequestedVerts;
239 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
240 SK_ARRAY_COUNT(gTextVertexAttribs));
241 bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL);
242 if (flush) {
243 this->flushGlyphs();
244 fContext->flush();
245 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
246 SK_ARRAY_COUNT(gTextVertexAttribs));
247 }
248 fMaxVertices = kDefaultRequestedVerts;
249 // ignore return, no point in flushing again.
250 fDrawTarget->geometryHints(&fMaxVertices, NULL);
251
252 int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads();
253 if (fMaxVertices < kMinRequestedVerts) {
254 fMaxVertices = kDefaultRequestedVerts;
255 } else if (fMaxVertices > maxQuadVertices) {
256 // don't exceed the limit of the index buffer
257 fMaxVertices = maxQuadVertices;
258 }
259 bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices,
260 0,
261 GrTCast<void**>(&fVertices),
262 NULL);
263 GrAlwaysAssert(success);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000264 SkASSERT(2*sizeof(SkPoint) == fDrawTarget->getDrawState().getVertexSize());
jvanverth@google.comd830d132013-11-11 20:54:09 +0000265 }
266
267 SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft);
268 SkScalar dy = SkIntToScalar(glyph->fBounds.fTop);
269 SkScalar width = SkIntToScalar(glyph->fBounds.width());
270 SkScalar height = SkIntToScalar(glyph->fBounds.height());
271
272 SkScalar scale = fTextRatio;
273 dx *= scale;
274 dy *= scale;
275 sx += dx;
276 sy += dy;
277 width *= scale;
278 height *= scale;
skia.committer@gmail.coma3b53272014-02-15 03:02:15 +0000279
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000280 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX);
281 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY);
282 SkFixed tw = SkIntToFixed(glyph->fBounds.width());
283 SkFixed th = SkIntToFixed(glyph->fBounds.height());
jvanverth@google.comd830d132013-11-11 20:54:09 +0000284
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000285 static const size_t kVertexSize = 2 * sizeof(SkPoint);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000286 fVertices[2*fCurrVertex].setRectFan(sx,
287 sy,
288 sx + width,
289 sy + height,
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000290 kVertexSize);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000291 fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)),
292 SkFixedToFloat(texture->normalizeFixedY(ty)),
293 SkFixedToFloat(texture->normalizeFixedX(tx + tw)),
294 SkFixedToFloat(texture->normalizeFixedY(ty + th)),
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000295 kVertexSize);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000296 fCurrVertex += 4;
297}
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000298
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000299inline void GrDistanceFieldTextContext::init(const GrPaint& paint, const SkPaint& skPaint) {
300 GrTextContext::init(paint, skPaint);
301
302 fStrike = NULL;
303
304 fCurrTexture = NULL;
305 fCurrVertex = 0;
306
307 fVertices = NULL;
308 fMaxVertices = 0;
309
commit-bot@chromium.orgdc5cd852014-04-02 19:24:32 +0000310 if (fSkPaint.getTextSize() <= kSmallDFFontLimit) {
311 fTextRatio = fSkPaint.getTextSize()/kSmallDFFontSize;
312 fSkPaint.setTextSize(SkIntToScalar(kSmallDFFontSize));
313 } else if (fSkPaint.getTextSize() <= kMediumDFFontLimit) {
314 fTextRatio = fSkPaint.getTextSize()/kMediumDFFontSize;
315 fSkPaint.setTextSize(SkIntToScalar(kMediumDFFontSize));
316 } else {
317 fTextRatio = fSkPaint.getTextSize()/kLargeDFFontSize;
318 fSkPaint.setTextSize(SkIntToScalar(kLargeDFFontSize));
319 }
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000320
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000321 fSkPaint.setLCDRenderText(false);
322 fSkPaint.setAutohinted(false);
commit-bot@chromium.org0bed43c2014-03-14 21:22:38 +0000323 fSkPaint.setSubpixelText(true);
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000324}
325
326inline void GrDistanceFieldTextContext::finish() {
327 flushGlyphs();
328
329 GrTextContext::finish();
330}
331
332void GrDistanceFieldTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
333 const char text[], size_t byteLength,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000334 SkScalar x, SkScalar y) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000335 SkASSERT(byteLength == 0 || text != NULL);
336
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000337 // nothing to draw or can't draw
338 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/
339 || fSkPaint.getRasterizer()) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000340 return;
341 }
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000342
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000343 this->init(paint, skPaint);
344
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000345 SkScalar sizeRatio = fTextRatio;
346
347 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
348
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000349 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, NULL);
350 SkGlyphCache* cache = autoCache.getCache();
351 GrFontScaler* fontScaler = GetGrFontScaler(cache);
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000352
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000353 // need to measure first
354 // TODO - generate positions and pre-load cache as well?
355 const char* stop = text + byteLength;
356 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
357 SkFixed stopX = 0;
358 SkFixed stopY = 0;
359
360 const char* textPtr = text;
361 while (textPtr < stop) {
362 // don't need x, y here, since all subpixel variants will have the
363 // same advance
364 const SkGlyph& glyph = glyphCacheProc(cache, &textPtr, 0, 0);
365
366 stopX += glyph.fAdvanceX;
367 stopY += glyph.fAdvanceY;
368 }
369 SkASSERT(textPtr == stop);
370
371 SkScalar alignX = SkFixedToScalar(stopX)*sizeRatio;
372 SkScalar alignY = SkFixedToScalar(stopY)*sizeRatio;
373
374 if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
375 alignX = SkScalarHalf(alignX);
376 alignY = SkScalarHalf(alignY);
377 }
378
379 x -= alignX;
380 y -= alignY;
381 }
382
383 SkFixed fx = SkScalarToFixed(x) + SK_FixedHalf;
384 SkFixed fy = SkScalarToFixed(y) + SK_FixedHalf;
385 SkFixed fixedScale = SkScalarToFixed(sizeRatio);
386 while (text < stop) {
commit-bot@chromium.orga9dae712014-03-24 18:34:04 +0000387 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000388
389 if (glyph.fWidth) {
390 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
391 glyph.getSubXFixed(),
392 glyph.getSubYFixed()),
393 SkFixedFloorToFixed(fx),
394 SkFixedFloorToFixed(fy),
395 fontScaler);
396 }
397
398 fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale);
399 fy += SkFixedMul_portable(glyph.fAdvanceY, fixedScale);
400 }
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000401
402 this->finish();
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000403}
404
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000405void GrDistanceFieldTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPaint,
406 const char text[], size_t byteLength,
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000407 const SkScalar pos[], SkScalar constY,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000408 int scalarsPerPosition) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000409
410 SkASSERT(byteLength == 0 || text != NULL);
411 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
412
413 // nothing to draw
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000414 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000415 return;
416 }
417
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000418 this->init(paint, skPaint);
419
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000420 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
421
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000422 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, NULL);
423 SkGlyphCache* cache = autoCache.getCache();
424 GrFontScaler* fontScaler = GetGrFontScaler(cache);
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000425
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000426 const char* stop = text + byteLength;
427
428 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
429 while (text < stop) {
430 // the last 2 parameters are ignored
431 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
432
433 if (glyph.fWidth) {
434 SkScalar x = pos[0];
435 SkScalar y = scalarsPerPosition == 1 ? constY : pos[1];
436
437 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
438 glyph.getSubXFixed(),
439 glyph.getSubYFixed()),
440 SkScalarToFixed(x) + SK_FixedHalf, //d1g.fHalfSampleX,
441 SkScalarToFixed(y) + SK_FixedHalf, //d1g.fHalfSampleY,
442 fontScaler);
443 }
444 pos += scalarsPerPosition;
445 }
446 } else {
447 int alignShift = SkPaint::kCenter_Align == fSkPaint.getTextAlign() ? 1 : 0;
448 while (text < stop) {
449 // the last 2 parameters are ignored
450 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
451
452 if (glyph.fWidth) {
453 SkScalar x = pos[0];
454 SkScalar y = scalarsPerPosition == 1 ? constY : pos[1];
skia.committer@gmail.com22e96722013-12-20 07:01:36 +0000455
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000456 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
457 glyph.getSubXFixed(),
458 glyph.getSubYFixed()),
459 SkScalarToFixed(x) - (glyph.fAdvanceX >> alignShift)
460 + SK_FixedHalf, //d1g.fHalfSampleX,
461 SkScalarToFixed(y) - (glyph.fAdvanceY >> alignShift)
462 + SK_FixedHalf, //d1g.fHalfSampleY,
463 fontScaler);
464 }
465 pos += scalarsPerPosition;
466 }
467 }
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000468
469 this->finish();
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000470}