Oops, these files were supposed to go in.
authordarin <darin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 16 Mar 2006 08:54:13 +0000 (08:54 +0000)
committerdarin <darin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 16 Mar 2006 08:54:13 +0000 (08:54 +0000)
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@13330 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/html/CanvasGradient.cpp [new file with mode: 0644]
WebCore/html/CanvasGradient.h [new file with mode: 0644]
WebCore/html/CanvasGradient.idl [new file with mode: 0644]
WebCore/html/CanvasPattern.cpp [new file with mode: 0644]
WebCore/html/CanvasPattern.h [new file with mode: 0644]
WebCore/html/CanvasPattern.idl [new file with mode: 0644]
WebCore/html/CanvasRenderingContext2D.cpp [new file with mode: 0644]
WebCore/html/CanvasRenderingContext2D.h [new file with mode: 0644]
WebCore/html/CanvasRenderingContext2D.idl [new file with mode: 0644]
WebCore/html/CanvasStyle.cpp [new file with mode: 0644]
WebCore/html/CanvasStyle.h [new file with mode: 0644]

diff --git a/WebCore/html/CanvasGradient.cpp b/WebCore/html/CanvasGradient.cpp
new file mode 100644 (file)
index 0000000..8768910
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "CanvasGradient.h"
+
+#include "cssparser.h"
+#include <stdlib.h>
+
+#if __APPLE__
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
+namespace WebCore {
+
+CanvasGradient::CanvasGradient(const FloatPoint& p0, const FloatPoint& p1)
+    : m_radial(false), m_p0(p0), m_p1(p1), m_stopsSorted(false), m_lastStop(0)
+#if __APPLE__
+    , m_shading(0)
+#endif
+{
+}
+
+CanvasGradient::CanvasGradient(const FloatPoint& p0, float r0, const FloatPoint& p1, float r1)
+    : m_radial(true), m_p0(p0), m_p1(p1), m_r0(r0), m_r1(r1), m_stopsSorted(false), m_lastStop(0)
+#if __APPLE__
+    , m_shading(0)
+#endif
+{
+}
+
+CanvasGradient::~CanvasGradient()
+{
+#if __APPLE__
+    CGShadingRelease(m_shading);
+#endif
+}
+
+void CanvasGradient::addColorStop(float value, const String& color)
+{
+    RGBA32 rgba = CSSParser::parseColor(color);
+    m_stops.append(ColorStop(value,
+        ((rgba >> 16) & 0xFF) / 255.0f,
+        ((rgba >> 8) & 0xFF) / 255.0f,
+        (rgba & 0xFF) / 255.0f,
+        ((rgba >> 24) & 0xFF) / 255.0f));
+
+    m_stopsSorted = false;
+
+#if __APPLE__
+    CGShadingRelease(m_shading);
+    m_shading = 0;
+#endif
+}
+
+#if __APPLE__
+
+static void gradientCallback(void* info, const float* in, float* out)
+{
+    static_cast<CanvasGradient*>(info)->getColor(*in, &out[0], &out[1], &out[2], &out[3]);
+}
+
+static void gradientReleaseCallback(void* info)
+{
+    static_cast<CanvasGradient*>(info)->deref();
+}
+
+CGShadingRef CanvasGradient::platformShading()
+{
+    if (m_shading)
+        return m_shading;
+
+    const float intervalRanges[2] = { 0, 1 };
+    const float colorComponentRanges[4 * 2] = { 0, 1, 0, 1, 0, 1, 0, 1 };
+    const CGFunctionCallbacks gradientCallbacks = { 0, gradientCallback, gradientReleaseCallback };
+    ref();
+    CGFunctionRef colorFunction = CGFunctionCreate(this, 1, intervalRanges, 4, colorComponentRanges, &gradientCallbacks);
+
+    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+
+    if (m_radial)
+        m_shading = CGShadingCreateRadial(colorSpace, m_p0, m_r0, m_p1, m_r1, colorFunction, true, true);
+    else
+        m_shading = CGShadingCreateAxial(colorSpace, m_p0, m_p1, colorFunction, true, true);
+
+    CGColorSpaceRelease(colorSpace);
+    CGFunctionRelease(colorFunction);
+
+    return m_shading;
+}
+
+#endif
+
+void CanvasGradient::getColor(float value, float* r, float* g, float* b, float* a)
+{
+    ASSERT(value >= 0);
+    ASSERT(value <= 1);
+
+    if (value <= 0) {
+        *r = m_stops.first().red;
+        *g = m_stops.first().green;
+        *b = m_stops.first().blue;
+        *a = m_stops.first().alpha;
+        return;
+    }
+    if (value >= 1) {
+        *r = m_stops.last().red;
+        *g = m_stops.last().green;
+        *b = m_stops.last().blue;
+        *a = m_stops.last().alpha;
+        return;
+    }
+
+    // Find stop before and stop after and interpolate.
+    int stop = findStop(value);
+    const ColorStop& lastStop = m_stops[stop];    
+    const ColorStop& nextStop = m_stops[stop + 1];
+    float stopFraction = (value - lastStop.stop) / (nextStop.stop - lastStop.stop);
+    *r = lastStop.red + (nextStop.red - lastStop.red) * stopFraction;
+    *g = lastStop.green + (nextStop.green - lastStop.green) * stopFraction;
+    *b = lastStop.blue + (nextStop.blue - lastStop.blue) * stopFraction;
+    *a = lastStop.alpha + (nextStop.alpha - lastStop.alpha) * stopFraction;
+}
+
+static int compareStops(const void* a, const void* b)
+{
+    float as = static_cast<const CanvasGradient::ColorStop*>(a)->stop;
+    float bs = static_cast<const CanvasGradient::ColorStop*>(b)->stop;
+
+    if (as > bs)
+        return 1;
+    if (as < bs)
+        return -1;
+    return 0;
+}
+
+int CanvasGradient::findStop(float value) const
+{
+    if (!m_stopsSorted) {
+        bool addZeroStop = true;
+        bool addOneStop = true;
+        if (m_stops.size()) {
+            qsort(m_stops.data(), m_stops.size(), sizeof(ColorStop), compareStops);
+            addZeroStop = m_stops.first().stop != 0;
+            addOneStop = m_stops.last().stop != 1;
+        }
+        if (addZeroStop)
+            m_stops.insert(0, ColorStop(0, 0, 0, 0, 1));
+        if (addOneStop)
+            m_stops.append(ColorStop(1, 0, 0, 0, 1));
+        m_stopsSorted = true;
+    }
+
+    ASSERT(value >= 0);
+    ASSERT(value <= 1);
+
+    int numStops = m_stops.size();
+    ASSERT(numStops >= 2);
+    ASSERT(m_lastStop < numStops - 1);
+
+    int i = m_lastStop;
+    if (value < m_stops[i].stop)
+        i = 1;
+    else
+        i = m_lastStop + 1;
+
+    for (; i < numStops - 1; ++i)
+        if (value < m_stops[i].stop)
+            break;
+
+    m_lastStop = i - 1;
+    return m_lastStop;
+}
+
+} //namespace
diff --git a/WebCore/html/CanvasGradient.h b/WebCore/html/CanvasGradient.h
new file mode 100644 (file)
index 0000000..b19b286
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef HTMLGradient_h
+#define HTMLGradient_h
+
+#include "FloatPoint.h"
+#include "Shared.h"
+#include <kxmlcore/Vector.h>
+
+#if __APPLE__
+typedef struct CGShading* CGShadingRef;
+#endif
+
+namespace WebCore {
+
+    class String;
+
+    class CanvasGradient : public Shared<CanvasGradient> {
+    public:
+        CanvasGradient(const FloatPoint& p0, const FloatPoint& p1);
+        CanvasGradient(const FloatPoint& p0, float r0, const FloatPoint& p1, float r1);
+        ~CanvasGradient();
+
+        void addColorStop(float, const String& color);
+
+        void getColor(float value, float* r, float* g, float* b, float* a);
+
+#if __APPLE__
+        CGShadingRef platformShading();
+#endif
+
+        struct ColorStop {
+            float stop;
+            float red;
+            float green;
+            float blue;
+            float alpha;
+            
+            ColorStop() : stop(0), red(0), green(0), blue(0), alpha(0) { }
+            ColorStop(float s, float r, float g, float b, float a) : stop(s), red(r), green(g), blue(b), alpha(a) { }
+        };
+
+    private:
+        int findStop(float value) const;
+
+        bool m_radial;
+        FloatPoint m_p0, m_p1;
+        float m_r0, m_r1;
+        mutable Vector<ColorStop> m_stops;
+        mutable bool m_stopsSorted;
+        mutable int m_lastStop;
+
+#if __APPLE__
+        CGShadingRef m_shading;
+#endif
+    };
+
+} //namespace
+
+#endif
diff --git a/WebCore/html/CanvasGradient.idl b/WebCore/html/CanvasGradient.idl
new file mode 100644 (file)
index 0000000..2d00e97
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+module html {
+
+    interface CanvasGradient {
+
+        void addColorStop(in float offset, in DOMString color);
+
+    };
+
+}
diff --git a/WebCore/html/CanvasPattern.cpp b/WebCore/html/CanvasPattern.cpp
new file mode 100644 (file)
index 0000000..65c9186
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "CanvasPattern.h"
+
+#include "CachedImage.h"
+#include "FloatRect.h"
+#include "Image.h"
+
+namespace WebCore {
+
+CanvasPattern::CanvasPattern(CachedImage* cachedImage, const String& repetitionType)
+    : m_cachedImage(cachedImage)
+    , m_repeatX(!(equalIgnoringCase(repetitionType, "repeat-y") || equalIgnoringCase(repetitionType, "no-repeat")))
+    , m_repeatY(!(equalIgnoringCase(repetitionType, "repeat-x") || equalIgnoringCase(repetitionType, "no-repeat")))
+{
+    if (cachedImage)
+        cachedImage->ref(this);
+}
+
+CanvasPattern::~CanvasPattern()
+{
+    if (m_cachedImage)
+        m_cachedImage->deref(this);
+}
+
+#if __APPLE__
+
+static void patternCallback(void* info, CGContextRef context)
+{
+    CachedImage* cachedImage = static_cast<CanvasPattern*>(info)->cachedImage();
+    if (!cachedImage)
+        return;
+    Image* image = cachedImage->image();
+    if (!image)
+        return;
+
+    FloatRect rect = image->rect();
+    
+    // FIXME: Is using CGImageRef directly really superior to asking the image to draw?
+    if (image->getCGImageRef()) {
+        CGContextDrawImage(context, rect, image->getCGImageRef());
+        return;
+    }
+
+    image->drawInRect(rect, rect, Image::CompositeSourceOver, context);
+}
+
+static void patternReleaseCallback(void* info)
+{
+    static_cast<CanvasPattern*>(info)->deref();
+}
+
+CGPatternRef CanvasPattern::createPattern(const CGAffineTransform& transform)
+{
+    if (!m_cachedImage)
+        return 0;
+    Image* image = m_cachedImage->image();
+    if (!image)
+        return 0;
+
+    CGAffineTransform patternTransform =
+        CGAffineTransformTranslate(CGAffineTransformScale(transform, 1, -1), 0, -image->height());
+
+    float xStep = m_repeatX ? image->width() : 0;
+    float yStep = m_repeatY ? image->height() : 0;
+
+    const CGPatternCallbacks patternCallbacks = { 0, patternCallback, patternReleaseCallback };
+    ref();
+    return CGPatternCreate(this, image->rect(), patternTransform, xStep, yStep,
+        kCGPatternTilingConstantSpacing, TRUE, &patternCallbacks);
+}
+
+#endif
+
+}
diff --git a/WebCore/html/CanvasPattern.h b/WebCore/html/CanvasPattern.h
new file mode 100644 (file)
index 0000000..1e30229
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef HTMLImagePattern_h
+#define HTMLImagePattern_h
+
+#include "CachedObjectClient.h"
+#include "Shared.h"
+
+#if __APPLE__
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
+namespace WebCore {
+
+    class CachedImage;
+    class String;
+
+    class CanvasPattern : public Shared<CanvasPattern>, CachedObjectClient {
+    public:
+        CanvasPattern(CachedImage*, const String& repetitionType);
+        ~CanvasPattern();
+
+        CachedImage* cachedImage() const { return m_cachedImage; }
+
+#if __APPLE__
+        CGPatternRef createPattern(const CGAffineTransform&);
+#endif
+
+    private:
+        CachedImage* const m_cachedImage;
+        const bool m_repeatX;
+        const bool m_repeatY;
+    };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/html/CanvasPattern.idl b/WebCore/html/CanvasPattern.idl
new file mode 100644 (file)
index 0000000..2e836ad
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+module html {
+
+    interface CanvasPattern {
+
+    };
+
+}
diff --git a/WebCore/html/CanvasRenderingContext2D.cpp b/WebCore/html/CanvasRenderingContext2D.cpp
new file mode 100644 (file)
index 0000000..265a44d
--- /dev/null
@@ -0,0 +1,1006 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "CanvasRenderingContext2D.h"
+
+#include "GraphicsContext.h"
+#include "CanvasStyle.h"
+#include "CanvasGradient.h"
+#include "CanvasPattern.h"
+#include "cssparser.h"
+#include "html_canvasimpl.h"
+#include "htmlnames.h"
+#include "render_canvasimage.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElementImpl* canvas)
+    : m_canvas(canvas)
+    , m_stateStack(1)
+{
+}
+
+void CanvasRenderingContext2D::reset()
+{
+    m_stateStack.resize(1);
+    m_stateStack.first() = State();
+}
+
+CanvasRenderingContext2D::State::State()
+    : m_strokeStyle(new CanvasStyle("black"))
+    , m_fillStyle(new CanvasStyle("black"))
+    , m_lineWidth(1)
+    , m_lineCap("butt")
+    , m_lineJoin("miter")
+    , m_miterLimit(10)
+    , m_shadowBlur(0)
+    , m_shadowColor("black")
+    , m_globalAlpha(1)
+    , m_globalComposite("source-over")
+#if __APPLE__
+    , m_platformContextStrokeStyleIsPattern(false)
+    , m_platformContextFillStyleIsPattern(false)
+#endif
+{
+}
+
+void CanvasRenderingContext2D::save()
+{
+    ASSERT(m_stateStack.size() >= 1);
+    m_stateStack.append(state());
+
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+    CGContextSaveGState(c);
+#endif
+}
+
+void CanvasRenderingContext2D::restore()
+{
+    ASSERT(m_stateStack.size() >= 1);
+    if (m_stateStack.size() <= 1)
+        return;
+    m_stateStack.removeLast();
+
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+    CGContextRestoreGState(c);
+#endif
+}
+
+CanvasStyle* CanvasRenderingContext2D::strokeStyle() const
+{
+    return state().m_strokeStyle.get();
+}
+
+void CanvasRenderingContext2D::setStrokeStyle(PassRefPtr<CanvasStyle> style)
+{
+    if (!style)
+        return;
+    state().m_strokeStyle = style;
+
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    state().m_strokeStyle->applyStrokeColor(drawingContext());
+    state().m_platformContextStrokeStyleIsPattern = false;
+#endif
+}
+
+CanvasStyle* CanvasRenderingContext2D::fillStyle() const
+{
+    return state().m_fillStyle.get();
+}
+
+void CanvasRenderingContext2D::setFillStyle(PassRefPtr<CanvasStyle> style)
+{
+    if (!style)
+        return;
+    state().m_fillStyle = style;
+
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    state().m_fillStyle->applyFillColor(drawingContext());
+    state().m_platformContextFillStyleIsPattern = false;
+#endif
+}
+
+float CanvasRenderingContext2D::lineWidth() const
+{
+    return state().m_lineWidth;
+}
+
+void CanvasRenderingContext2D::setLineWidth(float width)
+{
+    state().m_lineWidth = width;
+
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextSetLineWidth(drawingContext(), width);
+#endif
+}
+
+String CanvasRenderingContext2D::lineCap() const
+{
+    return state().m_lineCap;
+}
+
+void CanvasRenderingContext2D::setLineCap(const String& cap)
+{
+    // FIXME: Should we store the actual string passed, or should we
+    // convert it to "round", "square", or "butt"?
+    state().m_lineCap = cap;
+
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    if (equalIgnoringCase(cap, "round"))
+        CGContextSetLineCap(drawingContext(), kCGLineCapRound);
+    else if (equalIgnoringCase(cap, "square"))
+        CGContextSetLineCap(drawingContext(), kCGLineCapSquare);
+    else
+        CGContextSetLineCap(drawingContext(), kCGLineCapButt);
+#endif
+}
+
+String CanvasRenderingContext2D::lineJoin() const
+{
+    return state().m_lineJoin;
+}
+
+void CanvasRenderingContext2D::setLineJoin(const String& join)
+{
+    // FIXME: Should we store the actual string passed, or should we
+    // convert it to "round", "bevel", or "miter"?
+    state().m_lineJoin = join;
+
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    if (equalIgnoringCase(join, "round"))
+        CGContextSetLineJoin(drawingContext(), kCGLineJoinRound);
+    else if (equalIgnoringCase(join, "bevel"))
+        CGContextSetLineJoin(drawingContext(), kCGLineJoinBevel);
+    else
+        CGContextSetLineJoin(drawingContext(), kCGLineJoinMiter);
+#endif
+}
+
+float CanvasRenderingContext2D::miterLimit() const
+{
+    return state().m_miterLimit;
+}
+
+void CanvasRenderingContext2D::setMiterLimit(float limit)
+{
+    state().m_miterLimit = limit;
+
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextSetMiterLimit(drawingContext(), limit);
+#endif
+}
+
+float CanvasRenderingContext2D::shadowOffsetX() const
+{
+    return state().m_shadowOffset.width();
+}
+
+void CanvasRenderingContext2D::setShadowOffsetX(float x)
+{
+    state().m_shadowOffset.setWidth(x);
+    applyShadow();
+}
+
+float CanvasRenderingContext2D::shadowOffsetY() const
+{
+    return state().m_shadowOffset.height();
+}
+
+void CanvasRenderingContext2D::setShadowOffsetY(float y)
+{
+    state().m_shadowOffset.setHeight(y);
+    applyShadow();
+}
+
+float CanvasRenderingContext2D::shadowBlur() const
+{
+    return state().m_shadowBlur;
+}
+
+void CanvasRenderingContext2D::setShadowBlur(float blur)
+{
+    state().m_shadowBlur = blur;
+    applyShadow();
+}
+
+String CanvasRenderingContext2D::shadowColor() const
+{
+    // FIXME: What should this return if you called setShadow with a non-string color.
+    return state().m_shadowColor;
+}
+
+void CanvasRenderingContext2D::setShadowColor(const String& color)
+{
+    state().m_shadowColor = color;
+    applyShadow();
+}
+
+float CanvasRenderingContext2D::globalAlpha() const
+{
+    return state().m_globalAlpha;
+}
+
+void CanvasRenderingContext2D::setGlobalAlpha(float alpha)
+{
+    state().m_globalAlpha = alpha;
+
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextSetAlpha(drawingContext(), alpha);
+#endif
+}
+
+String CanvasRenderingContext2D::globalCompositeOperation() const
+{
+    return state().m_globalComposite;
+}
+
+void CanvasRenderingContext2D::setGlobalCompositeOperation(const String& operation)
+{
+    state().m_globalComposite = operation;
+
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    GraphicsContext::setCompositeOperation(drawingContext(), operation.qstring());
+#endif
+}
+
+void CanvasRenderingContext2D::scale(float sx, float sy)
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextScaleCTM(drawingContext(), sx, sy);
+#endif
+}
+
+void CanvasRenderingContext2D::rotate(float angleInRadians)
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRotateCTM(drawingContext(), angleInRadians);
+#endif
+}
+
+void CanvasRenderingContext2D::translate(float tx, float ty)
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextTranslateCTM(drawingContext(), tx, ty);
+#endif
+}
+
+void CanvasRenderingContext2D::setStrokeColor(const String& color)
+{
+    setStrokeStyle(new CanvasStyle(color));
+}
+
+void CanvasRenderingContext2D::setStrokeColor(float grayLevel)
+{
+    setStrokeStyle(new CanvasStyle(grayLevel, 1));
+}
+
+void CanvasRenderingContext2D::setStrokeColor(const String& color, float alpha)
+{
+    setStrokeStyle(new CanvasStyle(color, alpha));
+}
+
+void CanvasRenderingContext2D::setStrokeColor(float grayLevel, float alpha)
+{
+    setStrokeStyle(new CanvasStyle(grayLevel, alpha));
+}
+
+void CanvasRenderingContext2D::setStrokeColor(float r, float g, float b, float a)
+{
+    setStrokeStyle(new CanvasStyle(r, g, b, a));
+}
+
+void CanvasRenderingContext2D::setStrokeColor(float c, float m, float y, float k, float a)
+{
+    setStrokeStyle(new CanvasStyle(c, m, y, k, a));
+}
+
+void CanvasRenderingContext2D::setFillColor(const String& color)
+{
+    setFillStyle(new CanvasStyle(color));
+}
+
+void CanvasRenderingContext2D::setFillColor(float grayLevel)
+{
+    setFillStyle(new CanvasStyle(grayLevel, 1));
+}
+
+void CanvasRenderingContext2D::setFillColor(const String& color, float alpha)
+{
+    setFillStyle(new CanvasStyle(color, 1));
+}
+
+void CanvasRenderingContext2D::setFillColor(float grayLevel, float alpha)
+{
+    setFillStyle(new CanvasStyle(grayLevel, alpha));
+}
+
+void CanvasRenderingContext2D::setFillColor(float r, float g, float b, float a)
+{
+    setFillStyle(new CanvasStyle(r, g, b, a));
+}
+
+void CanvasRenderingContext2D::setFillColor(float c, float m, float y, float k, float a)
+{
+    setFillStyle(new CanvasStyle(c, m, y, k, a));
+}
+
+void CanvasRenderingContext2D::beginPath()
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+    CGContextBeginPath(c);
+#endif
+}
+
+void CanvasRenderingContext2D::closePath()
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+    CGContextClosePath(c);
+#endif
+}
+
+void CanvasRenderingContext2D::moveTo(float x, float y)
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+    CGContextMoveToPoint(c, x, y);
+#endif
+}
+
+void CanvasRenderingContext2D::lineTo(float x, float y)
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+    CGContextAddLineToPoint(c, x, y);
+#endif
+}
+
+void CanvasRenderingContext2D::quadraticCurveTo(float cpx, float cpy, float x, float y)
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+    CGContextAddQuadCurveToPoint(c, cpx, cpy, x, y);
+#endif
+}
+
+void CanvasRenderingContext2D::bezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, float x, float y)
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+    CGContextAddCurveToPoint(drawingContext(), cp1x, cp1y, cp2x, cp2y, x, y);
+#endif
+}
+
+void CanvasRenderingContext2D::arcTo(float x0, float y0, float x1, float y1, float radius)
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+    CGContextAddArcToPoint(drawingContext(), x0, y0, x1, y1, radius);
+#endif
+}
+
+void CanvasRenderingContext2D::arc(float x, float y, float r, float sa, float ea, bool clockwise)
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+    CGContextAddArc(drawingContext(), x, y, r, sa, ea, clockwise);
+#endif
+}
+
+void CanvasRenderingContext2D::rect(float x, float y, float width, float height)
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+    CGContextAddRect(drawingContext(), CGRectMake(x, y, width, height));
+#endif
+}
+
+void CanvasRenderingContext2D::fill()
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+
+    willDraw(CGContextGetPathBoundingBox(c));
+
+    if (state().m_fillStyle->gradient()) {
+        // Shading works on the entire clip region, so convert the current path to a clip.
+        CGContextSaveGState(c);        
+        CGContextClip(c);
+        CGContextDrawShading(c, state().m_fillStyle->gradient()->platformShading());        
+        CGContextRestoreGState(c);
+    } else {
+        if (state().m_fillStyle->pattern())
+            applyFillPattern();
+        CGContextFillPath(c);
+    }
+#endif
+}
+
+void CanvasRenderingContext2D::stroke()
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+
+    // FIXME: Is this right for negative widths?
+    float lineWidth = state().m_lineWidth;
+    float inset = -lineWidth / 2;
+    CGRect boundingRect = CGRectInset(CGContextGetPathBoundingBox(c), inset, inset);
+
+    willDraw(boundingRect);
+
+    if (state().m_strokeStyle->gradient()) {
+        // Shading works on the entire clip region, so convert the current path to a clip.
+        CGContextSaveGState(c);        
+        CGContextReplacePathWithStrokedPath(c);
+        CGContextClip(c);
+        CGContextDrawShading(c, state().m_strokeStyle->gradient()->platformShading());        
+        CGContextRestoreGState(c);
+    } else {
+        if (state().m_strokeStyle->pattern())
+            applyStrokePattern();
+        CGContextStrokePath(c);
+    }
+#endif
+}
+
+void CanvasRenderingContext2D::clip()
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+    CGContextClip(c);
+#endif
+}
+
+void CanvasRenderingContext2D::clearRect(float x, float y, float width, float height)
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+    CGRect rect = CGRectMake(x, y, width, height);
+
+    willDraw(rect);
+
+    CGContextClearRect(c, rect);
+#endif
+}
+
+void CanvasRenderingContext2D::fillRect(float x, float y, float width, float height)
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+    CGRect rect = CGRectMake(x, y, width, height);
+
+    willDraw(rect);
+
+    if (state().m_fillStyle->gradient()) {
+        // Shading works on the entire clip region, so convert the rect to a clip.
+        CGContextSaveGState(c);        
+        CGContextClipToRect(c, rect);
+        CGContextDrawShading(c, state().m_fillStyle->gradient()->platformShading());        
+        CGContextRestoreGState(c);
+    } else {
+        if (state().m_fillStyle->pattern())
+            applyFillPattern();
+        CGContextFillRect(c, rect);
+    }
+#endif
+}
+
+void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float height)
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+
+    // FIXME: Is this right for negative widths?
+    float lineWidth = state().m_lineWidth;
+    float inset = -lineWidth / 2;
+    CGRect rect = CGRectMake(x, y, width, height);
+    CGRect boundingRect = CGRectInset(rect, inset, inset);
+
+    willDraw(boundingRect);
+
+    // FIXME: No support for gradients!
+    if (state().m_strokeStyle->pattern())
+        applyStrokePattern();
+    CGContextStrokeRect(c, rect);
+#endif
+}
+
+void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float height, float lineWidth)
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+
+    // FIXME: Is this right for negative widths?
+    float inset = -lineWidth / 2;
+    CGRect rect = CGRectMake(x, y, width, height);
+    CGRect boundingRect = CGRectInset(rect, inset, inset);
+
+    willDraw(boundingRect);
+
+    // FIXME: No support for gradients!
+    if (state().m_strokeStyle->pattern())
+        applyStrokePattern();
+    CGContextStrokeRectWithWidth(c, rect, lineWidth);
+#endif
+}
+
+void CanvasRenderingContext2D::setShadow(float width, float height, float blur)
+{
+    state().m_shadowOffset = FloatSize(width, height);
+    state().m_shadowBlur = blur;
+    state().m_shadowColor = "";
+    applyShadow();
+}
+
+void CanvasRenderingContext2D::setShadow(float width, float height, float blur, const String& color)
+{
+    state().m_shadowOffset = FloatSize(width, height);
+    state().m_shadowBlur = blur;
+    state().m_shadowColor = color;
+    applyShadow();
+}
+
+void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float grayLevel)
+{
+    state().m_shadowOffset = FloatSize(width, height);
+    state().m_shadowBlur = blur;
+    state().m_shadowColor = "";
+
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+    const float components[2] = { grayLevel, 1 };
+    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
+    CGColorRef color = CGColorCreate(colorSpace, components);
+    CGColorSpaceRelease(colorSpace);
+    CGContextSetShadowWithColor(c, CGSizeMake(width, height), blur, color);
+    CGColorRelease(color);
+#endif
+}
+
+void CanvasRenderingContext2D::setShadow(float width, float height, float blur, const String& color, float alpha)
+{
+    state().m_shadowOffset = FloatSize(width, height);
+    state().m_shadowBlur = blur;
+    state().m_shadowColor = color;
+
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+    RGBA32 rgba = CSSParser::parseColor(color);
+    const float components[4] = {
+        ((rgba >> 16) & 0xFF) / 255.0f,
+        ((rgba >> 8) & 0xFF) / 255.0f,
+        (rgba & 0xFF) / 255.0f,
+        alpha
+    };
+    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+    CGColorRef shadowColor = CGColorCreate(colorSpace, components);
+    CGColorSpaceRelease(colorSpace);
+    CGContextSetShadowWithColor(c, CGSizeMake(width, height), blur, shadowColor);
+    CGColorRelease(shadowColor);
+#endif
+}
+
+void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float grayLevel, float alpha)
+{
+    state().m_shadowOffset = FloatSize(width, height);
+    state().m_shadowBlur = blur;
+    state().m_shadowColor = "";
+
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+    const float components[2] = { grayLevel, alpha };
+    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
+    CGColorRef color = CGColorCreate(colorSpace, components);
+    CGColorSpaceRelease(colorSpace);
+    CGContextSetShadowWithColor(c, CGSizeMake(width, height), blur, color);
+    CGColorRelease(color);
+#endif
+}
+
+void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float r, float g, float b, float a)
+{
+    state().m_shadowOffset = FloatSize(width, height);
+    state().m_shadowBlur = blur;
+    state().m_shadowColor = "";
+
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+    const float components[4] = { r, g, b, a };
+    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+    CGColorRef shadowColor = CGColorCreate(colorSpace, components);
+    CGColorSpaceRelease(colorSpace);
+    CGContextSetShadowWithColor(c, CGSizeMake(width, height), blur, shadowColor);
+    CGColorRelease(shadowColor);
+#endif
+}
+
+void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float c, float m, float y, float k, float a)
+{
+    state().m_shadowOffset = FloatSize(width, height);
+    state().m_shadowBlur = blur;
+    state().m_shadowColor = "";
+
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef dc = drawingContext();
+    if (!dc)
+        return;
+    const float components[5] = { c, m, y, k, a };
+    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceCMYK();
+    CGColorRef shadowColor = CGColorCreate(colorSpace, components);
+    CGColorSpaceRelease(colorSpace);
+    CGContextSetShadowWithColor(dc, CGSizeMake(width, height), blur, shadowColor);
+    CGColorRelease(shadowColor);
+#endif
+}
+
+void CanvasRenderingContext2D::clearShadow()
+{
+    state().m_shadowOffset = FloatSize();
+    state().m_shadowBlur = 0;
+    state().m_shadowColor = "";
+    applyShadow();
+}
+
+void CanvasRenderingContext2D::applyShadow()
+{
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+    RGBA32 rgba = state().m_shadowColor.isEmpty() ? 0 : CSSParser::parseColor(state().m_shadowColor);
+    const float components[4] = {
+        ((rgba >> 16) & 0xFF) / 255.0f,
+        ((rgba >> 8) & 0xFF) / 255.0f,
+        (rgba & 0xFF) / 255.0f,
+        ((rgba >> 24) & 0xFF) / 255.0f
+    };
+    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+    CGColorRef color = CGColorCreate(colorSpace, components);
+    CGColorSpaceRelease(colorSpace);
+    CGContextSetShadowWithColor(c, state().m_shadowOffset, state().m_shadowBlur, color);
+    CGColorRelease(color);
+#endif
+}
+
+// FIXME: This only exists because canvas is a subclass of image.
+static IntSize imageOrCanvasSize(HTMLImageElementImpl* image)
+{
+    if (image->hasLocalName(canvasTag))
+        return static_cast<HTMLCanvasElementImpl*>(image)->size();
+    if (CachedImage* cachedImage = image->cachedImage())
+        return cachedImage->imageSize();
+    return IntSize();
+}
+
+void CanvasRenderingContext2D::drawImage(HTMLImageElementImpl* image, float x, float y)
+{
+    if (!image)
+        return;
+    IntSize size = imageOrCanvasSize(image);
+    drawImage(image, 0, 0, size.width(), size.height(), x, y, size.width(), size.height());
+}
+
+void CanvasRenderingContext2D::drawImage(HTMLImageElementImpl* image, float x, float y, float width, float height)
+{
+    if (!image)
+        return;
+    IntSize size = imageOrCanvasSize(image);
+    drawImage(image, 0, 0, size.width(), size.height(), x, y, width, height);
+}
+
+void CanvasRenderingContext2D::drawImage(HTMLImageElementImpl* image,
+    float sx, float sy, float sw, float sh,
+    float dx, float dy, float dw, float dh)
+{
+    if (!image)
+        return;
+
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+
+    FloatRect destRect = FloatRect(dx, dy, dw, dh);
+
+    if (!image->hasLocalName(canvasTag)) {
+        CachedImage* cachedImage = image->cachedImage();
+        if (!cachedImage)
+            return;
+
+        willDraw(destRect);
+        cachedImage->image()->drawInRect(destRect, FloatRect(sx, sy, sw, sh),
+            Image::compositeOperatorFromString(state().m_globalComposite), c);
+        return;
+    }
+
+    CGImageRef platformImage = static_cast<HTMLCanvasElementImpl*>(image)->createPlatformImage();
+    if (!platformImage)
+        return;
+
+    willDraw(destRect);
+
+    float iw = CGImageGetWidth(platformImage);
+    float ih = CGImageGetHeight(platformImage);
+    if (sx == 0 && sy == 0 && iw == sw && ih == sh) {
+        // Fast path, yay!
+        CGContextDrawImage(c, CGRectMake(dx, dy, dw, dh), platformImage);
+    } else {
+        // Slow path, boo!
+        // Create a new bitmap of the appropriate size and then draw that into our context.
+
+        size_t csw = static_cast<size_t>(ceilf(sw));
+        size_t csh = static_cast<size_t>(ceilf(sh));
+
+        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+        size_t bytesPerRow = csw * 4;
+        void* buffer = fastMalloc(csh * bytesPerRow);
+
+        CGContextRef clippedSourceContext = CGBitmapContextCreate(buffer, csw, csh,
+            8, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast);
+        CGColorSpaceRelease(colorSpace);
+        CGContextTranslateCTM(clippedSourceContext, -sx, -sy);
+        CGContextDrawImage(clippedSourceContext, CGRectMake(0, 0, iw, ih), platformImage);
+
+        CGImageRef clippedSourceImage = CGBitmapContextCreateImage(clippedSourceContext);
+        CGContextRelease(clippedSourceContext);
+
+        CGContextDrawImage(c, CGRectMake(dx, dy, dw, dh), clippedSourceImage);
+        CGImageRelease(clippedSourceImage);
+        
+        fastFree(buffer);
+    }
+
+    CGImageRelease(platformImage);
+#endif
+}
+
+// FIXME: Why isn't this just another overload of drawImage? Why have a different name?
+void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElementImpl* image,
+    float sx, float sy, float sw, float sh,
+    float dx, float dy, float dw, float dh,
+    const String& compositeOperation)
+{
+    if (!image)
+        return;
+
+    // FIXME: Do this through platform-independent GraphicsContext API.
+#if __APPLE__
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+
+    FloatRect destRect = FloatRect(dx, dy, dw, dh);
+
+    // FIXME: Does not support using a canvas as a source image.
+    CachedImage* cachedImage = image->cachedImage();
+    if (!cachedImage)
+        return;
+
+    willDraw(destRect);
+
+    cachedImage->image()->drawInRect(destRect, FloatRect(sx, sy, sw, sh),
+        Image::compositeOperatorFromString(compositeOperation), c);
+#endif
+}
+
+void CanvasRenderingContext2D::setAlpha(float alpha)
+{
+    setGlobalAlpha(alpha);
+}
+
+void CanvasRenderingContext2D::setCompositeOperation(const String& operation)
+{
+    setGlobalCompositeOperation(operation);
+}
+
+PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1)
+{
+    return new CanvasGradient(FloatPoint(x0, y0), FloatPoint(x1, y1));
+}
+
+PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1)
+{
+    return new CanvasGradient(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1);
+}
+
+PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageElementImpl* image, const String& repetitionType)
+{
+    return new CanvasPattern(image ? image->cachedImage() : 0, repetitionType);
+}
+
+void CanvasRenderingContext2D::willDraw(const FloatRect&)
+{
+    if (!m_canvas)
+        return;
+    RenderCanvasImage* renderer = static_cast<RenderCanvasImage*>(m_canvas->renderer());
+    if (renderer)
+        renderer->setNeedsImageUpdate();
+}
+
+#if __APPLE__
+
+CGContextRef CanvasRenderingContext2D::drawingContext() const
+{
+    if (!m_canvas)
+        return 0;
+    RenderCanvasImage* renderer = static_cast<RenderCanvasImage*>(m_canvas->renderer());
+    if (!renderer)
+        return 0;
+    return renderer->drawingContext();
+}
+
+void CanvasRenderingContext2D::applyStrokePattern()
+{
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+
+    // Check for case where the pattern is already set.
+    CGAffineTransform m = CGContextGetCTM(c);
+    if (state().m_platformContextStrokeStyleIsPattern
+            && CGAffineTransformEqualToTransform(m, state().m_strokeStylePatternTransform))
+        return;
+
+    CanvasPattern* pattern = state().m_strokeStyle->pattern();
+    if (!pattern)
+        return;
+
+    CGPatternRef platformPattern = pattern->createPattern(m);
+    if (!platformPattern)
+        return;
+
+    CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(0);
+    CGContextSetStrokeColorSpace(c, patternSpace);
+    CGColorSpaceRelease(patternSpace);
+
+    const float patternAlpha = 1;
+    CGContextSetStrokePattern(c, platformPattern, &patternAlpha);
+    CGPatternRelease(platformPattern);
+
+    state().m_platformContextStrokeStyleIsPattern = true;
+    state().m_strokeStylePatternTransform = m;
+}
+
+void CanvasRenderingContext2D::applyFillPattern()
+{
+    CGContextRef c = drawingContext();
+    if (!c)
+        return;
+
+    // Check for case where the pattern is already set.
+    CGAffineTransform m = CGContextGetCTM(c);
+    if (state().m_platformContextFillStyleIsPattern
+            && CGAffineTransformEqualToTransform(m, state().m_fillStylePatternTransform))
+        return;
+
+    CanvasPattern* pattern = state().m_fillStyle->pattern();
+    if (!pattern)
+        return;
+
+    CGPatternRef platformPattern = pattern->createPattern(m);
+    if (!platformPattern)
+        return;
+
+    CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(0);
+    CGContextSetFillColorSpace(c, patternSpace);
+    CGColorSpaceRelease(patternSpace);
+
+    const float patternAlpha = 1;
+    CGContextSetFillPattern(c, platformPattern, &patternAlpha);
+    CGPatternRelease(platformPattern);
+
+    state().m_platformContextFillStyleIsPattern = true;
+    state().m_fillStylePatternTransform = m;
+}
+
+#endif
+
+} // namespace WebCore
diff --git a/WebCore/html/CanvasRenderingContext2D.h b/WebCore/html/CanvasRenderingContext2D.h
new file mode 100644 (file)
index 0000000..904a0f9
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef HTMLCanvas2DContext_h
+#define HTMLCanvas2DContext_h
+
+#include "FloatRect.h"
+#include "PlatformString.h"
+#include "Shared.h"
+#include <kxmlcore/PassRefPtr.h>
+#include <kxmlcore/RefPtr.h>
+#include <kxmlcore/Vector.h>
+
+#if __APPLE__
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
+namespace WebCore {
+
+    class HTMLCanvasElementImpl;
+    class CanvasStyle;
+    class HTMLImageElementImpl;
+    class CanvasGradient;
+    class CanvasPattern;
+
+    class CanvasRenderingContext2D : public Shared<CanvasRenderingContext2D> {
+    public:
+        CanvasRenderingContext2D(HTMLCanvasElementImpl*);
+
+        HTMLCanvasElementImpl* canvas() const { return m_canvas; }
+
+        CanvasStyle* strokeStyle() const;
+        void setStrokeStyle(PassRefPtr<CanvasStyle>);
+
+        CanvasStyle* fillStyle() const;
+        void setFillStyle(PassRefPtr<CanvasStyle>);
+
+        float lineWidth() const;
+        void setLineWidth(float);
+
+        String lineCap() const;
+        void setLineCap(const String&);
+
+        String lineJoin() const;
+        void setLineJoin(const String&);
+
+        float miterLimit() const;
+        void setMiterLimit(float);
+
+        float shadowOffsetX() const;
+        void setShadowOffsetX(float);
+
+        float shadowOffsetY() const;
+        void setShadowOffsetY(float);
+
+        float shadowBlur() const;
+        void setShadowBlur(float);
+
+        String shadowColor() const;
+        void setShadowColor(const String&);
+
+        float globalAlpha() const;
+        void setGlobalAlpha(float);
+
+        String globalCompositeOperation() const;
+        void setGlobalCompositeOperation(const String&);
+
+        void save();
+        void restore();
+
+        void scale(float sx, float sy);
+        void rotate(float angleInRadians);
+        void translate(float tx, float ty);
+
+        void setStrokeColor(const String& color);
+        void setStrokeColor(float grayLevel);
+        void setStrokeColor(const String& color, float alpha);
+        void setStrokeColor(float grayLevel, float alpha);
+        void setStrokeColor(float r, float g, float b, float a);
+        void setStrokeColor(float c, float m, float y, float k, float a);
+
+        void setFillColor(const String& color);
+        void setFillColor(float grayLevel);
+        void setFillColor(const String& color, float alpha);
+        void setFillColor(float grayLevel, float alpha);
+        void setFillColor(float r, float g, float b, float a);
+        void setFillColor(float c, float m, float y, float k, float a);
+
+        void beginPath();
+        void closePath();
+
+        void moveTo(float x, float y);
+        void lineTo(float x, float y);
+        void quadraticCurveTo(float cpx, float cpy, float x, float y);
+        void bezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, float x, float y);
+        void arcTo(float x0, float y0, float x1, float y1, float radius);
+        void arc(float x, float y, float r, float sa, float ea, bool clockwise);
+        void rect(float x, float y, float width, float height);
+
+        void fill();
+        void stroke();
+        void clip();
+
+        void clearRect(float x, float y, float width, float height);
+        void fillRect(float x, float y, float width, float height);
+        void strokeRect(float x, float y, float width, float height);
+        void strokeRect(float x, float y, float width, float height, float width);
+
+        void setShadow(float width, float height, float blur);
+        void setShadow(float width, float height, float blur, const String& color);
+        void setShadow(float width, float height, float blur, float grayLevel);
+        void setShadow(float width, float height, float blur, const String& color, float alpha);
+        void setShadow(float width, float height, float blur, float grayLevel, float alpha);
+        void setShadow(float width, float height, float blur, float r, float g, float b, float a);
+        void setShadow(float width, float height, float blur, float c, float m, float y, float k, float a);
+
+        void clearShadow();
+
+        void drawImage(HTMLImageElementImpl*, float x, float y);
+        void drawImage(HTMLImageElementImpl*, float x, float y, float width, float height);
+        void drawImage(HTMLImageElementImpl*, float sx, float sy, float sw, float sh,
+            float dx, float dy, float dw, float dh);
+
+        void drawImageFromRect(HTMLImageElementImpl*, float sx, float sy, float sw, float sh,
+            float dx, float dy, float dw, float dh, const String& compositeOperation);
+
+        void setAlpha(float);
+
+        void setCompositeOperation(const String&);
+
+        PassRefPtr<CanvasGradient> createLinearGradient(float x0, float y0, float x1, float y1);
+        PassRefPtr<CanvasGradient> createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1);
+        PassRefPtr<CanvasPattern> createPattern(HTMLImageElementImpl*, const String& repetitionType);
+
+        void reset();
+        void detachCanvas() { m_canvas = 0; }
+
+    private:
+        struct State {
+            State();
+
+            RefPtr<CanvasStyle> m_strokeStyle;
+            RefPtr<CanvasStyle> m_fillStyle;
+            float m_lineWidth;
+            String m_lineCap;
+            String m_lineJoin;
+            float m_miterLimit;
+            FloatSize m_shadowOffset;
+            float m_shadowBlur;
+            String m_shadowColor;
+            float m_globalAlpha;
+            String m_globalComposite;
+#if __APPLE__
+            bool m_platformContextStrokeStyleIsPattern;
+            CGAffineTransform m_strokeStylePatternTransform;
+            bool m_platformContextFillStyleIsPattern;
+            CGAffineTransform m_fillStylePatternTransform;
+#endif
+        };
+
+        State& state() { return m_stateStack.last(); }
+        const State& state() const { return m_stateStack.last(); }
+
+        void applyShadow();
+
+        void willDraw(const FloatRect&);
+
+#if __APPLE__
+        void applyStrokePattern();
+        void applyFillPattern();
+
+        // FIXME: Use GraphicsContext instead.
+        CGContextRef drawingContext() const;
+#endif
+
+        HTMLCanvasElementImpl* m_canvas;
+        Vector<State, 1> m_stateStack;
+    };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/html/CanvasRenderingContext2D.idl b/WebCore/html/CanvasRenderingContext2D.idl
new file mode 100644 (file)
index 0000000..c5696f3
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+module html {
+
+    interface [LegacyParent=JSCanvasRenderingContext2DBase] CanvasRenderingContext2D {
+
+        // Web Applications 1.0 draft
+
+        readonly attribute HTMLCanvasElement canvas;
+
+        void save();
+        void restore();
+
+        void scale(in float sx, in float sy);
+        void rotate(in float angle);
+        void translate(in float tx, in float ty);
+
+        attribute float globalAlpha;
+        attribute DOMString globalCompositeOperation;
+
+        CanvasGradient createLinearGradient(in float x0, in float y0, in float x1, in float y1);
+        CanvasGradient createRadialGradient(in float x0, in float y0, in float r0, in float x1, in float y1, in float r1);
+
+        attribute float lineWidth;
+        attribute DOMString lineCap;
+        attribute DOMString lineJoin;
+        attribute float miterLimit;
+
+        attribute float shadowOffsetX;
+        attribute float shadowOffsetY;
+        attribute float shadowBlur;
+        attribute DOMString shadowColor;
+
+        void clearRect(in float x, in float y, in float width, in float height);
+        void fillRect(in float x, in float y, in float width, in float height);
+
+        void beginPath();
+        void closePath();
+        void moveTo(in float x, in float y);
+        void lineTo(in float x, in float y);
+        void quadraticCurveTo(in float cpx, in float cpy, in float x, in float y);
+        void bezierCurveTo(in float cp1x, in float cp1y, in float cp2x, in float cp2y, in float x, in float y);
+        void arcTo(in float x1, in float y1, in float x2, in float y2, in float radius);
+        void rect(in float x, in float y, in float width, in float height);
+        void arc(in float x, in float y, in float radius, in float startAngle, in float endAngle, in boolean clockwise);
+        void fill();
+        void stroke();
+        void clip();
+
+        // other
+
+        void setAlpha(in float alpha);
+        void setCompositeOperation(in DOMString compositeOperation);
+
+        void setLineWidth(in float width);
+        void setLineCap(in DOMString cap);
+        void setLineJoin(in DOMString join);
+        void setMiterLimit(in float limit);
+
+        void clearShadow();
+
+    };
+
+}
diff --git a/WebCore/html/CanvasStyle.cpp b/WebCore/html/CanvasStyle.cpp
new file mode 100644 (file)
index 0000000..c35c2c1
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "CanvasStyle.h"
+
+#include "CanvasGradient.h"
+#include "CanvasPattern.h"
+#include "cssparser.h"
+
+#if __APPLE__
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
+namespace WebCore {
+
+CanvasStyle::CanvasStyle(const String& color)
+    : m_type(ColorString), m_color(color)
+{
+}
+
+CanvasStyle::CanvasStyle(float grayLevel)
+    : m_type(GrayLevel), m_alpha(1), m_grayLevel(grayLevel)
+{
+}
+
+CanvasStyle::CanvasStyle(const String& color, float alpha)
+    : m_type(ColorStringWithAlpha), m_color(color), m_alpha(alpha)
+{
+}
+
+CanvasStyle::CanvasStyle(float grayLevel, float alpha)
+    : m_type(GrayLevel), m_alpha(alpha), m_grayLevel(grayLevel)
+{
+}
+
+CanvasStyle::CanvasStyle(float r, float g, float b, float a)
+    : m_type(RGBA), m_alpha(a), m_red(r), m_green(g), m_blue(b)
+{
+}
+
+CanvasStyle::CanvasStyle(float c, float m, float y, float k, float a)
+    : m_type(CMYKA), m_alpha(a), m_cyan(c), m_magenta(m), m_yellow(y), m_black(k)
+{
+}
+
+CanvasStyle::CanvasStyle(PassRefPtr<CanvasGradient> gradient)
+    : m_type(gradient ? Gradient : ColorString), m_gradient(gradient)
+{
+}
+
+CanvasStyle::CanvasStyle(PassRefPtr<CanvasPattern> pattern)
+    : m_type(pattern ? ImagePattern : ColorString), m_pattern(pattern)
+{
+}
+
+#if __APPLE__
+
+void CanvasStyle::applyStrokeColor(CGContextRef context)
+{
+    if (!context)
+        return;
+    switch (m_type) {
+        case ColorString: {
+            RGBA32 color = CSSParser::parseColor(m_color);
+            CGContextSetRGBStrokeColor(context,
+                ((color >> 16) & 0xFF) / 255.0f,
+                ((color >> 8) & 0xFF) / 255.0f,
+                (color & 0xFF) / 255.0f,
+                ((color >> 24) & 0xFF) / 255.0f);
+            break;
+        }
+        case ColorStringWithAlpha: {
+            RGBA32 color = CSSParser::parseColor(m_color);
+            CGContextSetRGBStrokeColor(context,
+                ((color >> 16) & 0xFF) / 255.0f,
+                ((color >> 8) & 0xFF) / 255.0f,
+                (color & 0xFF) / 255.0f,
+                m_alpha);
+            break;
+        }
+        case GrayLevel:
+            CGContextSetGrayStrokeColor(context, m_grayLevel, m_alpha);
+            break;
+        case RGBA:
+            CGContextSetRGBStrokeColor(context, m_red, m_green, m_blue, m_alpha);
+            break;
+        case CMYKA:
+            CGContextSetCMYKStrokeColor(context, m_cyan, m_magenta, m_yellow, m_black, m_alpha);
+            break;
+        case Gradient:
+        case ImagePattern:
+            break;
+    }
+}
+
+void CanvasStyle::applyFillColor(CGContextRef context)
+{
+    if (!context)
+        return;
+    switch (m_type) {
+        case ColorString: {
+            RGBA32 color = CSSParser::parseColor(m_color);
+            CGContextSetRGBFillColor(context,
+                ((color >> 16) & 0xFF) / 255.0f,
+                ((color >> 8) & 0xFF) / 255.0f,
+                (color & 0xFF) / 255.0f,
+                ((color >> 24) & 0xFF) / 255.0f);
+            break;
+        }
+        case ColorStringWithAlpha: {
+            RGBA32 color = CSSParser::parseColor(m_color);
+            CGContextSetRGBFillColor(context,
+                ((color >> 16) & 0xFF) / 255.0f,
+                ((color >> 8) & 0xFF) / 255.0f,
+                (color & 0xFF) / 255.0f,
+                m_alpha);
+            break;
+        }
+        case GrayLevel:
+            CGContextSetGrayFillColor(context, m_grayLevel, m_alpha);
+            break;
+        case RGBA:
+            CGContextSetRGBFillColor(context, m_red, m_green, m_blue, m_alpha);
+            break;
+        case CMYKA:
+            CGContextSetCMYKFillColor(context, m_cyan, m_magenta, m_yellow, m_black, m_alpha);
+            break;
+        case Gradient:
+        case ImagePattern:
+            break;
+    }
+}
+
+#endif
+
+}
diff --git a/WebCore/html/CanvasStyle.h b/WebCore/html/CanvasStyle.h
new file mode 100644 (file)
index 0000000..479a1ce
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef HTMLCanvasStyle_h
+#define HTMLCanvasStyle_h
+
+#include "PlatformString.h"
+#include "Shared.h"
+#include <kxmlcore/PassRefPtr.h>
+
+#if __APPLE__
+typedef struct CGContext* CGContextRef;
+#endif
+
+namespace WebCore {
+
+    class CanvasGradient;
+    class CanvasPattern;
+
+    class CanvasStyle : public Shared<CanvasStyle> {
+    public:
+        CanvasStyle(const String& color);
+        CanvasStyle(float grayLevel);
+        CanvasStyle(const String& color, float alpha);
+        CanvasStyle(float grayLevel, float alpha);
+        CanvasStyle(float r, float g, float b, float a);
+        CanvasStyle(float c, float m, float y, float k, float a);
+        CanvasStyle(PassRefPtr<CanvasGradient>);
+        CanvasStyle(PassRefPtr<CanvasPattern>);
+
+        String color() const { return m_color; }
+        CanvasGradient* gradient() const { return m_gradient.get(); }
+        CanvasPattern* pattern() const { return m_pattern.get(); }
+
+#if __APPLE__
+        // These do nothing for gradients or patterns.
+        void applyFillColor(CGContextRef);
+        void applyStrokeColor(CGContextRef);
+#endif
+
+    private:
+        enum Type { ColorString, ColorStringWithAlpha, GrayLevel, RGBA, CMYKA, Gradient, ImagePattern };
+
+        Type m_type;
+
+        String m_color;
+        RefPtr<CanvasGradient> m_gradient;
+        RefPtr<CanvasPattern> m_pattern;
+
+        float m_alpha;
+
+        float m_grayLevel;
+
+        float m_red;
+        float m_green;
+        float m_blue;
+
+        float m_cyan;
+        float m_magenta;
+        float m_yellow;
+        float m_black;
+    };
+
+} // namespace WebCore
+
+#endif