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:
Jonathan Watt 2014-10-30 09:34:09 +00:00
Родитель 0cde139d10
Коммит ecfd6db484
2 изменённых файлов: 110 добавлений и 21 удалений

Просмотреть файл

@ -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.