Bug 1814239 - Expose Point/Size rounded-to-multiple helpers, and use them from MaybeRoundToDisplayPixels. r=tnikkel,gfx-reviewers,nical

Turns out we already had code for this in NumericTools.h, so reuse it.

I thought I was going to need this code somewhere else though I didn't
end up needing it.

While at it clean up unnecessary template params I noticed.

Differential Revision: https://phabricator.services.mozilla.com/D168460
This commit is contained in:
Emilio Cobos Álvarez
2023-02-06 12:28:47 +00:00
parent 6ebc85d55e
commit 87a5843804
8 changed files with 73 additions and 49 deletions

View File

@@ -12,8 +12,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/MathAlgorithms.h"
namespace mozilla {
namespace gfx {
namespace mozilla::gfx {
/**
* Do not use this class directly. Subclass it, pass that subclass as the
@@ -97,7 +96,6 @@ struct BaseCoord {
}
};
} // namespace gfx
} // namespace mozilla
} // namespace mozilla::gfx
#endif /* MOZILLA_GFX_BASECOORD_H_ */

View File

@@ -17,8 +17,7 @@
#include "mozilla/gfx/ScaleFactors2D.h"
#include "Types.h"
namespace mozilla {
namespace gfx {
namespace mozilla::gfx {
/**
* Rectangles have two interpretations: a set of (zero-size) points,
@@ -740,7 +739,6 @@ struct BaseRect {
}
};
} // namespace gfx
} // namespace mozilla
} // namespace mozilla::gfx
#endif /* MOZILLA_GFX_BASERECT_H_ */

View File

@@ -12,8 +12,7 @@
#include "mozilla/Attributes.h"
namespace mozilla {
namespace gfx {
namespace mozilla::gfx {
/**
* Do not use this class directly. Subclass it, pass that subclass as the
@@ -109,7 +108,6 @@ struct BaseSize {
}
};
} // namespace gfx
} // namespace mozilla
} // namespace mozilla::gfx
#endif /* MOZILLA_GFX_BASESIZE_H_ */

View File

@@ -7,6 +7,8 @@
#ifndef MOZILLA_GFX_NUMERICTOOLS_H_
#define MOZILLA_GFX_NUMERICTOOLS_H_
#include <cstdint>
namespace mozilla {
// XXX - Move these into mfbt/MathAlgorithms.h?
@@ -35,6 +37,10 @@ inline int32_t RoundUpToMultiple(int32_t x, int32_t aMultiplier) {
return x - mod;
}
inline int32_t RoundToMultiple(int32_t x, int32_t aMultiplier) {
return RoundDownToMultiple(x + aMultiplier / 2, aMultiplier);
}
} // namespace mozilla
#endif /* MOZILLA_GFX_NUMERICTOOLS_H_ */

View File

@@ -16,6 +16,7 @@
#include "BasePoint4D.h"
#include "BaseSize.h"
#include "mozilla/Maybe.h"
#include "mozilla/gfx/NumericTools.h"
#include <cmath>
#include <type_traits>
@@ -80,32 +81,32 @@ struct MOZ_EMPTY_BASES IntPointTyped
constexpr IntPointTyped(ToInt aX, ToInt aY)
: Super(Coord(aX.value), Coord(aY.value)) {}
static IntPointTyped<Units> Round(float aX, float aY) {
static IntPointTyped Round(float aX, float aY) {
return IntPointTyped(int32_t(floorf(aX + 0.5f)),
int32_t(floorf(aY + 0.5f)));
}
static IntPointTyped<Units> Ceil(float aX, float aY) {
static IntPointTyped Ceil(float aX, float aY) {
return IntPointTyped(int32_t(ceilf(aX)), int32_t(ceilf(aY)));
}
static IntPointTyped<Units> Floor(float aX, float aY) {
static IntPointTyped Floor(float aX, float aY) {
return IntPointTyped(int32_t(floorf(aX)), int32_t(floorf(aY)));
}
static IntPointTyped<Units> Truncate(float aX, float aY) {
static IntPointTyped Truncate(float aX, float aY) {
return IntPointTyped(int32_t(aX), int32_t(aY));
}
static IntPointTyped<Units> Round(const PointTyped<Units, float>& aPoint);
static IntPointTyped<Units> Ceil(const PointTyped<Units, float>& aPoint);
static IntPointTyped<Units> Floor(const PointTyped<Units, float>& aPoint);
static IntPointTyped<Units> Truncate(const PointTyped<Units, float>& aPoint);
static IntPointTyped Round(const PointTyped<Units, float>& aPoint);
static IntPointTyped Ceil(const PointTyped<Units, float>& aPoint);
static IntPointTyped Floor(const PointTyped<Units, float>& aPoint);
static IntPointTyped Truncate(const PointTyped<Units, float>& aPoint);
// XXX When all of the code is ported, the following functions to convert to
// and from unknown types should be removed.
static IntPointTyped<Units> FromUnknownPoint(
static IntPointTyped FromUnknownPoint(
const IntPointTyped<UnknownUnits>& aPoint) {
return IntPointTyped<Units>(aPoint.x, aPoint.y);
}
@@ -113,6 +114,11 @@ struct MOZ_EMPTY_BASES IntPointTyped
IntPointTyped<UnknownUnits> ToUnknownPoint() const {
return IntPointTyped<UnknownUnits>(this->x, this->y);
}
IntPointTyped RoundedToMultiple(int32_t aMultiplier) const {
return {RoundToMultiple(this->x, aMultiplier),
RoundToMultiple(this->y, aMultiplier)};
}
};
typedef IntPointTyped<UnknownUnits> IntPoint;
@@ -278,34 +284,49 @@ struct MOZ_EMPTY_BASES IntSizeTyped
constexpr IntSizeTyped(ToInt aWidth, ToInt aHeight)
: Super(aWidth.value, aHeight.value) {}
static IntSizeTyped<Units> Round(float aWidth, float aHeight) {
static IntSizeTyped Round(float aWidth, float aHeight) {
return IntSizeTyped(int32_t(floorf(aWidth + 0.5)),
int32_t(floorf(aHeight + 0.5)));
}
static IntSizeTyped<Units> Truncate(float aWidth, float aHeight) {
static IntSizeTyped Truncate(float aWidth, float aHeight) {
return IntSizeTyped(int32_t(aWidth), int32_t(aHeight));
}
static IntSizeTyped<Units> Ceil(float aWidth, float aHeight) {
static IntSizeTyped Ceil(float aWidth, float aHeight) {
return IntSizeTyped(int32_t(ceil(aWidth)), int32_t(ceil(aHeight)));
}
static IntSizeTyped<Units> Floor(float aWidth, float aHeight) {
static IntSizeTyped Floor(float aWidth, float aHeight) {
return IntSizeTyped(int32_t(floorf(aWidth)), int32_t(floorf(aHeight)));
}
static IntSizeTyped<Units> Round(const SizeTyped<Units, float>& aSize);
static IntSizeTyped<Units> Ceil(const SizeTyped<Units, float>& aSize);
static IntSizeTyped<Units> Floor(const SizeTyped<Units, float>& aSize);
static IntSizeTyped<Units> Truncate(const SizeTyped<Units, float>& aSize);
static IntSizeTyped Round(const SizeTyped<Units, float>& aSize);
static IntSizeTyped Ceil(const SizeTyped<Units, float>& aSize);
static IntSizeTyped Floor(const SizeTyped<Units, float>& aSize);
static IntSizeTyped Truncate(const SizeTyped<Units, float>& aSize);
IntSizeTyped TruncatedToMultiple(int32_t aMultiplier) const {
if (aMultiplier == 1) {
return *this;
}
return {RoundDownToMultiple(this->width, aMultiplier),
RoundDownToMultiple(this->height, aMultiplier)};
}
IntSizeTyped CeiledToMultiple(int32_t aMultiplier) const {
if (aMultiplier == 1) {
return *this;
}
return {RoundUpToMultiple(this->width, aMultiplier),
RoundUpToMultiple(this->height, aMultiplier)};
}
// XXX When all of the code is ported, the following functions to convert to
// and from unknown types should be removed.
static IntSizeTyped<Units> FromUnknownSize(
const IntSizeTyped<UnknownUnits>& aSize) {
return IntSizeTyped<Units>(aSize.width, aSize.height);
static IntSizeTyped FromUnknownSize(const IntSizeTyped<UnknownUnits>& aSize) {
return IntSizeTyped(aSize.width, aSize.height);
}
IntSizeTyped<UnknownUnits> ToUnknownSize() const {

View File

@@ -13,6 +13,7 @@ using namespace mozilla::gfx;
TestPoint::TestPoint() {
REGISTER_TEST(TestPoint, Addition);
REGISTER_TEST(TestPoint, Subtraction);
REGISTER_TEST(TestPoint, RoundToMultiple);
}
void TestPoint::Addition() {
@@ -40,3 +41,13 @@ void TestPoint::Subtraction() {
VERIFY(a.x == -3.f);
VERIFY(a.y == 7.f);
}
void TestPoint::RoundToMultiple() {
const int32_t roundTo = 2;
IntPoint p(478, -394);
VERIFY(p.RoundedToMultiple(roundTo) == p);
IntPoint p2(478, 393);
VERIFY(p2.RoundedToMultiple(roundTo) != p2);
}

View File

@@ -14,4 +14,5 @@ class TestPoint : public TestBase {
void Addition();
void Subtraction();
void RoundToMultiple();
};

View File

@@ -219,23 +219,14 @@ static LayoutDeviceIntRect MaybeRoundToDisplayPixels(
return aRect;
}
auto Truncate = [&](int32_t i) { return (i / aRound) * aRound; };
auto Round = [&](int32_t i) { return Truncate(i + aRound / 2); };
auto RoundSize = [&](int32_t i) {
if (i % aRound == 0) {
return i;
}
const auto truncated = Truncate(i);
if (NS_WARN_IF(aTransparency == TransparencyMode::Opaque)) {
// If the widget doesn't support transparency, we prefer truncating to
// ceiling, so that we don't have extra pixels not painted by our frame.
return truncated;
}
return truncated + aRound;
};
return LayoutDeviceIntRect(Round(aRect.x), Round(aRect.y),
RoundSize(aRect.width), RoundSize(aRect.height));
// If the widget doesn't support transparency, we prefer truncating to
// ceiling, so that we don't have extra pixels not painted by our frame.
auto size = aTransparency == TransparencyMode::Opaque
? aRect.Size().TruncatedToMultiple(aRound)
: aRect.Size().CeiledToMultiple(aRound);
Unused << NS_WARN_IF(aTransparency == TransparencyMode::Opaque &&
size != aRect.Size());
return {aRect.TopLeft().RoundedToMultiple(aRound), size};
}
LayoutDeviceIntRect nsView::CalcWidgetBounds(WindowType aType,