blob: fe3fa31c196a8d8ba3e4f480e6a3d5009dbb5062 [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
57 fCurrTexture = NULL;
58 fCurrVertex = 0;
bsalomon1c63bf62014-07-22 13:09:46 -070059 fEffectTextureUniqueID = SK_InvalidUniqueID;
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +000060
61 fVertices = NULL;
commit-bot@chromium.org3ae0e6c2014-02-11 18:24:25 +000062
63 fVertexBounds.setLargestInverted();
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +000064}
65
66GrBitmapTextContext::~GrBitmapTextContext() {
67 this->flushGlyphs();
68}
69
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +000070bool GrBitmapTextContext::canDraw(const SkPaint& paint) {
71 return !SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix());
72}
73
commit-bot@chromium.org42a89572013-10-28 15:13:50 +000074static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
75 unsigned r = SkColorGetR(c);
76 unsigned g = SkColorGetG(c);
77 unsigned b = SkColorGetB(c);
78 return GrColorPackRGBA(r, g, b, 0xff);
79}
80
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +000081void GrBitmapTextContext::flushGlyphs() {
82 if (NULL == fDrawTarget) {
83 return;
84 }
85
86 GrDrawState* drawState = fDrawTarget->drawState();
87 GrDrawState::AutoRestoreEffects are(drawState);
88 drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget());
89
90 if (fCurrVertex > 0) {
91 // setup our sampler state for our text texture/atlas
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000092 SkASSERT(SkIsAlign4(fCurrVertex));
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +000093 SkASSERT(fCurrTexture);
94 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode);
95
bsalomon1c63bf62014-07-22 13:09:46 -070096 uint32_t textureUniqueID = fCurrTexture->getUniqueID();
bsalomon8b2fac42014-06-19 14:13:45 -070097
bsalomon1c63bf62014-07-22 13:09:46 -070098 if (textureUniqueID != fEffectTextureUniqueID) {
bsalomon8b2fac42014-06-19 14:13:45 -070099 fCachedEffect.reset(GrCustomCoordsTextureEffect::Create(fCurrTexture, 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 fDrawTarget->resetVertexSource();
155 fVertices = NULL;
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000156 fCurrVertex = 0;
commit-bot@chromium.org3ae0e6c2014-02-11 18:24:25 +0000157 fVertexBounds.setLargestInverted();
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000158 SkSafeSetNull(fCurrTexture);
159 }
160}
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
167 fCurrTexture = NULL;
168 fCurrVertex = 0;
169
170 fVertices = NULL;
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000171}
172
173inline void GrBitmapTextContext::finish() {
bsalomon594069f2014-06-06 06:16:34 -0700174 this->flushGlyphs();
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000175
176 GrTextContext::finish();
177}
178
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000179void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000180 const char text[], size_t byteLength,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000181 SkScalar x, SkScalar y) {
182 SkASSERT(byteLength == 0 || text != NULL);
183
184 // nothing to draw
185 if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) {
186 return;
187 }
188
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000189 this->init(paint, skPaint);
190
jvanverth1d386192014-07-25 11:31:13 -0700191 if (NULL == fDrawTarget) {
192 return;
193 }
194
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000195 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
196
197 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMatrix());
198 SkGlyphCache* cache = autoCache.getCache();
199 GrFontScaler* fontScaler = GetGrFontScaler(cache);
jvanverth1d386192014-07-25 11:31:13 -0700200 if (NULL == fStrike) {
201 fStrike = fContext->getFontCache()->getStrike(fontScaler, false);
202 }
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000203
204 // transform our starting point
205 {
206 SkPoint loc;
207 fContext->getMatrix().mapXY(x, y, &loc);
208 x = loc.fX;
209 y = loc.fY;
210 }
211
212 // need to measure first
213 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
214 SkVector stop;
215
216 MeasureText(cache, glyphCacheProc, text, byteLength, &stop);
217
218 SkScalar stopX = stop.fX;
219 SkScalar stopY = stop.fY;
220
221 if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
222 stopX = SkScalarHalf(stopX);
223 stopY = SkScalarHalf(stopY);
224 }
225 x -= stopX;
226 y -= stopY;
227 }
228
229 const char* stop = text + byteLength;
230
jvanverth1d386192014-07-25 11:31:13 -0700231 // allocate vertices
232 SkASSERT(NULL == fVertices);
233 bool useColorVerts = kA8_GrMaskFormat == fStrike->getMaskFormat();
234 if (useColorVerts) {
235 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
236 SK_ARRAY_COUNT(gTextVertexWithColorAttribs));
237 } else {
238 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
239 SK_ARRAY_COUNT(gTextVertexAttribs));
240 }
241 int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
242 bool success = fDrawTarget->reserveVertexAndIndexSpace(4*numGlyphs,
243 0,
244 &fVertices,
245 NULL);
246 GrAlwaysAssert(success);
247
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000248 SkAutoKern autokern;
249
250 SkFixed fxMask = ~0;
251 SkFixed fyMask = ~0;
252 SkFixed halfSampleX, halfSampleY;
253 if (cache->isSubpixel()) {
254 halfSampleX = halfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits);
255 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(fContext->getMatrix());
256 if (kX_SkAxisAlignment == baseline) {
257 fyMask = 0;
258 halfSampleY = SK_FixedHalf;
259 } else if (kY_SkAxisAlignment == baseline) {
260 fxMask = 0;
261 halfSampleX = SK_FixedHalf;
262 }
263 } else {
264 halfSampleX = halfSampleY = SK_FixedHalf;
265 }
266
267 SkFixed fx = SkScalarToFixed(x) + halfSampleX;
268 SkFixed fy = SkScalarToFixed(y) + halfSampleY;
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000269
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000270 GrContext::AutoMatrix autoMatrix;
271 autoMatrix.setIdentity(fContext, &fPaint);
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000272
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000273 while (text < stop) {
274 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
275
276 fx += autokern.adjust(glyph);
277
278 if (glyph.fWidth) {
279 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
280 glyph.getSubXFixed(),
281 glyph.getSubYFixed()),
282 SkFixedFloorToFixed(fx),
283 SkFixedFloorToFixed(fy),
284 fontScaler);
285 }
286
287 fx += glyph.fAdvanceX;
288 fy += glyph.fAdvanceY;
289 }
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000290
291 this->finish();
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000292}
293
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000294void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPaint,
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000295 const char text[], size_t byteLength,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000296 const SkScalar pos[], SkScalar constY,
297 int scalarsPerPosition) {
298 SkASSERT(byteLength == 0 || text != NULL);
299 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
300
301 // nothing to draw
302 if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) {
303 return;
304 }
305
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000306 this->init(paint, skPaint);
307
jvanverth1d386192014-07-25 11:31:13 -0700308 if (NULL == fDrawTarget) {
309 return;
310 }
311
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000312 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
313
314 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMatrix());
315 SkGlyphCache* cache = autoCache.getCache();
316 GrFontScaler* fontScaler = GetGrFontScaler(cache);
jvanverth1d386192014-07-25 11:31:13 -0700317
318 if (NULL == fStrike) {
319 fStrike = fContext->getFontCache()->getStrike(fontScaler, false);
320 }
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000321
322 // store original matrix before we reset, so we can use it to transform positions
323 SkMatrix ctm = fContext->getMatrix();
324 GrContext::AutoMatrix autoMatrix;
325 autoMatrix.setIdentity(fContext, &fPaint);
326
jvanverth1d386192014-07-25 11:31:13 -0700327 // allocate vertices
328 SkASSERT(NULL == fVertices);
329 bool useColorVerts = kA8_GrMaskFormat == fStrike->getMaskFormat();
330 if (useColorVerts) {
331 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
332 SK_ARRAY_COUNT(gTextVertexWithColorAttribs));
333 } else {
334 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
335 SK_ARRAY_COUNT(gTextVertexAttribs));
336 }
337 int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
338 bool success = fDrawTarget->reserveVertexAndIndexSpace(4*numGlyphs,
339 0,
340 &fVertices,
341 NULL);
342 GrAlwaysAssert(success);
343
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000344 const char* stop = text + byteLength;
kkinnunencb9a2c82014-06-12 23:06:28 -0700345 SkTextAlignProc alignProc(fSkPaint.getTextAlign());
346 SkTextMapStateProc tmsProc(ctm, constY, scalarsPerPosition);
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000347 SkFixed halfSampleX = 0, halfSampleY = 0;
348
349 if (cache->isSubpixel()) {
350 // maybe we should skip the rounding if linearText is set
351 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(ctm);
352
353 SkFixed fxMask = ~0;
354 SkFixed fyMask = ~0;
355 if (kX_SkAxisAlignment == baseline) {
356 fyMask = 0;
357#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
358 halfSampleY = SK_FixedHalf;
359#endif
360 } else if (kY_SkAxisAlignment == baseline) {
361 fxMask = 0;
362#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
363 halfSampleX = SK_FixedHalf;
364#endif
365 }
366
367 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
368 while (text < stop) {
kkinnunencb9a2c82014-06-12 23:06:28 -0700369 SkPoint tmsLoc;
370 tmsProc(pos, &tmsLoc);
371 SkFixed fx = SkScalarToFixed(tmsLoc.fX) + halfSampleX;
372 SkFixed fy = SkScalarToFixed(tmsLoc.fY) + halfSampleY;
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000373
374 const SkGlyph& glyph = glyphCacheProc(cache, &text,
375 fx & fxMask, fy & fyMask);
376
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 pos += scalarsPerPosition;
386 }
387 } else {
388 while (text < stop) {
389 const char* currentText = text;
390 const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);
391
392 if (metricGlyph.fWidth) {
393 SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
394 SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
kkinnunencb9a2c82014-06-12 23:06:28 -0700395 SkPoint tmsLoc;
396 tmsProc(pos, &tmsLoc);
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000397 SkIPoint fixedLoc;
kkinnunencb9a2c82014-06-12 23:06:28 -0700398 alignProc(tmsLoc, metricGlyph, &fixedLoc);
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000399
400 SkFixed fx = fixedLoc.fX + halfSampleX;
401 SkFixed fy = fixedLoc.fY + halfSampleY;
402
403 // have to call again, now that we've been "aligned"
404 const SkGlyph& glyph = glyphCacheProc(cache, &currentText,
405 fx & fxMask, fy & fyMask);
406 // the assumption is that the metrics haven't changed
407 SkASSERT(prevAdvX == glyph.fAdvanceX);
408 SkASSERT(prevAdvY == glyph.fAdvanceY);
409 SkASSERT(glyph.fWidth);
410
411 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
412 glyph.getSubXFixed(),
413 glyph.getSubYFixed()),
414 SkFixedFloorToFixed(fx),
415 SkFixedFloorToFixed(fy),
416 fontScaler);
417 }
418 pos += scalarsPerPosition;
419 }
420 }
421 } else { // not subpixel
422
423 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
424 while (text < stop) {
425 // the last 2 parameters are ignored
426 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
427
428 if (glyph.fWidth) {
kkinnunencb9a2c82014-06-12 23:06:28 -0700429 SkPoint tmsLoc;
430 tmsProc(pos, &tmsLoc);
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000431
kkinnunencb9a2c82014-06-12 23:06:28 -0700432 SkFixed fx = SkScalarToFixed(tmsLoc.fX) + SK_FixedHalf; //halfSampleX;
433 SkFixed fy = SkScalarToFixed(tmsLoc.fY) + SK_FixedHalf; //halfSampleY;
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000434 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
435 glyph.getSubXFixed(),
436 glyph.getSubYFixed()),
437 SkFixedFloorToFixed(fx),
438 SkFixedFloorToFixed(fy),
439 fontScaler);
440 }
441 pos += scalarsPerPosition;
442 }
443 } else {
444 while (text < stop) {
445 // the last 2 parameters are ignored
446 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
447
448 if (glyph.fWidth) {
kkinnunencb9a2c82014-06-12 23:06:28 -0700449 SkPoint tmsLoc;
450 tmsProc(pos, &tmsLoc);
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000451
452 SkIPoint fixedLoc;
kkinnunencb9a2c82014-06-12 23:06:28 -0700453 alignProc(tmsLoc, glyph, &fixedLoc);
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000454
455 SkFixed fx = fixedLoc.fX + SK_FixedHalf; //halfSampleX;
456 SkFixed fy = fixedLoc.fY + SK_FixedHalf; //halfSampleY;
457 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
458 glyph.getSubXFixed(),
459 glyph.getSubYFixed()),
460 SkFixedFloorToFixed(fx),
461 SkFixedFloorToFixed(fy),
462 fontScaler);
463 }
464 pos += scalarsPerPosition;
465 }
466 }
467 }
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000468
469 this->finish();
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000470}
471
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000472void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000473 SkFixed vx, SkFixed vy,
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000474 GrFontScaler* scaler) {
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000475 GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
476 if (NULL == glyph || glyph->fBounds.isEmpty()) {
477 return;
478 }
479
480 vx += SkIntToFixed(glyph->fBounds.fLeft);
481 vy += SkIntToFixed(glyph->fBounds.fTop);
482
483 // keep them as ints until we've done the clip-test
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000484 SkFixed width = glyph->fBounds.width();
485 SkFixed height = glyph->fBounds.height();
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000486
487 // check if we clipped out
488 if (true || NULL == glyph->fPlot) {
489 int x = vx >> 16;
490 int y = vy >> 16;
491 if (fClipRect.quickReject(x, y, x + width, y + height)) {
492// SkCLZ(3); // so we can set a break-point in the debugger
493 return;
494 }
495 }
496
497 if (NULL == glyph->fPlot) {
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000498 if (fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000499 goto HAS_ATLAS;
500 }
501
502 // try to clear out an unused plot before we flush
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000503 if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
504 fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000505 goto HAS_ATLAS;
506 }
507
508 if (c_DumpFontCache) {
509#ifdef SK_DEVELOPER
510 fContext->getFontCache()->dump();
511#endif
512 }
513
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000514 // flush any accumulated draws to allow us to free up a plot
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000515 this->flushGlyphs();
516 fContext->flush();
517
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000518 // we should have an unused plot now
519 if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
520 fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000521 goto HAS_ATLAS;
522 }
523
524 if (NULL == glyph->fPath) {
525 SkPath* path = SkNEW(SkPath);
526 if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
527 // flag the glyph as being dead?
528 delete path;
529 return;
530 }
531 glyph->fPath = path;
532 }
533
534 GrContext::AutoMatrix am;
535 SkMatrix translate;
536 translate.setTranslate(SkFixedToScalar(vx - SkIntToFixed(glyph->fBounds.fLeft)),
537 SkFixedToScalar(vy - SkIntToFixed(glyph->fBounds.fTop)));
538 GrPaint tmpPaint(fPaint);
539 am.setPreConcat(fContext, translate, &tmpPaint);
egdanield58a0ba2014-06-11 10:30:05 -0700540 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
541 fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo);
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000542 return;
543 }
544
545HAS_ATLAS:
546 SkASSERT(glyph->fPlot);
547 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken();
548 glyph->fPlot->setDrawToken(drawToken);
549
550 // now promote them to fixed (TODO: Rethink using fixed pt).
551 width = SkIntToFixed(width);
552 height = SkIntToFixed(height);
553
554 GrTexture* texture = glyph->fPlot->texture();
555 SkASSERT(texture);
556
jvanverth1d386192014-07-25 11:31:13 -0700557 if (fCurrTexture != texture) {
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000558 this->flushGlyphs();
559 fCurrTexture = texture;
560 fCurrTexture->ref();
561 }
562
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000563 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX);
564 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY);
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000565
commit-bot@chromium.org3ae0e6c2014-02-11 18:24:25 +0000566 SkRect r;
567 r.fLeft = SkFixedToFloat(vx);
568 r.fTop = SkFixedToFloat(vy);
569 r.fRight = SkFixedToFloat(vx + width);
570 r.fBottom = SkFixedToFloat(vy + height);
571
572 fVertexBounds.growToInclude(r);
573
jvanverth1d386192014-07-25 11:31:13 -0700574 bool useColorVerts = kA8_GrMaskFormat == fStrike->getMaskFormat();
bsalomon594069f2014-06-06 06:16:34 -0700575 size_t vertSize = useColorVerts ? (2 * sizeof(SkPoint) + sizeof(GrColor)) :
576 (2 * sizeof(SkPoint));
577
578 SkASSERT(vertSize == fDrawTarget->getDrawState().getVertexSize());
579
580 SkPoint* positions = reinterpret_cast<SkPoint*>(
581 reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex);
582 positions->setRectFan(r.fLeft, r.fTop, r.fRight, r.fBottom, vertSize);
583
584 // The texture coords are last in both the with and without color vertex layouts.
585 SkPoint* textureCoords = reinterpret_cast<SkPoint*>(
586 reinterpret_cast<intptr_t>(positions) + vertSize - sizeof(SkPoint));
587 textureCoords->setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)),
588 SkFixedToFloat(texture->normalizeFixedY(ty)),
589 SkFixedToFloat(texture->normalizeFixedX(tx + width)),
590 SkFixedToFloat(texture->normalizeFixedY(ty + height)),
591 vertSize);
592 if (useColorVerts) {
593 // color comes after position.
594 GrColor* colors = reinterpret_cast<GrColor*>(positions + 1);
595 for (int i = 0; i < 4; ++i) {
596 *colors = fPaint.getColor();
597 colors = reinterpret_cast<GrColor*>(reinterpret_cast<intptr_t>(colors) + vertSize);
598 }
599 }
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000600 fCurrVertex += 4;
601}