SkMatrixImageFilter.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /*
  2. * Copyright 2014 The Android Open Source Project
  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 "src/core/SkMatrixImageFilter.h"
  8. #include "include/core/SkCanvas.h"
  9. #include "include/core/SkRect.h"
  10. #include "src/core/SkImageFilterPriv.h"
  11. #include "src/core/SkReadBuffer.h"
  12. #include "src/core/SkSpecialImage.h"
  13. #include "src/core/SkSpecialSurface.h"
  14. #include "src/core/SkWriteBuffer.h"
  15. SkMatrixImageFilter::SkMatrixImageFilter(const SkMatrix& transform,
  16. SkFilterQuality filterQuality,
  17. sk_sp<SkImageFilter> input)
  18. : INHERITED(&input, 1, nullptr)
  19. , fTransform(transform)
  20. , fFilterQuality(filterQuality) {
  21. }
  22. sk_sp<SkImageFilter> SkMatrixImageFilter::Make(const SkMatrix& transform,
  23. SkFilterQuality filterQuality,
  24. sk_sp<SkImageFilter> input) {
  25. return sk_sp<SkImageFilter>(new SkMatrixImageFilter(transform,
  26. filterQuality,
  27. std::move(input)));
  28. }
  29. sk_sp<SkFlattenable> SkMatrixImageFilter::CreateProc(SkReadBuffer& buffer) {
  30. SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
  31. SkMatrix matrix;
  32. buffer.readMatrix(&matrix);
  33. return Make(matrix, buffer.read32LE(kLast_SkFilterQuality), common.getInput(0));
  34. }
  35. void SkMatrixImageFilter::flatten(SkWriteBuffer& buffer) const {
  36. this->INHERITED::flatten(buffer);
  37. buffer.writeMatrix(fTransform);
  38. buffer.writeInt(fFilterQuality);
  39. }
  40. sk_sp<SkSpecialImage> SkMatrixImageFilter::onFilterImage(SkSpecialImage* source,
  41. const Context& ctx,
  42. SkIPoint* offset) const {
  43. SkIPoint inputOffset = SkIPoint::Make(0, 0);
  44. sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset));
  45. if (!input) {
  46. return nullptr;
  47. }
  48. SkMatrix matrix;
  49. if (!ctx.ctm().invert(&matrix)) {
  50. return nullptr;
  51. }
  52. matrix.postConcat(fTransform);
  53. matrix.postConcat(ctx.ctm());
  54. const SkIRect srcBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(),
  55. input->width(), input->height());
  56. const SkRect srcRect = SkRect::Make(srcBounds);
  57. SkRect dstRect;
  58. matrix.mapRect(&dstRect, srcRect);
  59. SkIRect dstBounds;
  60. dstRect.roundOut(&dstBounds);
  61. sk_sp<SkSpecialSurface> surf(input->makeSurface(ctx.outputProperties(), dstBounds.size()));
  62. if (!surf) {
  63. return nullptr;
  64. }
  65. SkCanvas* canvas = surf->getCanvas();
  66. SkASSERT(canvas);
  67. canvas->clear(0x0);
  68. canvas->translate(-SkIntToScalar(dstBounds.x()), -SkIntToScalar(dstBounds.y()));
  69. canvas->concat(matrix);
  70. SkPaint paint;
  71. paint.setAntiAlias(true);
  72. paint.setBlendMode(SkBlendMode::kSrc);
  73. paint.setFilterQuality(fFilterQuality);
  74. input->draw(canvas, srcRect.x(), srcRect.y(), &paint);
  75. offset->fX = dstBounds.fLeft;
  76. offset->fY = dstBounds.fTop;
  77. return surf->makeImageSnapshot();
  78. }
  79. SkRect SkMatrixImageFilter::computeFastBounds(const SkRect& src) const {
  80. SkRect bounds = this->getInput(0) ? this->getInput(0)->computeFastBounds(src) : src;
  81. SkRect dst;
  82. fTransform.mapRect(&dst, bounds);
  83. return dst;
  84. }
  85. SkIRect SkMatrixImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm,
  86. MapDirection dir, const SkIRect* inputRect) const {
  87. SkMatrix matrix;
  88. if (!ctm.invert(&matrix)) {
  89. return src;
  90. }
  91. if (kForward_MapDirection == dir) {
  92. matrix.postConcat(fTransform);
  93. } else {
  94. SkMatrix transformInverse;
  95. if (!fTransform.invert(&transformInverse)) {
  96. return src;
  97. }
  98. matrix.postConcat(transformInverse);
  99. }
  100. matrix.postConcat(ctm);
  101. SkRect floatBounds;
  102. matrix.mapRect(&floatBounds, SkRect::Make(src));
  103. SkIRect result = floatBounds.roundOut();
  104. if (kReverse_MapDirection == dir && kNone_SkFilterQuality != fFilterQuality) {
  105. // When filtering we might need some pixels in the source that might be otherwise
  106. // clipped off.
  107. result.outset(1, 1);
  108. }
  109. return result;
  110. }