OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 The Android Open Source Project | 2 * Copyright 2012 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 "SkImageFilter.h" | 8 #include "SkImageFilter.h" |
9 | 9 |
10 #include "SkCanvas.h" | 10 #include "SkCanvas.h" |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 // grown the bounds beyond the original clip. This can happen for | 340 // grown the bounds beyond the original clip. This can happen for |
341 // example in tiling, where the clip is much smaller than the filtered | 341 // example in tiling, where the clip is much smaller than the filtered |
342 // primitive. If we didn't do this, we would be processing the filter | 342 // primitive. If we didn't do this, we would be processing the filter |
343 // at the full crop rect size in every tile. | 343 // at the full crop rect size in every tile. |
344 return dstBounds->intersect(ctx.clipBounds()); | 344 return dstBounds->intersect(ctx.clipBounds()); |
345 } | 345 } |
346 | 346 |
347 // Return a larger (newWidth x newHeight) copy of 'src' with black padding | 347 // Return a larger (newWidth x newHeight) copy of 'src' with black padding |
348 // around it. | 348 // around it. |
349 static sk_sp<SkSpecialImage> pad_image(SkSpecialImage* src, | 349 static sk_sp<SkSpecialImage> pad_image(SkSpecialImage* src, |
| 350 const SkImageFilter::OutputProperties& ou
tProps, |
350 int newWidth, int newHeight, int offX, in
t offY) { | 351 int newWidth, int newHeight, int offX, in
t offY) { |
351 // We explicitly want to operate in the source's color space here | 352 // We would like to operate in the source's color space (so that we return a
n "identical" |
352 SkImageFilter::OutputProperties outProps(src->getColorSpace()); | 353 // image, other than the padding. To achieve that, we'd create new output pr
operties: |
| 354 // |
| 355 // SkImageFilter::OutputProperties outProps(src->getColorSpace()); |
| 356 // |
| 357 // That fails in at least two ways. For formats that are texturable but not
renderable (like |
| 358 // F16 on some ES implementations), we can't create a surface to do the work
. For sRGB, images |
| 359 // may be tagged with an sRGB color space (which leads to an sRGB config in
makeSurface). But |
| 360 // the actual config of that sRGB image on a device with no sRGB support is
non-sRGB. |
| 361 // |
| 362 // Rather than try to special case these situations, we execute the image pa
dding in the |
| 363 // destination color space. This should not affect the output of the DAG in
(almost) any case, |
| 364 // because the result of this call is going to be used as an input, where it
would have been |
| 365 // switched to the destination space anyway. The one exception would be a fi
lter that expected |
| 366 // to consume unclamped F16 data, but the padded version of the image is pre
-clamped to 8888. |
| 367 // We can revisit this logic if that ever becomes an actual problem. |
353 sk_sp<SkSpecialSurface> surf(src->makeSurface(outProps, SkISize::Make(newWid
th, newHeight))); | 368 sk_sp<SkSpecialSurface> surf(src->makeSurface(outProps, SkISize::Make(newWid
th, newHeight))); |
354 if (!surf) { | 369 if (!surf) { |
355 return nullptr; | 370 return nullptr; |
356 } | 371 } |
357 | 372 |
358 SkCanvas* canvas = surf->getCanvas(); | 373 SkCanvas* canvas = surf->getCanvas(); |
359 SkASSERT(canvas); | 374 SkASSERT(canvas); |
360 | 375 |
361 canvas->clear(0x0); | 376 canvas->clear(0x0); |
362 | 377 |
(...skipping 11 matching lines...) Expand all Loading... |
374 | 389 |
375 SkIRect dstBounds = this->onFilterNodeBounds(srcBounds, ctx.ctm(), kForward_
MapDirection); | 390 SkIRect dstBounds = this->onFilterNodeBounds(srcBounds, ctx.ctm(), kForward_
MapDirection); |
376 fCropRect.applyTo(dstBounds, ctx.ctm(), this->affectsTransparentBlack(), bou
nds); | 391 fCropRect.applyTo(dstBounds, ctx.ctm(), this->affectsTransparentBlack(), bou
nds); |
377 if (!bounds->intersect(ctx.clipBounds())) { | 392 if (!bounds->intersect(ctx.clipBounds())) { |
378 return nullptr; | 393 return nullptr; |
379 } | 394 } |
380 | 395 |
381 if (srcBounds.contains(*bounds)) { | 396 if (srcBounds.contains(*bounds)) { |
382 return sk_sp<SkSpecialImage>(SkRef(src)); | 397 return sk_sp<SkSpecialImage>(SkRef(src)); |
383 } else { | 398 } else { |
384 sk_sp<SkSpecialImage> img(pad_image(src, | 399 sk_sp<SkSpecialImage> img(pad_image(src, ctx.outputProperties(), |
385 bounds->width(), bounds->height(), | 400 bounds->width(), bounds->height(), |
386 srcOffset->x() - bounds->x(), | 401 srcOffset->x() - bounds->x(), |
387 srcOffset->y() - bounds->y())); | 402 srcOffset->y() - bounds->y())); |
388 *srcOffset = SkIPoint::Make(bounds->x(), bounds->y()); | 403 *srcOffset = SkIPoint::Make(bounds->x(), bounds->y()); |
389 return img; | 404 return img; |
390 } | 405 } |
391 } | 406 } |
392 | 407 |
393 SkIRect SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, | 408 SkIRect SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, |
394 MapDirection direction) const { | 409 MapDirection direction) const { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 sk_sp<SkSpecialImage> result(input->filterImage(src, this->mapContext(ctx),
offset)); | 462 sk_sp<SkSpecialImage> result(input->filterImage(src, this->mapContext(ctx),
offset)); |
448 | 463 |
449 SkASSERT(!result || src->isTextureBacked() == result->isTextureBacked()); | 464 SkASSERT(!result || src->isTextureBacked() == result->isTextureBacked()); |
450 | 465 |
451 return result; | 466 return result; |
452 } | 467 } |
453 | 468 |
454 void SkImageFilter::PurgeCache() { | 469 void SkImageFilter::PurgeCache() { |
455 SkImageFilterCache::Get()->purge(); | 470 SkImageFilterCache::Get()->purge(); |
456 } | 471 } |
OLD | NEW |