summaryrefslogtreecommitdiffstats
path: root/WebCore/html/CanvasGradient.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/html/CanvasGradient.cpp')
-rw-r--r--WebCore/html/CanvasGradient.cpp261
1 files changed, 13 insertions, 248 deletions
diff --git a/WebCore/html/CanvasGradient.cpp b/WebCore/html/CanvasGradient.cpp
index e3e3726..693d8f7 100644
--- a/WebCore/html/CanvasGradient.cpp
+++ b/WebCore/html/CanvasGradient.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
*
* Redistribution and use in source and binary forms, with or without
@@ -28,269 +28,34 @@
#include "CanvasGradient.h"
#include "CSSParser.h"
-
-#if PLATFORM(CG)
-#include <ApplicationServices/ApplicationServices.h>
-#elif PLATFORM(QT)
-#include <QGradient>
-#elif PLATFORM(CAIRO)
-#include <cairo.h>
-#endif
-
-#ifdef ANDROID_CANVAS_IMPL
-#include "GraphicsContext.h"
-#include "SkColorShader.h"
-#endif
+#include "ExceptionCode.h"
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 PLATFORM(CG)
- , m_shading(0)
-#elif PLATFORM(QT)
- , m_shading(0)
-#elif PLATFORM(CAIRO)
- , m_shading(0)
-#endif
-#ifdef ANDROID_CANVAS_IMPL
- , m_platformGradient(NULL)
-#endif
+ : m_gradient(Gradient::create(p0, p1))
{
}
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 PLATFORM(CG)
- , m_shading(0)
-#elif PLATFORM(QT)
- , m_shading(0)
-#elif PLATFORM(CAIRO)
- , m_shading(0)
-#endif
-#ifdef ANDROID_CANVAS_IMPL
- , m_platformGradient(NULL)
-#endif
-{
-}
-
-CanvasGradient::~CanvasGradient()
-{
-#if PLATFORM(CG)
- CGShadingRelease(m_shading);
-#elif PLATFORM(QT)
- delete m_shading;
-#elif PLATFORM(CAIRO)
- cairo_pattern_destroy(m_shading);
-#endif
-#ifdef ANDROID_CANVAS_IMPL
- if (m_platformGradient)
- GraphicsContext::freePlatformGradient(m_platformGradient);
-#endif
-}
-
-void CanvasGradient::addColorStop(float value, const String& color)
+ : m_gradient(Gradient::create(p0, r0, p1, r1))
{
- RGBA32 rgba = 0; // default is transparant black
- CSSParser::parseColor(rgba, 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 PLATFORM(CG)
- CGShadingRelease(m_shading);
- m_shading = 0;
-#elif PLATFORM(QT)
- delete m_shading;
- m_shading = 0;
-#elif PLATFORM(CAIRO)
- cairo_pattern_destroy(m_shading);
- m_shading = 0;
-#endif
-}
-
-#if PLATFORM(CG)
-
-static void gradientCallback(void* info, const CGFloat* in, CGFloat* out)
-{
- float r, g, b, a;
- static_cast<CanvasGradient*>(info)->getColor(*in, &r, &g, &b, &a);
- out[0] = r;
- out[1] = g;
- out[2] = b;
- out[3] = a;
}
-CGShadingRef CanvasGradient::platformShading()
-{
- if (m_shading)
- return m_shading;
-
- const CGFloat intervalRanges[2] = { 0, 1 };
- const CGFloat colorComponentRanges[4 * 2] = { 0, 1, 0, 1, 0, 1, 0, 1 };
- const CGFunctionCallbacks gradientCallbacks = { 0, gradientCallback, 0 };
- 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;
-}
-
-#elif PLATFORM(QT)
-
-QGradient* CanvasGradient::platformShading()
-{
- if (m_shading)
- return m_shading;
-
- if (m_radial)
- m_shading = new QRadialGradient(m_p0.x(), m_p0.y(), m_r0, m_p1.x(), m_p1.y());
- else m_shading = new QLinearGradient(m_p0.x(), m_p0.y(), m_p1.x(), m_p1.y());
-
- QColor stopColor;
- Vector<ColorStop>::iterator stopIterator = m_stops.begin();;
- while (stopIterator != m_stops.end()) {
- stopColor.setRgbF(stopIterator->red, stopIterator->green, stopIterator->blue, stopIterator->alpha);
- m_shading->setColorAt(stopIterator->stop, stopColor);
- ++stopIterator;
- }
-
- return m_shading;
-}
-
-#elif PLATFORM(CAIRO)
-
-cairo_pattern_t* CanvasGradient::platformShading()
+void CanvasGradient::addColorStop(float value, const String& color, ExceptionCode& ec)
{
- if (m_shading)
- return m_shading;
-
- if (m_radial)
- m_shading = cairo_pattern_create_radial(m_p0.x(), m_p0.y(), m_r0, m_p1.x(), m_p1.y(), m_r1);
- else
- m_shading = cairo_pattern_create_linear(m_p0.x(), m_p0.y(), m_p1.x(), m_p1.y());
-
- Vector<ColorStop>::iterator stopIterator = m_stops.begin();
- while (stopIterator != m_stops.end()) {
- cairo_pattern_add_color_stop_rgba(m_shading, stopIterator->stop, stopIterator->red, stopIterator->green, stopIterator->blue, stopIterator->alpha);
- ++stopIterator;
- }
-
- return m_shading;
-}
-
-#endif
-
-static inline bool compareStops(const CanvasGradient::ColorStop &a, const CanvasGradient::ColorStop &b)
-{
- return a.stop < b.stop;
-}
-
-void CanvasGradient::getColor(float value, float* r, float* g, float* b, float* a)
-{
- ASSERT(value >= 0);
- ASSERT(value <= 1);
-
- if (m_stops.isEmpty()) {
- *r = 0;
- *g = 0;
- *b = 0;
- *a = 0;
- return;
- }
- if (!m_stopsSorted) {
- if (m_stops.size())
- std::stable_sort(m_stops.begin(), m_stops.end(), compareStops);
- m_stopsSorted = true;
- }
- if (value <= 0 || value <= m_stops.first().stop) {
- *r = m_stops.first().red;
- *g = m_stops.first().green;
- *b = m_stops.first().blue;
- *a = m_stops.first().alpha;
+ if (!(value >= 0 && value <= 1.0f)) {
+ ec = INDEX_SIZE_ERR;
return;
}
- if (value >= 1 || value >= m_stops.last().stop) {
- *r = m_stops.last().red;
- *g = m_stops.last().green;
- *b = m_stops.last().blue;
- *a = m_stops.last().alpha;
+
+ RGBA32 rgba = 0;
+ if (!CSSParser::parseColor(rgba, color)) {
+ ec = SYNTAX_ERR;
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;
-}
-
-int CanvasGradient::findStop(float value) const
-{
- ASSERT(value >= 0);
- ASSERT(value <= 1);
- ASSERT(m_stopsSorted);
-
- 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;
-}
-
-#ifdef ANDROID_CANVAS_IMPL
-PlatformGradient* CanvasGradient::platformGradient()
-{
- PlatformGradient* pg = m_platformGradient;
- int count = m_stops.size();
-
- if (NULL == pg) {
- // it seems the spec says a zero-size gradient draws transparent
- if (0 == count) {
- pg = new SkColorShader(0);
- } else {
- // call this to ensure that data[] is sorted
- float r, g, b, a;
- (void)getColor(0, &r, &g, &b, &a);
-
- const float* data = (const float*)m_stops.data();
-
- if (m_radial)
- pg = GraphicsContext::newPlatformRadialGradient(m_p0, m_r0, m_p1, m_r1, data, count);
- else
- pg = GraphicsContext::newPlatformLinearGradient(m_p0, m_p1, data, count);
- }
- m_platformGradient = pg;
- }
- return pg;
+ m_gradient->addColorStop(value, Color(rgba));
}
-#endif
-} //namespace
+} // namespace