summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/platform/graphics/Gradient.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/WebKit/Source/platform/graphics/Gradient.cpp')
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/Gradient.cpp108
1 files changed, 47 insertions, 61 deletions
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/Gradient.cpp b/chromium/third_party/WebKit/Source/platform/graphics/Gradient.cpp
index f81ad11061a..91c4f47f4cb 100644
--- a/chromium/third_party/WebKit/Source/platform/graphics/Gradient.cpp
+++ b/chromium/third_party/WebKit/Source/platform/graphics/Gradient.cpp
@@ -29,38 +29,41 @@
#include "platform/graphics/Gradient.h"
#include "platform/geometry/FloatRect.h"
-#include "platform/graphics/Color.h"
#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/skia/SkiaUtils.h"
+#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkColorShader.h"
#include "third_party/skia/include/core/SkShader.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
+typedef Vector<SkScalar, 8> ColorStopOffsetVector;
+typedef Vector<SkColor, 8> ColorStopColorVector;
+
namespace WebCore {
Gradient::Gradient(const FloatPoint& p0, const FloatPoint& p1)
- : m_radial(false)
- , m_p0(p0)
+ : m_p0(p0)
, m_p1(p1)
, m_r0(0)
, m_r1(0)
, m_aspectRatio(1)
+ , m_radial(false)
, m_stopsSorted(false)
- , m_spreadMethod(SpreadMethodPad)
, m_drawInPMColorSpace(false)
+ , m_spreadMethod(SpreadMethodPad)
{
}
Gradient::Gradient(const FloatPoint& p0, float r0, const FloatPoint& p1, float r1, float aspectRatio)
- : m_radial(true)
- , m_p0(p0)
+ : m_p0(p0)
, m_p1(p1)
, m_r0(r0)
, m_r1(r1)
, m_aspectRatio(aspectRatio)
+ , m_radial(true)
, m_stopsSorted(false)
- , m_spreadMethod(SpreadMethodPad)
, m_drawInPMColorSpace(false)
+ , m_spreadMethod(SpreadMethodPad)
{
}
@@ -68,32 +71,23 @@ Gradient::~Gradient()
{
}
-void Gradient::addColorStop(float value, const Color& color)
+static inline bool compareStops(const Gradient::ColorStop& a, const Gradient::ColorStop& b)
{
- float r;
- float g;
- float b;
- float a;
- color.getRGBA(r, g, b, a);
- m_stops.append(ColorStop(value, r, g, b, a));
-
- m_stopsSorted = false;
- m_gradient.clear();
+ return a.stop < b.stop;
}
void Gradient::addColorStop(const Gradient::ColorStop& stop)
{
- m_stops.append(stop);
+ if (m_stops.isEmpty()) {
+ m_stopsSorted = true;
+ } else {
+ m_stopsSorted = m_stopsSorted && compareStops(m_stops.last(), stop);
+ }
- m_stopsSorted = false;
+ m_stops.append(stop);
m_gradient.clear();
}
-static inline bool compareStops(const Gradient::ColorStop& a, const Gradient::ColorStop& b)
-{
- return a.stop < b.stop;
-}
-
void Gradient::sortStopsIfNecessary()
{
if (m_stopsSorted)
@@ -110,7 +104,7 @@ void Gradient::sortStopsIfNecessary()
bool Gradient::hasAlpha() const
{
for (size_t i = 0; i < m_stops.size(); i++) {
- if (m_stops[i].alpha < 1)
+ if (m_stops[i].color.hasAlpha())
return true;
}
@@ -143,18 +137,7 @@ void Gradient::setGradientSpaceTransform(const AffineTransform& gradientSpaceTra
return;
m_gradientSpaceTransformation = gradientSpaceTransformation;
- if (m_gradient)
- m_gradient->setLocalMatrix(affineTransformToSkMatrix(m_gradientSpaceTransformation));
-}
-
-static inline U8CPU F2B(float x)
-{
- return static_cast<int>(x * 255);
-}
-
-static SkColor makeSkColor(float a, float r, float g, float b)
-{
- return SkColorSetARGB(F2B(a), F2B(r), F2B(g), F2B(b));
+ m_gradient.clear();
}
// Determine the total number of stops needed, including pseudo-stops at the
@@ -173,19 +156,25 @@ static size_t totalStopsNeeded(const Gradient::ColorStop* stopData, size_t count
return countUsed;
}
+// FIXME: This would be more at home as Color::operator SkColor.
+static inline SkColor makeSkColor(const Color& c)
+{
+ return SkColorSetARGB(c.alpha(), c.red(), c.green(), c.blue());
+}
+
// Collect sorted stop position and color information into the pos and colors
// buffers, ensuring stops at both 0.0 and 1.0. The buffers must be large
// enough to hold information for all stops, including the new endpoints if
// stops at 0.0 and 1.0 aren't already included.
static void fillStops(const Gradient::ColorStop* stopData,
- size_t count, SkScalar* pos, SkColor* colors)
+ size_t count, ColorStopOffsetVector& pos, ColorStopColorVector& colors)
{
const Gradient::ColorStop* stop = stopData;
size_t start = 0;
if (count < 1) {
// A gradient with no stops must be transparent black.
pos[0] = WebCoreFloatToSkScalar(0.0);
- colors[0] = makeSkColor(0.0, 0.0, 0.0, 0.0);
+ colors[0] = SK_ColorTRANSPARENT;
start = 1;
} else if (stop->stop > 0.0) {
// Copy the first stop to 0.0. The first stop position may have a slight
@@ -193,13 +182,13 @@ static void fillStops(const Gradient::ColorStop* stopData,
// 0.0 comes through cleanly and people aren't likely to want a gradient
// with a stop at (0 + epsilon).
pos[0] = WebCoreFloatToSkScalar(0.0);
- colors[0] = makeSkColor(stop->alpha, stop->red, stop->green, stop->blue);
+ colors[0] = makeSkColor(stop->color);
start = 1;
}
for (size_t i = start; i < start + count; i++) {
pos[i] = WebCoreFloatToSkScalar(stop->stop);
- colors[i] = makeSkColor(stop->alpha, stop->red, stop->green, stop->blue);
+ colors[i] = makeSkColor(stop->color);
++stop;
}
@@ -223,11 +212,8 @@ SkShader* Gradient::shader()
ASSERT(countUsed >= 2);
ASSERT(countUsed >= m_stops.size());
- // FIXME: Why is all this manual pointer math needed?!
- SkAutoMalloc storage(countUsed * (sizeof(SkColor) + sizeof(SkScalar)));
- SkColor* colors = (SkColor*)storage.get();
- SkScalar* pos = (SkScalar*)(colors + countUsed);
-
+ ColorStopOffsetVector pos(countUsed);
+ ColorStopColorVector colors(countUsed);
fillStops(m_stops.data(), m_stops.size(), pos, colors);
SkShader::TileMode tile = SkShader::kClamp_TileMode;
@@ -245,36 +231,36 @@ SkShader* Gradient::shader()
uint32_t shouldDrawInPMColorSpace = m_drawInPMColorSpace ? SkGradientShader::kInterpolateColorsInPremul_Flag : 0;
if (m_radial) {
+ if (aspectRatio() != 1) {
+ // CSS3 elliptical gradients: apply the elliptical scaling at the
+ // gradient center point.
+ m_gradientSpaceTransformation.translate(m_p0.x(), m_p0.y());
+ m_gradientSpaceTransformation.scale(1, 1 / aspectRatio());
+ m_gradientSpaceTransformation.translate(-m_p0.x(), -m_p0.y());
+ ASSERT(m_p0 == m_p1);
+ }
+ SkMatrix localMatrix = affineTransformToSkMatrix(m_gradientSpaceTransformation);
+
// Since the two-point radial gradient is slower than the plain radial,
// only use it if we have to.
if (m_p0 == m_p1 && m_r0 <= 0.0f) {
- m_gradient = adoptRef(SkGradientShader::CreateRadial(m_p1, m_r1, colors, pos, static_cast<int>(countUsed), tile, 0, shouldDrawInPMColorSpace));
+ m_gradient = adoptRef(SkGradientShader::CreateRadial(m_p1.data(), m_r1, colors.data(), pos.data(), static_cast<int>(countUsed), tile, shouldDrawInPMColorSpace, &localMatrix));
} else {
// The radii we give to Skia must be positive. If we're given a
// negative radius, ask for zero instead.
SkScalar radius0 = m_r0 >= 0.0f ? WebCoreFloatToSkScalar(m_r0) : 0;
SkScalar radius1 = m_r1 >= 0.0f ? WebCoreFloatToSkScalar(m_r1) : 0;
- m_gradient = adoptRef(SkGradientShader::CreateTwoPointConical(m_p0, radius0, m_p1, radius1, colors, pos, static_cast<int>(countUsed), tile, 0, shouldDrawInPMColorSpace));
- }
-
- if (aspectRatio() != 1) {
- // CSS3 elliptical gradients: apply the elliptical scaling at the
- // gradient center point.
- m_gradientSpaceTransformation.translate(m_p0.x(), m_p0.y());
- m_gradientSpaceTransformation.scale(1, 1 / aspectRatio());
- m_gradientSpaceTransformation.translate(-m_p0.x(), -m_p0.y());
- ASSERT(m_p0 == m_p1);
+ m_gradient = adoptRef(SkGradientShader::CreateTwoPointConical(m_p0.data(), radius0, m_p1.data(), radius1, colors.data(), pos.data(), static_cast<int>(countUsed), tile, shouldDrawInPMColorSpace, &localMatrix));
}
} else {
- SkPoint pts[2] = { m_p0, m_p1 };
- m_gradient = adoptRef(SkGradientShader::CreateLinear(pts, colors, pos, static_cast<int>(countUsed), tile, 0, shouldDrawInPMColorSpace));
+ SkPoint pts[2] = { m_p0.data(), m_p1.data() };
+ SkMatrix localMatrix = affineTransformToSkMatrix(m_gradientSpaceTransformation);
+ m_gradient = adoptRef(SkGradientShader::CreateLinear(pts, colors.data(), pos.data(), static_cast<int>(countUsed), tile, shouldDrawInPMColorSpace, &localMatrix));
}
if (!m_gradient) {
// use last color, since our "geometry" was degenerate (e.g. radius==0)
m_gradient = adoptRef(new SkColorShader(colors[countUsed - 1]));
- } else {
- m_gradient->setLocalMatrix(affineTransformToSkMatrix(m_gradientSpaceTransformation));
}
return m_gradient.get();
}