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 |