Home | History | Annotate | Download | only in canvas
      1 /*
      2  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
      3  * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies)
      4  * Copyright (C) 2007 Alp Toker <alp (at) atoker.com>
      5  * Copyright (C) 2008 Eric Seidel <eric (at) webkit.org>
      6  * Copyright (C) 2008 Dirk Schulze <krit (at) webkit.org>
      7  * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
      8  * Copyright (C) 2012 Intel Corporation. All rights reserved.
      9  * Copyright (C) 2012, 2013 Adobe Systems Incorporated. All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  *
     15  * 1.  Redistributions of source code must retain the above copyright
     16  *     notice, this list of conditions and the following disclaimer.
     17  * 2.  Redistributions in binary form must reproduce the above copyright
     18  *     notice, this list of conditions and the following disclaimer in the
     19  *     documentation and/or other materials provided with the distribution.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
     22  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     24  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
     25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
     26  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     28  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
     30  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
     31  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32  * SUCH DAMAGE.
     33  */
     34 
     35 #include "config.h"
     36 #include "core/html/canvas/CanvasPathMethods.h"
     37 
     38 #include "bindings/v8/ExceptionState.h"
     39 #include "core/dom/ExceptionCode.h"
     40 #include "core/platform/graphics/FloatRect.h"
     41 #include "wtf/MathExtras.h"
     42 
     43 namespace WebCore {
     44 
     45 void CanvasPathMethods::closePath()
     46 {
     47     if (m_path.isEmpty())
     48         return;
     49 
     50     FloatRect boundRect = m_path.boundingRect();
     51     if (boundRect.width() || boundRect.height())
     52         m_path.closeSubpath();
     53 }
     54 
     55 void CanvasPathMethods::moveTo(float x, float y)
     56 {
     57     if (!std::isfinite(x) || !std::isfinite(y))
     58         return;
     59     if (!isTransformInvertible())
     60         return;
     61     m_path.moveTo(FloatPoint(x, y));
     62 }
     63 
     64 void CanvasPathMethods::lineTo(float x, float y)
     65 {
     66     if (!std::isfinite(x) || !std::isfinite(y))
     67         return;
     68     if (!isTransformInvertible())
     69         return;
     70 
     71     FloatPoint p1 = FloatPoint(x, y);
     72     if (!m_path.hasCurrentPoint())
     73         m_path.moveTo(p1);
     74     else if (p1 != m_path.currentPoint())
     75         m_path.addLineTo(p1);
     76 }
     77 
     78 void CanvasPathMethods::quadraticCurveTo(float cpx, float cpy, float x, float y)
     79 {
     80     if (!std::isfinite(cpx) || !std::isfinite(cpy) || !std::isfinite(x) || !std::isfinite(y))
     81         return;
     82     if (!isTransformInvertible())
     83         return;
     84     if (!m_path.hasCurrentPoint())
     85         m_path.moveTo(FloatPoint(cpx, cpy));
     86 
     87     FloatPoint p1 = FloatPoint(x, y);
     88     FloatPoint cp = FloatPoint(cpx, cpy);
     89     if (p1 != m_path.currentPoint() || p1 != cp)
     90         m_path.addQuadCurveTo(cp, p1);
     91 }
     92 
     93 void CanvasPathMethods::bezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, float x, float y)
     94 {
     95     if (!std::isfinite(cp1x) || !std::isfinite(cp1y) || !std::isfinite(cp2x) || !std::isfinite(cp2y) || !std::isfinite(x) || !std::isfinite(y))
     96         return;
     97     if (!isTransformInvertible())
     98         return;
     99     if (!m_path.hasCurrentPoint())
    100         m_path.moveTo(FloatPoint(cp1x, cp1y));
    101 
    102     FloatPoint p1 = FloatPoint(x, y);
    103     FloatPoint cp1 = FloatPoint(cp1x, cp1y);
    104     FloatPoint cp2 = FloatPoint(cp2x, cp2y);
    105     if (p1 != m_path.currentPoint() || p1 != cp1 ||  p1 != cp2)
    106         m_path.addBezierCurveTo(cp1, cp2, p1);
    107 }
    108 
    109 void CanvasPathMethods::arcTo(float x1, float y1, float x2, float y2, float r, ExceptionState& es)
    110 {
    111     if (!std::isfinite(x1) || !std::isfinite(y1) || !std::isfinite(x2) || !std::isfinite(y2) || !std::isfinite(r))
    112         return;
    113 
    114     if (r < 0) {
    115         es.throwDOMException(IndexSizeError);
    116         return;
    117     }
    118 
    119     if (!isTransformInvertible())
    120         return;
    121 
    122     FloatPoint p1 = FloatPoint(x1, y1);
    123     FloatPoint p2 = FloatPoint(x2, y2);
    124 
    125     if (!m_path.hasCurrentPoint())
    126         m_path.moveTo(p1);
    127     else if (p1 == m_path.currentPoint() || p1 == p2 || !r)
    128         lineTo(x1, y1);
    129     else
    130         m_path.addArcTo(p1, p2, r);
    131 }
    132 
    133 void CanvasPathMethods::arc(float x, float y, float r, float sa, float ea, bool anticlockwise, ExceptionState& es)
    134 {
    135     if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(r) || !std::isfinite(sa) || !std::isfinite(ea))
    136         return;
    137 
    138     if (r < 0) {
    139         es.throwDOMException(IndexSizeError);
    140         return;
    141     }
    142 
    143     if (!r || sa == ea) {
    144         // The arc is empty but we still need to draw the connecting line.
    145         lineTo(x + r * cosf(sa), y + r * sinf(sa));
    146         return;
    147     }
    148 
    149     if (!isTransformInvertible())
    150         return;
    151 
    152     // If 'sa' and 'ea' differ by more than 2Pi, just add a circle starting/ending at 'sa'.
    153     if (anticlockwise && sa - ea >= 2 * piFloat) {
    154         m_path.addArc(FloatPoint(x, y), r, sa, sa - 2 * piFloat, anticlockwise);
    155         return;
    156     }
    157     if (!anticlockwise && ea - sa >= 2 * piFloat) {
    158         m_path.addArc(FloatPoint(x, y), r, sa, sa + 2 * piFloat, anticlockwise);
    159         return;
    160     }
    161 
    162     m_path.addArc(FloatPoint(x, y), r, sa, ea, anticlockwise);
    163 }
    164 
    165 void CanvasPathMethods::rect(float x, float y, float width, float height)
    166 {
    167     if (!isTransformInvertible())
    168         return;
    169 
    170     if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(width) || !std::isfinite(height))
    171         return;
    172 
    173     if (!width && !height) {
    174         m_path.moveTo(FloatPoint(x, y));
    175         return;
    176     }
    177 
    178     m_path.addRect(FloatRect(x, y, width, height));
    179 }
    180 }
    181