SkDropShadowImageFilter.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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/SkDropShadowImageFilter.h"
  8. #include "include/core/SkCanvas.h"
  9. #include "include/effects/SkBlurImageFilter.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. sk_sp<SkImageFilter> SkDropShadowImageFilter::Make(SkScalar dx, SkScalar dy,
  16. SkScalar sigmaX, SkScalar sigmaY,
  17. SkColor color, ShadowMode shadowMode,
  18. sk_sp<SkImageFilter> input,
  19. const CropRect* cropRect) {
  20. return sk_sp<SkImageFilter>(new SkDropShadowImageFilter(dx, dy, sigmaX, sigmaY,
  21. color, shadowMode,
  22. std::move(input),
  23. cropRect));
  24. }
  25. SkDropShadowImageFilter::SkDropShadowImageFilter(SkScalar dx, SkScalar dy,
  26. SkScalar sigmaX, SkScalar sigmaY, SkColor color,
  27. ShadowMode shadowMode, sk_sp<SkImageFilter> input,
  28. const CropRect* cropRect)
  29. : INHERITED(&input, 1, cropRect)
  30. , fDx(dx)
  31. , fDy(dy)
  32. , fSigmaX(sigmaX)
  33. , fSigmaY(sigmaY)
  34. , fColor(color)
  35. , fShadowMode(shadowMode) {
  36. }
  37. sk_sp<SkFlattenable> SkDropShadowImageFilter::CreateProc(SkReadBuffer& buffer) {
  38. SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
  39. SkScalar dx = buffer.readScalar();
  40. SkScalar dy = buffer.readScalar();
  41. SkScalar sigmaX = buffer.readScalar();
  42. SkScalar sigmaY = buffer.readScalar();
  43. SkColor color = buffer.readColor();
  44. ShadowMode shadowMode = buffer.read32LE(kLast_ShadowMode);
  45. return Make(dx, dy, sigmaX, sigmaY, color, shadowMode, common.getInput(0), &common.cropRect());
  46. }
  47. void SkDropShadowImageFilter::flatten(SkWriteBuffer& buffer) const {
  48. this->INHERITED::flatten(buffer);
  49. buffer.writeScalar(fDx);
  50. buffer.writeScalar(fDy);
  51. buffer.writeScalar(fSigmaX);
  52. buffer.writeScalar(fSigmaY);
  53. buffer.writeColor(fColor);
  54. buffer.writeInt(static_cast<int>(fShadowMode));
  55. }
  56. sk_sp<SkSpecialImage> SkDropShadowImageFilter::onFilterImage(SkSpecialImage* source,
  57. const Context& ctx,
  58. SkIPoint* offset) const {
  59. SkIPoint inputOffset = SkIPoint::Make(0, 0);
  60. sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset));
  61. if (!input) {
  62. return nullptr;
  63. }
  64. const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(),
  65. input->width(), input->height());
  66. SkIRect bounds;
  67. if (!this->applyCropRect(ctx, inputBounds, &bounds)) {
  68. return nullptr;
  69. }
  70. sk_sp<SkSpecialSurface> surf(source->makeSurface(ctx.outputProperties(), bounds.size()));
  71. if (!surf) {
  72. return nullptr;
  73. }
  74. SkCanvas* canvas = surf->getCanvas();
  75. SkASSERT(canvas);
  76. canvas->clear(0x0);
  77. SkVector sigma = SkVector::Make(fSigmaX, fSigmaY);
  78. ctx.ctm().mapVectors(&sigma, 1);
  79. sigma.fX = SkMaxScalar(0, sigma.fX);
  80. sigma.fY = SkMaxScalar(0, sigma.fY);
  81. SkPaint paint;
  82. paint.setAntiAlias(true);
  83. paint.setImageFilter(SkBlurImageFilter::Make(sigma.fX, sigma.fY, nullptr));
  84. paint.setColorFilter(SkColorFilters::Blend(fColor, SkBlendMode::kSrcIn));
  85. SkVector offsetVec = SkVector::Make(fDx, fDy);
  86. ctx.ctm().mapVectors(&offsetVec, 1);
  87. canvas->translate(SkIntToScalar(inputOffset.fX - bounds.fLeft),
  88. SkIntToScalar(inputOffset.fY - bounds.fTop));
  89. input->draw(canvas, offsetVec.fX, offsetVec.fY, &paint);
  90. if (fShadowMode == kDrawShadowAndForeground_ShadowMode) {
  91. input->draw(canvas, 0, 0, nullptr);
  92. }
  93. offset->fX = bounds.fLeft;
  94. offset->fY = bounds.fTop;
  95. return surf->makeImageSnapshot();
  96. }
  97. SkRect SkDropShadowImageFilter::computeFastBounds(const SkRect& src) const {
  98. SkRect bounds = this->getInput(0) ? this->getInput(0)->computeFastBounds(src) : src;
  99. SkRect shadowBounds = bounds;
  100. shadowBounds.offset(fDx, fDy);
  101. shadowBounds.outset(fSigmaX * 3, fSigmaY * 3);
  102. if (fShadowMode == kDrawShadowAndForeground_ShadowMode) {
  103. bounds.join(shadowBounds);
  104. } else {
  105. bounds = shadowBounds;
  106. }
  107. return bounds;
  108. }
  109. SkIRect SkDropShadowImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm,
  110. MapDirection dir, const SkIRect* inputRect) const {
  111. SkVector offsetVec = SkVector::Make(fDx, fDy);
  112. if (kReverse_MapDirection == dir) {
  113. offsetVec.negate();
  114. }
  115. ctm.mapVectors(&offsetVec, 1);
  116. SkIRect dst = src.makeOffset(SkScalarCeilToInt(offsetVec.x()),
  117. SkScalarCeilToInt(offsetVec.y()));
  118. SkVector sigma = SkVector::Make(fSigmaX, fSigmaY);
  119. ctm.mapVectors(&sigma, 1);
  120. dst.outset(
  121. SkScalarCeilToInt(SkScalarAbs(sigma.x() * 3)),
  122. SkScalarCeilToInt(SkScalarAbs(sigma.y() * 3)));
  123. if (fShadowMode == kDrawShadowAndForeground_ShadowMode) {
  124. dst.join(src);
  125. }
  126. return dst;
  127. }