Guard against large content bounds for layer mapping calculations
Bug: chromium:1232744, chromium:1226344 Change-Id: I1fda9fb01f8c501bb5b410a8c7cd292f53b13142 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/438577 Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
parent
06273bcb8a
commit
c7829eb316
@ -657,10 +657,10 @@ static void check_drawdevice_colorspaces(SkColorSpace* src, SkColorSpace* dst) {
|
||||
|
||||
// Helper function to compute the center reference point used for scale decomposition under
|
||||
// non-linear transformations.
|
||||
static bool compute_decomposition_center(const SkMatrix& dstToLocal,
|
||||
const skif::ParameterSpace<SkRect>* contentBounds,
|
||||
const skif::DeviceSpace<SkIRect>& targetOutput,
|
||||
skif::ParameterSpace<SkPoint>* out) {
|
||||
static skif::ParameterSpace<SkPoint> compute_decomposition_center(
|
||||
const SkMatrix& dstToLocal,
|
||||
const skif::ParameterSpace<SkRect>* contentBounds,
|
||||
const skif::DeviceSpace<SkIRect>& targetOutput) {
|
||||
// Will use the inverse and center of the device bounds if the content bounds aren't provided.
|
||||
SkRect rect = contentBounds ? SkRect(*contentBounds) : SkRect::Make(SkIRect(targetOutput));
|
||||
SkPoint center = {rect.centerX(), rect.centerY()};
|
||||
@ -670,8 +670,7 @@ static bool compute_decomposition_center(const SkMatrix& dstToLocal,
|
||||
dstToLocal.mapPoints(¢er, 1);
|
||||
}
|
||||
|
||||
*out = skif::ParameterSpace<SkPoint>(center);
|
||||
return true;
|
||||
return skif::ParameterSpace<SkPoint>(center);
|
||||
}
|
||||
|
||||
// Compute suitable transformations and layer bounds for a new layer that will be used as the source
|
||||
@ -686,13 +685,14 @@ static std::pair<skif::Mapping, skif::LayerSpace<SkIRect>> get_layer_mapping_and
|
||||
const skif::DeviceSpace<SkIRect>& targetOutput,
|
||||
const skif::ParameterSpace<SkRect>* contentBounds = nullptr,
|
||||
bool mustCoverDst = true) {
|
||||
skif::ParameterSpace<SkPoint> center;
|
||||
SkMatrix dstToLocal;
|
||||
if (!localToDst.isFinite() ||
|
||||
!localToDst.invert(&dstToLocal) ||
|
||||
!compute_decomposition_center(dstToLocal, contentBounds, targetOutput, ¢er)) {
|
||||
!localToDst.invert(&dstToLocal)) {
|
||||
return {{}, skif::LayerSpace<SkIRect>(SkIRect::MakeEmpty())};
|
||||
}
|
||||
|
||||
skif::ParameterSpace<SkPoint> center =
|
||||
compute_decomposition_center(dstToLocal, contentBounds, targetOutput);
|
||||
// *after* possibly getting a representative point from the provided content bounds, it might
|
||||
// be necessary to discard the bounds for subsequent layer calculations.
|
||||
if (mustCoverDst) {
|
||||
@ -743,7 +743,11 @@ static std::pair<skif::Mapping, skif::LayerSpace<SkIRect>> get_layer_mapping_and
|
||||
SkMatrix adjust = SkMatrix::MakeRectToRect(SkRect::Make(SkIRect(layerBounds)),
|
||||
SkRect::Make(SkIRect(newLayerBounds)),
|
||||
SkMatrix::kFill_ScaleToFit);
|
||||
if (!mapping.adjustLayerSpace(adjust)) {
|
||||
// If the adjust matrix isn't invertible, or if multiplying it into the device transform
|
||||
// causes overflows, then subsequent SkDevice coordinate spaces would be invalid, so
|
||||
// just return the empty bounds and skip the layer.
|
||||
if (!mapping.adjustLayerSpace(adjust) ||
|
||||
!mapping.deviceMatrix().isFinite()) {
|
||||
layerBounds = skif::LayerSpace<SkIRect>(SkIRect::MakeEmpty());
|
||||
} else {
|
||||
layerBounds = newLayerBounds;
|
||||
|
@ -50,12 +50,13 @@ Mapping Mapping::DecomposeCTM(const SkMatrix& ctm, const SkImageFilter* filter,
|
||||
// Perspective, which has a non-uniform scaling effect on the filter. Pick a single scale
|
||||
// factor that best matches where the filter will be evaluated.
|
||||
SkScalar scale = SkMatrixPriv::DifferentialAreaScale(ctm, SkPoint(representativePoint));
|
||||
if (SkScalarIsFinite(scale)) {
|
||||
if (SkScalarIsFinite(scale) && !SkScalarNearlyZero(scale)) {
|
||||
// Now take the sqrt to go from an area scale factor to a scaling per X and Y
|
||||
// FIXME: It would be nice to be able to choose a non-uniform scale.
|
||||
scale = SkScalarSqrt(scale);
|
||||
} else {
|
||||
// The representative point was behind the W = 0 plane, so don't factor out any scale.
|
||||
// NOTE: This makes remainder and layer the same as the MatrixCapability::Translate case
|
||||
scale = 1.f;
|
||||
}
|
||||
|
||||
@ -63,6 +64,7 @@ Mapping Mapping::DecomposeCTM(const SkMatrix& ctm, const SkImageFilter* filter,
|
||||
remainder.preScale(SkScalarInvert(scale), SkScalarInvert(scale));
|
||||
layer = SkMatrix::Scale(scale, scale);
|
||||
}
|
||||
|
||||
return Mapping(remainder, layer);
|
||||
}
|
||||
|
||||
|
@ -1864,8 +1864,7 @@ SkScalar SkMatrixPriv::DifferentialAreaScale(const SkMatrix& m, const SkPoint& p
|
||||
m.getScaleX(), m.getSkewY(), m.getPerspX(),
|
||||
m.getSkewX(), m.getScaleY(), m.getPerspY());
|
||||
|
||||
SkScalar denom = 1.f / xyw.fZ; // 1/w
|
||||
double denom = 1.0 / xyw.fZ; // 1/w
|
||||
denom = denom * denom * denom; // 1/w^3
|
||||
|
||||
return SkScalarAbs(SkDoubleToScalar(sk_determinant(jacobian.fMat, true)) * denom);
|
||||
return SkScalarAbs(SkDoubleToScalar(sk_determinant(jacobian.fMat, true) * denom));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user