1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_AspectRatio_h
8 #define mozilla_AspectRatio_h
10 /* The aspect ratio of a box, in a "width / height" format. */
12 #include "mozilla/Attributes.h"
13 #include "mozilla/gfx/BaseSize.h"
25 enum LogicalAxis
: uint8_t;
29 enum class UseBoxSizing
: uint8_t {
30 // The aspect ratio works with content box dimensions always.
32 // The aspect ratio works with the dimensions of the box specified by
38 friend struct IPC::ParamTraits
<mozilla::AspectRatio
>;
40 AspectRatio() = default;
41 explicit AspectRatio(float aRatio
,
42 UseBoxSizing aUseBoxSizing
= UseBoxSizing::No
)
43 : mRatio(std::max(aRatio
, 0.0f
)), mUseBoxSizing(aUseBoxSizing
) {}
45 static AspectRatio
FromSize(float aWidth
, float aHeight
,
46 UseBoxSizing aUseBoxSizing
= UseBoxSizing::No
) {
47 if (aWidth
== 0.0f
|| aHeight
== 0.0f
) {
48 // For the degenerate ratio, we don't care about which box sizing we are
49 // using, so using default constructor is fine.
52 return AspectRatio(aWidth
/ aHeight
, aUseBoxSizing
);
55 template <typename T
, typename Sub
>
56 static AspectRatio
FromSize(const gfx::BaseSize
<T
, Sub
>& aSize
) {
57 return FromSize(aSize
.Width(), aSize
.Height());
60 explicit operator bool() const { return mRatio
!= 0.0f
; }
62 nscoord
ApplyTo(nscoord aCoord
) const {
63 MOZ_DIAGNOSTIC_ASSERT(*this);
64 return NSCoordSaturatingNonnegativeMultiply(aCoord
, mRatio
);
67 float ApplyToFloat(float aFloat
) const {
68 MOZ_DIAGNOSTIC_ASSERT(*this);
69 return mRatio
* aFloat
;
72 // Inverts the ratio, in order to get the height / width ratio.
73 [[nodiscard
]] AspectRatio
Inverted() const {
77 // Clamp to a small epsilon, in case mRatio is absurdly large & produces
78 // 0.0f in the division here (so that valid ratios always generate other
79 // valid ratios when inverted).
81 std::max(std::numeric_limits
<float>::epsilon(), 1.0f
/ mRatio
),
85 [[nodiscard
]] inline AspectRatio
ConvertToWritingMode(
86 const WritingMode
& aWM
) const;
89 * This method computes the ratio-dependent size by the ratio-determining size
90 * and aspect-ratio (i.e. preferred aspect ratio). Basically this function
91 * will be used in the calculation of 'auto' sizes when the preferred
92 * aspect ratio is not 'auto'.
94 * @param aRatioDependentAxis The ratio depenedent axis of the box.
95 * @param aWM The writing mode of the box.
96 * @param aRatioDetermingSize The content-box size on the ratio determining
97 * axis. Basically, we use this size and |mRatio|
98 * to compute the size on the ratio-dependent
100 * @param aContentBoxSizeToBoxSizingAdjust The border padding box size
101 * adjustment. We need this because
102 * aspect-ratio should take the
103 * box-sizing into account if its
104 * style is '<ratio>'. If its style
105 * is 'auto & <ratio>', we should use
106 * content-box dimensions always.
107 * If the callers want the ratio to
108 * apply to the content-box size, we
109 * should pass a zero LogicalSize.
110 * If mUseBoxSizing is No, we ignore
111 * this parameter because we should
112 * use content box dimensions always.
114 * The return value is the content-box size on the ratio-dependent axis.
115 * Plese see the definition of the ratio-dependent axis and the
116 * ratio-determining axis in the spec:
117 * https://drafts.csswg.org/css-sizing-4/#aspect-ratio
119 [[nodiscard
]] nscoord
ComputeRatioDependentSize(
120 LogicalAxis aRatioDependentAxis
, const WritingMode
& aWM
,
121 nscoord aRatioDeterminingSize
,
122 const LogicalSize
& aContentBoxSizeToBoxSizingAdjust
) const;
124 bool operator==(const AspectRatio
& aOther
) const {
125 return mRatio
== aOther
.mRatio
;
128 bool operator!=(const AspectRatio
& aOther
) const {
129 return !(*this == aOther
);
132 bool operator<(const AspectRatio
& aOther
) const {
133 return mRatio
< aOther
.mRatio
;
137 // 0.0f represents no aspect ratio.
139 UseBoxSizing mUseBoxSizing
= UseBoxSizing::No
;
142 } // namespace mozilla
144 #endif // mozilla_AspectRatio_h