blob: 638ec597074bbef9010c3faaea188000af41c4e1 [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.org8128d8c2013-12-19 16:12:25 +000026static const int kBaseDFFontSize = 32;
27
jvanverth@google.comd830d132013-11-11 20:54:09 +000028SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
29 "Dump the contents of the font cache before every purge.");
30
commit-bot@chromium.orgae796122014-03-12 17:05:46 +000031#if SK_FORCE_DISTANCEFIELD_FONTS
32static const bool kForceDistanceFieldFonts = true;
33#else
34static const bool kForceDistanceFieldFonts = false;
35#endif
36
skia.committer@gmail.come5d70152014-01-29 07:01:48 +000037GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +000038 const SkDeviceProperties& properties)
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +000039 : GrTextContext(context, properties) {
jvanverth@google.comd830d132013-11-11 20:54:09 +000040 fStrike = NULL;
41
42 fCurrTexture = NULL;
43 fCurrVertex = 0;
44
45 fVertices = NULL;
46 fMaxVertices = 0;
47}
48
49GrDistanceFieldTextContext::~GrDistanceFieldTextContext() {
50 this->flushGlyphs();
51}
52
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +000053bool GrDistanceFieldTextContext::canDraw(const SkPaint& paint) {
commit-bot@chromium.orgae796122014-03-12 17:05:46 +000054 return (kForceDistanceFieldFonts || paint.isDistanceFieldTextTEMP()) &&
commit-bot@chromium.orgb97c3ff2014-03-11 17:07:15 +000055 !paint.getRasterizer() && !paint.getMaskFilter() &&
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +000056 paint.getStyle() == SkPaint::kFill_Style &&
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +000057 fContext->getTextTarget()->caps()->shaderDerivativeSupport() &&
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +000058 !SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix());
59}
60
jvanverth@google.comd830d132013-11-11 20:54:09 +000061static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
62 unsigned r = SkColorGetR(c);
63 unsigned g = SkColorGetG(c);
64 unsigned b = SkColorGetB(c);
65 return GrColorPackRGBA(r, g, b, 0xff);
66}
67
68void GrDistanceFieldTextContext::flushGlyphs() {
69 if (NULL == fDrawTarget) {
70 return;
71 }
72
73 GrDrawState* drawState = fDrawTarget->drawState();
74 GrDrawState::AutoRestoreEffects are(drawState);
75 drawState->setFromPaint(fPaint, fContext->getMatrix(), fContext->getRenderTarget());
76
77 if (fCurrVertex > 0) {
78 // setup our sampler state for our text texture/atlas
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000079 SkASSERT(SkIsAlign4(fCurrVertex));
jvanverth@google.comd830d132013-11-11 20:54:09 +000080 SkASSERT(fCurrTexture);
81 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode);
82
83 // This effect could be stored with one of the cache objects (atlas?)
84 drawState->addCoverageEffect(
commit-bot@chromium.org4362a382014-03-26 19:49:03 +000085 GrDistanceFieldTextureEffect::Create(fCurrTexture, params,
86 fContext->getMatrix().isSimilarity()),
87 kGlyphCoordsAttributeIndex)->unref();
jvanverth@google.comd830d132013-11-11 20:54:09 +000088
89 if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) {
90 if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
91 kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
92 fPaint.numColorStages()) {
93 GrPrintf("LCD Text will not draw correctly.\n");
94 }
95 // We don't use the GrPaint's color in this case because it's been premultiplied by
96 // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
97 // the mask texture color. The end result is that we get
98 // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +000099 int a = SkColorGetA(fSkPaint.getColor());
jvanverth@google.comd830d132013-11-11 20:54:09 +0000100 // paintAlpha
101 drawState->setColor(SkColorSetARGB(a, a, a, a));
102 // paintColor
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000103 drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor()));
jvanverth@google.comd830d132013-11-11 20:54:09 +0000104 drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
105 } else {
106 // set back to normal in case we took LCD path previously.
107 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
108 drawState->setColor(fPaint.getColor());
109 }
110
111 int nGlyphs = fCurrVertex / 4;
112 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
113 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
114 nGlyphs,
115 4, 6);
116 fDrawTarget->resetVertexSource();
117 fVertices = NULL;
118 fMaxVertices = 0;
119 fCurrVertex = 0;
120 SkSafeSetNull(fCurrTexture);
121 }
122}
123
124namespace {
125
126// position + texture coord
127extern const GrVertexAttrib gTextVertexAttribs[] = {
128 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000129 {kVec2f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding}
jvanverth@google.comd830d132013-11-11 20:54:09 +0000130};
131
132};
133
134void GrDistanceFieldTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000135 SkFixed vx, SkFixed vy,
jvanverth@google.comd830d132013-11-11 20:54:09 +0000136 GrFontScaler* scaler) {
137 if (NULL == fDrawTarget) {
138 return;
139 }
140 if (NULL == fStrike) {
141 fStrike = fContext->getFontCache()->getStrike(scaler, true);
142 }
143
144 GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
145 if (NULL == glyph || glyph->fBounds.isEmpty()) {
146 return;
147 }
148
149 SkScalar sx = SkFixedToScalar(vx);
150 SkScalar sy = SkFixedToScalar(vy);
151/*
152 // not valid, need to find a different solution for this
153 vx += SkIntToFixed(glyph->fBounds.fLeft);
154 vy += SkIntToFixed(glyph->fBounds.fTop);
skia.committer@gmail.com11a253b2013-11-12 07:02:05 +0000155
jvanverth@google.comd830d132013-11-11 20:54:09 +0000156 // keep them as ints until we've done the clip-test
157 GrFixed width = glyph->fBounds.width();
158 GrFixed height = glyph->fBounds.height();
159
160 // check if we clipped out
161 if (true || NULL == glyph->fPlot) {
162 int x = vx >> 16;
163 int y = vy >> 16;
164 if (fClipRect.quickReject(x, y, x + width, y + height)) {
165// SkCLZ(3); // so we can set a break-point in the debugger
166 return;
167 }
168 }
169*/
170 if (NULL == glyph->fPlot) {
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000171 if (fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comd830d132013-11-11 20:54:09 +0000172 goto HAS_ATLAS;
173 }
174
175 // try to clear out an unused plot before we flush
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000176 if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
177 fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comd830d132013-11-11 20:54:09 +0000178 goto HAS_ATLAS;
179 }
180
181 if (c_DumpFontCache) {
182#ifdef SK_DEVELOPER
183 fContext->getFontCache()->dump();
184#endif
185 }
186
187 // before we purge the cache, we must flush any accumulated draws
188 this->flushGlyphs();
189 fContext->flush();
190
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000191 // we should have an unused plot now
192 if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
193 fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comd830d132013-11-11 20:54:09 +0000194 goto HAS_ATLAS;
195 }
196
197 if (NULL == glyph->fPath) {
198 SkPath* path = SkNEW(SkPath);
199 if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
200 // flag the glyph as being dead?
201 delete path;
202 return;
203 }
204 glyph->fPath = path;
205 }
206
207 GrContext::AutoMatrix am;
208 SkMatrix translate;
209 translate.setTranslate(sx, sy);
210 GrPaint tmpPaint(fPaint);
211 am.setPreConcat(fContext, translate, &tmpPaint);
212 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
213 fContext->drawPath(tmpPaint, *glyph->fPath, stroke);
214 return;
215 }
216
217HAS_ATLAS:
218 SkASSERT(glyph->fPlot);
219 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken();
220 glyph->fPlot->setDrawToken(drawToken);
221
222 GrTexture* texture = glyph->fPlot->texture();
223 SkASSERT(texture);
224
225 if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) {
226 this->flushGlyphs();
227 fCurrTexture = texture;
228 fCurrTexture->ref();
229 }
230
231 if (NULL == fVertices) {
232 // If we need to reserve vertices allow the draw target to suggest
233 // a number of verts to reserve and whether to perform a flush.
234 fMaxVertices = kMinRequestedVerts;
235 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
236 SK_ARRAY_COUNT(gTextVertexAttribs));
237 bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL);
238 if (flush) {
239 this->flushGlyphs();
240 fContext->flush();
241 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
242 SK_ARRAY_COUNT(gTextVertexAttribs));
243 }
244 fMaxVertices = kDefaultRequestedVerts;
245 // ignore return, no point in flushing again.
246 fDrawTarget->geometryHints(&fMaxVertices, NULL);
247
248 int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads();
249 if (fMaxVertices < kMinRequestedVerts) {
250 fMaxVertices = kDefaultRequestedVerts;
251 } else if (fMaxVertices > maxQuadVertices) {
252 // don't exceed the limit of the index buffer
253 fMaxVertices = maxQuadVertices;
254 }
255 bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices,
256 0,
257 GrTCast<void**>(&fVertices),
258 NULL);
259 GrAlwaysAssert(success);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000260 SkASSERT(2*sizeof(SkPoint) == fDrawTarget->getDrawState().getVertexSize());
jvanverth@google.comd830d132013-11-11 20:54:09 +0000261 }
262
263 SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft);
264 SkScalar dy = SkIntToScalar(glyph->fBounds.fTop);
265 SkScalar width = SkIntToScalar(glyph->fBounds.width());
266 SkScalar height = SkIntToScalar(glyph->fBounds.height());
267
268 SkScalar scale = fTextRatio;
269 dx *= scale;
270 dy *= scale;
271 sx += dx;
272 sy += dy;
273 width *= scale;
274 height *= scale;
skia.committer@gmail.coma3b53272014-02-15 03:02:15 +0000275
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000276 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX);
277 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY);
278 SkFixed tw = SkIntToFixed(glyph->fBounds.width());
279 SkFixed th = SkIntToFixed(glyph->fBounds.height());
jvanverth@google.comd830d132013-11-11 20:54:09 +0000280
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000281 static const size_t kVertexSize = 2 * sizeof(SkPoint);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000282 fVertices[2*fCurrVertex].setRectFan(sx,
283 sy,
284 sx + width,
285 sy + height,
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000286 kVertexSize);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000287 fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)),
288 SkFixedToFloat(texture->normalizeFixedY(ty)),
289 SkFixedToFloat(texture->normalizeFixedX(tx + tw)),
290 SkFixedToFloat(texture->normalizeFixedY(ty + th)),
commit-bot@chromium.org6c89c342014-02-14 21:48:29 +0000291 kVertexSize);
jvanverth@google.comd830d132013-11-11 20:54:09 +0000292 fCurrVertex += 4;
293}
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000294
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000295inline void GrDistanceFieldTextContext::init(const GrPaint& paint, const SkPaint& skPaint) {
296 GrTextContext::init(paint, skPaint);
297
298 fStrike = NULL;
299
300 fCurrTexture = NULL;
301 fCurrVertex = 0;
302
303 fVertices = NULL;
304 fMaxVertices = 0;
305
306 fTextRatio = fSkPaint.getTextSize()/kBaseDFFontSize;
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000307
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000308 fSkPaint.setTextSize(SkIntToScalar(kBaseDFFontSize));
309 fSkPaint.setLCDRenderText(false);
310 fSkPaint.setAutohinted(false);
commit-bot@chromium.org0bed43c2014-03-14 21:22:38 +0000311 fSkPaint.setSubpixelText(true);
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000312}
313
314inline void GrDistanceFieldTextContext::finish() {
315 flushGlyphs();
316
317 GrTextContext::finish();
318}
319
320void GrDistanceFieldTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
321 const char text[], size_t byteLength,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000322 SkScalar x, SkScalar y) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000323 SkASSERT(byteLength == 0 || text != NULL);
324
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000325 // nothing to draw or can't draw
326 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/
327 || fSkPaint.getRasterizer()) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000328 return;
329 }
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000330
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000331 this->init(paint, skPaint);
332
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000333 SkScalar sizeRatio = fTextRatio;
334
335 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
336
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000337 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, NULL);
338 SkGlyphCache* cache = autoCache.getCache();
339 GrFontScaler* fontScaler = GetGrFontScaler(cache);
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000340
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000341 // need to measure first
342 // TODO - generate positions and pre-load cache as well?
343 const char* stop = text + byteLength;
344 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
345 SkFixed stopX = 0;
346 SkFixed stopY = 0;
347
348 const char* textPtr = text;
349 while (textPtr < stop) {
350 // don't need x, y here, since all subpixel variants will have the
351 // same advance
352 const SkGlyph& glyph = glyphCacheProc(cache, &textPtr, 0, 0);
353
354 stopX += glyph.fAdvanceX;
355 stopY += glyph.fAdvanceY;
356 }
357 SkASSERT(textPtr == stop);
358
359 SkScalar alignX = SkFixedToScalar(stopX)*sizeRatio;
360 SkScalar alignY = SkFixedToScalar(stopY)*sizeRatio;
361
362 if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
363 alignX = SkScalarHalf(alignX);
364 alignY = SkScalarHalf(alignY);
365 }
366
367 x -= alignX;
368 y -= alignY;
369 }
370
371 SkFixed fx = SkScalarToFixed(x) + SK_FixedHalf;
372 SkFixed fy = SkScalarToFixed(y) + SK_FixedHalf;
373 SkFixed fixedScale = SkScalarToFixed(sizeRatio);
374 while (text < stop) {
commit-bot@chromium.orga9dae712014-03-24 18:34:04 +0000375 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000376
377 if (glyph.fWidth) {
378 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
379 glyph.getSubXFixed(),
380 glyph.getSubYFixed()),
381 SkFixedFloorToFixed(fx),
382 SkFixedFloorToFixed(fy),
383 fontScaler);
384 }
385
386 fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale);
387 fy += SkFixedMul_portable(glyph.fAdvanceY, fixedScale);
388 }
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000389
390 this->finish();
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000391}
392
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000393void GrDistanceFieldTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPaint,
394 const char text[], size_t byteLength,
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000395 const SkScalar pos[], SkScalar constY,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000396 int scalarsPerPosition) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000397
398 SkASSERT(byteLength == 0 || text != NULL);
399 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
400
401 // nothing to draw
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000402 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000403 return;
404 }
405
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000406 this->init(paint, skPaint);
407
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000408 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
409
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000410 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, NULL);
411 SkGlyphCache* cache = autoCache.getCache();
412 GrFontScaler* fontScaler = GetGrFontScaler(cache);
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000413
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000414 const char* stop = text + byteLength;
415
416 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
417 while (text < stop) {
418 // the last 2 parameters are ignored
419 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
420
421 if (glyph.fWidth) {
422 SkScalar x = pos[0];
423 SkScalar y = scalarsPerPosition == 1 ? constY : pos[1];
424
425 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
426 glyph.getSubXFixed(),
427 glyph.getSubYFixed()),
428 SkScalarToFixed(x) + SK_FixedHalf, //d1g.fHalfSampleX,
429 SkScalarToFixed(y) + SK_FixedHalf, //d1g.fHalfSampleY,
430 fontScaler);
431 }
432 pos += scalarsPerPosition;
433 }
434 } else {
435 int alignShift = SkPaint::kCenter_Align == fSkPaint.getTextAlign() ? 1 : 0;
436 while (text < stop) {
437 // the last 2 parameters are ignored
438 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
439
440 if (glyph.fWidth) {
441 SkScalar x = pos[0];
442 SkScalar y = scalarsPerPosition == 1 ? constY : pos[1];
skia.committer@gmail.com22e96722013-12-20 07:01:36 +0000443
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000444 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
445 glyph.getSubXFixed(),
446 glyph.getSubYFixed()),
447 SkScalarToFixed(x) - (glyph.fAdvanceX >> alignShift)
448 + SK_FixedHalf, //d1g.fHalfSampleX,
449 SkScalarToFixed(y) - (glyph.fAdvanceY >> alignShift)
450 + SK_FixedHalf, //d1g.fHalfSampleY,
451 fontScaler);
452 }
453 pos += scalarsPerPosition;
454 }
455 }
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000456
457 this->finish();
commit-bot@chromium.org8128d8c2013-12-19 16:12:25 +0000458}