Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(285)

Side by Side Diff: src/gpu/GrDistanceFieldTextContext.cpp

Issue 641613003: Rearrange code in TextContexts to be more consistent. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Some more indention clean up Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrDistanceFieldTextContext.h ('k') | src/gpu/GrStencilAndCoverTextContext.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2013 Google Inc. 2 * Copyright 2013 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "GrDistanceFieldTextContext.h" 8 #include "GrDistanceFieldTextContext.h"
9 #include "GrAtlas.h" 9 #include "GrAtlas.h"
10 #include "GrDrawTarget.h" 10 #include "GrDrawTarget.h"
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 fEffectColor = GrColor_ILLEGAL; 74 fEffectColor = GrColor_ILLEGAL;
75 fEffectFlags = 0; 75 fEffectFlags = 0;
76 76
77 fVertices = NULL; 77 fVertices = NULL;
78 fMaxVertices = 0; 78 fMaxVertices = 0;
79 79
80 fVertexBounds.setLargestInverted(); 80 fVertexBounds.setLargestInverted();
81 } 81 }
82 82
83 GrDistanceFieldTextContext::~GrDistanceFieldTextContext() { 83 GrDistanceFieldTextContext::~GrDistanceFieldTextContext() {
84 this->flushGlyphs(); 84 this->flush();
85 SkSafeSetNull(fGammaTexture); 85 SkSafeSetNull(fGammaTexture);
86 } 86 }
87 87
88 bool GrDistanceFieldTextContext::canDraw(const SkPaint& paint) { 88 bool GrDistanceFieldTextContext::canDraw(const SkPaint& paint) {
89 if (!fEnableDFRendering && !paint.isDistanceFieldTextTEMP()) { 89 if (!fEnableDFRendering && !paint.isDistanceFieldTextTEMP()) {
90 return false; 90 return false;
91 } 91 }
92 92
93 // rasterizers and mask filters modify alpha, which doesn't 93 // rasterizers and mask filters modify alpha, which doesn't
94 // translate well to distance 94 // translate well to distance
(...skipping 12 matching lines...) Expand all
107 if (SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix())) { 107 if (SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix())) {
108 return false; 108 return false;
109 } 109 }
110 110
111 // distance fields cannot represent color fonts 111 // distance fields cannot represent color fonts
112 SkScalerContext::Rec rec; 112 SkScalerContext::Rec rec;
113 SkScalerContext::MakeRec(paint, &fDeviceProperties, NULL, &rec); 113 SkScalerContext::MakeRec(paint, &fDeviceProperties, NULL, &rec);
114 return rec.getFormat() != SkMask::kARGB32_Format; 114 return rec.getFormat() != SkMask::kARGB32_Format;
115 } 115 }
116 116
117 inline void GrDistanceFieldTextContext::init(const GrPaint& paint, const SkPaint & skPaint) {
118 GrTextContext::init(paint, skPaint);
119
120 fStrike = NULL;
121
122 const SkMatrix& ctm = fContext->getMatrix();
123
124 // getMaxScale doesn't support perspective, so neither do we at the moment
125 SkASSERT(!ctm.hasPerspective());
126 SkScalar maxScale = ctm.getMaxScale();
127 SkScalar textSize = fSkPaint.getTextSize();
128 SkScalar scaledTextSize = textSize;
129 // if we have non-unity scale, we need to choose our base text size
130 // based on the SkPaint's text size multiplied by the max scale factor
131 // TODO: do we need to do this if we're scaling down (i.e. maxScale < 1)?
132 if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) {
133 scaledTextSize *= maxScale;
134 }
135
136 fCurrVertex = 0;
137
138 fVertices = NULL;
139
140 if (scaledTextSize <= kSmallDFFontLimit) {
141 fTextRatio = textSize / kSmallDFFontSize;
142 fSkPaint.setTextSize(SkIntToScalar(kSmallDFFontSize));
143 } else if (scaledTextSize <= kMediumDFFontLimit) {
144 fTextRatio = textSize / kMediumDFFontSize;
145 fSkPaint.setTextSize(SkIntToScalar(kMediumDFFontSize));
146 } else {
147 fTextRatio = textSize / kLargeDFFontSize;
148 fSkPaint.setTextSize(SkIntToScalar(kLargeDFFontSize));
149 }
150
151 fUseLCDText = fSkPaint.isLCDRenderText();
152
153 fSkPaint.setLCDRenderText(false);
154 fSkPaint.setAutohinted(false);
155 fSkPaint.setHinting(SkPaint::kNormal_Hinting);
156 fSkPaint.setSubpixelText(true);
157
158 }
159
160 static void setup_gamma_texture(GrContext* context, const SkGlyphCache* cache,
161 const SkDeviceProperties& deviceProperties,
162 GrTexture** gammaTexture) {
163 if (NULL == *gammaTexture) {
164 int width, height;
165 size_t size;
166
167 #ifdef SK_GAMMA_CONTRAST
168 SkScalar contrast = SK_GAMMA_CONTRAST;
169 #else
170 SkScalar contrast = 0.5f;
171 #endif
172 SkScalar paintGamma = deviceProperties.getGamma();
173 SkScalar deviceGamma = deviceProperties.getGamma();
174
175 size = SkScalerContext::GetGammaLUTSize(contrast, paintGamma, deviceGamm a,
176 &width, &height);
177
178 SkAutoTArray<uint8_t> data((int)size);
179 SkScalerContext::GetGammaLUTData(contrast, paintGamma, deviceGamma, data .get());
180
181 // TODO: Update this to use the cache rather than directly creating a te xture.
182 GrTextureDesc desc;
183 desc.fFlags = kDynamicUpdate_GrTextureFlagBit;
184 desc.fWidth = width;
185 desc.fHeight = height;
186 desc.fConfig = kAlpha_8_GrPixelConfig;
187
188 *gammaTexture = context->getGpu()->createTexture(desc, NULL, 0);
189 if (NULL == *gammaTexture) {
190 return;
191 }
192
193 context->writeTexturePixels(*gammaTexture,
194 0, 0, width, height,
195 (*gammaTexture)->config(), data.get(), 0,
196 GrContext::kDontFlush_PixelOpsFlag);
197 }
198 }
199
200 void GrDistanceFieldTextContext::drawText(const GrPaint& paint, const SkPaint& s kPaint,
201 const char text[], size_t byteLength,
202 SkScalar x, SkScalar y) {
203 SkASSERT(byteLength == 0 || text != NULL);
204
205 // nothing to draw or can't draw
206 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/
207 || fSkPaint.getRasterizer()) {
208 return;
209 }
210
211 this->init(paint, skPaint);
212
213 SkScalar sizeRatio = fTextRatio;
214
215 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
216
217 SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL);
218 SkGlyphCache* cache = autoCache.getCache();
219 GrFontScaler* fontScaler = GetGrFontScaler(cache);
220
221 setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture);
222
223 // need to measure first
224 // TODO - generate positions and pre-load cache as well?
225 const char* stop = text + byteLength;
226 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
227 SkFixed stopX = 0;
228 SkFixed stopY = 0;
229
230 const char* textPtr = text;
231 while (textPtr < stop) {
232 // don't need x, y here, since all subpixel variants will have the
233 // same advance
234 const SkGlyph& glyph = glyphCacheProc(cache, &textPtr, 0, 0);
235
236 stopX += glyph.fAdvanceX;
237 stopY += glyph.fAdvanceY;
238 }
239 SkASSERT(textPtr == stop);
240
241 SkScalar alignX = SkFixedToScalar(stopX)*sizeRatio;
242 SkScalar alignY = SkFixedToScalar(stopY)*sizeRatio;
243
244 if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
245 alignX = SkScalarHalf(alignX);
246 alignY = SkScalarHalf(alignY);
247 }
248
249 x -= alignX;
250 y -= alignY;
251 }
252
253 SkFixed fx = SkScalarToFixed(x);
254 SkFixed fy = SkScalarToFixed(y);
255 SkFixed fixedScale = SkScalarToFixed(sizeRatio);
256 while (text < stop) {
257 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
258
259 if (glyph.fWidth) {
260 this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
261 glyph.getSubXFixed(),
262 glyph.getSubYFixed()),
263 fx,
264 fy,
265 fontScaler);
266 }
267
268 fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale);
269 fy += SkFixedMul_portable(glyph.fAdvanceY, fixedScale);
270 }
271
272 this->finish();
273 }
274
275 void GrDistanceFieldTextContext::drawPosText(const GrPaint& paint, const SkPaint & skPaint,
276 const char text[], size_t byteLengt h,
277 const SkScalar pos[], int scalarsPe rPosition,
278 const SkPoint& offset) {
279
280 SkASSERT(byteLength == 0 || text != NULL);
281 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
282
283 // nothing to draw
284 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
285 return;
286 }
287
288 this->init(paint, skPaint);
289
290 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
291
292 SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL);
293 SkGlyphCache* cache = autoCache.getCache();
294 GrFontScaler* fontScaler = GetGrFontScaler(cache);
295
296 setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture);
297
298 const char* stop = text + byteLength;
299
300 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
301 while (text < stop) {
302 // the last 2 parameters are ignored
303 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
304
305 if (glyph.fWidth) {
306 SkScalar x = offset.x() + pos[0];
307 SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0) ;
308
309 this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
310 glyph.getSubXFixed(),
311 glyph.getSubYFixed()),
312 SkScalarToFixed(x),
313 SkScalarToFixed(y),
314 fontScaler);
315 }
316 pos += scalarsPerPosition;
317 }
318 } else {
319 int alignShift = SkPaint::kCenter_Align == fSkPaint.getTextAlign() ? 1 : 0;
320 while (text < stop) {
321 // the last 2 parameters are ignored
322 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
323
324 if (glyph.fWidth) {
325 SkScalar x = offset.x() + pos[0];
326 SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0) ;
327
328 this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
329 glyph.getSubXFixed(),
330 glyph.getSubYFixed()),
331 SkScalarToFixed(x) - (glyph.fAdvanceX >> align Shift),
332 SkScalarToFixed(y) - (glyph.fAdvanceY >> align Shift),
333 fontScaler);
334 }
335 pos += scalarsPerPosition;
336 }
337 }
338
339 this->finish();
340 }
341
117 static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) { 342 static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
118 unsigned r = SkColorGetR(c); 343 unsigned r = SkColorGetR(c);
119 unsigned g = SkColorGetG(c); 344 unsigned g = SkColorGetG(c);
120 unsigned b = SkColorGetB(c); 345 unsigned b = SkColorGetB(c);
121 return GrColorPackRGBA(r, g, b, 0xff); 346 return GrColorPackRGBA(r, g, b, 0xff);
122 } 347 }
123 348
124 void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColo r) { 349 void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColo r) {
125 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_ FilterMode); 350 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_ FilterMode);
126 GrTextureParams gammaParams(SkShader::kClamp_TileMode, GrTextureParams::kNon e_FilterMode); 351 GrTextureParams gammaParams(SkShader::kClamp_TileMode, GrTextureParams::kNon e_FilterMode);
127 352
128 uint32_t textureUniqueID = fCurrTexture->getUniqueID(); 353 uint32_t textureUniqueID = fCurrTexture->getUniqueID();
129 const SkMatrix& ctm = fContext->getMatrix(); 354 const SkMatrix& ctm = fContext->getMatrix();
130 355
131 // set up any flags 356 // set up any flags
132 uint32_t flags = 0; 357 uint32_t flags = 0;
133 flags |= ctm.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0; 358 flags |= ctm.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0;
134 flags |= fUseLCDText ? kUseLCD_DistanceFieldEffectFlag : 0; 359 flags |= fUseLCDText ? kUseLCD_DistanceFieldEffectFlag : 0;
135 flags |= fUseLCDText && ctm.rectStaysRect() ? 360 flags |= fUseLCDText && ctm.rectStaysRect() ?
136 kRectToRect_DistanceFieldEffectFlag : 0; 361 kRectToRect_DistanceFieldEffectFlag : 0;
137 bool useBGR = SkPixelGeometryIsBGR(fDeviceProperties.fPixelGeometry); 362 bool useBGR = SkPixelGeometryIsBGR(fDeviceProperties.fPixelGeometry);
138 flags |= fUseLCDText && useBGR ? kBGR_DistanceFieldEffectFlag : 0; 363 flags |= fUseLCDText && useBGR ? kBGR_DistanceFieldEffectFlag : 0;
139 364
140 // see if we need to create a new effect 365 // see if we need to create a new effect
141 if (textureUniqueID != fEffectTextureUniqueID || 366 if (textureUniqueID != fEffectTextureUniqueID ||
142 filteredColor != fEffectColor || 367 filteredColor != fEffectColor ||
143 flags != fEffectFlags) { 368 flags != fEffectFlags) {
144 if (fUseLCDText) { 369 if (fUseLCDText) {
145 GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredCol or); 370 GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredCol or);
146 fCachedGeometryProcessor.reset( 371 fCachedGeometryProcessor.reset(GrDistanceFieldLCDTextureEffect::Crea te(fCurrTexture,
147 GrDistanceFieldLCDTextureEffect::Create(fCurrTexture, 372 params,
148 params, 373 fGammaTexture,
149 fGammaTexture, 374 gammaParams,
150 gammaParams, 375 colorNoPreMul,
151 colorNoPreMul, 376 flags));
152 flags));
153 } else { 377 } else {
154 #ifdef SK_GAMMA_APPLY_TO_A8 378 #ifdef SK_GAMMA_APPLY_TO_A8
155 U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDevicePropertie s.getGamma(), 379 U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDevicePropertie s.getGamma(),
156 filteredColor); 380 filteredColor);
157 fCachedGeometryProcessor.reset( 381 fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create( fCurrTexture,
158 GrDistanceFieldTextureEffect::Create(fCurrTexture, 382 params,
159 params, 383 fGammaTexture,
160 fGammaTexture, 384 gammaParams,
161 gammaParams, 385 lum/255.f,
162 lum/255.f, 386 flags));
163 flags));
164 #else 387 #else
165 fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create( fCurrTexture, 388 fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create( fCurrTexture,
166 params, flags)); 389 params, flags));
167 #endif 390 #endif
168 } 391 }
169 fEffectTextureUniqueID = textureUniqueID; 392 fEffectTextureUniqueID = textureUniqueID;
170 fEffectColor = filteredColor; 393 fEffectColor = filteredColor;
171 fEffectFlags = flags; 394 fEffectFlags = flags;
172 } 395 }
173 396
174 } 397 }
175 398
176 void GrDistanceFieldTextContext::flushGlyphs() { 399 void GrDistanceFieldTextContext::appendGlyph(GrGlyph::PackedID packed,
400 SkFixed vx, SkFixed vy,
401 GrFontScaler* scaler) {
177 if (NULL == fDrawTarget) { 402 if (NULL == fDrawTarget) {
178 return; 403 return;
179 } 404 }
180 405
181 GrDrawState* drawState = fDrawTarget->drawState();
182 GrDrawState::AutoRestoreEffects are(drawState);
183
184 drawState->setFromPaint(fPaint, fContext->getMatrix(), fContext->getRenderTa rget());
185
186 if (fCurrVertex > 0) {
187 // setup our sampler state for our text texture/atlas
188 SkASSERT(SkIsAlign4(fCurrVertex));
189
190 // get our current color
191 SkColor filteredColor;
192 SkColorFilter* colorFilter = fSkPaint.getColorFilter();
193 if (colorFilter) {
194 filteredColor = colorFilter->filterColor(fSkPaint.getColor());
195 } else {
196 filteredColor = fSkPaint.getColor();
197 }
198 this->setupCoverageEffect(filteredColor);
199
200 // Effects could be stored with one of the cache objects (atlas?)
201 drawState->setGeometryProcessor(fCachedGeometryProcessor.get());
202
203 // Set draw state
204 if (fUseLCDText) {
205 GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredCol or);
206 if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
207 kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
208 fPaint.numColorStages()) {
209 GrPrintf("LCD Text will not draw correctly.\n");
210 }
211 SkASSERT(!drawState->hasColorVertexAttribute());
212 // We don't use the GrPaint's color in this case because it's been p remultiplied by
213 // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
214 // the mask texture color. The end result is that we get
215 // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstCo lor
216 int a = SkColorGetA(fSkPaint.getColor());
217 // paintAlpha
218 drawState->setColor(SkColorSetARGB(a, a, a, a));
219 // paintColor
220 drawState->setBlendConstant(colorNoPreMul);
221 drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
222 } else {
223 // set back to normal in case we took LCD path previously.
224 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlen dCoeff());
225 // We're using per-vertex color.
226 SkASSERT(drawState->hasColorVertexAttribute());
227 }
228 int nGlyphs = fCurrVertex / 4;
229 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
230 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
231 nGlyphs,
232 4, 6, &fVertexBounds);
233 fDrawTarget->resetVertexSource();
234 fVertices = NULL;
235 fMaxVertices = 0;
236 fCurrVertex = 0;
237 SkSafeSetNull(fCurrTexture);
238 fVertexBounds.setLargestInverted();
239 }
240 }
241
242 void GrDistanceFieldTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
243 SkFixed vx, SkFixed vy,
244 GrFontScaler* scaler) {
245 if (NULL == fDrawTarget) {
246 return;
247 }
248
249 if (NULL == fStrike) { 406 if (NULL == fStrike) {
250 fStrike = fContext->getFontCache()->getStrike(scaler, true); 407 fStrike = fContext->getFontCache()->getStrike(scaler, true);
251 } 408 }
252 409
253 GrGlyph* glyph = fStrike->getGlyph(packed, scaler); 410 GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
254 if (NULL == glyph || glyph->fBounds.isEmpty()) { 411 if (NULL == glyph || glyph->fBounds.isEmpty()) {
255 return; 412 return;
256 } 413 }
257 414
258 SkScalar sx = SkFixedToScalar(vx); 415 SkScalar sx = SkFixedToScalar(vx);
259 SkScalar sy = SkFixedToScalar(vy); 416 SkScalar sy = SkFixedToScalar(vy);
260 /* 417 /*
261 // not valid, need to find a different solution for this 418 // not valid, need to find a different solution for this
262 vx += SkIntToFixed(glyph->fBounds.fLeft); 419 vx += SkIntToFixed(glyph->fBounds.fLeft);
(...skipping 25 matching lines...) Expand all
288 goto HAS_ATLAS; 445 goto HAS_ATLAS;
289 } 446 }
290 447
291 if (c_DumpFontCache) { 448 if (c_DumpFontCache) {
292 #ifdef SK_DEVELOPER 449 #ifdef SK_DEVELOPER
293 fContext->getFontCache()->dump(); 450 fContext->getFontCache()->dump();
294 #endif 451 #endif
295 } 452 }
296 453
297 // before we purge the cache, we must flush any accumulated draws 454 // before we purge the cache, we must flush any accumulated draws
298 this->flushGlyphs(); 455 this->flush();
299 fContext->flush(); 456 fContext->flush();
300 457
301 // we should have an unused plot now 458 // we should have an unused plot now
302 if (fContext->getFontCache()->freeUnusedPlot(fStrike) && 459 if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
303 fStrike->addGlyphToAtlas(glyph, scaler)) { 460 fStrike->addGlyphToAtlas(glyph, scaler)) {
304 goto HAS_ATLAS; 461 goto HAS_ATLAS;
305 } 462 }
306 } 463 }
307 464
308 if (NULL == glyph->fPath) { 465 if (NULL == glyph->fPath) {
(...skipping 19 matching lines...) Expand all
328 485
329 HAS_ATLAS: 486 HAS_ATLAS:
330 SkASSERT(glyph->fPlot); 487 SkASSERT(glyph->fPlot);
331 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken(); 488 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken();
332 glyph->fPlot->setDrawToken(drawToken); 489 glyph->fPlot->setDrawToken(drawToken);
333 490
334 GrTexture* texture = glyph->fPlot->texture(); 491 GrTexture* texture = glyph->fPlot->texture();
335 SkASSERT(texture); 492 SkASSERT(texture);
336 493
337 if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) { 494 if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) {
338 this->flushGlyphs(); 495 this->flush();
339 fCurrTexture = texture; 496 fCurrTexture = texture;
340 fCurrTexture->ref(); 497 fCurrTexture->ref();
341 } 498 }
342 499
343 bool useColorVerts = !fUseLCDText; 500 bool useColorVerts = !fUseLCDText;
344 501
345 if (NULL == fVertices) { 502 if (NULL == fVertices) {
346 // If we need to reserve vertices allow the draw target to suggest 503 // If we need to reserve vertices allow the draw target to suggest
347 // a number of verts to reserve and whether to perform a flush. 504 // a number of verts to reserve and whether to perform a flush.
348 fMaxVertices = kMinRequestedVerts; 505 fMaxVertices = kMinRequestedVerts;
349 if (useColorVerts) { 506 if (useColorVerts) {
350 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttri bs>( 507 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttri bs>(
351 SK_ARRAY_COUNT(gTextVertexWi thColorAttribs), 508 SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize);
352 kTextVAColorSize);
353 } else { 509 } else {
354 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( 510 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
355 SK_ARRAY_COUNT(gTextVertexAt tribs), 511 SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize);
356 kTextVASize);
357 } 512 }
358 bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL); 513 bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL);
359 if (flush) { 514 if (flush) {
360 this->flushGlyphs(); 515 this->flush();
361 fContext->flush(); 516 fContext->flush();
362 if (useColorVerts) { 517 if (useColorVerts) {
363 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorA ttribs>( 518 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorA ttribs>(
364 SK_ARRAY_COUNT(gTextVertexWi thColorAttribs), 519 SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSiz e);
365 kTextVAColorSize);
366 } else { 520 } else {
367 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( 521 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
368 SK_ARRAY_COUNT(gTextVertexAt tribs), 522 SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize);
369 kTextVASize);
370 } 523 }
371 } 524 }
372 fMaxVertices = kDefaultRequestedVerts; 525 fMaxVertices = kDefaultRequestedVerts;
373 // ignore return, no point in flushing again. 526 // ignore return, no point in flushing again.
374 fDrawTarget->geometryHints(&fMaxVertices, NULL); 527 fDrawTarget->geometryHints(&fMaxVertices, NULL);
375 528
376 int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads(); 529 int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads();
377 if (fMaxVertices < kMinRequestedVerts) { 530 if (fMaxVertices < kMinRequestedVerts) {
378 fMaxVertices = kDefaultRequestedVerts; 531 fMaxVertices = kDefaultRequestedVerts;
379 } else if (fMaxVertices > maxQuadVertices) { 532 } else if (fMaxVertices > maxQuadVertices) {
380 // don't exceed the limit of the index buffer 533 // don't exceed the limit of the index buffer
381 fMaxVertices = maxQuadVertices; 534 fMaxVertices = maxQuadVertices;
382 } 535 }
383 bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices, 536 bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices,
384 0, 537 0,
385 &fVertices, 538 &fVertices,
386 NULL); 539 NULL);
387 GrAlwaysAssert(success); 540 GrAlwaysAssert(success);
388 } 541 }
389 542
390 SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft + SK_DistanceFieldInset); 543 SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft + SK_DistanceFieldInset);
391 SkScalar dy = SkIntToScalar(glyph->fBounds.fTop + SK_DistanceFieldInset); 544 SkScalar dy = SkIntToScalar(glyph->fBounds.fTop + SK_DistanceFieldInset);
392 SkScalar width = SkIntToScalar(glyph->fBounds.width() - 2*SK_DistanceFieldIn set); 545 SkScalar width = SkIntToScalar(glyph->fBounds.width() - 2*SK_DistanceFieldIn set);
393 SkScalar height = SkIntToScalar(glyph->fBounds.height() - 2*SK_DistanceField Inset); 546 SkScalar height = SkIntToScalar(glyph->fBounds.height() - 2*SK_DistanceField Inset);
394 547
395 SkScalar scale = fTextRatio; 548 SkScalar scale = fTextRatio;
396 dx *= scale; 549 dx *= scale;
397 dy *= scale; 550 dy *= scale;
398 sx += dx; 551 sx += dx;
399 sy += dy; 552 sy += dy;
400 width *= scale; 553 width *= scale;
401 height *= scale; 554 height *= scale;
402 555
403 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX + SK_DistanceFieldInset); 556 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX + SK_DistanceFieldInset);
404 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY + SK_DistanceFieldInset); 557 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY + SK_DistanceFieldInset);
405 SkFixed tw = SkIntToFixed(glyph->fBounds.width() - 2*SK_DistanceFieldInset); 558 SkFixed tw = SkIntToFixed(glyph->fBounds.width() - 2*SK_DistanceFieldInset);
406 SkFixed th = SkIntToFixed(glyph->fBounds.height() - 2*SK_DistanceFieldInset) ; 559 SkFixed th = SkIntToFixed(glyph->fBounds.height() - 2*SK_DistanceFieldInset) ;
407 560
408 SkRect r; 561 SkRect r;
409 r.fLeft = sx; 562 r.fLeft = sx;
410 r.fTop = sy; 563 r.fTop = sy;
411 r.fRight = sx + width; 564 r.fRight = sx + width;
412 r.fBottom = sy + height; 565 r.fBottom = sy + height;
413 566
414 fVertexBounds.joinNonEmptyArg(r); 567 fVertexBounds.joinNonEmptyArg(r);
415 568
416 size_t vertSize = fUseLCDText ? (2 * sizeof(SkPoint)) 569 size_t vertSize = fUseLCDText ? (2 * sizeof(SkPoint))
417 : (2 * sizeof(SkPoint) + sizeof(GrColor)); 570 : (2 * sizeof(SkPoint) + sizeof(GrColor));
418 571
419 SkASSERT(vertSize == fDrawTarget->getDrawState().getVertexStride()); 572 SkASSERT(vertSize == fDrawTarget->getDrawState().getVertexStride());
420 573
421 SkPoint* positions = reinterpret_cast<SkPoint*>( 574 SkPoint* positions = reinterpret_cast<SkPoint*>(
422 reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex); 575 reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex);
423 positions->setRectFan(r.fLeft, r.fTop, r.fRight, r.fBottom, vertSize); 576 positions->setRectFan(r.fLeft, r.fTop, r.fRight, r.fBottom, vertSize);
424 577
425 // The texture coords are last in both the with and without color vertex lay outs. 578 // The texture coords are last in both the with and without color vertex lay outs.
426 SkPoint* textureCoords = reinterpret_cast<SkPoint*>( 579 SkPoint* textureCoords = reinterpret_cast<SkPoint*>(
427 reinterpret_cast<intptr_t>(positions) + vertSize - sizeof(SkPoint)) ; 580 reinterpret_cast<intptr_t>(positions) + vertSize - sizeof(SkPoint));
428 textureCoords->setRectFan(SkFixedToFloat(texture->texturePriv().normalizeFix edX(tx)), 581 textureCoords->setRectFan(SkFixedToFloat(texture->texturePriv().normalizeFix edX(tx)),
429 SkFixedToFloat(texture->texturePriv().normalizeFix edY(ty)), 582 SkFixedToFloat(texture->texturePriv().normalizeFix edY(ty)),
430 SkFixedToFloat(texture->texturePriv().normalizeFix edX(tx + tw)), 583 SkFixedToFloat(texture->texturePriv().normalizeFix edX(tx + tw)),
431 SkFixedToFloat(texture->texturePriv().normalizeFix edY(ty + th)), 584 SkFixedToFloat(texture->texturePriv().normalizeFix edY(ty + th)),
432 vertSize); 585 vertSize);
433 if (useColorVerts) { 586 if (useColorVerts) {
434 if (0xFF == GrColorUnpackA(fPaint.getColor())) { 587 if (0xFF == GrColorUnpackA(fPaint.getColor())) {
435 fDrawTarget->drawState()->setHint(GrDrawState::kVertexColorsAreOpaqu e_Hint, true); 588 fDrawTarget->drawState()->setHint(GrDrawState::kVertexColorsAreOpaqu e_Hint, true);
436 } 589 }
437 // color comes after position. 590 // color comes after position.
438 GrColor* colors = reinterpret_cast<GrColor*>(positions + 1); 591 GrColor* colors = reinterpret_cast<GrColor*>(positions + 1);
439 for (int i = 0; i < 4; ++i) { 592 for (int i = 0; i < 4; ++i) {
440 *colors = fPaint.getColor(); 593 *colors = fPaint.getColor();
441 colors = reinterpret_cast<GrColor*>(reinterpret_cast<intptr_t>(color s) + vertSize); 594 colors = reinterpret_cast<GrColor*>(reinterpret_cast<intptr_t>(color s) + vertSize);
442 } 595 }
443 } 596 }
444 597
445 fCurrVertex += 4; 598 fCurrVertex += 4;
446 } 599 }
447 600
448 inline void GrDistanceFieldTextContext::init(const GrPaint& paint, const SkPaint & skPaint) { 601 void GrDistanceFieldTextContext::flush() {
449 GrTextContext::init(paint, skPaint); 602 if (NULL == fDrawTarget) {
450 603 return;
451 fStrike = NULL;
452
453 const SkMatrix& ctm = fContext->getMatrix();
454
455 // getMaxScale doesn't support perspective, so neither do we at the moment
456 SkASSERT(!ctm.hasPerspective());
457 SkScalar maxScale = ctm.getMaxScale();
458 SkScalar textSize = fSkPaint.getTextSize();
459 SkScalar scaledTextSize = textSize;
460 // if we have non-unity scale, we need to choose our base text size
461 // based on the SkPaint's text size multiplied by the max scale factor
462 // TODO: do we need to do this if we're scaling down (i.e. maxScale < 1)?
463 if (maxScale > 0 && !SkScalarNearlyEqual(maxScale, SK_Scalar1)) {
464 scaledTextSize *= maxScale;
465 } 604 }
466 605
467 fCurrVertex = 0; 606 GrDrawState* drawState = fDrawTarget->drawState();
607 GrDrawState::AutoRestoreEffects are(drawState);
468 608
469 fVertices = NULL; 609 drawState->setFromPaint(fPaint, fContext->getMatrix(), fContext->getRenderTa rget());
470 610
471 if (scaledTextSize <= kSmallDFFontLimit) { 611 if (fCurrVertex > 0) {
472 fTextRatio = textSize / kSmallDFFontSize; 612 // setup our sampler state for our text texture/atlas
473 fSkPaint.setTextSize(SkIntToScalar(kSmallDFFontSize)); 613 SkASSERT(SkIsAlign4(fCurrVertex));
474 } else if (scaledTextSize <= kMediumDFFontLimit) { 614
475 fTextRatio = textSize / kMediumDFFontSize; 615 // get our current color
476 fSkPaint.setTextSize(SkIntToScalar(kMediumDFFontSize)); 616 SkColor filteredColor;
477 } else { 617 SkColorFilter* colorFilter = fSkPaint.getColorFilter();
478 fTextRatio = textSize / kLargeDFFontSize; 618 if (colorFilter) {
479 fSkPaint.setTextSize(SkIntToScalar(kLargeDFFontSize)); 619 filteredColor = colorFilter->filterColor(fSkPaint.getColor());
620 } else {
621 filteredColor = fSkPaint.getColor();
622 }
623 this->setupCoverageEffect(filteredColor);
624
625 // Effects could be stored with one of the cache objects (atlas?)
626 drawState->setGeometryProcessor(fCachedGeometryProcessor.get());
627
628 // Set draw state
629 if (fUseLCDText) {
630 GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredCol or);
631 if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
632 kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
633 fPaint.numColorStages()) {
634 GrPrintf("LCD Text will not draw correctly.\n");
635 }
636 SkASSERT(!drawState->hasColorVertexAttribute());
637 // We don't use the GrPaint's color in this case because it's been p remultiplied by
638 // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
639 // the mask texture color. The end result is that we get
640 // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstCo lor
641 int a = SkColorGetA(fSkPaint.getColor());
642 // paintAlpha
643 drawState->setColor(SkColorSetARGB(a, a, a, a));
644 // paintColor
645 drawState->setBlendConstant(colorNoPreMul);
646 drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
647 } else {
648 // set back to normal in case we took LCD path previously.
649 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlen dCoeff());
650 // We're using per-vertex color.
651 SkASSERT(drawState->hasColorVertexAttribute());
652 }
653 int nGlyphs = fCurrVertex / 4;
654 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
655 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
656 nGlyphs,
657 4, 6, &fVertexBounds);
658 fDrawTarget->resetVertexSource();
659 fVertices = NULL;
660 fMaxVertices = 0;
661 fCurrVertex = 0;
662 SkSafeSetNull(fCurrTexture);
663 fVertexBounds.setLargestInverted();
480 } 664 }
481
482 fUseLCDText = fSkPaint.isLCDRenderText();
483
484 fSkPaint.setLCDRenderText(false);
485 fSkPaint.setAutohinted(false);
486 fSkPaint.setHinting(SkPaint::kNormal_Hinting);
487 fSkPaint.setSubpixelText(true);
488
489 } 665 }
490 666
491 inline void GrDistanceFieldTextContext::finish() { 667 inline void GrDistanceFieldTextContext::finish() {
492 this->flushGlyphs(); 668 this->flush();
493 669
494 GrTextContext::finish(); 670 GrTextContext::finish();
495 } 671 }
496 672
497 static void setup_gamma_texture(GrContext* context, const SkGlyphCache* cache,
498 const SkDeviceProperties& deviceProperties,
499 GrTexture** gammaTexture) {
500 if (NULL == *gammaTexture) {
501 int width, height;
502 size_t size;
503
504 #ifdef SK_GAMMA_CONTRAST
505 SkScalar contrast = SK_GAMMA_CONTRAST;
506 #else
507 SkScalar contrast = 0.5f;
508 #endif
509 SkScalar paintGamma = deviceProperties.getGamma();
510 SkScalar deviceGamma = deviceProperties.getGamma();
511
512 size = SkScalerContext::GetGammaLUTSize(contrast, paintGamma, deviceGamm a,
513 &width, &height);
514
515 SkAutoTArray<uint8_t> data((int)size);
516 SkScalerContext::GetGammaLUTData(contrast, paintGamma, deviceGamma, data .get());
517
518 // TODO: Update this to use the cache rather than directly creating a te xture.
519 GrTextureDesc desc;
520 desc.fFlags = kDynamicUpdate_GrTextureFlagBit;
521 desc.fWidth = width;
522 desc.fHeight = height;
523 desc.fConfig = kAlpha_8_GrPixelConfig;
524
525 *gammaTexture = context->getGpu()->createTexture(desc, NULL, 0);
526 if (NULL == *gammaTexture) {
527 return;
528 }
529
530 context->writeTexturePixels(*gammaTexture,
531 0, 0, width, height,
532 (*gammaTexture)->config(), data.get(), 0,
533 GrContext::kDontFlush_PixelOpsFlag);
534 }
535 }
536
537 void GrDistanceFieldTextContext::drawText(const GrPaint& paint, const SkPaint& s kPaint,
538 const char text[], size_t byteLength,
539 SkScalar x, SkScalar y) {
540 SkASSERT(byteLength == 0 || text != NULL);
541
542 // nothing to draw or can't draw
543 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/
544 || fSkPaint.getRasterizer()) {
545 return;
546 }
547
548 this->init(paint, skPaint);
549
550 SkScalar sizeRatio = fTextRatio;
551
552 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
553
554 SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL);
555 SkGlyphCache* cache = autoCache.getCache();
556 GrFontScaler* fontScaler = GetGrFontScaler(cache);
557
558 setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture);
559
560 // need to measure first
561 // TODO - generate positions and pre-load cache as well?
562 const char* stop = text + byteLength;
563 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
564 SkFixed stopX = 0;
565 SkFixed stopY = 0;
566
567 const char* textPtr = text;
568 while (textPtr < stop) {
569 // don't need x, y here, since all subpixel variants will have the
570 // same advance
571 const SkGlyph& glyph = glyphCacheProc(cache, &textPtr, 0, 0);
572
573 stopX += glyph.fAdvanceX;
574 stopY += glyph.fAdvanceY;
575 }
576 SkASSERT(textPtr == stop);
577
578 SkScalar alignX = SkFixedToScalar(stopX)*sizeRatio;
579 SkScalar alignY = SkFixedToScalar(stopY)*sizeRatio;
580
581 if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
582 alignX = SkScalarHalf(alignX);
583 alignY = SkScalarHalf(alignY);
584 }
585
586 x -= alignX;
587 y -= alignY;
588 }
589
590 SkFixed fx = SkScalarToFixed(x);
591 SkFixed fy = SkScalarToFixed(y);
592 SkFixed fixedScale = SkScalarToFixed(sizeRatio);
593 while (text < stop) {
594 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
595
596 if (glyph.fWidth) {
597 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
598 glyph.getSubXFixed(),
599 glyph.getSubYFixed()),
600 fx,
601 fy,
602 fontScaler);
603 }
604
605 fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale);
606 fy += SkFixedMul_portable(glyph.fAdvanceY, fixedScale);
607 }
608
609 this->finish();
610 }
611
612 void GrDistanceFieldTextContext::drawPosText(const GrPaint& paint, const SkPaint & skPaint,
613 const char text[], size_t byteLengt h,
614 const SkScalar pos[], int scalarsPe rPosition,
615 const SkPoint& offset) {
616
617 SkASSERT(byteLength == 0 || text != NULL);
618 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
619
620 // nothing to draw
621 if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
622 return;
623 }
624
625 this->init(paint, skPaint);
626
627 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
628
629 SkAutoGlyphCacheNoGamma autoCache(fSkPaint, &fDeviceProperties, NULL);
630 SkGlyphCache* cache = autoCache.getCache();
631 GrFontScaler* fontScaler = GetGrFontScaler(cache);
632
633 setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture);
634
635 const char* stop = text + byteLength;
636
637 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
638 while (text < stop) {
639 // the last 2 parameters are ignored
640 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
641
642 if (glyph.fWidth) {
643 SkScalar x = offset.x() + pos[0];
644 SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0) ;
645
646 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
647 glyph.getSubXFixed(),
648 glyph.getSubYFixed()),
649 SkScalarToFixed(x),
650 SkScalarToFixed(y),
651 fontScaler);
652 }
653 pos += scalarsPerPosition;
654 }
655 } else {
656 int alignShift = SkPaint::kCenter_Align == fSkPaint.getTextAlign() ? 1 : 0;
657 while (text < stop) {
658 // the last 2 parameters are ignored
659 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
660
661 if (glyph.fWidth) {
662 SkScalar x = offset.x() + pos[0];
663 SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0) ;
664
665 this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
666 glyph.getSubXFixed(),
667 glyph.getSubYFixed()),
668 SkScalarToFixed(x) - (glyph.fAdvanceX >> a lignShift),
669 SkScalarToFixed(y) - (glyph.fAdvanceY >> a lignShift),
670 fontScaler);
671 }
672 pos += scalarsPerPosition;
673 }
674 }
675
676 this->finish();
677 }
OLDNEW
« no previous file with comments | « src/gpu/GrDistanceFieldTextContext.h ('k') | src/gpu/GrStencilAndCoverTextContext.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698