blob: a74d7b64cf4023d3a88f44cb1961f16f4e8fd110 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/impeller/geometry/rounding_radii.h"
namespace impeller {
static inline void NormalizeEmptyToZero(Size& radii) {
if (radii.IsEmpty()) {
radii = Size();
}
}
static inline void AdjustScale(Scalar& radius1,
Scalar& radius2,
Scalar dimension,
Scalar& scale) {
FML_DCHECK(radius1 >= 0.0f && radius2 >= 0.0f);
FML_DCHECK(dimension > 0.0f);
if (radius1 + radius2 > dimension) {
scale = std::min(scale, dimension / (radius1 + radius2));
}
}
RoundingRadii RoundingRadii::Scaled(const Rect& in_bounds) const {
Rect bounds = in_bounds.GetPositive();
if (bounds.IsEmpty() || //
AreAllCornersEmpty() || !IsFinite()) {
// Normalize empty radii.
return RoundingRadii();
}
// Copy the incoming radii so that we can work on normalizing them to the
// particular rectangle they are paired with without disturbing the caller.
RoundingRadii radii = *this;
// If any corner is flat or has a negative value, normalize it to zeros
// We do this first so that the unnecessary non-flat part of that radius
// does not contribute to the global scaling below.
NormalizeEmptyToZero(radii.top_left);
NormalizeEmptyToZero(radii.top_right);
NormalizeEmptyToZero(radii.bottom_left);
NormalizeEmptyToZero(radii.bottom_right);
// Now determine a global scale to apply to all of the radii to ensure
// that none of the adjacent pairs of radius values sum to larger than
// the corresponding dimension of the rectangle.
Size size = bounds.GetSize();
Scalar scale = 1.0f;
// clang-format off
AdjustScale(radii.top_left.width, radii.top_right.width, size.width,
scale);
AdjustScale(radii.bottom_left.width, radii.bottom_right.width, size.width,
scale);
AdjustScale(radii.top_left.height, radii.bottom_left.height, size.height,
scale);
AdjustScale(radii.top_right.height, radii.bottom_right.height, size.height,
scale);
// clang-format on
if (scale < 1.0f) {
radii = radii * scale;
}
return radii;
}
} // namespace impeller