SkShaderMaskFilter.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*
  2. * Copyright 2018 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/core/SkCanvas.h"
  8. #include "include/core/SkString.h"
  9. #include "include/effects/SkShaderMaskFilter.h"
  10. #include "src/core/SkMaskFilterBase.h"
  11. #include "src/core/SkReadBuffer.h"
  12. #include "src/shaders/SkShaderBase.h"
  13. class SkShaderMF : public SkMaskFilterBase {
  14. public:
  15. SkShaderMF(sk_sp<SkShader> shader) : fShader(std::move(shader)) {}
  16. SkMask::Format getFormat() const override { return SkMask::kA8_Format; }
  17. bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
  18. SkIPoint* margin) const override;
  19. void computeFastBounds(const SkRect& src, SkRect* dst) const override {
  20. *dst = src;
  21. }
  22. bool asABlur(BlurRec*) const override { return false; }
  23. protected:
  24. #if SK_SUPPORT_GPU
  25. std::unique_ptr<GrFragmentProcessor> onAsFragmentProcessor(const GrFPArgs&) const override;
  26. bool onHasFragmentProcessor() const override;
  27. #endif
  28. private:
  29. SK_FLATTENABLE_HOOKS(SkShaderMF)
  30. sk_sp<SkShader> fShader;
  31. SkShaderMF(SkReadBuffer&);
  32. void flatten(SkWriteBuffer&) const override;
  33. friend class SkShaderMaskFilter;
  34. typedef SkMaskFilter INHERITED;
  35. };
  36. sk_sp<SkFlattenable> SkShaderMF::CreateProc(SkReadBuffer& buffer) {
  37. return SkShaderMaskFilter::Make(buffer.readShader());
  38. }
  39. void SkShaderMF::flatten(SkWriteBuffer& buffer) const {
  40. buffer.writeFlattenable(fShader.get());
  41. }
  42. static void rect_memcpy(void* dst, size_t dstRB, const void* src, size_t srcRB,
  43. size_t copyBytes, int rows) {
  44. for (int i = 0; i < rows; ++i) {
  45. memcpy(dst, src, copyBytes);
  46. dst = (char*)dst + dstRB;
  47. src = (const char*)src + srcRB;
  48. }
  49. }
  50. bool SkShaderMF::filterMask(SkMask* dst, const SkMask& src, const SkMatrix& ctm,
  51. SkIPoint* margin) const {
  52. if (src.fFormat != SkMask::kA8_Format) {
  53. return false;
  54. }
  55. if (margin) {
  56. margin->set(0, 0);
  57. }
  58. dst->fBounds = src.fBounds;
  59. dst->fRowBytes = src.fBounds.width(); // need alignment?
  60. dst->fFormat = SkMask::kA8_Format;
  61. if (src.fImage == nullptr) {
  62. dst->fImage = nullptr;
  63. return true;
  64. }
  65. size_t size = dst->computeImageSize();
  66. if (0 == size) {
  67. return false; // too big to allocate, abort
  68. }
  69. // Allocate and initialize dst image with a copy of the src image
  70. dst->fImage = SkMask::AllocImage(size);
  71. rect_memcpy(dst->fImage, dst->fRowBytes, src.fImage, src.fRowBytes,
  72. src.fBounds.width() * sizeof(uint8_t), src.fBounds.height());
  73. // Now we have a dst-mask, just need to setup a canvas and draw into it
  74. SkBitmap bitmap;
  75. if (!bitmap.installMaskPixels(*dst)) {
  76. return false;
  77. }
  78. SkPaint paint;
  79. paint.setShader(fShader);
  80. paint.setFilterQuality(SkFilterQuality::kLow_SkFilterQuality);
  81. // this blendmode is the trick: we only draw the shader where the mask is
  82. paint.setBlendMode(SkBlendMode::kSrcIn);
  83. SkCanvas canvas(bitmap);
  84. canvas.translate(-SkIntToScalar(dst->fBounds.fLeft), -SkIntToScalar(dst->fBounds.fTop));
  85. canvas.concat(ctm);
  86. canvas.drawPaint(paint);
  87. return true;
  88. }
  89. ///////////////////////////////////////////////////////////////////////////////////////////////////
  90. #if SK_SUPPORT_GPU
  91. #include "src/gpu/GrFragmentProcessor.h"
  92. std::unique_ptr<GrFragmentProcessor> SkShaderMF::onAsFragmentProcessor(const GrFPArgs& args) const {
  93. return GrFragmentProcessor::MulInputByChildAlpha(as_SB(fShader)->asFragmentProcessor(args));
  94. }
  95. bool SkShaderMF::onHasFragmentProcessor() const {
  96. return true;
  97. }
  98. #endif
  99. ///////////////////////////////////////////////////////////////////////////////////////////////////
  100. sk_sp<SkMaskFilter> SkShaderMaskFilter::Make(sk_sp<SkShader> shader) {
  101. return shader ? sk_sp<SkMaskFilter>(new SkShaderMF(std::move(shader))) : nullptr;
  102. }
  103. void SkShaderMaskFilter::RegisterFlattenables() { SK_REGISTER_FLATTENABLE(SkShaderMF); }