40 SkMagnifierImageFilter(
const SkRect& lensBounds,
46 , fLensBounds(lensBounds)
47 , fZoomAmount(zoomAmount)
57 friend void ::SkRegisterMagnifierImageFilterFlattenable();
89 zoomAmount <= 0.f ||
inset < 0.f ||
99 if (zoomAmount > 1.f) {
101 sampling, std::move(input)));
125 buffer.readRect(&lensBounds);
135 buffer.writeScalar(fZoomAmount);
136 buffer.writeScalar(fInset);
137 buffer.writeSampling(fSampling);
148 GetKnownRuntimeEffect(SkKnownRuntimeEffects::StableKey::kMagnifier);
151 builder.child(
"src") = std::move(input);
154 builder.uniform(
"lensBounds") =
SkRect(lensBounds);
155 builder.uniform(
"zoomXform") =
SkV4{zoomXform.rc(0, 2), zoomXform.rc(1, 2),
156 zoomXform.rc(0, 0), zoomXform.rc(1, 1)};
160 return builder.makeShader();
188 zoomCenter = expectedChildOutput.clamp(zoomCenter);
195 SkASSERT(this->getCTMCapability() == MatrixCapability::kScaleTranslate);
196 float invZoom = 1.f / fZoomAmount;
206 lensBounds.left() * invZoom + zoomCenter.x()*(1.f - invZoom),
207 lensBounds.top() * invZoom + zoomCenter.y()*(1.f - invZoom),
208 lensBounds.right() * invZoom + zoomCenter.x()*(1.f - invZoom),
209 lensBounds.bottom()* invZoom + zoomCenter.y()*(1.f - invZoom)}};
215 if (!expectedChildOutput.contains(visibleLensBounds)) {
218 srcRect = zoomXform.mapRect(visibleLensBounds);
220 if (expectedChildOutput.width() >= srcRect.width() &&
221 expectedChildOutput.height() >= srcRect.height()) {
222 float left = srcRect.left() < expectedChildOutput.left() ?
223 expectedChildOutput.left() :
224 std::min(srcRect.right(), expectedChildOutput.right()) - srcRect.width();
225 float top = srcRect.top() < expectedChildOutput.top() ?
226 expectedChildOutput.top() :
227 std::min(srcRect.bottom(), expectedChildOutput.bottom()) - srcRect.height();
249 return childOutput.
applyTransform(context, invZoomXform, fSampling)
250 .
applyCrop(context, lensBounds.roundOut());
256 {}, ShaderFlags::kNonTrivialSampling, fSampling);
261 }, lensBounds.roundOut());
276 return this->getChildInputLayerBounds(0, mapping, requiredInput, contentBounds);
279std::optional<skif::LayerSpace<SkIRect>> SkMagnifierImageFilter::onGetOutputLayerBounds(
283 auto output = this->getChildOutputLayerBounds(0, mapping, contentBounds);
285 if (!output || lensBounds.intersect(*output)) {
293SkRect SkMagnifierImageFilter::computeFastBounds(
const SkRect& src)
const {
294 SkRect bounds = this->getInput(0) ? this->getInput(0)->computeFastBounds(src) :
src;
#define SkAssertResult(cond)
#define SK_FLATTENABLE_HOOKS(type)
#define SK_REGISTER_FLATTENABLE(type)
static bool SkIsFinite(T x, Pack... values)
#define SK_IMAGEFILTER_UNFLATTEN_COMMON(localVar, expectedCount)
void SkRegisterMagnifierImageFilterFlattenable()
static sk_sp< SkShader > make_magnifier_shader(sk_sp< SkShader > input, const skif::LayerSpace< SkRect > &lensBounds, const skif::LayerSpace< SkMatrix > &zoomXform, const skif::LayerSpace< SkSize > &inset)
static bool left(const SkPoint &p0, const SkPoint &p1)
sk_sp< T > sk_ref_sp(T *obj)
virtual skif::LayerSpace< SkIRect > onGetInputLayerBounds(const skif::Mapping &mapping, const skif::LayerSpace< SkIRect > &desiredOutput, std::optional< skif::LayerSpace< SkIRect > > contentBounds) const =0
void flatten(SkWriteBuffer &) const override
virtual std::optional< skif::LayerSpace< SkIRect > > onGetOutputLayerBounds(const skif::Mapping &mapping, std::optional< skif::LayerSpace< SkIRect > > contentBounds) const =0
virtual skif::FilterResult onFilterImage(const skif::Context &context) const =0
virtual SkRect computeFastBounds(const SkRect &bounds) const
static sk_sp< SkImageFilter > Magnifier(const SkRect &lensBounds, SkScalar zoomAmount, SkScalar inset, const SkSamplingOptions &sampling, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Crop(const SkRect &rect, SkTileMode tileMode, sk_sp< SkImageFilter > input)
const LayerSpace< SkIRect > & desiredOutput() const
const FilterResult & source() const
Context withNewDesiredOutput(const LayerSpace< SkIRect > &desiredOutput) const
const Mapping & mapping() const
FilterResult applyCrop(const Context &ctx, const LayerSpace< SkIRect > &crop, SkTileMode tileMode=SkTileMode::kDecal) const
LayerSpace< SkIRect > layerBounds() const
FilterResult applyTransform(const Context &ctx, const LayerSpace< SkMatrix > &transform, const SkSamplingOptions &sampling) const
LayerSpace< T > paramToLayer(const ParameterSpace< T > ¶mGeometry) const
static const uint8_t buffer[]
Optional< SkRect > bounds
SkSamplingOptions sampling
static SkRect inset(const SkRect &r)
static constexpr SkRect MakeEmpty()
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
constexpr float height() const
constexpr float width() const