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

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

Issue 406523003: Send less transform data when drawing text with nvpr (Closed) Base URL: https://skia.googlesource.com/skia.git@clupload-pathrange
Patch Set: Really fix compiler warnings Created 6 years, 4 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/GrStencilAndCoverTextContext.h ('k') | no next file » | 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 2014 Google Inc. 2 * Copyright 2014 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 "GrStencilAndCoverTextContext.h" 8 #include "GrStencilAndCoverTextContext.h"
9 #include "GrDrawTarget.h" 9 #include "GrDrawTarget.h"
10 #include "GrGpu.h" 10 #include "GrGpu.h"
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 // too. This in turn has the side-effect that NVPR can not stroke the paths, 144 // too. This in turn has the side-effect that NVPR can not stroke the paths,
145 // as the stroke in NVPR is defined in object-space. 145 // as the stroke in NVPR is defined in object-space.
146 // NOTE: here we have following coincidence that works at the moment: 146 // NOTE: here we have following coincidence that works at the moment:
147 // - When using the device-space glyphs, the transforms we pass to NVPR 147 // - When using the device-space glyphs, the transforms we pass to NVPR
148 // instanced drawing are the global transforms, and the view transform is 148 // instanced drawing are the global transforms, and the view transform is
149 // identity. NVPR can not use non-affine transforms in the instanced 149 // identity. NVPR can not use non-affine transforms in the instanced
150 // drawing. This is taken care of by SkDraw::ShouldDrawTextAsPaths since it 150 // drawing. This is taken care of by SkDraw::ShouldDrawTextAsPaths since it
151 // will turn off the use of device-space glyphs when perspective transforms 151 // will turn off the use of device-space glyphs when perspective transforms
152 // are in use. 152 // are in use.
153 153
154 fGlyphTransform = fContext->getMatrix(); 154 this->init(paint, skPaint, byteLength, kUseIfNeeded_DeviceSpaceGlyphsBehavio r);
155
156 this->init(paint, skPaint, byteLength);
157 155
158 SkMatrix* glyphCacheTransform = NULL; 156 SkMatrix* glyphCacheTransform = NULL;
159 // Transform our starting point. 157 // Transform our starting point.
160 if (fNeedsDeviceSpaceGlyphs) { 158 if (fNeedsDeviceSpaceGlyphs) {
161 SkPoint loc; 159 SkPoint loc;
162 fGlyphTransform.mapXY(x, y, &loc); 160 fContextInitialMatrix.mapXY(x, y, &loc);
163 x = loc.fX; 161 x = loc.fX;
164 y = loc.fY; 162 y = loc.fY;
165 glyphCacheTransform = &fGlyphTransform; 163 glyphCacheTransform = &fContextInitialMatrix;
166 } 164 }
167 165
168 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); 166 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
169 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, glyphCacheTransform ); 167 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, glyphCacheTransform );
170 fGlyphCache = autoCache.getCache(); 168 fGlyphCache = autoCache.getCache();
171 fGlyphs = GlyphPathRange::Create(fContext, fGlyphCache, fStroke); 169 fGlyphs = GlyphPathRange::Create(fContext, fGlyphCache, fStroke);
170 fTransformType = GrDrawTarget::kTranslate_PathTransformType;
172 171
173 const char* stop = text + byteLength; 172 const char* stop = text + byteLength;
174 173
175 // Measure first if needed. 174 // Measure first if needed.
176 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) { 175 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
177 SkFixed stopX = 0; 176 SkFixed stopX = 0;
178 SkFixed stopY = 0; 177 SkFixed stopY = 0;
179 178
180 const char* textPtr = text; 179 const char* textPtr = text;
181 while (textPtr < stop) { 180 while (textPtr < stop) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 return; 234 return;
236 } 235 }
237 236
238 // This is the fast path. Here we do not bake in the device-transform to 237 // This is the fast path. Here we do not bake in the device-transform to
239 // the glyph outline or the advances. This is because we do not need to 238 // the glyph outline or the advances. This is because we do not need to
240 // position the glyphs at all, since the caller has done the positioning. 239 // position the glyphs at all, since the caller has done the positioning.
241 // The positioning is based on SkPaint::measureText of individual 240 // The positioning is based on SkPaint::measureText of individual
242 // glyphs. That already uses glyph cache without device transforms. Device 241 // glyphs. That already uses glyph cache without device transforms. Device
243 // transform is not part of SkPaint::measureText API, and thus we use the 242 // transform is not part of SkPaint::measureText API, and thus we use the
244 // same glyphs as what were measured. 243 // same glyphs as what were measured.
245 fGlyphTransform.reset();
246 244
247 this->init(paint, skPaint, byteLength); 245 const float textTranslateY = (1 == scalarsPerPosition ? constY : 0);
246 this->init(paint, skPaint, byteLength, kDoNotUse_DeviceSpaceGlyphsBehavior, textTranslateY);
248 247
249 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); 248 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
250 249
251 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, NULL); 250 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, NULL);
252 fGlyphCache = autoCache.getCache(); 251 fGlyphCache = autoCache.getCache();
253 fGlyphs = GlyphPathRange::Create(fContext, fGlyphCache, fStroke); 252 fGlyphs = GlyphPathRange::Create(fContext, fGlyphCache, fStroke);
254 253
255 const char* stop = text + byteLength; 254 const char* stop = text + byteLength;
256 SkTextAlignProcScalar alignProc(fSkPaint.getTextAlign());
257 SkTextMapStateProc tmsProc(SkMatrix::I(), constY, scalarsPerPosition);
258 255
259 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) { 256 if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
260 while (text < stop) { 257 if (1 == scalarsPerPosition) {
261 SkPoint loc; 258 fTransformType = GrDrawTarget::kTranslateX_PathTransformType;
262 tmsProc(pos, &loc); 259 while (text < stop) {
263 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); 260 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
264 if (glyph.fWidth) { 261 if (glyph.fWidth) {
265 this->appendGlyph(glyph.getGlyphID(), loc.x(), loc.y()); 262 this->appendGlyph(glyph.getGlyphID(), *pos);
263 }
264 pos++;
266 } 265 }
267 pos += scalarsPerPosition; 266 } else {
267 SkASSERT(2 == scalarsPerPosition);
268 fTransformType = GrDrawTarget::kTranslate_PathTransformType;
269 while (text < stop) {
270 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
271 if (glyph.fWidth) {
272 this->appendGlyph(glyph.getGlyphID(), pos[0], pos[1]);
273 }
274 pos += 2;
275 }
268 } 276 }
269 } else { 277 } else {
278 fTransformType = GrDrawTarget::kTranslate_PathTransformType;
279 SkTextMapStateProc tmsProc(SkMatrix::I(), 0, scalarsPerPosition);
280 SkTextAlignProcScalar alignProc(fSkPaint.getTextAlign());
270 while (text < stop) { 281 while (text < stop) {
271 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0); 282 const SkGlyph& glyph = glyphCacheProc(fGlyphCache, &text, 0, 0);
272 if (glyph.fWidth) { 283 if (glyph.fWidth) {
273 SkPoint tmsLoc; 284 SkPoint tmsLoc;
274 tmsProc(pos, &tmsLoc); 285 tmsProc(pos, &tmsLoc);
275 SkPoint loc; 286 SkPoint loc;
276 alignProc(tmsLoc, glyph, &loc); 287 alignProc(tmsLoc, glyph, &loc);
277 288
278 this->appendGlyph(glyph.getGlyphID(), loc.x(), loc.y()); 289 this->appendGlyph(glyph.getGlyphID(), loc.x(), loc.y());
279 } 290 }
(...skipping 23 matching lines...) Expand all
303 } 314 }
304 315
305 // No color bitmap fonts. 316 // No color bitmap fonts.
306 SkScalerContext::Rec rec; 317 SkScalerContext::Rec rec;
307 SkScalerContext::MakeRec(paint, &fDeviceProperties, NULL, &rec); 318 SkScalerContext::MakeRec(paint, &fDeviceProperties, NULL, &rec);
308 return rec.getFormat() != SkMask::kARGB32_Format; 319 return rec.getFormat() != SkMask::kARGB32_Format;
309 } 320 }
310 321
311 void GrStencilAndCoverTextContext::init(const GrPaint& paint, 322 void GrStencilAndCoverTextContext::init(const GrPaint& paint,
312 const SkPaint& skPaint, 323 const SkPaint& skPaint,
313 size_t textByteLength) { 324 size_t textByteLength,
325 DeviceSpaceGlyphsBehavior deviceSpaceGly phsBehavior,
326 SkScalar textTranslateY) {
314 GrTextContext::init(paint, skPaint); 327 GrTextContext::init(paint, skPaint);
315 328
329 fContextInitialMatrix = fContext->getMatrix();
330
316 bool otherBackendsWillDrawAsPaths = 331 bool otherBackendsWillDrawAsPaths =
317 SkDraw::ShouldDrawTextAsPaths(skPaint, fContext->getMatrix()); 332 SkDraw::ShouldDrawTextAsPaths(skPaint, fContextInitialMatrix);
318 333
319 if (otherBackendsWillDrawAsPaths) { 334 if (otherBackendsWillDrawAsPaths) {
320 // This is to reproduce SkDraw::drawText_asPaths glyph positions. 335 // This is to reproduce SkDraw::drawText_asPaths glyph positions.
321 fSkPaint.setLinearText(true); 336 fSkPaint.setLinearText(true);
322 fTextRatio = fSkPaint.getTextSize() / SkPaint::kCanonicalTextSizeForPath s; 337 fTextRatio = fSkPaint.getTextSize() / SkPaint::kCanonicalTextSizeForPath s;
338 fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fSkPaint.getTe xtSize();
323 fSkPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths)) ; 339 fSkPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths)) ;
324 if (fSkPaint.getStyle() != SkPaint::kFill_Style) { 340 if (fSkPaint.getStyle() != SkPaint::kFill_Style) {
325 // Compensate the glyphs being scaled up by fTextRatio by scaling th e 341 // Compensate the glyphs being scaled up by fTextRatio by scaling th e
326 // stroke down. 342 // stroke down.
327 fSkPaint.setStrokeWidth(fSkPaint.getStrokeWidth() / fTextRatio); 343 fSkPaint.setStrokeWidth(fSkPaint.getStrokeWidth() / fTextRatio);
328 } 344 }
329 fNeedsDeviceSpaceGlyphs = false; 345 fNeedsDeviceSpaceGlyphs = false;
330 } else { 346 } else {
331 fTextRatio = 1.0f; 347 fTextRatio = fTextInverseRatio = 1.0f;
332 fNeedsDeviceSpaceGlyphs = (fGlyphTransform.getType() & 348 fNeedsDeviceSpaceGlyphs =
333 (SkMatrix::kScale_Mask | SkMatrix::kAffine_Mask)) != 0; 349 kUseIfNeeded_DeviceSpaceGlyphsBehavior == deviceSpaceGlyphsBehavior &&
350 (fContextInitialMatrix.getType() &
351 (SkMatrix::kScale_Mask | SkMatrix::kAffine_Mask)) != 0;
334 // SkDraw::ShouldDrawTextAsPaths takes care of perspective transforms. 352 // SkDraw::ShouldDrawTextAsPaths takes care of perspective transforms.
335 SkASSERT(!fGlyphTransform.hasPerspective()); 353 SkASSERT(!fContextInitialMatrix.hasPerspective());
336 if (fNeedsDeviceSpaceGlyphs) {
337 fPaint.localCoordChangeInverse(fGlyphTransform);
338 fContext->setIdentityMatrix();
339 }
340 } 354 }
341 355
342 fStroke = SkStrokeRec(fSkPaint); 356 fStroke = SkStrokeRec(fSkPaint);
343 357
344 if (fNeedsDeviceSpaceGlyphs) { 358 if (fNeedsDeviceSpaceGlyphs) {
359 SkASSERT(1.0f == fTextRatio);
360 SkASSERT(0.0f == textTranslateY);
361 fPaint.localCoordChangeInverse(fContextInitialMatrix);
362 fContext->setIdentityMatrix();
363
345 // The whole shape is baked into the glyph. Make NVPR just fill the 364 // The whole shape is baked into the glyph. Make NVPR just fill the
346 // baked shape. 365 // baked shape.
347 fStroke.setStrokeStyle(-1, false); 366 fStroke.setStrokeStyle(-1, false);
348 } else { 367 } else {
368 if (1.0f != fTextRatio || 0.0f != textTranslateY) {
369 SkMatrix textMatrix;
370 textMatrix.setTranslate(0, textTranslateY);
371 textMatrix.preScale(fTextRatio, fTextRatio);
372 fPaint.localCoordChange(textMatrix);
373 fContext->concatMatrix(textMatrix);
374 }
375
349 if (fSkPaint.getStrokeWidth() == 0.0f) { 376 if (fSkPaint.getStrokeWidth() == 0.0f) {
350 if (fSkPaint.getStyle() == SkPaint::kStrokeAndFill_Style) { 377 if (fSkPaint.getStyle() == SkPaint::kStrokeAndFill_Style) {
351 fStroke.setStrokeStyle(-1, false); 378 fStroke.setStrokeStyle(-1, false);
352 } else if (fSkPaint.getStyle() == SkPaint::kStroke_Style) { 379 } else if (fSkPaint.getStyle() == SkPaint::kStroke_Style) {
353 // Approximate hairline stroke. 380 // Approximate hairline stroke.
354 const SkMatrix& ctm = fContext->getMatrix(); 381 const SkMatrix& ctm = fContext->getMatrix();
355 SkScalar strokeWidth = SK_Scalar1 / 382 SkScalar strokeWidth = SK_Scalar1 /
356 (fTextRatio * SkVector::Make(ctm.getScaleX(), ctm.getSkewY() ).length()); 383 (SkVector::Make(ctm.getScaleX(), ctm.getSkewY()).length());
357 fStroke.setStrokeStyle(strokeWidth, false); 384 fStroke.setStrokeStyle(strokeWidth, false);
358 } 385 }
359 } 386 }
360 387
361 // Make glyph cache produce paths geometry for fill. We will stroke them 388 // Make glyph cache produce paths geometry for fill. We will stroke them
362 // by passing fStroke to drawPath. This is the fast path. 389 // by passing fStroke to drawPath. This is the fast path.
363 fSkPaint.setStyle(SkPaint::kFill_Style); 390 fSkPaint.setStyle(SkPaint::kFill_Style);
364 } 391 }
365 fStateRestore.set(fDrawTarget->drawState()); 392 fStateRestore.set(fDrawTarget->drawState());
366 393
367 fDrawTarget->drawState()->setFromPaint(fPaint, fContext->getMatrix(), 394 fDrawTarget->drawState()->setFromPaint(fPaint, fContext->getMatrix(),
368 fContext->getRenderTarget()); 395 fContext->getRenderTarget());
369 396
370 GR_STATIC_CONST_SAME_STENCIL(kStencilPass, 397 GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
371 kZero_StencilOp, 398 kZero_StencilOp,
372 kZero_StencilOp, 399 kZero_StencilOp,
373 kNotEqual_StencilFunc, 400 kNotEqual_StencilFunc,
374 0xffff, 401 0xffff,
375 0x0000, 402 0x0000,
376 0xffff); 403 0xffff);
377 404
378 *fDrawTarget->drawState()->stencil() = kStencilPass; 405 *fDrawTarget->drawState()->stencil() = kStencilPass;
379 406
380 SkASSERT(0 == fPendingGlyphCount); 407 SkASSERT(0 == fPendingGlyphCount);
381 } 408 }
382 409
383 inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x, float y) { 410 inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x) {
411 SkASSERT(GrDrawTarget::kTranslateX_PathTransformType == fTransformType);
412
384 if (fPendingGlyphCount >= kGlyphBufferSize) { 413 if (fPendingGlyphCount >= kGlyphBufferSize) {
385 this->flush(); 414 this->flush();
386 } 415 }
416
417 fGlyphs->preloadGlyph(glyphID, fGlyphCache);
418
419 fIndexBuffer[fPendingGlyphCount] = glyphID;
420 fTransformBuffer[fPendingGlyphCount] = fTextInverseRatio * x;
421
422 ++fPendingGlyphCount;
423 }
424
425 inline void GrStencilAndCoverTextContext::appendGlyph(uint16_t glyphID, float x, float y) {
426 SkASSERT(GrDrawTarget::kTranslate_PathTransformType == fTransformType);
427
428 if (fPendingGlyphCount >= kGlyphBufferSize) {
429 this->flush();
430 }
387 431
388 fGlyphs->preloadGlyph(glyphID, fGlyphCache); 432 fGlyphs->preloadGlyph(glyphID, fGlyphCache);
389 433
390 fIndexBuffer[fPendingGlyphCount] = glyphID; 434 fIndexBuffer[fPendingGlyphCount] = glyphID;
391 fTransformBuffer[6 * fPendingGlyphCount + 0] = fTextRatio; 435 fTransformBuffer[2 * fPendingGlyphCount] = fTextInverseRatio * x;
392 fTransformBuffer[6 * fPendingGlyphCount + 1] = 0; 436 fTransformBuffer[2 * fPendingGlyphCount + 1] = fTextInverseRatio * y;
393 fTransformBuffer[6 * fPendingGlyphCount + 2] = x;
394 fTransformBuffer[6 * fPendingGlyphCount + 3] = 0;
395 fTransformBuffer[6 * fPendingGlyphCount + 4] = fTextRatio;
396 fTransformBuffer[6 * fPendingGlyphCount + 5] = y;
397 437
398 ++fPendingGlyphCount; 438 ++fPendingGlyphCount;
399 } 439 }
400 440
401 void GrStencilAndCoverTextContext::flush() { 441 void GrStencilAndCoverTextContext::flush() {
402 if (0 == fPendingGlyphCount) { 442 if (0 == fPendingGlyphCount) {
403 return; 443 return;
404 } 444 }
405 445
406 fDrawTarget->drawPaths(fGlyphs->pathRange(), fIndexBuffer, fPendingGlyphCoun t, 446 fDrawTarget->drawPaths(fGlyphs->pathRange(), fIndexBuffer, fPendingGlyphCoun t,
407 fTransformBuffer, GrDrawTarget::kAffine_PathTransform Type, 447 fTransformBuffer, fTransformType, SkPath::kWinding_Fi llType);
408 SkPath::kWinding_FillType);
409 448
410 fPendingGlyphCount = 0; 449 fPendingGlyphCount = 0;
411 } 450 }
412 451
413 void GrStencilAndCoverTextContext::finish() { 452 void GrStencilAndCoverTextContext::finish() {
414 this->flush(); 453 this->flush();
415 454
416 SkSafeUnref(fGlyphs); 455 SkSafeUnref(fGlyphs);
417 fGlyphs = NULL; 456 fGlyphs = NULL;
418 fGlyphCache = NULL; 457 fGlyphCache = NULL;
419 458
420 fDrawTarget->drawState()->stencil()->setDisabled(); 459 fDrawTarget->drawState()->stencil()->setDisabled();
421 fStateRestore.set(NULL); 460 fStateRestore.set(NULL);
422 if (fNeedsDeviceSpaceGlyphs) { 461 fContext->setMatrix(fContextInitialMatrix);
423 fContext->setMatrix(fGlyphTransform);
424 }
425 GrTextContext::finish(); 462 GrTextContext::finish();
426 } 463 }
427 464
OLDNEW
« no previous file with comments | « src/gpu/GrStencilAndCoverTextContext.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698