blob: cc657c6eaf6b90434e2cff99928ae4f770cbc342 [file] [log] [blame]
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +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 "GrBitmapTextContext.h"
9#include "GrAtlas.h"
10#include "GrDrawTarget.h"
11#include "GrFontScaler.h"
12#include "GrIndexBuffer.h"
egdanield58a0ba2014-06-11 10:30:05 -070013#include "GrStrokeInfo.h"
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +000014#include "GrTextStrike.h"
15#include "GrTextStrike_impl.h"
commit-bot@chromium.org42a89572013-10-28 15:13:50 +000016#include "SkColorPriv.h"
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +000017#include "SkPath.h"
18#include "SkRTConf.h"
19#include "SkStrokeRec.h"
20#include "effects/GrCustomCoordsTextureEffect.h"
21
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +000022#include "SkAutoKern.h"
commit-bot@chromium.org9f94b912014-01-30 15:22:54 +000023#include "SkDraw.h"
kkinnunencb9a2c82014-06-12 23:06:28 -070024#include "SkDrawProcs.h"
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +000025#include "SkGlyphCache.h"
26#include "SkGpuDevice.h"
27#include "SkGr.h"
kkinnunencb9a2c82014-06-12 23:06:28 -070028#include "SkTextMapStateProc.h"
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +000029
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +000030SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
31 "Dump the contents of the font cache before every purge.");
32
bsalomon594069f2014-06-06 06:16:34 -070033static const int kGlyphCoordsNoColorAttributeIndex = 1;
34static const int kGlyphCoordsWithColorAttributeIndex = 2;
35
36namespace {
37// position + texture coord
38extern const GrVertexAttrib gTextVertexAttribs[] = {
39 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
40 {kVec2f_GrVertexAttribType, sizeof(SkPoint) , kEffect_GrVertexAttribBinding}
41};
42
43// position + color + texture coord
44extern const GrVertexAttrib gTextVertexWithColorAttribs[] = {
45 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
46 {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding},
47 {kVec2f_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kEffect_GrVertexAttribBinding}
48};
49
50};
51
skia.committer@gmail.come5d70152014-01-29 07:01:48 +000052GrBitmapTextContext::GrBitmapTextContext(GrContext* context,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +000053 const SkDeviceProperties& properties)
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +000054 : GrTextContext(context, properties) {
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +000055 fStrike = NULL;
56
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +000057 fCurrVertex = 0;
bsalomon1c63bf62014-07-22 13:09:46 -070058 fEffectTextureUniqueID = SK_InvalidUniqueID;
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +000059
60 fVertices = NULL;
commit-bot@chromium.org3ae0e6c2014-02-11 18:24:25 +000061
62 fVertexBounds.setLargestInverted();
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +000063}
64
65GrBitmapTextContext::~GrBitmapTextContext() {
66 this->flushGlyphs();
67}
68
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +000069bool GrBitmapTextContext::canDraw(const SkPaint& paint) {
70 return !SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix());
71}
72
commit-bot@chromium.org42a89572013-10-28 15:13:50 +000073static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
74 unsigned r = SkColorGetR(c);
75 unsigned g = SkColorGetG(c);
76 unsigned b = SkColorGetB(c);
77 return GrColorPackRGBA(r, g, b, 0xff);
78}
79
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +000080void GrBitmapTextContext::flushGlyphs() {
81 if (NULL == fDrawTarget) {
82 return;
83 }
84
85 GrDrawState* drawState = fDrawTarget->drawState();
86 GrDrawState::AutoRestoreEffects are(drawState);
87 drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget());
88
89 if (fCurrVertex > 0) {
90 // setup our sampler state for our text texture/atlas
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000091 SkASSERT(SkIsAlign4(fCurrVertex));
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +000092 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode);
93
jvanverthf17bc6c2014-07-25 16:46:53 -070094 GrTexture* currTexture = fStrike->getTexture();
95 SkASSERT(currTexture);
96 uint32_t textureUniqueID = currTexture->getUniqueID();
bsalomon8b2fac42014-06-19 14:13:45 -070097
bsalomon1c63bf62014-07-22 13:09:46 -070098 if (textureUniqueID != fEffectTextureUniqueID) {
jvanverthf17bc6c2014-07-25 16:46:53 -070099 fCachedEffect.reset(GrCustomCoordsTextureEffect::Create(currTexture, params));
bsalomon1c63bf62014-07-22 13:09:46 -0700100 fEffectTextureUniqueID = textureUniqueID;
bsalomon8b2fac42014-06-19 14:13:45 -0700101 }
102
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000103 // This effect could be stored with one of the cache objects (atlas?)
bsalomon594069f2014-06-06 06:16:34 -0700104 int coordsIdx = drawState->hasColorVertexAttribute() ? kGlyphCoordsWithColorAttributeIndex :
105 kGlyphCoordsNoColorAttributeIndex;
bsalomon8b2fac42014-06-19 14:13:45 -0700106 drawState->addCoverageEffect(fCachedEffect.get(), coordsIdx);
bsalomon594069f2014-06-06 06:16:34 -0700107 SkASSERT(NULL != fStrike);
108 switch (fStrike->getMaskFormat()) {
109 // Color bitmap text
110 case kARGB_GrMaskFormat:
111 SkASSERT(!drawState->hasColorVertexAttribute());
112 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
113 drawState->setColor(0xffffffff);
114 break;
115 // LCD text
116 case kA888_GrMaskFormat:
117 case kA565_GrMaskFormat: {
118 if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
119 kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
120 fPaint.numColorStages()) {
121 GrPrintf("LCD Text will not draw correctly.\n");
122 }
123 SkASSERT(!drawState->hasColorVertexAttribute());
124 // We don't use the GrPaint's color in this case because it's been premultiplied by
125 // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
126 // the mask texture color. The end result is that we get
127 // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
128 int a = SkColorGetA(fSkPaint.getColor());
129 // paintAlpha
130 drawState->setColor(SkColorSetARGB(a, a, a, a));
131 // paintColor
132 drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor()));
133 drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
134 break;
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000135 }
bsalomon594069f2014-06-06 06:16:34 -0700136 // Grayscale/BW text
137 case kA8_GrMaskFormat:
138 // set back to normal in case we took LCD path previously.
139 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
140 //drawState->setColor(fPaint.getColor());
141 // We're using per-vertex color.
142 SkASSERT(drawState->hasColorVertexAttribute());
143 drawState->setColor(0xFFFFFFFF);
144 break;
145 default:
146 SkFAIL("Unexepected mask format.");
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000147 }
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000148 int nGlyphs = fCurrVertex / 4;
149 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
150 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
151 nGlyphs,
commit-bot@chromium.org3ae0e6c2014-02-11 18:24:25 +0000152 4, 6, &fVertexBounds);
commit-bot@chromium.org42a89572013-10-28 15:13:50 +0000153
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000154 fCurrVertex = 0;
commit-bot@chromium.org3ae0e6c2014-02-11 18:24:25 +0000155 fVertexBounds.setLargestInverted();
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000156 }
jvanverthf17bc6c2014-07-25 16:46:53 -0700157
158 fDrawTarget->resetVertexSource();
159 fVertices = NULL;
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000160}
161
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000162inline void GrBitmapTextContext::init(const GrPaint& paint, const SkPaint& skPaint) {
163 GrTextContext::init(paint, skPaint);
164
165 fStrike = NULL;
166
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000167 fCurrVertex = 0;
168
169 fVertices = NULL;
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000170}
171
172inline void GrBitmapTextContext::finish() {
bsalomon594069f2014-06-06 06:16:34 -0700173 this->flushGlyphs();
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000174
175 GrTextContext::finish();
176}
177
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000178void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000179 const char text[], size_t byteLength,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000180 SkScalar x, SkScalar y) {
181 SkASSERT(byteLength == 0 || text != NULL);
182
183 // nothing to draw
184 if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) {
185 return;
186 }
187
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000188 this->init(paint, skPaint);
189
jvanverthf17bc6c2014-07-25 16:46:53 -0700190 if (NULL == fDrawTarget) {
191 return;
192 }
193
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000194 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
195
196 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMatrix());
197 SkGlyphCache* cache = autoCache.getCache();
198 GrFontScaler* fontScaler = GetGrFontScaler(cache);
jvanverthf17bc6c2014-07-25 16:46:53 -0700199 if (NULL == fStrike) {
200 fStrike = fContext->getFontCache()->getStrike(fontScaler, false);
201 }
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000202
203 // transform our starting point
204 {
205 SkPoint loc;
206 fContext->getMatrix().mapXY(x, y, &loc);
207 x = loc.fX;
208 y = loc.fY;
209 }
210
211 // need to measure first
212 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
213 SkVector stop;
214
215 MeasureText(cache, glyphCacheProc, text, byteLength, &stop);
216
217 SkScalar stopX = stop.fX;
218 SkScalar stopY = stop.fY;
219
220 if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
221 stopX = SkScalarHalf(stopX);
222 stopY = SkScalarHalf(stopY);
223 }
224 x -= stopX;
225 y -= stopY;
226 }
227
228 const char* stop = text + byteLength;
229
jvanverthf17bc6c2014-07-25 16:46:53 -0700230 // allocate vertices
231 SkASSERT(NULL == fVertices);
232 bool useColorVerts = kA8_GrMaskFormat == fStrike->getMaskFormat();
233 if (useColorVerts) {
234 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
235 SK_ARRAY_COUNT(gTextVertexWithColorAttribs));
236 } else {
237 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
238 SK_ARRAY_COUNT(gTextVertexAttribs));
239 }
240 int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
241 bool success = fDrawTarget->reserveVertexAndIndexSpace(4*numGlyphs,
242 0,
243 &fVertices,
244 NULL);
245 GrAlwaysAssert(success);
246
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000247 SkAutoKern autokern;
248
249 SkFixed fxMask = ~0;
250 SkFixed fyMask = ~0;
251 SkFixed halfSampleX, halfSampleY;
252 if (cache->isSubpixel()) {
253 halfSampleX = halfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits);
254 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(fContext->getMatrix());
255 if (kX_SkAxisAlignment == baseline) {
256 fyMask = 0;
257 halfSampleY = SK_FixedHalf;
258 } else if (kY_SkAxisAlignment == baseline) {
259 fxMask = 0;
260 halfSampleX = SK_FixedHalf;
261 }
262 } else {
263 halfSampleX = halfSampleY = SK_FixedHalf;
264 }
265
266 SkFixed fx = SkScalarToFixed(x) + halfSampleX;
267 SkFixed fy = SkScalarToFixed(y) + halfSampleY;
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000268
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000269 GrContext::AutoMatrix autoMatrix;
270 autoMatrix.setIdentity(fContext, &fPaint);
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000271
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000272 while (text < stop) {
273 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
274
275 fx += autokern.adjust(glyph);
276
277 if (glyph.fWidth) {
278 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
279 glyph.getSubXFixed(),
280 glyph.getSubYFixed()),
281 SkFixedFloorToFixed(fx),
282 SkFixedFloorToFixed(fy),
283 fontScaler);
284 }
285
286 fx += glyph.fAdvanceX;
287 fy += glyph.fAdvanceY;
288 }
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000289
290 this->finish();
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000291}
292
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000293void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPaint,
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000294 const char text[], size_t byteLength,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000295 const SkScalar pos[], SkScalar constY,
296 int scalarsPerPosition) {
297 SkASSERT(byteLength == 0 || text != NULL);
298 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
299
300 // nothing to draw
301 if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) {
302 return;
303 }
304
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000305 this->init(paint, skPaint);
306
jvanverthf17bc6c2014-07-25 16:46:53 -0700307 if (NULL == fDrawTarget) {
308 return;
309 }
310
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000311 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
312
313 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMatrix());
314 SkGlyphCache* cache = autoCache.getCache();
315 GrFontScaler* fontScaler = GetGrFontScaler(cache);
jvanverthf17bc6c2014-07-25 16:46:53 -0700316
317 if (NULL == fStrike) {
318 fStrike = fContext->getFontCache()->getStrike(fontScaler, false);
319 }
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000320
321 // store original matrix before we reset, so we can use it to transform positions
322 SkMatrix ctm = fContext->getMatrix();
323 GrContext::AutoMatrix autoMatrix;
324 autoMatrix.setIdentity(fContext, &fPaint);
325
jvanverthf17bc6c2014-07-25 16:46:53 -0700326 // allocate vertices
327 SkASSERT(NULL == fVertices);
328 bool useColorVerts = kA8_GrMaskFormat == fStrike->getMaskFormat();
329 if (useColorVerts) {
330 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
331 SK_ARRAY_COUNT(gTextVertexWithColorAttribs));
332 } else {
333 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
334 SK_ARRAY_COUNT(gTextVertexAttribs));
335 }
336 int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
337 bool success = fDrawTarget->reserveVertexAndIndexSpace(4*numGlyphs,
338 0,
339 &fVertices,
340 NULL);
341 GrAlwaysAssert(success);
342
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000343 const char* stop = text + byteLength;
kkinnunencb9a2c82014-06-12 23:06:28 -0700344 SkTextAlignProc alignProc(fSkPaint.getTextAlign());
345 SkTextMapStateProc tmsProc(ctm, constY, scalarsPerPosition);
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000346 SkFixed halfSampleX = 0, halfSampleY = 0;
347
348 if (cache->isSubpixel()) {
349 // maybe we should skip the rounding if linearText is set
350 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(ctm);
351
352 SkFixed fxMask = ~0;
353 SkFixed fyMask = ~0;
354 if (kX_SkAxisAlignment == baseline) {
355 fyMask = 0;
356#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
357 halfSampleY = SK_FixedHalf;
358#endif
359 } else if (kY_SkAxisAlignment == baseline) {
360 fxMask = 0;
361#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
362 halfSampleX = SK_FixedHalf;
363#endif
364 }
365
366 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
367 while (text < stop) {
kkinnunencb9a2c82014-06-12 23:06:28 -0700368 SkPoint tmsLoc;
369 tmsProc(pos, &tmsLoc);
370 SkFixed fx = SkScalarToFixed(tmsLoc.fX) + halfSampleX;
371 SkFixed fy = SkScalarToFixed(tmsLoc.fY) + halfSampleY;
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000372
373 const SkGlyph& glyph = glyphCacheProc(cache, &text,
374 fx & fxMask, fy & fyMask);
375
376 if (glyph.fWidth) {
377 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
378 glyph.getSubXFixed(),
379 glyph.getSubYFixed()),
380 SkFixedFloorToFixed(fx),
381 SkFixedFloorToFixed(fy),
382 fontScaler);
383 }
384 pos += scalarsPerPosition;
385 }
386 } else {
387 while (text < stop) {
388 const char* currentText = text;
389 const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);
390
391 if (metricGlyph.fWidth) {
392 SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
393 SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
kkinnunencb9a2c82014-06-12 23:06:28 -0700394 SkPoint tmsLoc;
395 tmsProc(pos, &tmsLoc);
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000396 SkIPoint fixedLoc;
kkinnunencb9a2c82014-06-12 23:06:28 -0700397 alignProc(tmsLoc, metricGlyph, &fixedLoc);
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000398
399 SkFixed fx = fixedLoc.fX + halfSampleX;
400 SkFixed fy = fixedLoc.fY + halfSampleY;
401
402 // have to call again, now that we've been "aligned"
403 const SkGlyph& glyph = glyphCacheProc(cache, &currentText,
404 fx & fxMask, fy & fyMask);
405 // the assumption is that the metrics haven't changed
406 SkASSERT(prevAdvX == glyph.fAdvanceX);
407 SkASSERT(prevAdvY == glyph.fAdvanceY);
408 SkASSERT(glyph.fWidth);
409
410 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
411 glyph.getSubXFixed(),
412 glyph.getSubYFixed()),
413 SkFixedFloorToFixed(fx),
414 SkFixedFloorToFixed(fy),
415 fontScaler);
416 }
417 pos += scalarsPerPosition;
418 }
419 }
420 } else { // not subpixel
421
422 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
423 while (text < stop) {
424 // the last 2 parameters are ignored
425 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
426
427 if (glyph.fWidth) {
kkinnunencb9a2c82014-06-12 23:06:28 -0700428 SkPoint tmsLoc;
429 tmsProc(pos, &tmsLoc);
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000430
kkinnunencb9a2c82014-06-12 23:06:28 -0700431 SkFixed fx = SkScalarToFixed(tmsLoc.fX) + SK_FixedHalf; //halfSampleX;
432 SkFixed fy = SkScalarToFixed(tmsLoc.fY) + SK_FixedHalf; //halfSampleY;
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000433 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
434 glyph.getSubXFixed(),
435 glyph.getSubYFixed()),
436 SkFixedFloorToFixed(fx),
437 SkFixedFloorToFixed(fy),
438 fontScaler);
439 }
440 pos += scalarsPerPosition;
441 }
442 } else {
443 while (text < stop) {
444 // the last 2 parameters are ignored
445 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
446
447 if (glyph.fWidth) {
kkinnunencb9a2c82014-06-12 23:06:28 -0700448 SkPoint tmsLoc;
449 tmsProc(pos, &tmsLoc);
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000450
451 SkIPoint fixedLoc;
kkinnunencb9a2c82014-06-12 23:06:28 -0700452 alignProc(tmsLoc, glyph, &fixedLoc);
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000453
454 SkFixed fx = fixedLoc.fX + SK_FixedHalf; //halfSampleX;
455 SkFixed fy = fixedLoc.fY + SK_FixedHalf; //halfSampleY;
456 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
457 glyph.getSubXFixed(),
458 glyph.getSubYFixed()),
459 SkFixedFloorToFixed(fx),
460 SkFixedFloorToFixed(fy),
461 fontScaler);
462 }
463 pos += scalarsPerPosition;
464 }
465 }
466 }
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000467
468 this->finish();
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000469}
470
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000471void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000472 SkFixed vx, SkFixed vy,
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000473 GrFontScaler* scaler) {
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000474 GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
475 if (NULL == glyph || glyph->fBounds.isEmpty()) {
476 return;
477 }
478
479 vx += SkIntToFixed(glyph->fBounds.fLeft);
480 vy += SkIntToFixed(glyph->fBounds.fTop);
481
482 // keep them as ints until we've done the clip-test
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000483 SkFixed width = glyph->fBounds.width();
484 SkFixed height = glyph->fBounds.height();
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000485
486 // check if we clipped out
487 if (true || NULL == glyph->fPlot) {
488 int x = vx >> 16;
489 int y = vy >> 16;
490 if (fClipRect.quickReject(x, y, x + width, y + height)) {
491// SkCLZ(3); // so we can set a break-point in the debugger
492 return;
493 }
494 }
495
496 if (NULL == glyph->fPlot) {
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000497 if (fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000498 goto HAS_ATLAS;
499 }
500
501 // try to clear out an unused plot before we flush
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000502 if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
503 fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000504 goto HAS_ATLAS;
505 }
506
507 if (c_DumpFontCache) {
508#ifdef SK_DEVELOPER
509 fContext->getFontCache()->dump();
510#endif
511 }
512
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000513 // flush any accumulated draws to allow us to free up a plot
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000514 this->flushGlyphs();
515 fContext->flush();
516
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000517 // we should have an unused plot now
518 if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
519 fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000520 goto HAS_ATLAS;
521 }
522
523 if (NULL == glyph->fPath) {
524 SkPath* path = SkNEW(SkPath);
525 if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
526 // flag the glyph as being dead?
527 delete path;
528 return;
529 }
530 glyph->fPath = path;
531 }
532
533 GrContext::AutoMatrix am;
534 SkMatrix translate;
535 translate.setTranslate(SkFixedToScalar(vx - SkIntToFixed(glyph->fBounds.fLeft)),
536 SkFixedToScalar(vy - SkIntToFixed(glyph->fBounds.fTop)));
537 GrPaint tmpPaint(fPaint);
538 am.setPreConcat(fContext, translate, &tmpPaint);
egdanield58a0ba2014-06-11 10:30:05 -0700539 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
540 fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo);
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000541 return;
542 }
543
544HAS_ATLAS:
545 SkASSERT(glyph->fPlot);
546 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken();
547 glyph->fPlot->setDrawToken(drawToken);
548
549 // now promote them to fixed (TODO: Rethink using fixed pt).
550 width = SkIntToFixed(width);
551 height = SkIntToFixed(height);
552
553 GrTexture* texture = glyph->fPlot->texture();
554 SkASSERT(texture);
555
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000556 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX);
557 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY);
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000558
commit-bot@chromium.org3ae0e6c2014-02-11 18:24:25 +0000559 SkRect r;
560 r.fLeft = SkFixedToFloat(vx);
561 r.fTop = SkFixedToFloat(vy);
562 r.fRight = SkFixedToFloat(vx + width);
563 r.fBottom = SkFixedToFloat(vy + height);
564
565 fVertexBounds.growToInclude(r);
566
jvanverthf17bc6c2014-07-25 16:46:53 -0700567 bool useColorVerts = kA8_GrMaskFormat == fStrike->getMaskFormat();
bsalomon594069f2014-06-06 06:16:34 -0700568 size_t vertSize = useColorVerts ? (2 * sizeof(SkPoint) + sizeof(GrColor)) :
569 (2 * sizeof(SkPoint));
570
571 SkASSERT(vertSize == fDrawTarget->getDrawState().getVertexSize());
572
573 SkPoint* positions = reinterpret_cast<SkPoint*>(
574 reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex);
575 positions->setRectFan(r.fLeft, r.fTop, r.fRight, r.fBottom, vertSize);
576
577 // The texture coords are last in both the with and without color vertex layouts.
578 SkPoint* textureCoords = reinterpret_cast<SkPoint*>(
579 reinterpret_cast<intptr_t>(positions) + vertSize - sizeof(SkPoint));
580 textureCoords->setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)),
581 SkFixedToFloat(texture->normalizeFixedY(ty)),
582 SkFixedToFloat(texture->normalizeFixedX(tx + width)),
583 SkFixedToFloat(texture->normalizeFixedY(ty + height)),
584 vertSize);
585 if (useColorVerts) {
586 // color comes after position.
587 GrColor* colors = reinterpret_cast<GrColor*>(positions + 1);
588 for (int i = 0; i < 4; ++i) {
589 *colors = fPaint.getColor();
590 colors = reinterpret_cast<GrColor*>(reinterpret_cast<intptr_t>(colors) + vertSize);
591 }
592 }
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000593 fCurrVertex += 4;
594}