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

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: add flag for chrome 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
robertphillips 2015/04/29 18:50:05 imagefilter -> imagefilter that is a colorfilter ?
reed1 2015/04/29 19:05:37 Done.
331 // The paint has both a colorfilter and an imagefilter.
332 SkAutoTUnref<SkColorFilter> autoImgCF(imgCF);
333 return SkColorFilter::CreateComposeFilter(imgCF, paintCF);
334 #endif
335 }
336
302 class AutoDrawLooper { 337 class AutoDrawLooper {
303 public: 338 public:
304 AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint, 339 AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint,
305 bool skipLayerForImageFilter = false, 340 bool skipLayerForImageFilter = false,
306 const SkRect* bounds = NULL) : fOrigPaint(paint) { 341 const SkRect* bounds = NULL) : fOrigPaint(paint) {
307 fCanvas = canvas; 342 fCanvas = canvas;
308 fFilter = canvas->getDrawFilter(); 343 fFilter = canvas->getDrawFilter();
309 fPaint = &fOrigPaint; 344 fPaint = &fOrigPaint;
310 fSaveCount = canvas->getSaveCount(); 345 fSaveCount = canvas->getSaveCount();
311 fTempLayerForImageFilter = false; 346 fTempLayerForImageFilter = false;
312 fDone = false; 347 fDone = false;
313 348
314 if (!skipLayerForImageFilter && fOrigPaint.getImageFilter()) { 349 SkColorFilter* simplifiedCF = image_to_color_filter(fOrigPaint);
350 if (simplifiedCF) {
351 SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
352 paint->setColorFilter(simplifiedCF)->unref();
353 paint->setImageFilter(NULL);
354 fPaint = paint;
355 }
356
357 if (!skipLayerForImageFilter && fPaint->getImageFilter()) {
315 /** 358 /**
316 * We implement ImageFilters for a given draw by creating a layer, then applying the 359 * 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 360 * 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. 361 * we call restore() to xfer that layer to the main canvas.
319 * 362 *
320 * 1. SaveLayer (with a paint containing the current imagefilter an d xfermode) 363 * 1. SaveLayer (with a paint containing the current imagefilter an d xfermode)
321 * 2. Generate the src pixels: 364 * 2. Generate the src pixels:
322 * Remove the imagefilter and the xfermode from the paint that we (AutoDrawLooper) 365 * 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 366 * return (fPaint). We then draw the primitive (using srcover) into a cleared
324 * buffer/surface. 367 * buffer/surface.
325 * 3. Restore the layer created in #1 368 * 3. Restore the layer created in #1
326 * The imagefilter is passed the buffer/surface from the layer (now filled with the 369 * 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 370 * 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. 371 * draw onto the previous layer using the xfermode from the ori ginal paint.
329 */ 372 */
330 SkPaint tmp; 373 SkPaint tmp;
331 tmp.setImageFilter(fOrigPaint.getImageFilter()); 374 tmp.setImageFilter(fPaint->getImageFilter());
332 tmp.setXfermode(fOrigPaint.getXfermode()); 375 tmp.setXfermode(fPaint->getXfermode());
333 (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLa yer_SaveFlag, 376 (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLa yer_SaveFlag,
334 SkCanvas::kFullLayer_SaveLayerStrate gy); 377 SkCanvas::kFullLayer_SaveLayerStrate gy);
335 fTempLayerForImageFilter = true; 378 fTempLayerForImageFilter = true;
336 // we remove the imagefilter/xfermode inside doNext() 379 // we remove the imagefilter/xfermode inside doNext()
337 } 380 }
338 381
339 if (SkDrawLooper* looper = paint.getLooper()) { 382 if (SkDrawLooper* looper = paint.getLooper()) {
340 void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Contex t>( 383 void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Contex t>(
341 looper->contextSize()); 384 looper->contextSize());
342 fLooperContext = looper->createContext(canvas, buffer); 385 fLooperContext = looper->createContext(canvas, buffer);
343 fIsSimple = false; 386 fIsSimple = false;
344 } else { 387 } else {
345 fLooperContext = NULL; 388 fLooperContext = NULL;
346 // can we be marked as simple? 389 // can we be marked as simple?
347 fIsSimple = !fFilter && !fTempLayerForImageFilter; 390 fIsSimple = !fFilter && !fTempLayerForImageFilter;
348 } 391 }
349 392
350 uint32_t oldFlags = paint.getFlags(); 393 uint32_t oldFlags = paint.getFlags();
351 fNewPaintFlags = filter_paint_flags(props, oldFlags); 394 fNewPaintFlags = filter_paint_flags(props, oldFlags);
352 if (fIsSimple && (fNewPaintFlags != oldFlags)) { 395 if (fIsSimple && (fNewPaintFlags != oldFlags)) {
353 SkPaint* paint = fLazyPaint.set(fOrigPaint); 396 SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
354 paint->setFlags(fNewPaintFlags); 397 paint->setFlags(fNewPaintFlags);
355 fPaint = paint; 398 fPaint = paint;
356 // if we're not simple, doNext() will take care of calling setFlags( ) 399 // if we're not simple, doNext() will take care of calling setFlags( )
357 } 400 }
358 } 401 }
359 402
360 ~AutoDrawLooper() { 403 ~AutoDrawLooper() {
361 if (fTempLayerForImageFilter) { 404 if (fTempLayerForImageFilter) {
362 fCanvas->internalRestore(); 405 fCanvas->internalRestore();
363 } 406 }
364 SkASSERT(fCanvas->getSaveCount() == fSaveCount); 407 SkASSERT(fCanvas->getSaveCount() == fSaveCount);
365 } 408 }
366 409
367 const SkPaint& paint() const { 410 const SkPaint& paint() const {
368 SkASSERT(fPaint); 411 SkASSERT(fPaint);
369 return *fPaint; 412 return *fPaint;
370 } 413 }
371 414
372 bool next(SkDrawFilter::Type drawType) { 415 bool next(SkDrawFilter::Type drawType) {
373 if (fDone) { 416 if (fDone) {
374 return false; 417 return false;
375 } else if (fIsSimple) { 418 } else if (fIsSimple) {
376 fDone = true; 419 fDone = true;
377 return !fPaint->nothingToDraw(); 420 return !fPaint->nothingToDraw();
378 } else { 421 } else {
379 return this->doNext(drawType); 422 return this->doNext(drawType);
380 } 423 }
381 } 424 }
382 425
383 private: 426 private:
robertphillips 2015/04/29 18:50:05 fLazyPaintPerNext needs a better name (or a commen
reed1 2015/04/29 19:05:37 Done.
384 SkLazyPaint fLazyPaint; 427 SkLazyPaint fLazyPaintInit, fLazyPaintPerNext;
385 SkCanvas* fCanvas; 428 SkCanvas* fCanvas;
386 const SkPaint& fOrigPaint; 429 const SkPaint& fOrigPaint;
387 SkDrawFilter* fFilter; 430 SkDrawFilter* fFilter;
388 const SkPaint* fPaint; 431 const SkPaint* fPaint;
389 int fSaveCount; 432 int fSaveCount;
390 uint32_t fNewPaintFlags; 433 uint32_t fNewPaintFlags;
391 bool fTempLayerForImageFilter; 434 bool fTempLayerForImageFilter;
392 bool fDone; 435 bool fDone;
393 bool fIsSimple; 436 bool fIsSimple;
394 SkDrawLooper::Context* fLooperContext; 437 SkDrawLooper::Context* fLooperContext;
395 SkSmallAllocator<1, 32> fLooperContextAllocator; 438 SkSmallAllocator<1, 32> fLooperContextAllocator;
396 439
397 bool doNext(SkDrawFilter::Type drawType); 440 bool doNext(SkDrawFilter::Type drawType);
398 }; 441 };
399 442
400 bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) { 443 bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) {
401 fPaint = NULL; 444 fPaint = NULL;
402 SkASSERT(!fIsSimple); 445 SkASSERT(!fIsSimple);
403 SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter); 446 SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter);
404 447
405 SkPaint* paint = fLazyPaint.set(fOrigPaint); 448 SkPaint* paint = fLazyPaintPerNext.set(fLazyPaintInit.isValid() ?
449 *fLazyPaintInit.get() : fOrigPaint);
406 paint->setFlags(fNewPaintFlags); 450 paint->setFlags(fNewPaintFlags);
407 451
408 if (fTempLayerForImageFilter) { 452 if (fTempLayerForImageFilter) {
409 paint->setImageFilter(NULL); 453 paint->setImageFilter(NULL);
410 paint->setXfermode(NULL); 454 paint->setXfermode(NULL);
411 } 455 }
412 456
413 if (fLooperContext && !fLooperContext->next(fCanvas, paint)) { 457 if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
414 fDone = true; 458 fDone = true;
415 return false; 459 return false;
(...skipping 2176 matching lines...) Expand 10 before | Expand all | Expand 10 after
2592 } 2636 }
2593 2637
2594 if (matrix) { 2638 if (matrix) {
2595 canvas->concat(*matrix); 2639 canvas->concat(*matrix);
2596 } 2640 }
2597 } 2641 }
2598 2642
2599 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { 2643 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2600 fCanvas->restoreToCount(fSaveCount); 2644 fCanvas->restoreToCount(fSaveCount);
2601 } 2645 }
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