Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(511)

Unified Diff: third_party/WebKit/Source/platform/graphics/Gradient.cpp

Issue 2785203002: Split Gradient impl into separate classes (Closed)
Patch Set: review Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/WebKit/Source/platform/graphics/Gradient.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/platform/graphics/Gradient.cpp
diff --git a/third_party/WebKit/Source/platform/graphics/Gradient.cpp b/third_party/WebKit/Source/platform/graphics/Gradient.cpp
index caef1c6d7d2ee8dec3f9fbc5fb9ca325ecbd6203..2ed0e01614269ba26327a1b8845be2e3234a1f70 100644
--- a/third_party/WebKit/Source/platform/graphics/Gradient.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Gradient.cpp
@@ -27,6 +27,7 @@
#include "platform/graphics/Gradient.h"
+#include <algorithm>
#include "platform/geometry/FloatRect.h"
#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/paint/PaintShader.h"
@@ -34,44 +35,18 @@
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkMatrix.h"
#include "third_party/skia/include/core/SkShader.h"
+#include "third_party/skia/include/core/SkTLazy.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
-#include <algorithm>
-
-typedef Vector<SkScalar, 8> ColorStopOffsetVector;
-typedef Vector<SkColor, 8> ColorStopColorVector;
namespace blink {
-Gradient::Gradient(const FloatPoint& p0,
- const FloatPoint& p1,
+Gradient::Gradient(Type type,
GradientSpreadMethod spreadMethod,
ColorInterpolation interpolation)
- : m_p0(p0),
- m_p1(p1),
- m_r0(0),
- m_r1(0),
- m_aspectRatio(1),
- m_radial(false),
- m_stopsSorted(false),
+ : m_type(type),
m_spreadMethod(spreadMethod),
- m_colorInterpolation(interpolation) {}
-
-Gradient::Gradient(const FloatPoint& p0,
- float r0,
- const FloatPoint& p1,
- float r1,
- float aspectRatio,
- GradientSpreadMethod spreadMethod,
- ColorInterpolation interpolation)
- : m_p0(p0),
- m_p1(p1),
- m_r0(r0),
- m_r1(r1),
- m_aspectRatio(aspectRatio),
- m_radial(true),
- m_stopsSorted(false),
- m_spreadMethod(spreadMethod),
- m_colorInterpolation(interpolation) {}
+ m_colorInterpolation(interpolation),
+ m_stopsSorted(true) {}
Gradient::~Gradient() {}
@@ -118,23 +93,21 @@ static inline SkColor makeSkColor(const Color& c) {
// TODO(fmalita): theoretically Skia should provide the same 0.0/1.0 padding
// (making this logic redundant), but in practice there are rendering diffs;
// investigate.
-static void fillStops(const Vector<Gradient::ColorStop, 2>& stops,
- ColorStopOffsetVector& pos,
- ColorStopColorVector& colors) {
- if (stops.isEmpty()) {
+void Gradient::fillSkiaStops(ColorBuffer& colors, OffsetBuffer& pos) const {
+ if (m_stops.isEmpty()) {
// A gradient with no stops must be transparent black.
pos.push_back(WebCoreFloatToSkScalar(0));
colors.push_back(SK_ColorTRANSPARENT);
- } else if (stops.front().stop > 0) {
+ } else if (m_stops.front().stop > 0) {
// Copy the first stop to 0.0. The first stop position may have a slight
// rounding error, but we don't care in this float comparison, since
// 0.0 comes through cleanly and people aren't likely to want a gradient
// with a stop at (0 + epsilon).
pos.push_back(WebCoreFloatToSkScalar(0));
- colors.push_back(makeSkColor(stops.front().color));
+ colors.push_back(makeSkColor(m_stops.front().color));
}
- for (const auto& stop : stops) {
+ for (const auto& stop : m_stops) {
pos.push_back(WebCoreFloatToSkScalar(stop.stop));
colors.push_back(makeSkColor(stop.color));
}
@@ -148,17 +121,17 @@ static void fillStops(const Vector<Gradient::ColorStop, 2>& stops,
}
}
-sk_sp<PaintShader> Gradient::createShader(const SkMatrix& localMatrix) {
+sk_sp<PaintShader> Gradient::createShaderInternal(const SkMatrix& localMatrix) {
sortStopsIfNecessary();
- ASSERT(m_stopsSorted);
+ DCHECK(m_stopsSorted);
- ColorStopOffsetVector pos;
- ColorStopColorVector colors;
- pos.reserveCapacity(m_stops.size());
+ ColorBuffer colors;
colors.reserveCapacity(m_stops.size());
+ OffsetBuffer pos;
+ pos.reserveCapacity(m_stops.size());
- fillStops(m_stops, pos, colors);
- DCHECK_GE(pos.size(), 2ul);
+ fillSkiaStops(colors, pos);
+ DCHECK_GE(colors.size(), 2ul);
DCHECK_EQ(pos.size(), colors.size());
SkShader::TileMode tile = SkShader::kClamp_TileMode;
@@ -174,60 +147,132 @@ sk_sp<PaintShader> Gradient::createShader(const SkMatrix& localMatrix) {
break;
}
- sk_sp<SkShader> shader;
uint32_t flags = m_colorInterpolation == ColorInterpolation::Premultiplied
? SkGradientShader::kInterpolateColorsInPremul_Flag
: 0;
- if (m_radial) {
- SkMatrix adjustedLocalMatrix = localMatrix;
+ sk_sp<SkShader> shader = createShader(colors, pos, tile, flags, localMatrix);
+ if (!shader) {
+ // use last color, since our "geometry" was degenerate (e.g. radius==0)
+ shader = SkShader::MakeColorShader(colors.back());
+ }
+
+ return WrapSkShader(std::move(shader));
+}
+
+void Gradient::applyToFlags(PaintFlags& flags, const SkMatrix& localMatrix) {
+ if (!m_cachedShader || localMatrix != m_cachedShader->getLocalMatrix())
+ m_cachedShader = createShaderInternal(localMatrix);
+
+ flags.setShader(m_cachedShader);
+ // Legacy behavior: gradients are always dithered.
+ flags.setDither(true);
+}
+
+namespace {
+
+class LinearGradient final : public Gradient {
+ public:
+ LinearGradient(const FloatPoint& p0,
+ const FloatPoint& p1,
+ GradientSpreadMethod spreadMethod,
+ ColorInterpolation interpolation)
+ : Gradient(Type::Linear, spreadMethod, interpolation),
+ m_p0(p0),
+ m_p1(p1) {}
+
+ protected:
+ sk_sp<SkShader> createShader(const ColorBuffer& colors,
+ const OffsetBuffer& pos,
+ SkShader::TileMode tileMode,
+ uint32_t flags,
+ const SkMatrix& localMatrix) const override {
+ SkPoint pts[2] = {m_p0.data(), m_p1.data()};
+ return SkGradientShader::MakeLinear(pts, colors.data(), pos.data(),
+ static_cast<int>(colors.size()),
+ tileMode, flags, &localMatrix);
+ }
+
+ private:
+ FloatPoint m_p0;
+ FloatPoint m_p1;
+};
+
+class RadialGradient final : public Gradient {
+ public:
+ RadialGradient(const FloatPoint& p0,
+ float r0,
+ const FloatPoint& p1,
+ float r1,
+ float aspectRatio,
+ GradientSpreadMethod spreadMethod,
+ ColorInterpolation interpolation)
+ : Gradient(Type::Radial, spreadMethod, interpolation),
+ m_p0(p0),
+ m_p1(p1),
+ m_r0(r0),
+ m_r1(r1),
+ m_aspectRatio(aspectRatio) {}
+
+ protected:
+ sk_sp<SkShader> createShader(const ColorBuffer& colors,
+ const OffsetBuffer& pos,
+ SkShader::TileMode tileMode,
+ uint32_t flags,
+ const SkMatrix& localMatrix) const override {
+ SkTCopyOnFirstWrite<SkMatrix> adjustedLocalMatrix(localMatrix);
if (m_aspectRatio != 1) {
// CSS3 elliptical gradients: apply the elliptical scaling at the
// gradient center point.
- adjustedLocalMatrix.preTranslate(m_p0.x(), m_p0.y());
- adjustedLocalMatrix.preScale(1, 1 / m_aspectRatio);
- adjustedLocalMatrix.preTranslate(-m_p0.x(), -m_p0.y());
- ASSERT(m_p0 == m_p1);
+ DCHECK(m_p0 == m_p1);
+ adjustedLocalMatrix.writable()->preScale(1, 1 / m_aspectRatio, m_p0.x(),
+ m_p0.y());
}
// 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) {
- shader = SkGradientShader::MakeRadial(
- m_p1.data(), m_r1, colors.data(), pos.data(),
- static_cast<int>(colors.size()), tile, flags, &adjustedLocalMatrix);
- } 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;
- shader = SkGradientShader::MakeTwoPointConical(
- m_p0.data(), radius0, m_p1.data(), radius1, colors.data(), pos.data(),
- static_cast<int>(colors.size()), tile, flags, &adjustedLocalMatrix);
+ return SkGradientShader::MakeRadial(m_p1.data(), m_r1, colors.data(),
+ pos.data(),
+ static_cast<int>(colors.size()),
+ tileMode, flags, adjustedLocalMatrix);
}
- } else {
- SkPoint pts[2] = {m_p0.data(), m_p1.data()};
- shader = SkGradientShader::MakeLinear(pts, colors.data(), pos.data(),
- static_cast<int>(colors.size()), tile,
- flags, &localMatrix);
- }
- if (!shader) {
- // use last color, since our "geometry" was degenerate (e.g. radius==0)
- shader = SkShader::MakeColorShader(colors.back());
+ // The radii we give to Skia must be positive. If we're given a
+ // negative radius, ask for zero instead.
+ const SkScalar radius0 = std::max(WebCoreFloatToSkScalar(m_r0), 0.0f);
+ const SkScalar radius1 = std::max(WebCoreFloatToSkScalar(m_r1), 0.0f);
+ return SkGradientShader::MakeTwoPointConical(
+ m_p0.data(), radius0, m_p1.data(), radius1, colors.data(), pos.data(),
+ static_cast<int>(colors.size()), tileMode, flags, adjustedLocalMatrix);
}
- return WrapSkShader(shader);
+ private:
+ FloatPoint m_p0;
+ FloatPoint m_p1;
+ float m_r0;
+ float m_r1;
+ float m_aspectRatio; // For elliptical gradient, width / height.
+};
+
+} // anonymous ns
+
+PassRefPtr<Gradient> Gradient::createLinear(const FloatPoint& p0,
+ const FloatPoint& p1,
+ GradientSpreadMethod spreadMethod,
+ ColorInterpolation interpolation) {
+ return adoptRef(new LinearGradient(p0, p1, spreadMethod, interpolation));
}
-void Gradient::applyToFlags(PaintFlags& flags, const SkMatrix& localMatrix) {
- if (!m_cachedShader || localMatrix != m_cachedShader->getLocalMatrix())
- m_cachedShader = createShader(localMatrix);
-
- flags.setShader(m_cachedShader);
-
- // Legacy behavior: gradients are always dithered.
- flags.setDither(true);
+PassRefPtr<Gradient> Gradient::createRadial(const FloatPoint& p0,
+ float r0,
+ const FloatPoint& p1,
+ float r1,
+ float aspectRatio,
+ GradientSpreadMethod spreadMethod,
+ ColorInterpolation interpolation) {
+ return adoptRef(new RadialGradient(p0, r0, p1, r1, aspectRatio, spreadMethod,
+ interpolation));
}
} // namespace blink
« no previous file with comments | « third_party/WebKit/Source/platform/graphics/Gradient.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698