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

Side by Side Diff: src/core/SkCanvas.cpp

Issue 1091173003: apply xfermode after imagefilter when we create a tmp layer (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 8 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 | « no previous file | 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 2008 The Android Open Source Project 2 * Copyright 2008 The Android Open Source Project
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 "SkCanvas.h" 8 #include "SkCanvas.h"
9 #include "SkCanvasPriv.h" 9 #include "SkCanvasPriv.h"
10 #include "SkBitmapDevice.h" 10 #include "SkBitmapDevice.h"
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 301
302 class AutoDrawLooper { 302 class AutoDrawLooper {
303 public: 303 public:
304 AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint, 304 AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint,
305 bool skipLayerForImageFilter = false, 305 bool skipLayerForImageFilter = false,
306 const SkRect* bounds = NULL) : fOrigPaint(paint) { 306 const SkRect* bounds = NULL) : fOrigPaint(paint) {
307 fCanvas = canvas; 307 fCanvas = canvas;
308 fFilter = canvas->getDrawFilter(); 308 fFilter = canvas->getDrawFilter();
309 fPaint = &fOrigPaint; 309 fPaint = &fOrigPaint;
310 fSaveCount = canvas->getSaveCount(); 310 fSaveCount = canvas->getSaveCount();
311 fDoClearImageFilter = false; 311 fTempLayerForImageFilter = false;
312 fDone = false; 312 fDone = false;
313 313
314 if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) { 314 if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) {
315 /**
316 * We implement ImageFilters for a given draw by creating a layer, then applying the
317 * imagefilter to the pixels of that layer (its backing surface/ima ge), and then
318 * we call restore() to xfer that layer to the main canvas.
319 *
320 * 1. SaveLayer (with a paint containing the current imagefilter an d xfermode)
321 * 2. Generate the src pixels:
322 * Remove the imagefilter and the xfermode from the paint that we (AutoDrawLooper)
323 * return (fPaint). We then draw the primitive (using srcover) into a cleared
Stephen White 2015/04/20 14:55:45 Out of curiosity, would it be equivalent to use Sr
324 * buffer/surface.
325 * 3. Restore the layer created in #1
326 * The imagefilter is passed the buffer/surface from the layer (now filled with the
327 * src pixels of the primitive). It returns a new "filtered" bu ffer, which we
328 * draw onto the previous layer using the xfermode from the ori ginal paint.
329 */
315 SkPaint tmp; 330 SkPaint tmp;
316 tmp.setImageFilter(fOrigPaint.getImageFilter()); 331 tmp.setImageFilter(fOrigPaint.getImageFilter());
332 tmp.setXfermode(fOrigPaint.getXfermode());
317 (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLa yer_SaveFlag, 333 (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLa yer_SaveFlag,
318 SkCanvas::kFullLayer_SaveLayerStrate gy); 334 SkCanvas::kFullLayer_SaveLayerStrate gy);
319 // we'll clear the imageFilter for the actual draws in next(), so 335 fTempLayerForImageFilter = true;
320 // it will only be applied during the restore(). 336 // we remove the imagefilter/xfermode inside doNext()
321 fDoClearImageFilter = true;
322 } 337 }
323 338
324 if (SkDrawLooper* looper = paint.getLooper()) { 339 if (SkDrawLooper* looper = paint.getLooper()) {
325 void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Contex t>( 340 void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Contex t>(
326 looper->contextSize()); 341 looper->contextSize());
327 fLooperContext = looper->createContext(canvas, buffer); 342 fLooperContext = looper->createContext(canvas, buffer);
328 fIsSimple = false; 343 fIsSimple = false;
329 } else { 344 } else {
330 fLooperContext = NULL; 345 fLooperContext = NULL;
331 // can we be marked as simple? 346 // can we be marked as simple?
332 fIsSimple = !fFilter && !fDoClearImageFilter; 347 fIsSimple = !fFilter && !fTempLayerForImageFilter;
333 } 348 }
334 349
335 uint32_t oldFlags = paint.getFlags(); 350 uint32_t oldFlags = paint.getFlags();
336 fNewPaintFlags = filter_paint_flags(props, oldFlags); 351 fNewPaintFlags = filter_paint_flags(props, oldFlags);
337 if (fIsSimple && (fNewPaintFlags != oldFlags)) { 352 if (fIsSimple && (fNewPaintFlags != oldFlags)) {
338 SkPaint* paint = fLazyPaint.set(fOrigPaint); 353 SkPaint* paint = fLazyPaint.set(fOrigPaint);
339 paint->setFlags(fNewPaintFlags); 354 paint->setFlags(fNewPaintFlags);
340 fPaint = paint; 355 fPaint = paint;
341 // if we're not simple, doNext() will take care of calling setFlags( ) 356 // if we're not simple, doNext() will take care of calling setFlags( )
342 } 357 }
343 } 358 }
344 359
345 ~AutoDrawLooper() { 360 ~AutoDrawLooper() {
346 if (fDoClearImageFilter) { 361 if (fTempLayerForImageFilter) {
347 fCanvas->internalRestore(); 362 fCanvas->internalRestore();
348 } 363 }
349 SkASSERT(fCanvas->getSaveCount() == fSaveCount); 364 SkASSERT(fCanvas->getSaveCount() == fSaveCount);
350 } 365 }
351 366
352 const SkPaint& paint() const { 367 const SkPaint& paint() const {
353 SkASSERT(fPaint); 368 SkASSERT(fPaint);
354 return *fPaint; 369 return *fPaint;
355 } 370 }
356 371
357 bool next(SkDrawFilter::Type drawType) { 372 bool next(SkDrawFilter::Type drawType) {
358 if (fDone) { 373 if (fDone) {
359 return false; 374 return false;
360 } else if (fIsSimple) { 375 } else if (fIsSimple) {
361 fDone = true; 376 fDone = true;
362 return !fPaint->nothingToDraw(); 377 return !fPaint->nothingToDraw();
363 } else { 378 } else {
364 return this->doNext(drawType); 379 return this->doNext(drawType);
365 } 380 }
366 } 381 }
367 382
368 private: 383 private:
369 SkLazyPaint fLazyPaint; 384 SkLazyPaint fLazyPaint;
370 SkCanvas* fCanvas; 385 SkCanvas* fCanvas;
371 const SkPaint& fOrigPaint; 386 const SkPaint& fOrigPaint;
372 SkDrawFilter* fFilter; 387 SkDrawFilter* fFilter;
373 const SkPaint* fPaint; 388 const SkPaint* fPaint;
374 int fSaveCount; 389 int fSaveCount;
375 uint32_t fNewPaintFlags; 390 uint32_t fNewPaintFlags;
376 bool fDoClearImageFilter; 391 bool fTempLayerForImageFilter;
377 bool fDone; 392 bool fDone;
378 bool fIsSimple; 393 bool fIsSimple;
379 SkDrawLooper::Context* fLooperContext; 394 SkDrawLooper::Context* fLooperContext;
380 SkSmallAllocator<1, 32> fLooperContextAllocator; 395 SkSmallAllocator<1, 32> fLooperContextAllocator;
381 396
382 bool doNext(SkDrawFilter::Type drawType); 397 bool doNext(SkDrawFilter::Type drawType);
383 }; 398 };
384 399
385 bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) { 400 bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
386 fPaint = NULL; 401 fPaint = NULL;
387 SkASSERT(!fIsSimple); 402 SkASSERT(!fIsSimple);
388 SkASSERT(fLooperContext || fFilter || fDoClearImageFilter); 403 SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter);
389 404
390 SkPaint* paint = fLazyPaint.set(fOrigPaint); 405 SkPaint* paint = fLazyPaint.set(fOrigPaint);
391 paint->setFlags(fNewPaintFlags); 406 paint->setFlags(fNewPaintFlags);
392 407
393 if (fDoClearImageFilter) { 408 if (fTempLayerForImageFilter) {
394 paint->setImageFilter(NULL); 409 paint->setImageFilter(NULL);
410 paint->setXfermode(NULL);
395 } 411 }
396 412
397 if (fLooperContext && !fLooperContext->next(fCanvas, paint)) { 413 if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
398 fDone = true; 414 fDone = true;
399 return false; 415 return false;
400 } 416 }
401 if (fFilter) { 417 if (fFilter) {
402 if (!fFilter->filter(paint, drawType)) { 418 if (!fFilter->filter(paint, drawType)) {
403 fDone = true; 419 fDone = true;
404 return false; 420 return false;
(...skipping 2155 matching lines...) Expand 10 before | Expand all | Expand 10 after
2560 } 2576 }
2561 2577
2562 if (matrix) { 2578 if (matrix) {
2563 canvas->concat(*matrix); 2579 canvas->concat(*matrix);
2564 } 2580 }
2565 } 2581 }
2566 2582
2567 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { 2583 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2568 fCanvas->restoreToCount(fSaveCount); 2584 fCanvas->restoreToCount(fSaveCount);
2569 } 2585 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698