diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp index e2169be5fc85..b969458853d1 100644 --- a/content/canvas/src/nsCanvasRenderingContext2D.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp @@ -1751,83 +1751,53 @@ nsCanvasRenderingContext2D::ArcTo(float x1, float y1, float x2, float y2, float if (!FloatValidate(x1,y1,x2,y2,radius)) return NS_ERROR_DOM_SYNTAX_ERR; - if (radius <= 0) + if (radius < 0) return NS_ERROR_DOM_INDEX_SIZE_ERR; - /* This is an adaptation of the cairo_arc_to patch from Behdad - * Esfahbod; once that patch is accepted, we should remove this - * and just call cairo_arc_to() directly. - */ - - double angle0, angle1, angle2, angled; - double d0, d2; - double sin_, cos_; - double dc; - int forward; - gfxPoint p0 = mThebes->CurrentPoint(); - angle0 = atan2 (p0.y - y1, p0.x - x1); /* angle from (x1,y1) to (p0.x,p0.y) */ - angle2 = atan2 (y2 - y1, x2 - x1); /* angle from (x1,y1) to (x2,y2) */ - angle1 = (angle0 + angle2) / 2; /* angle from (x1,y1) to (xc,yc) */ + double dir, a2, b2, c2, cosx, sinx, d, anx, any, bnx, bny, x3, y3, x4, y4, cx, cy, angle0, angle1; + bool anticlockwise; - angled = angle2 - angle0; /* the angle (p0.x,p0.y)--(x1,y1)--(x2,y2) */ - - /* Shall we go forward or backward? */ - if (angled > M_PI || (angled < 0 && angled > -M_PI)) { - angle1 += M_PI; - angled = 2 * M_PI - angled; - forward = 1; - } else { - double tmp; - tmp = angle0; - angle0 = angle2; - angle2 = tmp; - forward = 0; + if ((x1 == p0.x && y1 == p0.y) || (x1 == x2 && y1 == y2) || radius == 0) { + mThebes->LineTo(gfxPoint(x1, y1)); + return NS_OK; } - angle0 += M_PI_2; /* angle from (xc,yc) to (p0.x,p0.y) */ - angle2 -= M_PI_2; /* angle from (xc,yc) to (x2,y2) */ - angled /= 2; /* the angle (p0.x,p0.y)--(x1,y1)--(xc,yc) */ - - - /* distance from (x1,y1) to (p0.x,p0.y) */ - d0 = sqrt ((p0.x-x1)*(p0.x-x1)+(p0.y-y1)*(p0.y-y1)); - /* distance from (x2,y2) to (p0.x,p0.y) */ - d2 = sqrt ((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); - - dc = -1; - sin_ = sin(angled); - cos_ = cos(angled); - if (fabs(cos_) >= 1e-5) { /* the arc may not fit */ - /* min distance of end-points from corner */ - double min_d = d0 < d2 ? d0 : d2; - /* max radius of an arc that fits */ - double max_r = min_d * sin_ / cos_; - - if (radius > max_r) { - /* arc with requested radius doesn't fit */ - radius = (float) max_r; - dc = min_d / cos_; /* distance of (xc,yc) from (x1,y1) */ - } + dir = (x2-x1)*(p0.y-y1) + (y2-y1)*(x1-p0.x); + if (dir == 0) { + mThebes->LineTo(gfxPoint(x1, y1)); + return NS_OK; } - if (dc < 0) - dc = radius / sin_; /* distance of (xc,yc) from (x1,y1) */ + a2 = (p0.x-x1)*(p0.x-x1) + (p0.y-y1)*(p0.y-y1); + b2 = (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2); + c2 = (p0.x-x2)*(p0.x-x2) + (p0.y-y2)*(p0.y-y2); + cosx = (a2+b2-c2)/(2*sqrt(a2*b2)); + sinx = sqrt(1 - cosx*cosx); + d = radius / ((1 - cosx) / sinx); - /* find (cx,cy), the center of the arc */ - gfxPoint c(x1 + sin(angle1) * dc, y1 + cos(angle1) * dc); + anx = (x1-p0.x) / sqrt(a2); + any = (y1-p0.y) / sqrt(a2); + bnx = (x1-x2) / sqrt(b2); + bny = (y1-y2) / sqrt(b2); + x3 = x1 - anx*d; + y3 = y1 - any*d; + x4 = x1 - bnx*d; + y4 = y1 - bny*d; + anticlockwise = (dir < 0); + cx = x3 + any*radius*(anticlockwise ? 1 : -1); + cy = y3 - anx*radius*(anticlockwise ? 1 : -1); + angle0 = atan2((y3-cy), (x3-cx)); + angle1 = atan2((y4-cy), (x4-cx)); - /* the arc operation draws the line from current point (p0.x,p0.y) - * to arc center too. */ + mThebes->LineTo(gfxPoint(x3, y3)); - if (forward) - mThebes->Arc(c, radius, angle0, angle2); + if (anticlockwise) + mThebes->NegativeArc(gfxPoint(cx, cy), radius, angle0, angle1); else - mThebes->NegativeArc(c, radius, angle2, angle0); - - mThebes->LineTo(gfxPoint(x2, y2)); + mThebes->Arc(gfxPoint(cx, cy), radius, angle0, angle1); return NS_OK; } diff --git a/content/canvas/test/test_2d.path.arcTo.coincide.1.html b/content/canvas/test/test_2d.path.arcTo.coincide.1.html index 652f0b6ef135..cf2789dcad11 100644 --- a/content/canvas/test/test_2d.path.arcTo.coincide.1.html +++ b/content/canvas/test/test_2d.path.arcTo.coincide.1.html @@ -55,9 +55,9 @@ ctx.moveTo(50, 25); ctx.arcTo(50, 25, 100, 25, 1); ctx.stroke(); -todo_isPixel(ctx, 50,1, 0,255,0,255, "50,1", "0,255,0,255", 0); -todo_isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0); -todo_isPixel(ctx, 50,48, 0,255,0,255, "50,48", "0,255,0,255", 0); +isPixel(ctx, 50,1, 0,255,0,255, "50,1", "0,255,0,255", 0); +isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0); +isPixel(ctx, 50,48, 0,255,0,255, "50,48", "0,255,0,255", 0); SimpleTest.finish(); diff --git a/content/canvas/test/test_2d.path.arcTo.collinear.1.html b/content/canvas/test/test_2d.path.arcTo.collinear.1.html index 142e707d5dbd..ce1b5b0bdc51 100644 --- a/content/canvas/test/test_2d.path.arcTo.collinear.1.html +++ b/content/canvas/test/test_2d.path.arcTo.collinear.1.html @@ -54,7 +54,7 @@ ctx.moveTo(-100, 25); ctx.arcTo(0, 25, 100, 25, 1); ctx.stroke(); -todo_isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0); +isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0); SimpleTest.finish(); diff --git a/content/canvas/test/test_2d.path.arcTo.shape.curve1.html b/content/canvas/test/test_2d.path.arcTo.shape.curve1.html index 872331cf9fbb..d345690eea17 100644 --- a/content/canvas/test/test_2d.path.arcTo.shape.curve1.html +++ b/content/canvas/test/test_2d.path.arcTo.shape.curve1.html @@ -69,8 +69,8 @@ isPixel(ctx, 73,27, 0,255,0,255, "73,27", "0,255,0,255", 0); isPixel(ctx, 78,36, 0,255,0,255, "78,36", "0,255,0,255", 0); isPixel(ctx, 79,35, 0,255,0,255, "79,35", "0,255,0,255", 0); isPixel(ctx, 80,44, 0,255,0,255, "80,44", "0,255,0,255", 0); -todo_isPixel(ctx, 80,45, 0,255,0,255, "80,45", "0,255,0,255", 0); -todo_isPixel(ctx, 80,46, 0,255,0,255, "80,46", "0,255,0,255", 0); +isPixel(ctx, 80,45, 0,255,0,255, "80,45", "0,255,0,255", 0); +isPixel(ctx, 80,46, 0,255,0,255, "80,46", "0,255,0,255", 0); SimpleTest.finish(); diff --git a/content/canvas/test/test_2d.path.arcTo.shape.curve2.html b/content/canvas/test/test_2d.path.arcTo.shape.curve2.html index bac4f5707d1a..94bdb716cb85 100644 --- a/content/canvas/test/test_2d.path.arcTo.shape.curve2.html +++ b/content/canvas/test/test_2d.path.arcTo.shape.curve2.html @@ -58,13 +58,13 @@ ctx.moveTo(10, 25); ctx.arcTo(75, 25, 75, 60, 20); ctx.stroke(); -todo_isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0); +isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0); isPixel(ctx, 55,19, 0,255,0,255, "55,19", "0,255,0,255", 0); isPixel(ctx, 55,20, 0,255,0,255, "55,20", "0,255,0,255", 0); -todo_isPixel(ctx, 55,21, 0,255,0,255, "55,21", "0,255,0,255", 0); +isPixel(ctx, 55,21, 0,255,0,255, "55,21", "0,255,0,255", 0); isPixel(ctx, 64,22, 0,255,0,255, "64,22", "0,255,0,255", 0); isPixel(ctx, 65,21, 0,255,0,255, "65,21", "0,255,0,255", 0); -todo_isPixel(ctx, 72,28, 0,255,0,255, "72,28", "0,255,0,255", 0); +isPixel(ctx, 72,28, 0,255,0,255, "72,28", "0,255,0,255", 0); isPixel(ctx, 73,27, 0,255,0,255, "73,27", "0,255,0,255", 0); isPixel(ctx, 78,36, 0,255,0,255, "78,36", "0,255,0,255", 0); isPixel(ctx, 79,35, 0,255,0,255, "79,35", "0,255,0,255", 0); diff --git a/content/canvas/test/test_2d.path.arcTo.shape.end.html b/content/canvas/test/test_2d.path.arcTo.shape.end.html index cc5f42812c9e..5f679ef599ac 100644 --- a/content/canvas/test/test_2d.path.arcTo.shape.end.html +++ b/content/canvas/test/test_2d.path.arcTo.shape.end.html @@ -48,10 +48,10 @@ ctx.arcTo(-100, 25, 200, 25, 10); ctx.stroke(); isPixel(ctx, 1,1, 0,255,0,255, "1,1", "0,255,0,255", 0); -todo_isPixel(ctx, 1,48, 0,255,0,255, "1,48", "0,255,0,255", 0); -todo_isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0); +isPixel(ctx, 1,48, 0,255,0,255, "1,48", "0,255,0,255", 0); +isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0); isPixel(ctx, 98,1, 0,255,0,255, "98,1", "0,255,0,255", 0); -todo_isPixel(ctx, 98,48, 0,255,0,255, "98,48", "0,255,0,255", 0); +isPixel(ctx, 98,48, 0,255,0,255, "98,48", "0,255,0,255", 0); SimpleTest.finish(); diff --git a/content/canvas/test/test_2d.path.arcTo.shape.start.html b/content/canvas/test/test_2d.path.arcTo.shape.start.html index 23a7bc172d0b..4a6aa40cb2a9 100644 --- a/content/canvas/test/test_2d.path.arcTo.shape.start.html +++ b/content/canvas/test/test_2d.path.arcTo.shape.start.html @@ -48,10 +48,10 @@ ctx.arcTo(200, 25, 200, 50, 10); ctx.stroke(); isPixel(ctx, 1,1, 0,255,0,255, "1,1", "0,255,0,255", 0); -todo_isPixel(ctx, 1,48, 0,255,0,255, "1,48", "0,255,0,255", 0); +isPixel(ctx, 1,48, 0,255,0,255, "1,48", "0,255,0,255", 0); isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0); isPixel(ctx, 98,1, 0,255,0,255, "98,1", "0,255,0,255", 0); -todo_isPixel(ctx, 98,48, 0,255,0,255, "98,48", "0,255,0,255", 0); +isPixel(ctx, 98,48, 0,255,0,255, "98,48", "0,255,0,255", 0); SimpleTest.finish(); diff --git a/content/canvas/test/test_2d.path.arcTo.zero.1.html b/content/canvas/test/test_2d.path.arcTo.zero.1.html index 4bde14652512..c4e63271c6c1 100644 --- a/content/canvas/test/test_2d.path.arcTo.zero.1.html +++ b/content/canvas/test/test_2d.path.arcTo.zero.1.html @@ -50,7 +50,7 @@ isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0); } catch (e) { _thrown_outer = true; } -todo(!_thrown_outer, 'should not throw exception'); +ok(!_thrown_outer, 'should not throw exception'); SimpleTest.finish(); diff --git a/content/canvas/test/test_2d.path.arcTo.zero.2.html b/content/canvas/test/test_2d.path.arcTo.zero.2.html index 294bdfcb1905..1647a06be5fb 100644 --- a/content/canvas/test/test_2d.path.arcTo.zero.2.html +++ b/content/canvas/test/test_2d.path.arcTo.zero.2.html @@ -50,7 +50,7 @@ isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0); } catch (e) { _thrown_outer = true; } -todo(!_thrown_outer, 'should not throw exception'); +ok(!_thrown_outer, 'should not throw exception'); SimpleTest.finish();