blob: 448e70980547c23220fd21cd6f2c44add0f89b44 [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;
commit-bot@chromium.org762cd802014-04-14 22:05:07 +0000242 SkMatrix ctm;
243 ctm.setScale(fTextRatio, fTextRatio);
244 ctm.postTranslate(sx, sy);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000245 GrPaint tmpPaint(fPaint);
commit-bot@chromium.org762cd802014-04-14 22:05:07 +0000246 am.setPreConcat(fContext, ctm, &tmpPaint);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000247 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
248 fContext->drawPath(tmpPaint, *glyph->fPath, stroke);
249 return;
250 }
251
252HAS_ATLAS:
253 SkASSERT(glyph->fPlot);
254 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken();
255 glyph->fPlot->setDrawToken(drawToken);
256
257 GrTexture* texture = glyph->fPlot->texture();
258 SkASSERT(texture);
259
260 if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) {
261 this->flushGlyphs();
262 fCurrTexture = texture;
263 fCurrTexture->ref();
264 }
265
266 if (NULL == fVertices) {
267 // If we need to reserve vertices allow the draw target to suggest
268 // a number of verts to reserve and whether to perform a flush.
269 fMaxVertices = kMinRequestedVerts;
270 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
271 SK_ARRAY_COUNT(gTextVertexAttribs));
272 bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL);
273 if (flush) {
274 this->flushGlyphs();
275 fContext->flush();
276 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
277 SK_ARRAY_COUNT(gTextVertexAttribs));
278 }
279 fMaxVertices = kDefaultRequestedVerts;
280 // ignore return, no point in flushing again.
281 fDrawTarget->geometryHints(&fMaxVertices, NULL);
282
283 int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads();
284 if (fMaxVertices < kMinRequestedVerts) {
285 fMaxVertices = kDefaultRequestedVerts;
286 } else if (fMaxVertices > maxQuadVertices) {
287 // don't exceed the limit of the index buffer
288 fMaxVertices = maxQuadVertices;
289 }
290 bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices,
291 0,
292 GrTCast<void**>(&fVertices),
293 NULL);
294 GrAlwaysAssert(success);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000295 SkASSERT(2*sizeof(SkPoint) == fDrawTarget->getDrawState().getVertexSize());
jvanverth@google.comd830d132013-11-11 20:54:09 +0000296 }
297
298 SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft);
299 SkScalar dy = SkIntToScalar(glyph->fBounds.fTop);
300 SkScalar width = SkIntToScalar(glyph->fBounds.width());
301 SkScalar height = SkIntToScalar(glyph->fBounds.height());
302
303 SkScalar scale = fTextRatio;
304 dx *= scale;
305 dy *= scale;
306 sx += dx;
307 sy += dy;
308 width *= scale;
309 height *= scale;
skia.committer@gmail.coma3b53272014-02-15 03:02:15 +0000310
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000311 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX);
312 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY);
313 SkFixed tw = SkIntToFixed(glyph->fBounds.width());
314 SkFixed th = SkIntToFixed(glyph->fBounds.height());
jvanverth@google.comd830d132013-11-11 20:54:09 +0000315
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000316 static const size_t kVertexSize = 2 * sizeof(SkPoint);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000317 fVertices[2*fCurrVertex].setRectFan(sx,
318 sy,
319 sx + width,
320 sy + height,
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000321 kVertexSize);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000322 fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)),
323 SkFixedToFloat(texture->normalizeFixedY(ty)),
324 SkFixedToFloat(texture->normalizeFixedX(tx + tw)),
325 SkFixedToFloat(texture->normalizeFixedY(ty + th)),
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000326 kVertexSize);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000327 fCurrVertex += 4;
328}
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000329
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000330inline void GrDistanceFieldTextContext::init(const GrPaint& paint, const SkPaint& skPaint) {
331 GrTextContext::init(paint, skPaint);
332
333 fStrike = NULL;
334
335 fCurrTexture = NULL;
336 fCurrVertex = 0;
337
338 fVertices = NULL;
339 fMaxVertices = 0;
340
commit-bot@chromium.orgdc5cd852014-04-02 19:24:32 +0000341 if (fSkPaint.getTextSize() <= kSmallDFFontLimit) {
342 fTextRatio = fSkPaint.getTextSize()/kSmallDFFontSize;
343 fSkPaint.setTextSize(SkIntToScalar(kSmallDFFontSize));
344 } else if (fSkPaint.getTextSize() <= kMediumDFFontLimit) {
345 fTextRatio = fSkPaint.getTextSize()/kMediumDFFontSize;
346 fSkPaint.setTextSize(SkIntToScalar(kMediumDFFontSize));
347 } else {
348 fTextRatio = fSkPaint.getTextSize()/kLargeDFFontSize;
349 fSkPaint.setTextSize(SkIntToScalar(kLargeDFFontSize));
350 }
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000351
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000352 fUseLCDText = fSkPaint.isLCDRenderText();
skia.committer@gmail.com221b9112014-04-04 03:04:32 +0000353
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000354 fSkPaint.setLCDRenderText(false);
355 fSkPaint.setAutohinted(false);
commit-bot@chromium.org0bed43c2014-03-14 21:22:38 +0000356 fSkPaint.setSubpixelText(true);
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000357}
358
359inline void GrDistanceFieldTextContext::finish() {
360 flushGlyphs();
361
362 GrTextContext::finish();
363}
364
365void GrDistanceFieldTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
366 const char text[], size_t byteLength,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000367 SkScalar x, SkScalar y) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000368 SkASSERT(byteLength == 0 || text != NULL);
369
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000370 // nothing to draw or can't draw
371 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/
372 || fSkPaint.getRasterizer()) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000373 return;
374 }
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000375
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000376 this->init(paint, skPaint);
377
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000378 SkScalar sizeRatio = fTextRatio;
379
380 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
381
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000382 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, NULL);
383 SkGlyphCache* cache = autoCache.getCache();
384 GrFontScaler* fontScaler = GetGrFontScaler(cache);
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000385
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000386 // need to measure first
387 // TODO - generate positions and pre-load cache as well?
388 const char* stop = text + byteLength;
389 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
390 SkFixed stopX = 0;
391 SkFixed stopY = 0;
392
393 const char* textPtr = text;
394 while (textPtr < stop) {
395 // don't need x, y here, since all subpixel variants will have the
396 // same advance
397 const SkGlyph& glyph = glyphCacheProc(cache, &textPtr, 0, 0);
398
399 stopX += glyph.fAdvanceX;
400 stopY += glyph.fAdvanceY;
401 }
402 SkASSERT(textPtr == stop);
403
404 SkScalar alignX = SkFixedToScalar(stopX)*sizeRatio;
405 SkScalar alignY = SkFixedToScalar(stopY)*sizeRatio;
406
407 if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
408 alignX = SkScalarHalf(alignX);
409 alignY = SkScalarHalf(alignY);
410 }
411
412 x -= alignX;
413 y -= alignY;
414 }
415
416 SkFixed fx = SkScalarToFixed(x) + SK_FixedHalf;
417 SkFixed fy = SkScalarToFixed(y) + SK_FixedHalf;
418 SkFixed fixedScale = SkScalarToFixed(sizeRatio);
419 while (text < stop) {
commit-bot@chromium.orga9dae712014-03-24 18:34:04 +0000420 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000421
422 if (glyph.fWidth) {
423 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
424 glyph.getSubXFixed(),
425 glyph.getSubYFixed()),
426 SkFixedFloorToFixed(fx),
427 SkFixedFloorToFixed(fy),
428 fontScaler);
429 }
430
431 fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale);
432 fy += SkFixedMul_portable(glyph.fAdvanceY, fixedScale);
433 }
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000434
435 this->finish();
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000436}
437
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000438void GrDistanceFieldTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPaint,
439 const char text[], size_t byteLength,
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000440 const SkScalar pos[], SkScalar constY,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000441 int scalarsPerPosition) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000442
443 SkASSERT(byteLength == 0 || text != NULL);
444 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
445
446 // nothing to draw
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000447 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000448 return;
449 }
450
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000451 this->init(paint, skPaint);
452
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000453 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
454
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000455 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, NULL);
456 SkGlyphCache* cache = autoCache.getCache();
457 GrFontScaler* fontScaler = GetGrFontScaler(cache);
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000458
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000459 const char* stop = text + byteLength;
460
461 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
462 while (text < stop) {
463 // the last 2 parameters are ignored
464 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
465
466 if (glyph.fWidth) {
467 SkScalar x = pos[0];
468 SkScalar y = scalarsPerPosition == 1 ? constY : pos[1];
469
470 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
471 glyph.getSubXFixed(),
472 glyph.getSubYFixed()),
473 SkScalarToFixed(x) + SK_FixedHalf, //d1g.fHalfSampleX,
474 SkScalarToFixed(y) + SK_FixedHalf, //d1g.fHalfSampleY,
475 fontScaler);
476 }
477 pos += scalarsPerPosition;
478 }
479 } else {
480 int alignShift = SkPaint::kCenter_Align == fSkPaint.getTextAlign() ? 1 : 0;
481 while (text < stop) {
482 // the last 2 parameters are ignored
483 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
484
485 if (glyph.fWidth) {
486 SkScalar x = pos[0];
487 SkScalar y = scalarsPerPosition == 1 ? constY : pos[1];
skia.committer@gmail.com22e96722013-12-20 07:01:36 +0000488
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000489 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
490 glyph.getSubXFixed(),
491 glyph.getSubYFixed()),
492 SkScalarToFixed(x) - (glyph.fAdvanceX >> alignShift)
493 + SK_FixedHalf, //d1g.fHalfSampleX,
494 SkScalarToFixed(y) - (glyph.fAdvanceY >> alignShift)
495 + SK_FixedHalf, //d1g.fHalfSampleY,
496 fontScaler);
497 }
498 pos += scalarsPerPosition;
499 }
500 }
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000501
502 this->finish();
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000503}