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

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

Issue 986353002: Use colorfilter instead of imagefilter when possible (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: update dox Created 5 years, 7 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"
11 #include "SkColorFilter.h"
11 #include "SkDeviceImageFilterProxy.h" 12 #include "SkDeviceImageFilterProxy.h"
12 #include "SkDraw.h" 13 #include "SkDraw.h"
13 #include "SkDrawable.h" 14 #include "SkDrawable.h"
14 #include "SkDrawFilter.h" 15 #include "SkDrawFilter.h"
15 #include "SkDrawLooper.h" 16 #include "SkDrawLooper.h"
16 #include "SkErrorInternals.h" 17 #include "SkErrorInternals.h"
17 #include "SkImage.h" 18 #include "SkImage.h"
18 #include "SkMetaData.h" 19 #include "SkMetaData.h"
19 #include "SkPathOps.h" 20 #include "SkPathOps.h"
20 #include "SkPatchUtils.h" 21 #include "SkPatchUtils.h"
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 SkCanvas* fCanvas; 293 SkCanvas* fCanvas;
293 const DeviceCM* fCurrLayer; 294 const DeviceCM* fCurrLayer;
294 const SkPaint* fPaint; // May be null. 295 const SkPaint* fPaint; // May be null.
295 SkBool8 fSkipEmptyClips; 296 SkBool8 fSkipEmptyClips;
296 297
297 typedef SkDraw INHERITED; 298 typedef SkDraw INHERITED;
298 }; 299 };
299 300
300 ///////////////////////////////////////////////////////////////////////////// 301 /////////////////////////////////////////////////////////////////////////////
301 302
303 static SkPaint* set_if_needed(SkLazyPaint* lazy, const SkPaint& orig) {
304 return lazy->isValid() ? lazy->get() : lazy->set(orig);
305 }
306
307 /**
308 * If the paint has an imagefilter, but it can be simplified to just a colorfil ter, return that
309 * colorfilter, else return NULL.
310 */
311 static SkColorFilter* image_to_color_filter(const SkPaint& paint) {
312 #ifdef SK_SUPPORT_LEGACY_IMAGEFILTER_TO_COLORFILTER
313 return NULL;
314 #else
315 SkImageFilter* imgf = paint.getImageFilter();
316 if (!imgf) {
317 return NULL;
318 }
319
320 SkColorFilter* imgCF;
321 if (!imgf->asAColorFilter(&imgCF)) {
322 return NULL;
323 }
324
325 SkColorFilter* paintCF = paint.getColorFilter();
326 if (NULL == paintCF) {
327 // there is no existing paint colorfilter, so we can just return the ima gefilter's
328 return imgCF;
329 }
330
331 // The paint has both a colorfilter(paintCF) and an imagefilter-which-is-a-c olorfilter(imgCF)
332 // and we need to combine them into a single colorfilter.
333 SkAutoTUnref<SkColorFilter> autoImgCF(imgCF);
334 return SkColorFilter::CreateComposeFilter(imgCF, paintCF);
335 #endif
336 }
337
302 class AutoDrawLooper { 338 class AutoDrawLooper {
303 public: 339 public:
304 AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint, 340 AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint,
305 bool skipLayerForImageFilter = false, 341 bool skipLayerForImageFilter = false,
306 const SkRect* bounds = NULL) : fOrigPaint(paint) { 342 const SkRect* bounds = NULL) : fOrigPaint(paint) {
307 fCanvas = canvas; 343 fCanvas = canvas;
308 fFilter = canvas->getDrawFilter(); 344 fFilter = canvas->getDrawFilter();
309 fPaint = &fOrigPaint; 345 fPaint = &fOrigPaint;
310 fSaveCount = canvas->getSaveCount(); 346 fSaveCount = canvas->getSaveCount();
311 fTempLayerForImageFilter = false; 347 fTempLayerForImageFilter = false;
312 fDone = false; 348 fDone = false;
313 349
314 if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) { 350 SkColorFilter* simplifiedCF = image_to_color_filter(fOrigPaint);
351 if (simplifiedCF) {
352 SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
353 paint->setColorFilter(simplifiedCF)->unref();
354 paint->setImageFilter(NULL);
355 fPaint = paint;
356 }
357
358 if (!skipLayerForImageFilter && fPaint->getImageFilter()) {
315 /** 359 /**
316 * We implement ImageFilters for a given draw by creating a layer, then applying the 360 * 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 361 * 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. 362 * we call restore() to xfer that layer to the main canvas.
319 * 363 *
320 * 1. SaveLayer (with a paint containing the current imagefilter an d xfermode) 364 * 1. SaveLayer (with a paint containing the current imagefilter an d xfermode)
321 * 2. Generate the src pixels: 365 * 2. Generate the src pixels:
322 * Remove the imagefilter and the xfermode from the paint that we (AutoDrawLooper) 366 * 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 367 * return (fPaint). We then draw the primitive (using srcover) into a cleared
324 * buffer/surface. 368 * buffer/surface.
325 * 3. Restore the layer created in #1 369 * 3. Restore the layer created in #1
326 * The imagefilter is passed the buffer/surface from the layer (now filled with the 370 * 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 371 * 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. 372 * draw onto the previous layer using the xfermode from the ori ginal paint.
329 */ 373 */
330 SkPaint tmp; 374 SkPaint tmp;
331 tmp.setImageFilter(fOrigPaint.getImageFilter()); 375 tmp.setImageFilter(fPaint->getImageFilter());
332 tmp.setXfermode(fOrigPaint.getXfermode()); 376 tmp.setXfermode(fPaint->getXfermode());
333 (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLa yer_SaveFlag, 377 (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLa yer_SaveFlag,
334 SkCanvas::kFullLayer_SaveLayerStrate gy); 378 SkCanvas::kFullLayer_SaveLayerStrate gy);
335 fTempLayerForImageFilter = true; 379 fTempLayerForImageFilter = true;
336 // we remove the imagefilter/xfermode inside doNext() 380 // we remove the imagefilter/xfermode inside doNext()
337 } 381 }
338 382
339 if (SkDrawLooper* looper = paint.getLooper()) { 383 if (SkDrawLooper* looper = paint.getLooper()) {
340 void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Contex t>( 384 void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Contex t>(
341 looper->contextSize()); 385 looper->contextSize());
342 fLooperContext = looper->createContext(canvas, buffer); 386 fLooperContext = looper->createContext(canvas, buffer);
343 fIsSimple = false; 387 fIsSimple = false;
344 } else { 388 } else {
345 fLooperContext = NULL; 389 fLooperContext = NULL;
346 // can we be marked as simple? 390 // can we be marked as simple?
347 fIsSimple = !fFilter && !fTempLayerForImageFilter; 391 fIsSimple = !fFilter && !fTempLayerForImageFilter;
348 } 392 }
349 393
350 uint32_t oldFlags = paint.getFlags(); 394 uint32_t oldFlags = paint.getFlags();
351 fNewPaintFlags = filter_paint_flags(props, oldFlags); 395 fNewPaintFlags = filter_paint_flags(props, oldFlags);
352 if (fIsSimple && (fNewPaintFlags != oldFlags)) { 396 if (fIsSimple && (fNewPaintFlags != oldFlags)) {
353 SkPaint* paint = fLazyPaint.set(fOrigPaint); 397 SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
354 paint->setFlags(fNewPaintFlags); 398 paint->setFlags(fNewPaintFlags);
355 fPaint = paint; 399 fPaint = paint;
356 // if we're not simple, doNext() will take care of calling setFlags( ) 400 // if we're not simple, doNext() will take care of calling setFlags( )
357 } 401 }
358 } 402 }
359 403
360 ~AutoDrawLooper() { 404 ~AutoDrawLooper() {
361 if (fTempLayerForImageFilter) { 405 if (fTempLayerForImageFilter) {
362 fCanvas->internalRestore(); 406 fCanvas->internalRestore();
363 } 407 }
(...skipping 10 matching lines...) Expand all
374 return false; 418 return false;
375 } else if (fIsSimple) { 419 } else if (fIsSimple) {
376 fDone = true; 420 fDone = true;
377 return !fPaint->nothingToDraw(); 421 return !fPaint->nothingToDraw();
378 } else { 422 } else {
379 return this->doNext(drawType); 423 return this->doNext(drawType);
380 } 424 }
381 } 425 }
382 426
383 private: 427 private:
384 SkLazyPaint fLazyPaint; 428 SkLazyPaint fLazyPaintInit; // base paint storage in case we need to mod ify it
429 SkLazyPaint fLazyPaintPerLooper; // per-draw-looper storage, so the loo per can modify it
385 SkCanvas* fCanvas; 430 SkCanvas* fCanvas;
386 const SkPaint& fOrigPaint; 431 const SkPaint& fOrigPaint;
387 SkDrawFilter* fFilter; 432 SkDrawFilter* fFilter;
388 const SkPaint* fPaint; 433 const SkPaint* fPaint;
389 int fSaveCount; 434 int fSaveCount;
390 uint32_t fNewPaintFlags; 435 uint32_t fNewPaintFlags;
391 bool fTempLayerForImageFilter; 436 bool fTempLayerForImageFilter;
392 bool fDone; 437 bool fDone;
393 bool fIsSimple; 438 bool fIsSimple;
394 SkDrawLooper::Context* fLooperContext; 439 SkDrawLooper::Context* fLooperContext;
395 SkSmallAllocator<1, 32> fLooperContextAllocator; 440 SkSmallAllocator<1, 32> fLooperContextAllocator;
396 441
397 bool doNext(SkDrawFilter::Type drawType); 442 bool doNext(SkDrawFilter::Type drawType);
398 }; 443 };
399 444
400 bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) { 445 bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
401 fPaint = NULL; 446 fPaint = NULL;
402 SkASSERT(!fIsSimple); 447 SkASSERT(!fIsSimple);
403 SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter); 448 SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter);
404 449
405 SkPaint* paint = fLazyPaint.set(fOrigPaint); 450 SkPaint* paint = fLazyPaintPerLooper.set(fLazyPaintInit.isValid() ?
451 *fLazyPaintInit.get() : fOrigPaint) ;
406 paint->setFlags(fNewPaintFlags); 452 paint->setFlags(fNewPaintFlags);
407 453
408 if (fTempLayerForImageFilter) { 454 if (fTempLayerForImageFilter) {
409 paint->setImageFilter(NULL); 455 paint->setImageFilter(NULL);
410 paint->setXfermode(NULL); 456 paint->setXfermode(NULL);
411 } 457 }
412 458
413 if (fLooperContext && !fLooperContext->next(fCanvas, paint)) { 459 if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
414 fDone = true; 460 fDone = true;
415 return false; 461 return false;
(...skipping 2176 matching lines...) Expand 10 before | Expand all | Expand 10 after
2592 } 2638 }
2593 2639
2594 if (matrix) { 2640 if (matrix) {
2595 canvas->concat(*matrix); 2641 canvas->concat(*matrix);
2596 } 2642 }
2597 } 2643 }
2598 2644
2599 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { 2645 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2600 fCanvas->restoreToCount(fSaveCount); 2646 fCanvas->restoreToCount(fSaveCount);
2601 } 2647 }
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