SkComposeImageFilter.cpp 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. /*
  2. * Copyright 2013 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "include/effects/SkComposeImageFilter.h"
  8. #include "src/core/SkImageFilterPriv.h"
  9. #include "src/core/SkReadBuffer.h"
  10. #include "src/core/SkSpecialImage.h"
  11. #include "src/core/SkWriteBuffer.h"
  12. sk_sp<SkImageFilter> SkComposeImageFilter::Make(sk_sp<SkImageFilter> outer,
  13. sk_sp<SkImageFilter> inner) {
  14. if (!outer) {
  15. return inner;
  16. }
  17. if (!inner) {
  18. return outer;
  19. }
  20. sk_sp<SkImageFilter> inputs[2] = { std::move(outer), std::move(inner) };
  21. return sk_sp<SkImageFilter>(new SkComposeImageFilter(inputs));
  22. }
  23. SkRect SkComposeImageFilter::computeFastBounds(const SkRect& src) const {
  24. SkImageFilter* outer = this->getInput(0);
  25. SkImageFilter* inner = this->getInput(1);
  26. return outer->computeFastBounds(inner->computeFastBounds(src));
  27. }
  28. sk_sp<SkSpecialImage> SkComposeImageFilter::onFilterImage(SkSpecialImage* source,
  29. const Context& ctx,
  30. SkIPoint* offset) const {
  31. // The bounds passed to the inner filter must be filtered by the outer
  32. // filter, so that the inner filter produces the pixels that the outer
  33. // filter requires as input. This matters if the outer filter moves pixels.
  34. SkIRect innerClipBounds;
  35. innerClipBounds = this->getInput(0)->filterBounds(ctx.clipBounds(), ctx.ctm(),
  36. kReverse_MapDirection, &ctx.clipBounds());
  37. Context innerContext(ctx.ctm(), innerClipBounds, ctx.cache(), ctx.outputProperties());
  38. SkIPoint innerOffset = SkIPoint::Make(0, 0);
  39. sk_sp<SkSpecialImage> inner(this->filterInput(1, source, innerContext, &innerOffset));
  40. if (!inner) {
  41. return nullptr;
  42. }
  43. SkMatrix outerMatrix(ctx.ctm());
  44. outerMatrix.postTranslate(SkIntToScalar(-innerOffset.x()), SkIntToScalar(-innerOffset.y()));
  45. SkIRect clipBounds = ctx.clipBounds();
  46. clipBounds.offset(-innerOffset.x(), -innerOffset.y());
  47. Context outerContext(outerMatrix, clipBounds, ctx.cache(), ctx.outputProperties());
  48. SkIPoint outerOffset = SkIPoint::Make(0, 0);
  49. sk_sp<SkSpecialImage> outer(this->filterInput(0, inner.get(), outerContext, &outerOffset));
  50. if (!outer) {
  51. return nullptr;
  52. }
  53. *offset = innerOffset + outerOffset;
  54. return outer;
  55. }
  56. SkIRect SkComposeImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
  57. MapDirection dir, const SkIRect* inputRect) const {
  58. SkImageFilter* outer = this->getInput(0);
  59. SkImageFilter* inner = this->getInput(1);
  60. const SkIRect innerRect = inner->filterBounds(src, ctm, dir, inputRect);
  61. return outer->filterBounds(innerRect, ctm, dir,
  62. kReverse_MapDirection == dir ? &innerRect : nullptr);
  63. }
  64. sk_sp<SkFlattenable> SkComposeImageFilter::CreateProc(SkReadBuffer& buffer) {
  65. SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2);
  66. return SkComposeImageFilter::Make(common.getInput(0), common.getInput(1));
  67. }