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