mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-06-12 01:29:43 +00:00
closes #473: implement Canvas Ellipse + M1239835
This commit is contained in:
parent
46b6faa6b2
commit
aebc3385bd
|
@ -51,6 +51,9 @@ public:
|
||||||
void Arc(double x, double y, double radius,
|
void Arc(double x, double y, double radius,
|
||||||
double startAngle, double endAngle, bool anticlockwise,
|
double startAngle, double endAngle, bool anticlockwise,
|
||||||
ErrorResult& error);
|
ErrorResult& error);
|
||||||
|
void Ellipse(double x, double y, double radiusX, double radiusY,
|
||||||
|
double rotation, double startAngle, double endAngle,
|
||||||
|
bool anticlockwise, ErrorResult& error);
|
||||||
|
|
||||||
void LineTo(const gfx::Point& aPoint);
|
void LineTo(const gfx::Point& aPoint);
|
||||||
void BezierTo(const gfx::Point& aCP1,
|
void BezierTo(const gfx::Point& aCP1,
|
||||||
|
|
|
@ -2498,8 +2498,11 @@ CanvasRenderingContext2D::UpdateFilter()
|
||||||
//
|
//
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
ValidateRect(double& aX, double& aY, double& aWidth, double& aHeight)
|
ValidateRect(double& aX, double& aY, double& aWidth, double& aHeight, bool aIsZeroSizeValid)
|
||||||
{
|
{
|
||||||
|
if (!aIsZeroSizeValid && (aWidth == 0.0 || aHeight == 0.0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// bug 1018527
|
// bug 1018527
|
||||||
// The values of canvas API input are in double precision, but Moz2D APIs are
|
// The values of canvas API input are in double precision, but Moz2D APIs are
|
||||||
|
@ -2530,7 +2533,8 @@ void
|
||||||
CanvasRenderingContext2D::ClearRect(double x, double y, double w,
|
CanvasRenderingContext2D::ClearRect(double x, double y, double w,
|
||||||
double h)
|
double h)
|
||||||
{
|
{
|
||||||
if(!ValidateRect(x, y, w, h)) {
|
// Do not allow zeros - it's a no-op at that point per spec.
|
||||||
|
if (!ValidateRect(x, y, w, h, false)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2547,7 +2551,7 @@ CanvasRenderingContext2D::FillRect(double x, double y, double w,
|
||||||
{
|
{
|
||||||
const ContextState &state = CurrentState();
|
const ContextState &state = CurrentState();
|
||||||
|
|
||||||
if(!ValidateRect(x, y, w, h)) {
|
if(!ValidateRect(x, y, w, h, true)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2625,7 +2629,7 @@ CanvasRenderingContext2D::StrokeRect(double x, double y, double w,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ValidateRect(x, y, w, h)) {
|
if(!ValidateRect(x, y, w, h, true)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2991,7 +2995,7 @@ CanvasRenderingContext2D::Arc(double x, double y, double r,
|
||||||
double startAngle, double endAngle,
|
double startAngle, double endAngle,
|
||||||
bool anticlockwise, ErrorResult& error)
|
bool anticlockwise, ErrorResult& error)
|
||||||
{
|
{
|
||||||
if (r < 0.0) {
|
if (MOZ_UNLIKELY(r < 0.0)) {
|
||||||
error.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
error.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3021,6 +3025,22 @@ CanvasRenderingContext2D::Rect(double x, double y, double w, double h)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CanvasRenderingContext2D::Ellipse(double aX, double aY, double aRadiusX, double aRadiusY,
|
||||||
|
double aRotation, double aStartAngle, double aEndAngle,
|
||||||
|
bool aAnticlockwise, ErrorResult& aError)
|
||||||
|
{
|
||||||
|
if (MOZ_UNLIKELY(aRadiusX < 0.0 || aRadiusY < 0.0)) {
|
||||||
|
aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsureWritablePath();
|
||||||
|
|
||||||
|
ArcToBezier(this, Point(aX, aY), Size(aRadiusX, aRadiusY), aStartAngle, aEndAngle,
|
||||||
|
aAnticlockwise, aRotation);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CanvasRenderingContext2D::EnsureWritablePath()
|
CanvasRenderingContext2D::EnsureWritablePath()
|
||||||
{
|
{
|
||||||
|
@ -4402,8 +4422,8 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& image,
|
||||||
MOZ_ASSERT(optional_argc == 0 || optional_argc == 2 || optional_argc == 6);
|
MOZ_ASSERT(optional_argc == 0 || optional_argc == 2 || optional_argc == 6);
|
||||||
|
|
||||||
if (optional_argc == 6) {
|
if (optional_argc == 6) {
|
||||||
if (!ValidateRect(sx, sy, sw, sh) ||
|
if (!ValidateRect(sx, sy, sw, sh, true) ||
|
||||||
!ValidateRect(dx, dy, dw, dh)) {
|
!ValidateRect(dx, dy, dw, dh, true)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5918,6 +5938,22 @@ CanvasPath::Arc(double x, double y, double radius,
|
||||||
ArcToBezier(this, Point(x, y), Size(radius, radius), startAngle, endAngle, anticlockwise);
|
ArcToBezier(this, Point(x, y), Size(radius, radius), startAngle, endAngle, anticlockwise);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CanvasPath::Ellipse(double x, double y, double radiusX, double radiusY,
|
||||||
|
double rotation, double startAngle, double endAngle,
|
||||||
|
bool anticlockwise, ErrorResult& error)
|
||||||
|
{
|
||||||
|
if (MOZ_UNLIKELY(radiusX < 0.0 || radiusY < 0.0)) {
|
||||||
|
error.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsurePathBuilder();
|
||||||
|
|
||||||
|
ArcToBezier(this, Point(x, y), Size(radiusX, radiusY), startAngle, endAngle,
|
||||||
|
anticlockwise, rotation);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CanvasPath::LineTo(const gfx::Point& aPoint)
|
CanvasPath::LineTo(const gfx::Point& aPoint)
|
||||||
{
|
{
|
||||||
|
|
|
@ -347,6 +347,9 @@ public:
|
||||||
void Rect(double x, double y, double w, double h);
|
void Rect(double x, double y, double w, double h);
|
||||||
void Arc(double x, double y, double radius, double startAngle,
|
void Arc(double x, double y, double radius, double startAngle,
|
||||||
double endAngle, bool anticlockwise, mozilla::ErrorResult& error);
|
double endAngle, bool anticlockwise, mozilla::ErrorResult& error);
|
||||||
|
void Ellipse(double aX, double aY, double aRadiusX, double aRadiusY,
|
||||||
|
double aRotation, double aStartAngle, double aEndAngle,
|
||||||
|
bool aAnticlockwise, ErrorResult& aError);
|
||||||
|
|
||||||
void GetMozCurrentTransform(JSContext* cx,
|
void GetMozCurrentTransform(JSContext* cx,
|
||||||
JS::MutableHandle<JSObject*> result,
|
JS::MutableHandle<JSObject*> result,
|
||||||
|
|
|
@ -298,7 +298,9 @@ interface CanvasPathMethods {
|
||||||
|
|
||||||
[Throws, LenientFloat]
|
[Throws, LenientFloat]
|
||||||
void arc(double x, double y, double radius, double startAngle, double endAngle, optional boolean anticlockwise = false);
|
void arc(double x, double y, double radius, double startAngle, double endAngle, optional boolean anticlockwise = false);
|
||||||
// NOT IMPLEMENTED [LenientFloat] void ellipse(double x, double y, double radiusX, double radiusY, double rotation, double startAngle, double endAngle, boolean anticlockwise);
|
|
||||||
|
[Throws, LenientFloat]
|
||||||
|
void ellipse(double x, double y, double radiusX, double radiusY, double rotation, double startAngle, double endAngle, optional boolean anticlockwise = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
interface CanvasGradient {
|
interface CanvasGradient {
|
||||||
|
|
|
@ -34,7 +34,8 @@ inline void PartialArcToBezier(T* aSink,
|
||||||
const Size& aRadius,
|
const Size& aRadius,
|
||||||
const Point& aStartPoint, const Point& aEndPoint,
|
const Point& aStartPoint, const Point& aEndPoint,
|
||||||
const Point& aStartOffset, const Point& aEndOffset,
|
const Point& aStartOffset, const Point& aEndOffset,
|
||||||
Float aKappaFactor = kKappaFactor)
|
Float aKappaFactor = kKappaFactor,
|
||||||
|
const Matrix& aTransform = Matrix())
|
||||||
{
|
{
|
||||||
Float kappaX = aKappaFactor * aRadius.width;
|
Float kappaX = aKappaFactor * aRadius.width;
|
||||||
Float kappaY = aKappaFactor * aRadius.height;
|
Float kappaY = aKappaFactor * aRadius.height;
|
||||||
|
@ -45,7 +46,7 @@ inline void PartialArcToBezier(T* aSink,
|
||||||
Point cp2 =
|
Point cp2 =
|
||||||
aEndPoint + Point(aEndOffset.y * kappaX, -aEndOffset.x * kappaY);
|
aEndPoint + Point(aEndOffset.y * kappaX, -aEndOffset.x * kappaY);
|
||||||
|
|
||||||
aSink->BezierTo(cp1, cp2, aEndPoint);
|
aSink->BezierTo(aTransform * cp1, aTransform * cp2, aTransform * aEndPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -90,7 +91,8 @@ inline void AcuteArcToBezier(T* aSink,
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void ArcToBezier(T* aSink, const Point &aOrigin, const Size &aRadius,
|
void ArcToBezier(T* aSink, const Point &aOrigin, const Size &aRadius,
|
||||||
float aStartAngle, float aEndAngle, bool aAntiClockwise)
|
float aStartAngle, float aEndAngle, bool aAntiClockwise,
|
||||||
|
float aRotation = 0.0f)
|
||||||
{
|
{
|
||||||
Float sweepDirection = aAntiClockwise ? -1.0f : 1.0f;
|
Float sweepDirection = aAntiClockwise ? -1.0f : 1.0f;
|
||||||
|
|
||||||
|
@ -111,23 +113,24 @@ void ArcToBezier(T* aSink, const Point &aOrigin, const Size &aRadius,
|
||||||
|
|
||||||
Float currentStartAngle = aStartAngle;
|
Float currentStartAngle = aStartAngle;
|
||||||
Point currentStartOffset(cosf(aStartAngle), sinf(aStartAngle));
|
Point currentStartOffset(cosf(aStartAngle), sinf(aStartAngle));
|
||||||
Point currentStartPoint(aOrigin.x + currentStartOffset.x * aRadius.width,
|
Point currentStartPoint(currentStartOffset.x * aRadius.width,
|
||||||
aOrigin.y + currentStartOffset.y * aRadius.height);
|
currentStartOffset.y * aRadius.height);
|
||||||
|
Matrix transform(cosf(aRotation), sinf(aRotation), -sinf(aRotation), cosf(aRotation), aOrigin.x, aOrigin.y);
|
||||||
aSink->LineTo(currentStartPoint);
|
aSink->LineTo(transform * currentStartPoint);
|
||||||
|
|
||||||
while (arcSweepLeft > 0) {
|
while (arcSweepLeft > 0) {
|
||||||
Float currentEndAngle =
|
Float currentEndAngle =
|
||||||
currentStartAngle + std::min(arcSweepLeft, Float(M_PI / 2.0f)) * sweepDirection;
|
currentStartAngle + std::min(arcSweepLeft, Float(M_PI / 2.0f)) * sweepDirection;
|
||||||
|
|
||||||
Point currentEndOffset(cosf(currentEndAngle), sinf(currentEndAngle));
|
Point currentEndOffset(cosf(currentEndAngle), sinf(currentEndAngle));
|
||||||
Point currentEndPoint(aOrigin.x + currentEndOffset.x * aRadius.width,
|
Point currentEndPoint(currentEndOffset.x * aRadius.width,
|
||||||
aOrigin.y + currentEndOffset.y * aRadius.height);
|
currentEndOffset.y * aRadius.height);
|
||||||
|
|
||||||
PartialArcToBezier(aSink, aRadius,
|
PartialArcToBezier(aSink, aRadius,
|
||||||
currentStartPoint, currentEndPoint,
|
currentStartPoint, currentEndPoint,
|
||||||
currentStartOffset, currentEndOffset,
|
currentStartOffset, currentEndOffset,
|
||||||
ComputeKappaFactor(currentEndAngle - currentStartAngle));
|
ComputeKappaFactor(currentEndAngle - currentStartAngle),
|
||||||
|
transform);
|
||||||
|
|
||||||
// We guarantee here the current point is the start point of the next
|
// We guarantee here the current point is the start point of the next
|
||||||
// curve segment.
|
// curve segment.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user