822 {
824
825 if (crop.isEmpty() || ctx.desiredOutput().isEmpty()) {
826
827 return {};
828 }
829
830
831
832 LayerSpace<SkIRect> cropContent = crop;
833 if (!fImage ||
834 !cropContent.intersect(fLayerBounds)) {
835
836 return {};
837 }
838
839
840 LayerSpace<SkIRect> fittedCrop = crop.relevantSubset(ctx.desiredOutput(),
tileMode);
841
842
843
844
845
846 if (!cropContent.intersect(fittedCrop)) {
847 return {};
848 }
849
850
851
852 auto periodicTransform = periodic_axis_transform(
tileMode, fittedCrop, ctx.desiredOutput());
853 if (periodicTransform) {
855 }
856
857 bool preserveTransparencyInCrop = false;
859
860 fittedCrop = cropContent;
861 } else if (fittedCrop.contains(ctx.desiredOutput())) {
863 fittedCrop = ctx.desiredOutput();
864 } else if (!cropContent.contains(fittedCrop)) {
865
866
867 preserveTransparencyInCrop = true;
869
872 }
873 }
874
875
876
877
878
880 LayerSpace<SkIPoint> origin;
881 if (!preserveTransparencyInCrop &&
882 is_nearly_integer_translation(fTransform, &origin) &&
883 (doubleClamp ||
884 !(this->analyzeBounds(fittedCrop) & BoundsAnalysis::kHasLayerFillingEffect))) {
885
886
887
888
889
890
891
892 FilterResult restrictedOutput = this->subset(origin, fittedCrop, doubleClamp);
893 restrictedOutput.updateTileMode(ctx,
tileMode);
894 if (restrictedOutput.fBoundary == PixelBoundary::kInitialized ||
896
897
898 restrictedOutput.fBoundary = PixelBoundary::kUnknown;
899 }
900 return restrictedOutput;
902
903
904 SkASSERT(!preserveTransparencyInCrop);
906 restrictedOutput.fLayerBounds = fittedCrop;
907 return restrictedOutput;
908 } else {
909
910
911 FilterResult tiled = this->resolve(ctx, fittedCrop,
true);
912 tiled.updateTileMode(ctx,
tileMode);
913 return tiled;
914 }
915}
static const SkMatrix & I()
static constexpr SkSamplingOptions kDefaultSampling
SkTileMode tileMode() const
FilterResult applyTransform(const Context &ctx, const LayerSpace< SkMatrix > &transform, const SkSamplingOptions &sampling) const
constexpr std::array< float, 9 > kIdentity