Changeset 180790 in webkit


Ignore:
Timestamp:
Feb 27, 2015 3:40:35 PM (9 years ago)
Author:
dino@apple.com
Message:

Add support for canvas ellipse method
https://bugs.webkit.org/show_bug.cgi?id=82791
<rdar://problem/11159172>

Patch by Sam Weinig <sam@webkit.org> on 2015-02-26
Reviewed by Dirk Schulze.

Source/WebCore:

Tests: fast/canvas/canvas-ellipse-360-winding.html

fast/canvas/canvas-ellipse-circumference-fill.html
fast/canvas/canvas-ellipse-circumference.html
fast/canvas/canvas-ellipse-connecting-line.html
fast/canvas/canvas-ellipse-negative-radius.html
fast/canvas/canvas-ellipse-zero-lineto.html
fast/canvas/canvas-ellipse.html

  • html/canvas/CanvasPathMethods.h:
  • html/canvas/CanvasPathMethods.cpp:

(WebCore::CanvasPathMethods::lineTo):
Convenience for passing a FloatPoint instead of two floats.

(WebCore::normalizeAngles):
Normalizes the angles as described in the HTML spec. Ensuring the startAngle
is greater than 0 and less than 2pi, and the the endAngle is at most 2pi
from the start angle.

(WebCore::CanvasPathMethods::arc):

  • Renames some of the parameters to be clearer.
  • Normalizes the angles for consistency with ellipse.
  • Moves hasInvertibleTransform() higher in the function for consistency.

(WebCore::CanvasPathMethods::ellipse): Added.

  • html/canvas/CanvasRenderingContext2D.idl:
  • html/canvas/DOMPath.idl:

Add ellipse(...).

  • platform/graphics/Path.h:
  • platform/graphics/cg/PathCG.cpp:

(WebCore::Path::addArc):
Rename parameters for clarity and use a nullptr.

(WebCore::Path::addEllipse):
Added. Constructs an ellipse via a transformed arc.

LayoutTests:

  • fast/canvas/canvas-ellipse-360-winding-expected.txt: Added.
  • fast/canvas/canvas-ellipse-360-winding.html: Added.
  • fast/canvas/canvas-ellipse-circumference-expected.txt: Added.
  • fast/canvas/canvas-ellipse-circumference-fill-expected.txt: Added.
  • fast/canvas/canvas-ellipse-circumference-fill.html: Added.
  • fast/canvas/canvas-ellipse-circumference.html: Added.
  • fast/canvas/canvas-ellipse-connecting-line-expected.html: Added.
  • fast/canvas/canvas-ellipse-connecting-line.html: Added.
  • fast/canvas/canvas-ellipse-expected.txt: Added.
  • fast/canvas/canvas-ellipse-negative-radius-expected.txt: Added.
  • fast/canvas/canvas-ellipse-negative-radius.html: Added.
  • fast/canvas/canvas-ellipse-zero-lineto-expected.txt: Added.
  • fast/canvas/canvas-ellipse-zero-lineto.html: Added.
  • fast/canvas/canvas-ellipse.html: Added.
  • fast/canvas/script-tests/canvas-ellipse-360-winding.js: Added.
  • fast/canvas/script-tests/canvas-ellipse.js: Added.
  • fast/canvas/script-tests/js-ellipse-implementation.js: Added.
  • platform/mac/fast/canvas/canvas-ellipse-circumference-expected.png: Added.
  • platform/mac/fast/canvas/canvas-ellipse-circumference-fill-expected.png: Added.
Location:
trunk
Files:
19 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r180789 r180790  
     12015-02-26  Sam Weinig  <sam@webkit.org>
     2
     3        Add support for canvas ellipse method
     4        https://bugs.webkit.org/show_bug.cgi?id=82791
     5        <rdar://problem/11159172>
     6
     7        Reviewed by Dirk Schulze.
     8
     9        * fast/canvas/canvas-ellipse-360-winding-expected.txt: Added.
     10        * fast/canvas/canvas-ellipse-360-winding.html: Added.
     11        * fast/canvas/canvas-ellipse-circumference-expected.txt: Added.
     12        * fast/canvas/canvas-ellipse-circumference-fill-expected.txt: Added.
     13        * fast/canvas/canvas-ellipse-circumference-fill.html: Added.
     14        * fast/canvas/canvas-ellipse-circumference.html: Added.
     15        * fast/canvas/canvas-ellipse-connecting-line-expected.html: Added.
     16        * fast/canvas/canvas-ellipse-connecting-line.html: Added.
     17        * fast/canvas/canvas-ellipse-expected.txt: Added.
     18        * fast/canvas/canvas-ellipse-negative-radius-expected.txt: Added.
     19        * fast/canvas/canvas-ellipse-negative-radius.html: Added.
     20        * fast/canvas/canvas-ellipse-zero-lineto-expected.txt: Added.
     21        * fast/canvas/canvas-ellipse-zero-lineto.html: Added.
     22        * fast/canvas/canvas-ellipse.html: Added.
     23        * fast/canvas/script-tests/canvas-ellipse-360-winding.js: Added.
     24        * fast/canvas/script-tests/canvas-ellipse.js: Added.
     25        * fast/canvas/script-tests/js-ellipse-implementation.js: Added.
     26        * platform/mac/fast/canvas/canvas-ellipse-circumference-expected.png: Added.
     27        * platform/mac/fast/canvas/canvas-ellipse-circumference-fill-expected.png: Added.
     28
    1292015-02-27  Alex Christensen  <achristensen@webkit.org>
    230
  • trunk/Source/WebCore/ChangeLog

    r180785 r180790  
     12015-02-26  Sam Weinig  <sam@webkit.org>
     2
     3        Add support for canvas ellipse method
     4        https://bugs.webkit.org/show_bug.cgi?id=82791
     5        <rdar://problem/11159172>
     6
     7        Reviewed by Dirk Schulze.
     8
     9        Tests: fast/canvas/canvas-ellipse-360-winding.html
     10               fast/canvas/canvas-ellipse-circumference-fill.html
     11               fast/canvas/canvas-ellipse-circumference.html
     12               fast/canvas/canvas-ellipse-connecting-line.html
     13               fast/canvas/canvas-ellipse-negative-radius.html
     14               fast/canvas/canvas-ellipse-zero-lineto.html
     15               fast/canvas/canvas-ellipse.html
     16
     17        * html/canvas/CanvasPathMethods.h:
     18        * html/canvas/CanvasPathMethods.cpp:
     19        (WebCore::CanvasPathMethods::lineTo):
     20        Convenience for passing a FloatPoint instead of two floats.
     21
     22        (WebCore::normalizeAngles):
     23        Normalizes the angles as described in the HTML spec. Ensuring the startAngle
     24        is greater than 0 and less than 2pi, and the the endAngle is at most 2pi
     25        from the start angle.
     26
     27        (WebCore::CanvasPathMethods::arc):
     28        - Renames some of the parameters to be clearer.
     29        - Normalizes the angles for consistency with ellipse.
     30        - Moves hasInvertibleTransform() higher in the function for consistency.
     31
     32        (WebCore::CanvasPathMethods::ellipse): Added.
     33
     34        * html/canvas/CanvasRenderingContext2D.idl:
     35        * html/canvas/DOMPath.idl:
     36        Add ellipse(...).
     37
     38        * platform/graphics/Path.h:
     39        * platform/graphics/cg/PathCG.cpp:
     40        (WebCore::Path::addArc):
     41        Rename parameters for clarity and use a nullptr.
     42
     43        (WebCore::Path::addEllipse):
     44        Added. Constructs an ellipse via a transformed arc.
     45
    1462015-02-27  Enrica Casucci  <enrica@apple.com>
    247
  • trunk/Source/WebCore/html/canvas/CanvasPathMethods.cpp

    r155752 r180790  
    3636#include "CanvasPathMethods.h"
    3737
     38#include "AffineTransform.h"
    3839#include "ExceptionCode.h"
    3940#include "FloatRect.h"
     
    5960        return;
    6061    m_path.moveTo(FloatPoint(x, y));
     62}
     63
     64void CanvasPathMethods::lineTo(FloatPoint point)
     65{
     66    lineTo(point.x(), point.y());
    6167}
    6268
     
    131137}
    132138
    133 void CanvasPathMethods::arc(float x, float y, float r, float sa, float ea, bool anticlockwise, ExceptionCode& ec)
    134 {
    135     ec = 0;
    136     if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(r) || !std::isfinite(sa) || !std::isfinite(ea))
    137         return;
    138 
    139     if (r < 0) {
     139static void normalizeAngles(float& startAngle, float& endAngle, bool anticlockwise)
     140{
     141    float newStartAngle = startAngle;
     142    if (newStartAngle < 0)
     143        newStartAngle = (2 * piFloat) + fmodf(newStartAngle, -(2 * piFloat));
     144    else
     145        newStartAngle = fmodf(newStartAngle, 2 * piFloat);
     146
     147    float delta = newStartAngle - startAngle;
     148    startAngle = newStartAngle;
     149    endAngle = endAngle + delta;
     150    ASSERT(newStartAngle >= 0 && newStartAngle < 2 * piFloat);
     151
     152    if (anticlockwise && startAngle - endAngle >= 2 * piFloat)
     153        endAngle = startAngle - 2 * piFloat;
     154    else if (!anticlockwise && endAngle - startAngle >= 2 * piFloat)
     155        endAngle = startAngle + 2 * piFloat;
     156}
     157
     158void CanvasPathMethods::arc(float x, float y, float radius, float startAngle, float endAngle, bool anticlockwise, ExceptionCode& ec)
     159{
     160    if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(radius) || !std::isfinite(startAngle) || !std::isfinite(endAngle))
     161        return;
     162
     163    if (radius < 0) {
    140164        ec = INDEX_SIZE_ERR;
    141165        return;
    142166    }
    143167
    144     if (!r || sa == ea) {
     168    if (!hasInvertibleTransform())
     169        return;
     170
     171    normalizeAngles(startAngle, endAngle, anticlockwise);
     172
     173    if (!radius || startAngle == endAngle) {
    145174        // The arc is empty but we still need to draw the connecting line.
    146         lineTo(x + r * cosf(sa), y + r * sinf(sa));
    147         return;
    148     }
    149 
    150     if (!hasInvertibleTransform())
    151         return;
    152 
    153     // If 'sa' and 'ea' differ by more than 2Pi, just add a circle starting/ending at 'sa'.
    154     if (anticlockwise && sa - ea >= 2 * piFloat) {
    155         m_path.addArc(FloatPoint(x, y), r, sa, sa - 2 * piFloat, anticlockwise);
    156         return;
    157     }
    158     if (!anticlockwise && ea - sa >= 2 * piFloat) {
    159         m_path.addArc(FloatPoint(x, y), r, sa, sa + 2 * piFloat, anticlockwise);
    160         return;
    161     }
    162 
    163     m_path.addArc(FloatPoint(x, y), r, sa, ea, anticlockwise);
     175        lineTo(x + radius * cosf(startAngle), y + radius * sinf(startAngle));
     176        return;
     177    }
     178
     179    m_path.addArc(FloatPoint(x, y), radius, startAngle, endAngle, anticlockwise);
     180}
     181   
     182void CanvasPathMethods::ellipse(float x, float y, float radiusX, float radiusY, float rotation, float startAngle, float endAngle, bool anticlockwise, ExceptionCode& ec)
     183{
     184    if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(radiusX) || !std::isfinite(radiusY) || !std::isfinite(rotation) || !std::isfinite(startAngle) || !std::isfinite(endAngle))
     185        return;
     186
     187    if (radiusX < 0 || radiusY < 0) {
     188        ec = INDEX_SIZE_ERR;
     189        return;
     190    }
     191
     192    if (!hasInvertibleTransform())
     193        return;
     194
     195    normalizeAngles(startAngle, endAngle, anticlockwise);
     196
     197    if ((!radiusX && !radiusY) || startAngle == endAngle) {
     198        AffineTransform transform;
     199        transform.translate(x, y).rotate(rad2deg(rotation));
     200
     201        lineTo(transform.mapPoint(FloatPoint(radiusX * cosf(startAngle), radiusY * sinf(startAngle))));
     202        return;
     203    }
     204
     205    if (!radiusX || !radiusY) {
     206        AffineTransform transform;
     207        transform.translate(x, y).rotate(rad2deg(rotation));
     208
     209        lineTo(transform.mapPoint(FloatPoint(radiusX * cosf(startAngle), radiusY * sinf(startAngle))));
     210
     211        if (!anticlockwise) {
     212            for (float angle = startAngle - fmodf(startAngle, piOverTwoFloat) + piOverTwoFloat; angle < endAngle; angle += piOverTwoFloat)
     213                lineTo(transform.mapPoint(FloatPoint(radiusX * cosf(angle), radiusY * sinf(angle))));
     214        } else {
     215            for (float angle = startAngle - fmodf(startAngle, piOverTwoFloat); angle > endAngle; angle -= piOverTwoFloat)
     216                lineTo(transform.mapPoint(FloatPoint(radiusX * cosf(angle), radiusY * sinf(angle))));
     217        }
     218
     219        lineTo(transform.mapPoint(FloatPoint(radiusX * cosf(endAngle), radiusY * sinf(endAngle))));
     220        return;
     221    }
     222
     223    m_path.addEllipse(FloatPoint(x, y), radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise);
    164224}
    165225
  • trunk/Source/WebCore/html/canvas/CanvasPathMethods.h

    r155752 r180790  
    4949    void arcTo(float x0, float y0, float x1, float y1, float radius, ExceptionCode&);
    5050    void arc(float x, float y, float r, float sa, float ea, bool anticlockwise, ExceptionCode&);
     51    void ellipse(float x, float y, float radiusX, float radiusY, float rotation, float startAngle, float endAngled, bool anticlockwise, ExceptionCode&);
    5152    void rect(float x, float y, float width, float height);
    5253
     
    5758    virtual bool hasInvertibleTransform() const { return true; }
    5859
     60    void lineTo(FloatPoint);
     61
    5962    Path m_path;
    6063};
  • trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.idl

    r173652 r180790  
    7979    [RaisesException] void arc(unrestricted float x, unrestricted float y, unrestricted float radius, unrestricted float startAngle,
    8080        unrestricted float endAngle, [Default=Undefined] optional boolean anticlockwise);
     81    [RaisesException] void ellipse(unrestricted float x, unrestricted float y, unrestricted float radiusX, unrestricted float radiusY, unrestricted float rotation, unrestricted float startAngle, unrestricted float endAngle, [Default=Undefined] optional boolean anticlockwise);
    8182
    8283    void fill(DOMPath path, optional CanvasWindingRule winding);
  • trunk/Source/WebCore/html/canvas/DOMPath.idl

    r167451 r180790  
    6464              [Default=Undefined] optional float height);
    6565    [RaisesException] void arc([Default=Undefined] optional float x,
    66              [Default=Undefined] optional float y,
    67              [Default=Undefined] optional float radius,
    68              [Default=Undefined] optional float startAngle,
    69              [Default=Undefined] optional float endAngle,
    70              [Default=Undefined] optional boolean anticlockwise);
     66                               [Default=Undefined] optional float y,
     67                               [Default=Undefined] optional float radius,
     68                               [Default=Undefined] optional float startAngle,
     69                               [Default=Undefined] optional float endAngle,
     70                               [Default=Undefined] optional boolean anticlockwise);
     71    [RaisesException] void ellipse(unrestricted float x, unrestricted float y, unrestricted float radiusX, unrestricted float radiusY, unrestricted float rotation, unrestricted float startAngle, unrestricted float endAngle, [Default=Undefined] optional boolean anticlockwise);
     72
    7173};
  • trunk/Source/WebCore/platform/graphics/Path.h

    r177739 r180790  
    123123        void addArc(const FloatPoint&, float radius, float startAngle, float endAngle, bool anticlockwise);
    124124        void addRect(const FloatRect&);
     125        void addEllipse(FloatPoint, float radiusX, float radiusY, float rotation, float startAngle, float endAngle, bool anticlockwise);
    125126        void addEllipse(const FloatRect&);
    126127
  • trunk/Source/WebCore/platform/graphics/cg/PathCG.cpp

    r178186 r180790  
    293293}
    294294
    295 void Path::addArc(const FloatPoint& p, float r, float sa, float ea, bool clockwise)
     295void Path::addArc(const FloatPoint& p, float radius, float startAngle, float endAngle, bool clockwise)
    296296{
    297297    // Workaround for <rdar://problem/5189233> CGPathAddArc hangs or crashes when passed inf as start or end angle
    298     if (std::isfinite(sa) && std::isfinite(ea))
    299         CGPathAddArc(ensurePlatformPath(), 0, p.x(), p.y(), r, sa, ea, clockwise);
     298    if (std::isfinite(startAngle) && std::isfinite(endAngle))
     299        CGPathAddArc(ensurePlatformPath(), nullptr, p.x(), p.y(), radius, startAngle, endAngle, clockwise);
    300300}
    301301
     
    303303{
    304304    CGPathAddRect(ensurePlatformPath(), 0, r);
     305}
     306
     307void Path::addEllipse(FloatPoint p, float radiusX, float radiusY, float rotation, float startAngle, float endAngle, bool anticlockwise)
     308{
     309    AffineTransform transform;
     310    transform.translate(p.x(), p.y()).rotate(rad2deg(rotation)).scale(radiusX, radiusY);
     311
     312    CGAffineTransform cgTransform = transform;
     313    CGPathAddArc(ensurePlatformPath(), &cgTransform, 0, 0, 1, startAngle, endAngle, anticlockwise);
    305314}
    306315
Note: See TracChangeset for help on using the changeset viewer.