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