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

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