blob: 17439b5672c6dbdca16c9ef4e7bd211fcaf10007 [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
egdaniel7b3d5ee2014-08-28 05:41:14 -070043static const size_t kTextVASize = 2 * sizeof(SkPoint);
44
bsalomon594069f2014-06-06 06:16:34 -070045// position + color + texture coord
46extern const GrVertexAttrib gTextVertexWithColorAttribs[] = {
47 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
48 {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding},
49 {kVec2f_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kEffect_GrVertexAttribBinding}
50};
51
egdaniel7b3d5ee2014-08-28 05:41:14 -070052static const size_t kTextVAColorSize = 2 * sizeof(SkPoint) + sizeof(GrColor);
53
bsalomon594069f2014-06-06 06:16:34 -070054};
55
skia.committer@gmail.come5d70152014-01-29 07:01:48 +000056GrBitmapTextContext::GrBitmapTextContext(GrContext* context,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +000057 const SkDeviceProperties& properties)
jvanverth63b9dc82014-08-28 10:39:40 -070058 : GrTextContext(context, properties)
59 , fStrike(NULL)
60 , fEffectTextureUniqueID(SK_InvalidUniqueID)
61 , fVertices(NULL)
62 , fVertexCount(0)
63 , fCurrVertex(0) {
commit-bot@chromium.org3ae0e6c2014-02-11 18:24:25 +000064 fVertexBounds.setLargestInverted();
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +000065}
66
67GrBitmapTextContext::~GrBitmapTextContext() {
68 this->flushGlyphs();
69}
70
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +000071bool GrBitmapTextContext::canDraw(const SkPaint& paint) {
72 return !SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix());
73}
74
commit-bot@chromium.org42a89572013-10-28 15:13:50 +000075static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
76 unsigned r = SkColorGetR(c);
77 unsigned g = SkColorGetG(c);
78 unsigned b = SkColorGetB(c);
79 return GrColorPackRGBA(r, g, b, 0xff);
80}
81
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +000082void GrBitmapTextContext::flushGlyphs() {
83 if (NULL == fDrawTarget) {
84 return;
85 }
86
87 GrDrawState* drawState = fDrawTarget->drawState();
88 GrDrawState::AutoRestoreEffects are(drawState);
89 drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget());
90
91 if (fCurrVertex > 0) {
92 // setup our sampler state for our text texture/atlas
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +000093 SkASSERT(SkIsAlign4(fCurrVertex));
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +000094 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode);
95
jvanverth63b9dc82014-08-28 10:39:40 -070096 GrTexture* currTexture = fStrike->getTexture();
97 SkASSERT(currTexture);
98 uint32_t textureUniqueID = currTexture->getUniqueID();
bsalomon8b2fac42014-06-19 14:13:45 -070099
bsalomon1c63bf62014-07-22 13:09:46 -0700100 if (textureUniqueID != fEffectTextureUniqueID) {
jvanverth63b9dc82014-08-28 10:39:40 -0700101 fCachedEffect.reset(GrCustomCoordsTextureEffect::Create(currTexture, params));
bsalomon1c63bf62014-07-22 13:09:46 -0700102 fEffectTextureUniqueID = textureUniqueID;
bsalomon8b2fac42014-06-19 14:13:45 -0700103 }
104
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000105 // This effect could be stored with one of the cache objects (atlas?)
bsalomon594069f2014-06-06 06:16:34 -0700106 int coordsIdx = drawState->hasColorVertexAttribute() ? kGlyphCoordsWithColorAttributeIndex :
107 kGlyphCoordsNoColorAttributeIndex;
bsalomon8b2fac42014-06-19 14:13:45 -0700108 drawState->addCoverageEffect(fCachedEffect.get(), coordsIdx);
bsalomon594069f2014-06-06 06:16:34 -0700109 SkASSERT(NULL != fStrike);
110 switch (fStrike->getMaskFormat()) {
111 // Color bitmap text
112 case kARGB_GrMaskFormat:
113 SkASSERT(!drawState->hasColorVertexAttribute());
114 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
115 drawState->setColor(0xffffffff);
116 break;
117 // LCD text
118 case kA888_GrMaskFormat:
119 case kA565_GrMaskFormat: {
120 if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
121 kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
122 fPaint.numColorStages()) {
123 GrPrintf("LCD Text will not draw correctly.\n");
124 }
125 SkASSERT(!drawState->hasColorVertexAttribute());
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
130 int a = SkColorGetA(fSkPaint.getColor());
131 // paintAlpha
132 drawState->setColor(SkColorSetARGB(a, a, a, a));
133 // paintColor
134 drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor()));
135 drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
136 break;
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000137 }
bsalomon594069f2014-06-06 06:16:34 -0700138 // Grayscale/BW text
139 case kA8_GrMaskFormat:
140 // set back to normal in case we took LCD path previously.
141 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
bsalomon594069f2014-06-06 06:16:34 -0700142 // We're using per-vertex color.
143 SkASSERT(drawState->hasColorVertexAttribute());
bsalomon594069f2014-06-06 06:16:34 -0700144 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);
jvanverth63b9dc82014-08-28 10:39:40 -0700153 fVertexCount = 0;
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 }
jvanverth63b9dc82014-08-28 10:39:40 -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
djsollen2e1a8262014-08-27 13:12:25 -0700167 fVertices = NULL;
jvanverth63b9dc82014-08-28 10:39:40 -0700168 fVertexCount = 0;
169 fCurrVertex = 0;
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
jvanverth63b9dc82014-08-28 10:39:40 -0700178void GrBitmapTextContext::allocateVertices(const char text[], size_t byteLength) {
179 SkASSERT(NULL == fVertices);
180 bool useColorVerts = kA8_GrMaskFormat == fStrike->getMaskFormat();
181 if (useColorVerts) {
182 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
183 SK_ARRAY_COUNT(gTextVertexWithColorAttribs),
184 kTextVAColorSize);
185 } else {
186 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
187 SK_ARRAY_COUNT(gTextVertexAttribs),
188 kTextVASize);
189 }
190 fVertexCount = 4*fSkPaint.textToGlyphs(text, byteLength, NULL);
191 bool success = fDrawTarget->reserveVertexAndIndexSpace(fVertexCount,
192 0,
193 &fVertices,
194 NULL);
195 GrAlwaysAssert(success);
196}
197
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000198void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000199 const char text[], size_t byteLength,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000200 SkScalar x, SkScalar y) {
201 SkASSERT(byteLength == 0 || text != NULL);
202
203 // nothing to draw
204 if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) {
205 return;
206 }
207
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000208 this->init(paint, skPaint);
jvanverth63b9dc82014-08-28 10:39:40 -0700209
210 if (NULL == fDrawTarget) {
211 return;
212 }
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000213
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000214 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
215
216 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMatrix());
217 SkGlyphCache* cache = autoCache.getCache();
218 GrFontScaler* fontScaler = GetGrFontScaler(cache);
jvanverth63b9dc82014-08-28 10:39:40 -0700219 if (NULL == fStrike) {
220 fStrike = fContext->getFontCache()->getStrike(fontScaler, false);
221 }
222
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000223 // transform our starting point
224 {
225 SkPoint loc;
226 fContext->getMatrix().mapXY(x, y, &loc);
227 x = loc.fX;
228 y = loc.fY;
229 }
230
231 // need to measure first
232 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
233 SkVector stop;
234
235 MeasureText(cache, glyphCacheProc, text, byteLength, &stop);
236
237 SkScalar stopX = stop.fX;
238 SkScalar stopY = stop.fY;
239
240 if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
241 stopX = SkScalarHalf(stopX);
242 stopY = SkScalarHalf(stopY);
243 }
244 x -= stopX;
245 y -= stopY;
246 }
247
248 const char* stop = text + byteLength;
249
jvanverth63b9dc82014-08-28 10:39:40 -0700250 this->allocateVertices(text, byteLength);
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000251
252 SkFixed fxMask = ~0;
253 SkFixed fyMask = ~0;
254 SkFixed halfSampleX, halfSampleY;
255 if (cache->isSubpixel()) {
256 halfSampleX = halfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits);
257 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(fContext->getMatrix());
258 if (kX_SkAxisAlignment == baseline) {
259 fyMask = 0;
260 halfSampleY = SK_FixedHalf;
261 } else if (kY_SkAxisAlignment == baseline) {
262 fxMask = 0;
263 halfSampleX = SK_FixedHalf;
264 }
265 } else {
266 halfSampleX = halfSampleY = SK_FixedHalf;
267 }
268
269 SkFixed fx = SkScalarToFixed(x) + halfSampleX;
270 SkFixed fy = SkScalarToFixed(y) + halfSampleY;
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000271
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000272 GrContext::AutoMatrix autoMatrix;
273 autoMatrix.setIdentity(fContext, &fPaint);
skia.committer@gmail.come5d70152014-01-29 07:01:48 +0000274
jvanverth63b9dc82014-08-28 10:39:40 -0700275 SkAutoKern autokern;
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000276 while (text < stop) {
277 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
278
279 fx += autokern.adjust(glyph);
280
281 if (glyph.fWidth) {
282 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
283 glyph.getSubXFixed(),
284 glyph.getSubYFixed()),
285 SkFixedFloorToFixed(fx),
286 SkFixedFloorToFixed(fy),
287 fontScaler);
288 }
289
290 fx += glyph.fAdvanceX;
291 fy += glyph.fAdvanceY;
292 }
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000293
294 this->finish();
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000295}
296
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000297void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPaint,
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000298 const char text[], size_t byteLength,
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000299 const SkScalar pos[], SkScalar constY,
300 int scalarsPerPosition) {
301 SkASSERT(byteLength == 0 || text != NULL);
302 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
303
304 // nothing to draw
305 if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) {
306 return;
307 }
308
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000309 this->init(paint, skPaint);
310
jvanverth63b9dc82014-08-28 10:39:40 -0700311 if (NULL == fDrawTarget) {
312 return;
313 }
314
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000315 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
316
317 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMatrix());
318 SkGlyphCache* cache = autoCache.getCache();
319 GrFontScaler* fontScaler = GetGrFontScaler(cache);
jvanverth63b9dc82014-08-28 10:39:40 -0700320 if (NULL == fStrike) {
321 fStrike = fContext->getFontCache()->getStrike(fontScaler, false);
322 }
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000323
324 // store original matrix before we reset, so we can use it to transform positions
325 SkMatrix ctm = fContext->getMatrix();
326 GrContext::AutoMatrix autoMatrix;
327 autoMatrix.setIdentity(fContext, &fPaint);
328
jvanverth63b9dc82014-08-28 10:39:40 -0700329 this->allocateVertices(text, byteLength);
330
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000331 const char* stop = text + byteLength;
kkinnunencb9a2c82014-06-12 23:06:28 -0700332 SkTextAlignProc alignProc(fSkPaint.getTextAlign());
333 SkTextMapStateProc tmsProc(ctm, constY, scalarsPerPosition);
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000334 SkFixed halfSampleX = 0, halfSampleY = 0;
335
336 if (cache->isSubpixel()) {
337 // maybe we should skip the rounding if linearText is set
338 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(ctm);
339
340 SkFixed fxMask = ~0;
341 SkFixed fyMask = ~0;
342 if (kX_SkAxisAlignment == baseline) {
343 fyMask = 0;
344#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
345 halfSampleY = SK_FixedHalf;
346#endif
347 } else if (kY_SkAxisAlignment == baseline) {
348 fxMask = 0;
349#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
350 halfSampleX = SK_FixedHalf;
351#endif
352 }
353
354 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
355 while (text < stop) {
kkinnunencb9a2c82014-06-12 23:06:28 -0700356 SkPoint tmsLoc;
357 tmsProc(pos, &tmsLoc);
358 SkFixed fx = SkScalarToFixed(tmsLoc.fX) + halfSampleX;
359 SkFixed fy = SkScalarToFixed(tmsLoc.fY) + halfSampleY;
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000360
361 const SkGlyph& glyph = glyphCacheProc(cache, &text,
362 fx & fxMask, fy & fyMask);
363
364 if (glyph.fWidth) {
365 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
366 glyph.getSubXFixed(),
367 glyph.getSubYFixed()),
368 SkFixedFloorToFixed(fx),
369 SkFixedFloorToFixed(fy),
370 fontScaler);
371 }
372 pos += scalarsPerPosition;
373 }
374 } else {
375 while (text < stop) {
376 const char* currentText = text;
377 const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);
378
379 if (metricGlyph.fWidth) {
380 SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
381 SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
kkinnunencb9a2c82014-06-12 23:06:28 -0700382 SkPoint tmsLoc;
383 tmsProc(pos, &tmsLoc);
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000384 SkIPoint fixedLoc;
kkinnunencb9a2c82014-06-12 23:06:28 -0700385 alignProc(tmsLoc, metricGlyph, &fixedLoc);
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000386
387 SkFixed fx = fixedLoc.fX + halfSampleX;
388 SkFixed fy = fixedLoc.fY + halfSampleY;
389
390 // have to call again, now that we've been "aligned"
391 const SkGlyph& glyph = glyphCacheProc(cache, &currentText,
392 fx & fxMask, fy & fyMask);
393 // the assumption is that the metrics haven't changed
394 SkASSERT(prevAdvX == glyph.fAdvanceX);
395 SkASSERT(prevAdvY == glyph.fAdvanceY);
396 SkASSERT(glyph.fWidth);
397
398 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
399 glyph.getSubXFixed(),
400 glyph.getSubYFixed()),
401 SkFixedFloorToFixed(fx),
402 SkFixedFloorToFixed(fy),
403 fontScaler);
404 }
405 pos += scalarsPerPosition;
406 }
407 }
408 } else { // not subpixel
409
410 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
411 while (text < stop) {
412 // the last 2 parameters are ignored
413 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
414
415 if (glyph.fWidth) {
kkinnunencb9a2c82014-06-12 23:06:28 -0700416 SkPoint tmsLoc;
417 tmsProc(pos, &tmsLoc);
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000418
kkinnunencb9a2c82014-06-12 23:06:28 -0700419 SkFixed fx = SkScalarToFixed(tmsLoc.fX) + SK_FixedHalf; //halfSampleX;
420 SkFixed fy = SkScalarToFixed(tmsLoc.fY) + SK_FixedHalf; //halfSampleY;
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000421 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
422 glyph.getSubXFixed(),
423 glyph.getSubYFixed()),
424 SkFixedFloorToFixed(fx),
425 SkFixedFloorToFixed(fy),
426 fontScaler);
427 }
428 pos += scalarsPerPosition;
429 }
430 } else {
431 while (text < stop) {
432 // the last 2 parameters are ignored
433 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
434
435 if (glyph.fWidth) {
kkinnunencb9a2c82014-06-12 23:06:28 -0700436 SkPoint tmsLoc;
437 tmsProc(pos, &tmsLoc);
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000438
439 SkIPoint fixedLoc;
kkinnunencb9a2c82014-06-12 23:06:28 -0700440 alignProc(tmsLoc, glyph, &fixedLoc);
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000441
442 SkFixed fx = fixedLoc.fX + SK_FixedHalf; //halfSampleX;
443 SkFixed fy = fixedLoc.fY + SK_FixedHalf; //halfSampleY;
444 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
445 glyph.getSubXFixed(),
446 glyph.getSubYFixed()),
447 SkFixedFloorToFixed(fx),
448 SkFixedFloorToFixed(fy),
449 fontScaler);
450 }
451 pos += scalarsPerPosition;
452 }
453 }
454 }
commit-bot@chromium.orgcbbc4812014-01-30 22:05:47 +0000455
456 this->finish();
commit-bot@chromium.orge8612d92014-01-28 22:02:07 +0000457}
458
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000459void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000460 SkFixed vx, SkFixed vy,
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000461 GrFontScaler* scaler) {
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000462 GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
463 if (NULL == glyph || glyph->fBounds.isEmpty()) {
464 return;
465 }
466
467 vx += SkIntToFixed(glyph->fBounds.fLeft);
468 vy += SkIntToFixed(glyph->fBounds.fTop);
469
470 // keep them as ints until we've done the clip-test
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000471 SkFixed width = glyph->fBounds.width();
472 SkFixed height = glyph->fBounds.height();
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000473
474 // check if we clipped out
475 if (true || NULL == glyph->fPlot) {
476 int x = vx >> 16;
477 int y = vy >> 16;
478 if (fClipRect.quickReject(x, y, x + width, y + height)) {
479// SkCLZ(3); // so we can set a break-point in the debugger
480 return;
481 }
482 }
483
484 if (NULL == glyph->fPlot) {
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000485 if (fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000486 goto HAS_ATLAS;
487 }
488
489 // try to clear out an unused plot before we flush
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000490 if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
491 fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000492 goto HAS_ATLAS;
493 }
494
495 if (c_DumpFontCache) {
496#ifdef SK_DEVELOPER
497 fContext->getFontCache()->dump();
498#endif
499 }
500
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000501 // flush any accumulated draws to allow us to free up a plot
jvanverth63b9dc82014-08-28 10:39:40 -0700502 int remainingVertexCount = fVertexCount - fCurrVertex;
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000503 this->flushGlyphs();
504 fContext->flush();
505
jvanverth63b9dc82014-08-28 10:39:40 -0700506 // need to reallocate the vertex buffer for the remaining glyphs
507 fVertexCount = remainingVertexCount;
508 bool success = fDrawTarget->reserveVertexAndIndexSpace(fVertexCount,
509 0,
510 &fVertices,
511 NULL);
512 GrAlwaysAssert(success);
513
commit-bot@chromium.orgc9b2c882014-03-03 14:30:25 +0000514 // we should have an unused plot now
515 if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
516 fStrike->addGlyphToAtlas(glyph, scaler)) {
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000517 goto HAS_ATLAS;
518 }
519
520 if (NULL == glyph->fPath) {
521 SkPath* path = SkNEW(SkPath);
522 if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
523 // flag the glyph as being dead?
524 delete path;
525 return;
526 }
527 glyph->fPath = path;
528 }
529
530 GrContext::AutoMatrix am;
531 SkMatrix translate;
532 translate.setTranslate(SkFixedToScalar(vx - SkIntToFixed(glyph->fBounds.fLeft)),
533 SkFixedToScalar(vy - SkIntToFixed(glyph->fBounds.fTop)));
534 GrPaint tmpPaint(fPaint);
535 am.setPreConcat(fContext, translate, &tmpPaint);
egdanield58a0ba2014-06-11 10:30:05 -0700536 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
537 fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo);
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000538 return;
539 }
540
541HAS_ATLAS:
542 SkASSERT(glyph->fPlot);
543 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken();
544 glyph->fPlot->setDrawToken(drawToken);
545
546 // now promote them to fixed (TODO: Rethink using fixed pt).
547 width = SkIntToFixed(width);
548 height = SkIntToFixed(height);
549
550 GrTexture* texture = glyph->fPlot->texture();
551 SkASSERT(texture);
552
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000553 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX);
554 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY);
jvanverth@google.comc7a40fa2013-10-16 18:15:34 +0000555
commit-bot@chromium.org3ae0e6c2014-02-11 18:24:25 +0000556 SkRect r;
557 r.fLeft = SkFixedToFloat(vx);
558 r.fTop = SkFixedToFloat(vy);
559 r.fRight = SkFixedToFloat(vx + width);
560 r.fBottom = SkFixedToFloat(vy + height);
561
562 fVertexBounds.growToInclude(r);
563
jvanverth63b9dc82014-08-28 10:39:40 -0700564 bool useColorVerts = kA8_GrMaskFormat == fStrike->getMaskFormat();
bsalomon594069f2014-06-06 06:16:34 -0700565 size_t vertSize = useColorVerts ? (2 * sizeof(SkPoint) + sizeof(GrColor)) :
566 (2 * sizeof(SkPoint));
567
egdaniel7b3d5ee2014-08-28 05:41:14 -0700568 SkASSERT(vertSize == fDrawTarget->getDrawState().getVertexStride());
bsalomon594069f2014-06-06 06:16:34 -0700569
570 SkPoint* positions = reinterpret_cast<SkPoint*>(
571 reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex);
572 positions->setRectFan(r.fLeft, r.fTop, r.fRight, r.fBottom, vertSize);
573
574 // The texture coords are last in both the with and without color vertex layouts.
575 SkPoint* textureCoords = reinterpret_cast<SkPoint*>(
576 reinterpret_cast<intptr_t>(positions) + vertSize - sizeof(SkPoint));
577 textureCoords->setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)),
578 SkFixedToFloat(texture->normalizeFixedY(ty)),
579 SkFixedToFloat(texture->normalizeFixedX(tx + width)),
580 SkFixedToFloat(texture->normalizeFixedY(ty + height)),
581 vertSize);
582 if (useColorVerts) {
bsalomon62c447d2014-08-08 08:08:50 -0700583 if (0xFF == GrColorUnpackA(fPaint.getColor())) {
584 fDrawTarget->drawState()->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
585 }
bsalomon594069f2014-06-06 06:16:34 -0700586 // 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}