diff options
Diffstat (limited to 'WebCore/html/CanvasGradient.cpp')
-rw-r--r-- | WebCore/html/CanvasGradient.cpp | 261 |
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 |