mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 1090494, part 1 - Add a RectCornerRadii struct to Moz2D's PathHelpers.h and add variants of AppendRoundedRectToPath and MakePathForRoundedRect that use it. r=mattwoodrow
This commit is contained in:
parent
0cde139d10
commit
ecfd6db484
@ -13,8 +13,7 @@ UserDataKey sDisablePixelSnapping;
|
||||
void
|
||||
AppendRoundedRectToPath(PathBuilder* aPathBuilder,
|
||||
const Rect& aRect,
|
||||
// paren's needed due to operator precedence:
|
||||
const Size(& aCornerRadii)[4],
|
||||
const RectCornerRadii& aRadii,
|
||||
bool aDrawClockwise)
|
||||
{
|
||||
// For CW drawing, this looks like:
|
||||
@ -106,14 +105,11 @@ AppendRoundedRectToPath(PathBuilder* aPathBuilder,
|
||||
|
||||
Point pc, p0, p1, p2, p3;
|
||||
|
||||
// The indexes of the corners:
|
||||
const int kTopLeft = 0, kTopRight = 1;
|
||||
|
||||
if (aDrawClockwise) {
|
||||
aPathBuilder->MoveTo(Point(aRect.X() + aCornerRadii[kTopLeft].width,
|
||||
aPathBuilder->MoveTo(Point(aRect.X() + aRadii[RectCorner::TopLeft].width,
|
||||
aRect.Y()));
|
||||
} else {
|
||||
aPathBuilder->MoveTo(Point(aRect.X() + aRect.Width() - aCornerRadii[kTopRight].width,
|
||||
aPathBuilder->MoveTo(Point(aRect.X() + aRect.Width() - aRadii[RectCorner::TopRight].width,
|
||||
aRect.Y()));
|
||||
}
|
||||
|
||||
@ -129,18 +125,18 @@ AppendRoundedRectToPath(PathBuilder* aPathBuilder,
|
||||
|
||||
pc = cornerCoords[c];
|
||||
|
||||
if (aCornerRadii[c].width > 0.0 && aCornerRadii[c].height > 0.0) {
|
||||
p0.x = pc.x + cornerMults[i].a * aCornerRadii[c].width;
|
||||
p0.y = pc.y + cornerMults[i].b * aCornerRadii[c].height;
|
||||
if (aRadii[c].width > 0.0 && aRadii[c].height > 0.0) {
|
||||
p0.x = pc.x + cornerMults[i].a * aRadii[c].width;
|
||||
p0.y = pc.y + cornerMults[i].b * aRadii[c].height;
|
||||
|
||||
p3.x = pc.x + cornerMults[i3].a * aCornerRadii[c].width;
|
||||
p3.y = pc.y + cornerMults[i3].b * aCornerRadii[c].height;
|
||||
p3.x = pc.x + cornerMults[i3].a * aRadii[c].width;
|
||||
p3.y = pc.y + cornerMults[i3].b * aRadii[c].height;
|
||||
|
||||
p1.x = p0.x + alpha * cornerMults[i2].a * aCornerRadii[c].width;
|
||||
p1.y = p0.y + alpha * cornerMults[i2].b * aCornerRadii[c].height;
|
||||
p1.x = p0.x + alpha * cornerMults[i2].a * aRadii[c].width;
|
||||
p1.y = p0.y + alpha * cornerMults[i2].b * aRadii[c].height;
|
||||
|
||||
p2.x = p3.x - alpha * cornerMults[i3].a * aCornerRadii[c].width;
|
||||
p2.y = p3.y - alpha * cornerMults[i3].b * aCornerRadii[c].height;
|
||||
p2.x = p3.x - alpha * cornerMults[i3].a * aRadii[c].width;
|
||||
p2.y = p3.y - alpha * cornerMults[i3].b * aRadii[c].height;
|
||||
|
||||
aPathBuilder->LineTo(p0);
|
||||
aPathBuilder->BezierTo(p1, p2, p3);
|
||||
@ -157,9 +153,9 @@ AppendEllipseToPath(PathBuilder* aPathBuilder,
|
||||
const Point& aCenter,
|
||||
const Size& aDimensions)
|
||||
{
|
||||
Size halfDim = aDimensions / 2.0;
|
||||
Size halfDim = aDimensions / 2.f;
|
||||
Rect rect(aCenter - Point(halfDim.width, halfDim.height), aDimensions);
|
||||
Size radii[] = { halfDim, halfDim, halfDim, halfDim };
|
||||
RectCornerRadii radii(halfDim.width, halfDim.height);
|
||||
|
||||
AppendRoundedRectToPath(aPathBuilder, rect, radii);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "2D.h"
|
||||
#include "mozilla/Constants.h"
|
||||
#include "mozilla/TypedEnum.h"
|
||||
#include "UserData.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -129,6 +130,80 @@ void EllipseToBezier(T* aSink, const Point &aOrigin, const Size &aRadius)
|
||||
}
|
||||
}
|
||||
|
||||
// We can't use MOZ_BEGIN_ENUM_CLASS here because that prevents the enum
|
||||
// values from being used for indexing. Wrapping the enum in a struct does at
|
||||
// least gives us name scoping.
|
||||
struct RectCorner {
|
||||
enum {
|
||||
// This order is important since AppendRoundedRectToPath and other code
|
||||
// depends on it!
|
||||
TopLeft = 0,
|
||||
TopRight = 1,
|
||||
BottomRight = 2,
|
||||
BottomLeft = 3,
|
||||
Count = 4
|
||||
};
|
||||
};
|
||||
|
||||
struct RectCornerRadii {
|
||||
Size radii[RectCorner::Count];
|
||||
|
||||
RectCornerRadii() {}
|
||||
|
||||
explicit RectCornerRadii(Float radius) {
|
||||
for (int i = 0; i < RectCorner::Count; i++) {
|
||||
radii[i].SizeTo(radius, radius);
|
||||
}
|
||||
}
|
||||
|
||||
explicit RectCornerRadii(Float radiusX, Float radiusY) {
|
||||
for (int i = 0; i < RectCorner::Count; i++) {
|
||||
radii[i].SizeTo(radiusX, radiusY);
|
||||
}
|
||||
}
|
||||
|
||||
RectCornerRadii(Float tl, Float tr, Float br, Float bl) {
|
||||
radii[RectCorner::TopLeft].SizeTo(tl, tl);
|
||||
radii[RectCorner::TopRight].SizeTo(tr, tr);
|
||||
radii[RectCorner::BottomRight].SizeTo(br, br);
|
||||
radii[RectCorner::BottomLeft].SizeTo(bl, bl);
|
||||
}
|
||||
|
||||
RectCornerRadii(const Size& tl, const Size& tr,
|
||||
const Size& br, const Size& bl) {
|
||||
radii[RectCorner::TopLeft] = tl;
|
||||
radii[RectCorner::TopRight] = tr;
|
||||
radii[RectCorner::BottomRight] = br;
|
||||
radii[RectCorner::BottomLeft] = bl;
|
||||
}
|
||||
|
||||
const Size& operator[](size_t aCorner) const {
|
||||
return radii[aCorner];
|
||||
}
|
||||
|
||||
Size& operator[](size_t aCorner) {
|
||||
return radii[aCorner];
|
||||
}
|
||||
|
||||
void Scale(Float aXScale, Float aYScale) {
|
||||
for (int i = 0; i < RectCorner::Count; i++) {
|
||||
radii[i].Scale(aXScale, aYScale);
|
||||
}
|
||||
}
|
||||
|
||||
const Size TopLeft() const { return radii[RectCorner::TopLeft]; }
|
||||
Size& TopLeft() { return radii[RectCorner::TopLeft]; }
|
||||
|
||||
const Size TopRight() const { return radii[RectCorner::TopRight]; }
|
||||
Size& TopRight() { return radii[RectCorner::TopRight]; }
|
||||
|
||||
const Size BottomRight() const { return radii[RectCorner::BottomRight]; }
|
||||
Size& BottomRight() { return radii[RectCorner::BottomRight]; }
|
||||
|
||||
const Size BottomLeft() const { return radii[RectCorner::BottomLeft]; }
|
||||
Size& BottomLeft() { return radii[RectCorner::BottomLeft]; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Appends a path represending a rounded rectangle to the path being built by
|
||||
* aPathBuilder.
|
||||
@ -143,19 +218,37 @@ void EllipseToBezier(T* aSink, const Point &aOrigin, const Size &aRadius)
|
||||
*/
|
||||
GFX2D_API void AppendRoundedRectToPath(PathBuilder* aPathBuilder,
|
||||
const Rect& aRect,
|
||||
const Size(& aCornerRadii)[4],
|
||||
const RectCornerRadii& aRadii,
|
||||
bool aDrawClockwise = true);
|
||||
|
||||
inline TemporaryRef<Path> MakePathForRoundedRect(const DrawTarget& aDrawTarget,
|
||||
const Rect& aRect,
|
||||
const Size(& aCornerRadii)[4],
|
||||
const RectCornerRadii& aRadii,
|
||||
bool aDrawClockwise = true)
|
||||
{
|
||||
RefPtr<PathBuilder> builder = aDrawTarget.CreatePathBuilder();
|
||||
AppendRoundedRectToPath(builder, aRect, aCornerRadii, aDrawClockwise);
|
||||
AppendRoundedRectToPath(builder, aRect, aRadii, aDrawClockwise);
|
||||
return builder->Finish();
|
||||
}
|
||||
|
||||
inline void AppendRoundedRectToPath(PathBuilder* aPathBuilder,
|
||||
const Rect& aRect,
|
||||
const Size(& aCornerRadii)[4],
|
||||
bool aDrawClockwise = true) {
|
||||
RectCornerRadii radii(aCornerRadii[0], aCornerRadii[1],
|
||||
aCornerRadii[2], aCornerRadii[3]);
|
||||
AppendRoundedRectToPath(aPathBuilder, aRect, radii, aDrawClockwise);
|
||||
}
|
||||
|
||||
inline TemporaryRef<Path> MakePathForRoundedRect(const DrawTarget& aDrawTarget,
|
||||
const Rect& aRect,
|
||||
const Size(& aCornerRadii)[4],
|
||||
bool aDrawClockwise = true) {
|
||||
RectCornerRadii radii(aCornerRadii[0], aCornerRadii[1],
|
||||
aCornerRadii[2], aCornerRadii[3]);
|
||||
return MakePathForRoundedRect(aDrawTarget, aRect, radii, aDrawClockwise);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a path represending an ellipse to the path being built by
|
||||
* aPathBuilder.
|
||||
|
Loading…
Reference in New Issue
Block a user