blob: 512420eb672090a205e665a47973fe3dd5892ec6 [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.org64b08a12014-04-15 17:53:21 +000017#include "SkDistanceFieldGen.h"
commit-bot@chromium.org9f94b912014-01-30 15:22:54 +000018#include "SkDraw.h"
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +000019#include "SkGpuDevice.h"
jvanverth@google.comd830d132013-11-11 20:54:09 +000020#include "SkPath.h"
21#include "SkRTConf.h"
22#include "SkStrokeRec.h"
23#include "effects/GrDistanceFieldTextureEffect.h"
24
25static const int kGlyphCoordsAttributeIndex = 1;
26
commit-bot@chromium.orgdc5cd852014-04-02 19:24:32 +000027static const int kSmallDFFontSize = 32;
28static const int kSmallDFFontLimit = 32;
29static const int kMediumDFFontSize = 64;
30static const int kMediumDFFontLimit = 64;
31static const int kLargeDFFontSize = 128;
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +000032
jvanverth@google.comd830d132013-11-11 20:54:09 +000033SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
34 "Dump the contents of the font cache before every purge.");
35
skia.committer@gmail.come5d70152014-01-29 07:01:48 +000036GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
commit-bot@chromium.org6fcd1ef2014-05-02 12:39:41 +000037 const SkDeviceProperties& properties,
38 bool enable)
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +000039 : GrTextContext(context, properties) {
commit-bot@chromium.org6fcd1ef2014-05-02 12:39:41 +000040#if SK_FORCE_DISTANCEFIELD_FONTS
41 fEnableDFRendering = true;
42#else
43 fEnableDFRendering = enable;
44#endif
jvanverth@google.comd830d132013-11-11 20:54:09 +000045 fStrike = NULL;
46
47 fCurrTexture = NULL;
48 fCurrVertex = 0;
49
50 fVertices = NULL;
51 fMaxVertices = 0;
52}
53
54GrDistanceFieldTextContext::~GrDistanceFieldTextContext() {
55 this->flushGlyphs();
56}
57
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +000058bool GrDistanceFieldTextContext::canDraw(const SkPaint& paint) {
commit-bot@chromium.org6fcd1ef2014-05-02 12:39:41 +000059 if (!fEnableDFRendering && !paint.isDistanceFieldTextTEMP()) {
commit-bot@chromium.orgeefd8a02014-04-08 20:14:32 +000060 return false;
61 }
62
skia.committer@gmail.come1d94432014-04-09 03:04:11 +000063 // rasterizers and mask filters modify alpha, which doesn't
commit-bot@chromium.orgeefd8a02014-04-08 20:14:32 +000064 // translate well to distance
65 if (paint.getRasterizer() || paint.getMaskFilter() ||
66 !fContext->getTextTarget()->caps()->shaderDerivativeSupport()) {
67 return false;
68 }
69
70 // TODO: add some stroking support
71 if (paint.getStyle() != SkPaint::kFill_Style) {
72 return false;
73 }
74
75 // TODO: choose an appropriate maximum scale for distance fields and
76 // enable perspective
77 if (SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix())) {
78 return false;
79 }
80
81 // distance fields cannot represent color fonts
82 SkScalerContext::Rec rec;
83 SkScalerContext::MakeRec(paint, &fDeviceProperties, NULL, &rec);
84 return rec.getFormat() != SkMask::kARGB32_Format;
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +000085}
86
jvanverth@google.comd830d132013-11-11 20:54:09 +000087static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
88 unsigned r = SkColorGetR(c);
89 unsigned g = SkColorGetG(c);
90 unsigned b = SkColorGetB(c);
91 return GrColorPackRGBA(r, g, b, 0xff);
92}
93
94void GrDistanceFieldTextContext::flushGlyphs() {
95 if (NULL == fDrawTarget) {
96 return;
97 }
98
99 GrDrawState* drawState = fDrawTarget->drawState();
100 GrDrawState::AutoRestoreEffects are(drawState);
101 drawState->setFromPaint(fPaint, fContext->getMatrix(), fContext->getRenderTarget());
102
103 if (fCurrVertex > 0) {
104 // setup our sampler state for our text texture/atlas
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000105 SkASSERT(SkIsAlign4(fCurrVertex));
jvanverth@google.comd830d132013-11-11 20:54:09 +0000106 SkASSERT(fCurrTexture);
107 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode);
108
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000109 // Effects could be stored with one of the cache objects (atlas?)
110 if (fUseLCDText) {
111 bool useBGR = SkDeviceProperties::Geometry::kBGR_Layout ==
112 fDeviceProperties.fGeometry.getLayout();
113 drawState->addCoverageEffect(GrDistanceFieldLCDTextureEffect::Create(
114 fCurrTexture,
115 params,
116 fContext->getMatrix().rectStaysRect() &&
117 fContext->getMatrix().isSimilarity(),
118 useBGR),
119 kGlyphCoordsAttributeIndex)->unref();
jvanverth@google.comd830d132013-11-11 20:54:09 +0000120
jvanverth@google.comd830d132013-11-11 20:54:09 +0000121 if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
122 kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
123 fPaint.numColorStages()) {
124 GrPrintf("LCD Text will not draw correctly.\n");
125 }
126 // We don't use the GrPaint's color in this case because it's been premultiplied by
127 // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
128 // the mask texture color. The end result is that we get
129 // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000130 int a = SkColorGetA(fSkPaint.getColor());
jvanverth@google.comd830d132013-11-11 20:54:09 +0000131 // paintAlpha
132 drawState->setColor(SkColorSetARGB(a, a, a, a));
133 // paintColor
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000134 drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor()));
jvanverth@google.comd830d132013-11-11 20:54:09 +0000135 drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
136 } else {
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000137 drawState->addCoverageEffect(GrDistanceFieldTextureEffect::Create(fCurrTexture, params,
138 fContext->getMatrix().isSimilarity()),
139 kGlyphCoordsAttributeIndex)->unref();
140
jvanverth@google.comd830d132013-11-11 20:54:09 +0000141 // set back to normal in case we took LCD path previously.
142 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
143 drawState->setColor(fPaint.getColor());
144 }
145
146 int nGlyphs = fCurrVertex / 4;
147 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
148 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
149 nGlyphs,
150 4, 6);
151 fDrawTarget->resetVertexSource();
152 fVertices = NULL;
153 fMaxVertices = 0;
154 fCurrVertex = 0;
155 SkSafeSetNull(fCurrTexture);
156 }
157}
158
159namespace {
160
161// position + texture coord
162extern const GrVertexAttrib gTextVertexAttribs[] = {
163 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000164 {kVec2f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding}
jvanverth@google.comd830d132013-11-11 20:54:09 +0000165};
166
167};
168
169void GrDistanceFieldTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000170 SkFixed vx, SkFixed vy,
jvanverth@google.comd830d132013-11-11 20:54:09 +0000171 GrFontScaler* scaler) {
172 if (NULL == fDrawTarget) {
173 return;
174 }
175 if (NULL == fStrike) {
176 fStrike = fContext->getFontCache()->getStrike(scaler, true);
177 }
178
179 GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
180 if (NULL == glyph || glyph->fBounds.isEmpty()) {
181 return;
182 }
183
184 SkScalar sx = SkFixedToScalar(vx);
185 SkScalar sy = SkFixedToScalar(vy);
186/*
187 // not valid, need to find a different solution for this
188 vx += SkIntToFixed(glyph->fBounds.fLeft);
189 vy += SkIntToFixed(glyph->fBounds.fTop);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000190
jvanverth@google.comd830d132013-11-11 20:54:09 +0000191 // keep them as ints until we've done the clip-test
192 GrFixed width = glyph->fBounds.width();
193 GrFixed height = glyph->fBounds.height();
194
195 // check if we clipped out
196 if (true || NULL == glyph->fPlot) {
197 int x = vx >> 16;
198 int y = vy >> 16;
199 if (fClipRect.quickReject(x, y, x + width, y + height)) {
200// SkCLZ(3); // so we can set a break-point in the debugger
201 return;
202 }
203 }
204*/
205 if (NULL == glyph->fPlot) {
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000206 if (fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comd830d132013-11-11 20:54:09 +0000207 goto HAS_ATLAS;
208 }
209
210 // try to clear out an unused plot before we flush
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000211 if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
212 fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comd830d132013-11-11 20:54:09 +0000213 goto HAS_ATLAS;
214 }
215
216 if (c_DumpFontCache) {
217#ifdef SK_DEVELOPER
218 fContext->getFontCache()->dump();
219#endif
220 }
221
222 // before we purge the cache, we must flush any accumulated draws
223 this->flushGlyphs();
224 fContext->flush();
225
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000226 // we should have an unused plot now
227 if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
228 fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comd830d132013-11-11 20:54:09 +0000229 goto HAS_ATLAS;
230 }
231
232 if (NULL == glyph->fPath) {
233 SkPath* path = SkNEW(SkPath);
234 if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
235 // flag the glyph as being dead?
236 delete path;
237 return;
238 }
239 glyph->fPath = path;
240 }
241
242 GrContext::AutoMatrix am;
commit-bot@chromium.org762cd802014-04-14 22:05:07 +0000243 SkMatrix ctm;
244 ctm.setScale(fTextRatio, fTextRatio);
245 ctm.postTranslate(sx, sy);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000246 GrPaint tmpPaint(fPaint);
commit-bot@chromium.org762cd802014-04-14 22:05:07 +0000247 am.setPreConcat(fContext, ctm, &tmpPaint);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000248 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
249 fContext->drawPath(tmpPaint, *glyph->fPath, stroke);
250 return;
251 }
252
253HAS_ATLAS:
254 SkASSERT(glyph->fPlot);
255 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken();
256 glyph->fPlot->setDrawToken(drawToken);
257
258 GrTexture* texture = glyph->fPlot->texture();
259 SkASSERT(texture);
260
261 if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) {
262 this->flushGlyphs();
263 fCurrTexture = texture;
264 fCurrTexture->ref();
265 }
266
267 if (NULL == fVertices) {
268 // If we need to reserve vertices allow the draw target to suggest
269 // a number of verts to reserve and whether to perform a flush.
270 fMaxVertices = kMinRequestedVerts;
271 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
272 SK_ARRAY_COUNT(gTextVertexAttribs));
273 bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL);
274 if (flush) {
275 this->flushGlyphs();
276 fContext->flush();
277 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
278 SK_ARRAY_COUNT(gTextVertexAttribs));
279 }
280 fMaxVertices = kDefaultRequestedVerts;
281 // ignore return, no point in flushing again.
282 fDrawTarget->geometryHints(&fMaxVertices, NULL);
283
284 int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads();
285 if (fMaxVertices < kMinRequestedVerts) {
286 fMaxVertices = kDefaultRequestedVerts;
287 } else if (fMaxVertices > maxQuadVertices) {
288 // don't exceed the limit of the index buffer
289 fMaxVertices = maxQuadVertices;
290 }
291 bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices,
292 0,
293 GrTCast<void**>(&fVertices),
294 NULL);
295 GrAlwaysAssert(success);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000296 SkASSERT(2*sizeof(SkPoint) == fDrawTarget->getDrawState().getVertexSize());
jvanverth@google.comd830d132013-11-11 20:54:09 +0000297 }
298
commit-bot@chromium.org64b08a12014-04-15 17:53:21 +0000299 SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft + SK_DistanceFieldInset);
300 SkScalar dy = SkIntToScalar(glyph->fBounds.fTop + SK_DistanceFieldInset);
301 SkScalar width = SkIntToScalar(glyph->fBounds.width() - 2*SK_DistanceFieldInset);
302 SkScalar height = SkIntToScalar(glyph->fBounds.height() - 2*SK_DistanceFieldInset);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000303
304 SkScalar scale = fTextRatio;
305 dx *= scale;
306 dy *= scale;
307 sx += dx;
308 sy += dy;
309 width *= scale;
310 height *= scale;
skia.committer@gmail.coma3b53272014-02-15 03:02:15 +0000311
commit-bot@chromium.org64b08a12014-04-15 17:53:21 +0000312 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX + SK_DistanceFieldInset);
313 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY + SK_DistanceFieldInset);
314 SkFixed tw = SkIntToFixed(glyph->fBounds.width() - 2*SK_DistanceFieldInset);
315 SkFixed th = SkIntToFixed(glyph->fBounds.height() - 2*SK_DistanceFieldInset);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000316
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000317 static const size_t kVertexSize = 2 * sizeof(SkPoint);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000318 fVertices[2*fCurrVertex].setRectFan(sx,
319 sy,
320 sx + width,
321 sy + height,
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000322 kVertexSize);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000323 fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)),
324 SkFixedToFloat(texture->normalizeFixedY(ty)),
325 SkFixedToFloat(texture->normalizeFixedX(tx + tw)),
326 SkFixedToFloat(texture->normalizeFixedY(ty + th)),
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000327 kVertexSize);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000328 fCurrVertex += 4;
329}
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000330
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000331inline void GrDistanceFieldTextContext::init(const GrPaint& paint, const SkPaint& skPaint) {
332 GrTextContext::init(paint, skPaint);
333
334 fStrike = NULL;
335
336 fCurrTexture = NULL;
337 fCurrVertex = 0;
338
339 fVertices = NULL;
340 fMaxVertices = 0;
341
commit-bot@chromium.orgdc5cd852014-04-02 19:24:32 +0000342 if (fSkPaint.getTextSize() <= kSmallDFFontLimit) {
343 fTextRatio = fSkPaint.getTextSize()/kSmallDFFontSize;
344 fSkPaint.setTextSize(SkIntToScalar(kSmallDFFontSize));
345 } else if (fSkPaint.getTextSize() <= kMediumDFFontLimit) {
346 fTextRatio = fSkPaint.getTextSize()/kMediumDFFontSize;
347 fSkPaint.setTextSize(SkIntToScalar(kMediumDFFontSize));
348 } else {
349 fTextRatio = fSkPaint.getTextSize()/kLargeDFFontSize;
350 fSkPaint.setTextSize(SkIntToScalar(kLargeDFFontSize));
351 }
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000352
commit-bot@chromium.org609ced42014-04-03 18:25:48 +0000353 fUseLCDText = fSkPaint.isLCDRenderText();
skia.committer@gmail.com221b9112014-04-04 03:04:32 +0000354
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000355 fSkPaint.setLCDRenderText(false);
356 fSkPaint.setAutohinted(false);
commit-bot@chromium.org0bed43c2014-03-14 21:22:38 +0000357 fSkPaint.setSubpixelText(true);
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000358}
359
360inline void GrDistanceFieldTextContext::finish() {
361 flushGlyphs();
362
363 GrTextContext::finish();
364}
365
366void GrDistanceFieldTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
367 const char text[], size_t byteLength,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000368 SkScalar x, SkScalar y) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000369 SkASSERT(byteLength == 0 || text != NULL);
370
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000371 // nothing to draw or can't draw
372 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/
373 || fSkPaint.getRasterizer()) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000374 return;
375 }
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000376
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000377 this->init(paint, skPaint);
378
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000379 SkScalar sizeRatio = fTextRatio;
380
381 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
382
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000383 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, NULL);
384 SkGlyphCache* cache = autoCache.getCache();
385 GrFontScaler* fontScaler = GetGrFontScaler(cache);
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000386
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000387 // need to measure first
388 // TODO - generate positions and pre-load cache as well?
389 const char* stop = text + byteLength;
390 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
391 SkFixed stopX = 0;
392 SkFixed stopY = 0;
393
394 const char* textPtr = text;
395 while (textPtr < stop) {
396 // don't need x, y here, since all subpixel variants will have the
397 // same advance
398 const SkGlyph& glyph = glyphCacheProc(cache, &textPtr, 0, 0);
399
400 stopX += glyph.fAdvanceX;
401 stopY += glyph.fAdvanceY;
402 }
403 SkASSERT(textPtr == stop);
404
405 SkScalar alignX = SkFixedToScalar(stopX)*sizeRatio;
406 SkScalar alignY = SkFixedToScalar(stopY)*sizeRatio;
407
408 if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
409 alignX = SkScalarHalf(alignX);
410 alignY = SkScalarHalf(alignY);
411 }
412
413 x -= alignX;
414 y -= alignY;
415 }
416
417 SkFixed fx = SkScalarToFixed(x) + SK_FixedHalf;
418 SkFixed fy = SkScalarToFixed(y) + SK_FixedHalf;
419 SkFixed fixedScale = SkScalarToFixed(sizeRatio);
420 while (text < stop) {
commit-bot@chromium.orga9dae712014-03-24 18:34:04 +0000421 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000422
423 if (glyph.fWidth) {
424 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
425 glyph.getSubXFixed(),
426 glyph.getSubYFixed()),
427 SkFixedFloorToFixed(fx),
428 SkFixedFloorToFixed(fy),
429 fontScaler);
430 }
431
432 fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale);
433 fy += SkFixedMul_portable(glyph.fAdvanceY, fixedScale);
434 }
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000435
436 this->finish();
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000437}
438
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000439void GrDistanceFieldTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPaint,
440 const char text[], size_t byteLength,
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000441 const SkScalar pos[], SkScalar constY,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000442 int scalarsPerPosition) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000443
444 SkASSERT(byteLength == 0 || text != NULL);
445 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
446
447 // nothing to draw
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000448 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000449 return;
450 }
451
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000452 this->init(paint, skPaint);
453
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000454 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
455
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000456 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, NULL);
457 SkGlyphCache* cache = autoCache.getCache();
458 GrFontScaler* fontScaler = GetGrFontScaler(cache);
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000459
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000460 const char* stop = text + byteLength;
461
462 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
463 while (text < stop) {
464 // the last 2 parameters are ignored
465 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
466
467 if (glyph.fWidth) {
468 SkScalar x = pos[0];
469 SkScalar y = scalarsPerPosition == 1 ? constY : pos[1];
470
471 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
472 glyph.getSubXFixed(),
473 glyph.getSubYFixed()),
474 SkScalarToFixed(x) + SK_FixedHalf, //d1g.fHalfSampleX,
475 SkScalarToFixed(y) + SK_FixedHalf, //d1g.fHalfSampleY,
476 fontScaler);
477 }
478 pos += scalarsPerPosition;
479 }
480 } else {
481 int alignShift = SkPaint::kCenter_Align == fSkPaint.getTextAlign() ? 1 : 0;
482 while (text < stop) {
483 // the last 2 parameters are ignored
484 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
485
486 if (glyph.fWidth) {
487 SkScalar x = pos[0];
488 SkScalar y = scalarsPerPosition == 1 ? constY : pos[1];
skia.committer@gmail.com22e96722013-12-20 07:01:36 +0000489
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000490 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
491 glyph.getSubXFixed(),
492 glyph.getSubYFixed()),
493 SkScalarToFixed(x) - (glyph.fAdvanceX >> alignShift)
494 + SK_FixedHalf, //d1g.fHalfSampleX,
495 SkScalarToFixed(y) - (glyph.fAdvanceY >> alignShift)
496 + SK_FixedHalf, //d1g.fHalfSampleY,
497 fontScaler);
498 }
499 pos += scalarsPerPosition;
500 }
501 }
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000502
503 this->finish();
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000504}