823 {
825
826 if (crop.isEmpty() || ctx.desiredOutput().isEmpty()) {
827
828 return {};
829 }
830
831
832
833 LayerSpace<SkIRect> cropContent = crop;
834 if (!fImage ||
835 !cropContent.intersect(fLayerBounds)) {
836
837 return {};
838 }
839
840
841 LayerSpace<SkIRect> fittedCrop = crop.relevantSubset(ctx.desiredOutput(),
tileMode);
842
843
844
845
846
847 if (!cropContent.intersect(fittedCrop)) {
848 return {};
849 }
850
851
852
853 auto periodicTransform = periodic_axis_transform(
tileMode, fittedCrop, ctx.desiredOutput());
854 if (periodicTransform) {
856 }
857
858 bool preserveTransparencyInCrop = false;
860
861 fittedCrop = cropContent;
862 } else if (fittedCrop.contains(ctx.desiredOutput())) {
864 fittedCrop = ctx.desiredOutput();
865 } else if (!cropContent.contains(fittedCrop)) {
866
867
868 preserveTransparencyInCrop = true;
870
873 }
874 }
875
876
877
878
879
881 LayerSpace<SkIPoint> origin;
882 if (!preserveTransparencyInCrop &&
883 is_nearly_integer_translation(fTransform, &origin) &&
884 (doubleClamp ||
885 !(this->analyzeBounds(fittedCrop) & BoundsAnalysis::kHasLayerFillingEffect))) {
886
887
888
889
890
891
892
893 FilterResult restrictedOutput = this->subset(origin, fittedCrop, doubleClamp);
894 restrictedOutput.updateTileMode(ctx,
tileMode);
895 if (restrictedOutput.fBoundary == PixelBoundary::kInitialized ||
897
898
899 restrictedOutput.fBoundary = PixelBoundary::kUnknown;
900 }
901 return restrictedOutput;
903
904
905 SkASSERT(!preserveTransparencyInCrop);
907 restrictedOutput.fLayerBounds = fittedCrop;
908 return restrictedOutput;
909 } else {
910
911
912 FilterResult tiled = this->resolve(ctx, fittedCrop,
true);
913 tiled.updateTileMode(ctx,
tileMode);
914 return tiled;
915 }
916}
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