| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |