mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Backed out changeset 1cb2802bb09b (bug 298281) for causing build bustage at nsCSSRenderingGradients.h CLOSED TREE
This commit is contained in:
parent
78b9b11c37
commit
a249c3e2e4
@ -1189,45 +1189,6 @@ bool nsCSSGradientRenderer::TryPaintTilesWithExtendMode(
|
||||
return true;
|
||||
}
|
||||
|
||||
class MOZ_STACK_CLASS WrColorStopInterpolator
|
||||
: public ColorStopInterpolator<WrColorStopInterpolator> {
|
||||
public:
|
||||
WrColorStopInterpolator(
|
||||
const nsTArray<ColorStop>& aStops,
|
||||
const StyleColorInterpolationMethod& aStyleColorInterpolationMethod,
|
||||
float aOpacity, nsTArray<wr::GradientStop>& aResult)
|
||||
: ColorStopInterpolator(aStops, aStyleColorInterpolationMethod),
|
||||
mResult(aResult),
|
||||
mOpacity(aOpacity),
|
||||
mOutputStop(0) {}
|
||||
|
||||
void CreateStops() {
|
||||
mResult.SetLengthAndRetainStorage(0);
|
||||
// we always emit at least two stops (start and end) for each input stop,
|
||||
// which avoids ambiguity with incomplete oklch/lch/hsv/hsb color stops for
|
||||
// the last stop pair, where the last color stop can't be interpreted on its
|
||||
// own because it actually depends on the previous stop.
|
||||
mResult.SetLength(mStops.Length() * 2 + kFullRangeExtraStops);
|
||||
mOutputStop = 0;
|
||||
ColorStopInterpolator::CreateStops();
|
||||
mResult.SetLength(mOutputStop);
|
||||
}
|
||||
|
||||
void CreateStop(float aPosition, DeviceColor aColor) {
|
||||
if (mOutputStop < mResult.Capacity()) {
|
||||
mResult[mOutputStop].color = wr::ToColorF(aColor);
|
||||
mResult[mOutputStop].color.a *= mOpacity;
|
||||
mResult[mOutputStop].offset = aPosition;
|
||||
mOutputStop++;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsTArray<wr::GradientStop>& mResult;
|
||||
float mOpacity;
|
||||
uint32_t mOutputStop;
|
||||
};
|
||||
|
||||
void nsCSSGradientRenderer::BuildWebRenderParameters(
|
||||
float aOpacity, wr::ExtendMode& aMode, nsTArray<wr::GradientStop>& aStops,
|
||||
LayoutDevicePoint& aLineStart, LayoutDevicePoint& aLineEnd,
|
||||
@ -1260,9 +1221,44 @@ void nsCSSGradientRenderer::BuildWebRenderParameters(
|
||||
if (mStops.Length() >= 2 &&
|
||||
(styleColorInterpolationMethod.space != StyleColorSpace::Srgb ||
|
||||
gfxPlatform::GetCMSMode() == CMSMode::All)) {
|
||||
WrColorStopInterpolator interpolator(mStops, styleColorInterpolationMethod,
|
||||
aOpacity, aStops);
|
||||
interpolator.CreateStops();
|
||||
aStops.SetLengthAndRetainStorage(0);
|
||||
// this could be made tunable, but at 1.0/128 the error is largely
|
||||
// irrelevant, as WebRender re-encodes it to 128 pairs of stops.
|
||||
//
|
||||
// note that we don't attempt to place the positions of these stops
|
||||
// precisely at intervals, we just add this many extra stops across the
|
||||
// range where it is convenient.
|
||||
const int fullRangeExtraStops = 128;
|
||||
// we always emit at least two stops (start and end) for each input stop,
|
||||
// which avoids ambiguity with incomplete oklch/lch/hsv/hsb color stops for
|
||||
// the last stop pair, where the last color stop can't be interpreted on its
|
||||
// own because it actually depends on the previous stop.
|
||||
aStops.SetLength(mStops.Length() * 2 + fullRangeExtraStops);
|
||||
uint32_t outputStop = 0;
|
||||
for (uint32_t i = 0; i < mStops.Length() - 1; i++) {
|
||||
auto& start = mStops[i];
|
||||
auto& end = i + 1 < mStops.Length() ? mStops[i + 1] : mStops[i];
|
||||
StyleAbsoluteColor startColor = start.mColor;
|
||||
StyleAbsoluteColor endColor = end.mColor;
|
||||
int extraStops = (int)(floor(end.mPosition * fullRangeExtraStops) -
|
||||
floor(start.mPosition * fullRangeExtraStops));
|
||||
extraStops = clamped(extraStops, 1, fullRangeExtraStops);
|
||||
float step = 1.0f / (float)extraStops;
|
||||
for (int extraStop = 0;
|
||||
extraStop <= extraStops && outputStop < aStops.Capacity();
|
||||
extraStop++) {
|
||||
auto lerp = (float)extraStop * step;
|
||||
auto position =
|
||||
start.mPosition + lerp * (end.mPosition - start.mPosition);
|
||||
StyleAbsoluteColor color = Servo_InterpolateColor(
|
||||
styleColorInterpolationMethod, &endColor, &startColor, lerp);
|
||||
aStops[outputStop].color = wr::ToColorF(ToDeviceColor(color));
|
||||
aStops[outputStop].color.a *= aOpacity;
|
||||
aStops[outputStop].offset = (float)position;
|
||||
outputStop++;
|
||||
}
|
||||
}
|
||||
aStops.SetLength(outputStop);
|
||||
} else {
|
||||
aStops.SetLength(mStops.Length());
|
||||
for (uint32_t i = 0; i < mStops.Length(); i++) {
|
||||
|
@ -38,50 +38,6 @@ struct ColorStop {
|
||||
StyleAbsoluteColor mColor;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class MOZ_STACK_CLASS ColorStopInterpolator {
|
||||
public:
|
||||
ColorStopInterpolator(
|
||||
const nsTArray<ColorStop>& aStops,
|
||||
const StyleColorInterpolationMethod& aStyleColorInterpolationMethod)
|
||||
: mStyleColorInterpolationMethod(aStyleColorInterpolationMethod),
|
||||
mStops(aStops) {}
|
||||
|
||||
void CreateStops() {
|
||||
for (uint32_t i = 0; i < mStops.Length() - 1; i++) {
|
||||
const auto& start = mStops[i];
|
||||
const auto& end = mStops[i + 1];
|
||||
uint32_t extraStops =
|
||||
(uint32_t)(floor(end.mPosition * kFullRangeExtraStops) -
|
||||
floor(start.mPosition * kFullRangeExtraStops));
|
||||
extraStops = clamped(extraStops, 1U, kFullRangeExtraStops);
|
||||
float step = 1.0f / (float)extraStops;
|
||||
for (uint32_t extraStop = 0; extraStop <= extraStops; extraStop++) {
|
||||
auto progress = (float)extraStop * step;
|
||||
auto position =
|
||||
start.mPosition + progress * (end.mPosition - start.mPosition);
|
||||
StyleAbsoluteColor color =
|
||||
Servo_InterpolateColor(mStyleColorInterpolationMethod, &end.mColor,
|
||||
&start.mColor, progress);
|
||||
static_cast<T*>(this)->CreateStop(float(position),
|
||||
gfx::ToDeviceColor(color));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
StyleColorInterpolationMethod mStyleColorInterpolationMethod;
|
||||
const nsTArray<ColorStop>& mStops;
|
||||
|
||||
// this could be made tunable, but at 1.0/128 the error is largely
|
||||
// irrelevant, as WebRender re-encodes it to 128 pairs of stops.
|
||||
//
|
||||
// note that we don't attempt to place the positions of these stops
|
||||
// precisely at intervals, we just add this many extra stops across the
|
||||
// range where it is convenient.
|
||||
inline static const uint32_t kFullRangeExtraStops = 128;
|
||||
};
|
||||
|
||||
class nsCSSGradientRenderer final {
|
||||
public:
|
||||
/**
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include "nsContentUtils.h"
|
||||
#include "SVGAnimatedTransformList.h"
|
||||
|
||||
// XXX Tight coupling with content classes ahead!
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::dom::SVGGradientElement_Binding;
|
||||
using namespace mozilla::dom::SVGUnitTypes_Binding;
|
||||
@ -208,53 +210,21 @@ dom::SVGRadialGradientElement* SVGGradientFrame::GetRadialGradientWithLength(
|
||||
//----------------------------------------------------------------------
|
||||
// SVGPaintServerFrame methods:
|
||||
|
||||
// helpers
|
||||
|
||||
static ColorStop GetStopInformation(const nsIFrame* aStopFrame,
|
||||
float aGraphicOpacity,
|
||||
float& aLastPosition) {
|
||||
// helper
|
||||
static void GetStopInformation(nsIFrame* aStopFrame, float* aOffset,
|
||||
nscolor* aStopColor, float* aStopOpacity) {
|
||||
nsIContent* stopContent = aStopFrame->GetContent();
|
||||
MOZ_ASSERT(stopContent && stopContent->IsSVGElement(nsGkAtoms::stop));
|
||||
|
||||
float position;
|
||||
static_cast<SVGStopElement*>(stopContent)
|
||||
->GetAnimatedNumberValues(&position, nullptr);
|
||||
->GetAnimatedNumberValues(aOffset, nullptr);
|
||||
|
||||
position = clamped(position, 0.0f, 1.0f);
|
||||
|
||||
if (position < aLastPosition) {
|
||||
position = aLastPosition;
|
||||
} else {
|
||||
aLastPosition = position;
|
||||
}
|
||||
|
||||
const auto* svgReset = aStopFrame->StyleSVGReset();
|
||||
|
||||
sRGBColor stopColor =
|
||||
sRGBColor::FromABGR(svgReset->mStopColor.CalcColor(aStopFrame));
|
||||
stopColor.a *= svgReset->mStopOpacity * aGraphicOpacity;
|
||||
|
||||
return ColorStop(position, false,
|
||||
StyleAbsoluteColor::FromColor(stopColor.ToABGR()));
|
||||
const nsStyleSVGReset* styleSVGReset = aStopFrame->StyleSVGReset();
|
||||
*aOffset = mozilla::clamped(*aOffset, 0.0f, 1.0f);
|
||||
*aStopColor = styleSVGReset->mStopColor.CalcColor(aStopFrame);
|
||||
*aStopOpacity = styleSVGReset->mStopOpacity;
|
||||
}
|
||||
|
||||
class MOZ_STACK_CLASS SVGColorStopInterpolator
|
||||
: public ColorStopInterpolator<SVGColorStopInterpolator> {
|
||||
public:
|
||||
SVGColorStopInterpolator(
|
||||
gfxPattern* aGradient, const nsTArray<ColorStop>& aStops,
|
||||
const StyleColorInterpolationMethod& aStyleColorInterpolationMethod)
|
||||
: ColorStopInterpolator(aStops, aStyleColorInterpolationMethod),
|
||||
mGradient(aGradient) {}
|
||||
|
||||
void CreateStop(float aPosition, DeviceColor aColor) {
|
||||
mGradient->AddColorStop(aPosition, aColor);
|
||||
}
|
||||
|
||||
private:
|
||||
gfxPattern* mGradient;
|
||||
};
|
||||
|
||||
already_AddRefed<gfxPattern> SVGGradientFrame::GetPaintServerPattern(
|
||||
nsIFrame* aSource, const DrawTarget* aDrawTarget,
|
||||
const gfxMatrix& aContextMatrix, StyleSVGPaint nsStyleSVG::*aFillOrStroke,
|
||||
@ -270,21 +240,29 @@ already_AddRefed<gfxPattern> SVGGradientFrame::GetPaintServerPattern(
|
||||
mSource = aSource->IsTextFrame() ? aSource->GetParent() : aSource;
|
||||
}
|
||||
|
||||
AutoTArray<ColorStop, 8> stops;
|
||||
GetStops(&stops, aGraphicOpacity);
|
||||
AutoTArray<nsIFrame*, 8> stopFrames;
|
||||
GetStopFrames(&stopFrames);
|
||||
|
||||
uint32_t nStops = stops.Length();
|
||||
uint32_t nStops = stopFrames.Length();
|
||||
|
||||
// SVG specification says that no stops should be treated like
|
||||
// the corresponding fill or stroke had "none" specified.
|
||||
if (nStops == 0) {
|
||||
RefPtr<gfxPattern> pattern = new gfxPattern(DeviceColor());
|
||||
return do_AddRef(new gfxPattern(DeviceColor()));
|
||||
}
|
||||
|
||||
if (nStops == 1 || GradientVectorLengthIsZero()) {
|
||||
auto* lastStopFrame = stopFrames[nStops - 1];
|
||||
const auto* svgReset = lastStopFrame->StyleSVGReset();
|
||||
// The gradient paints a single colour, using the stop-color of the last
|
||||
// gradient step if there are more than one.
|
||||
return do_AddRef(new gfxPattern(ToDeviceColor(stops.LastElement().mColor)));
|
||||
float stopOpacity = svgReset->mStopOpacity;
|
||||
nscolor stopColor = svgReset->mStopColor.CalcColor(lastStopFrame);
|
||||
|
||||
sRGBColor stopColor2 = sRGBColor::FromABGR(stopColor);
|
||||
stopColor2.a *= stopOpacity * aGraphicOpacity;
|
||||
return do_AddRef(new gfxPattern(ToDeviceColor(stopColor2)));
|
||||
}
|
||||
|
||||
// Get the transform list (if there is one). We do this after the returns
|
||||
@ -323,16 +301,23 @@ already_AddRefed<gfxPattern> SVGGradientFrame::GetPaintServerPattern(
|
||||
|
||||
gradient->SetMatrix(patternMatrix);
|
||||
|
||||
if (StyleSVG()->mColorInterpolation == StyleColorInterpolation::Linearrgb) {
|
||||
static constexpr auto interpolationMethod = StyleColorInterpolationMethod{
|
||||
StyleColorSpace::SrgbLinear, StyleHueInterpolationMethod::Shorter};
|
||||
SVGColorStopInterpolator interpolator(gradient, stops, interpolationMethod);
|
||||
interpolator.CreateStops();
|
||||
} else {
|
||||
// setup standard sRGB stops
|
||||
for (const auto& stop : stops) {
|
||||
gradient->AddColorStop(stop.mPosition, ToDeviceColor(stop.mColor));
|
||||
}
|
||||
// setup stops
|
||||
float lastOffset = 0.0f;
|
||||
|
||||
for (uint32_t i = 0; i < nStops; i++) {
|
||||
float offset, stopOpacity;
|
||||
nscolor stopColor;
|
||||
|
||||
GetStopInformation(stopFrames[i], &offset, &stopColor, &stopOpacity);
|
||||
|
||||
if (offset < lastOffset)
|
||||
offset = lastOffset;
|
||||
else
|
||||
lastOffset = offset;
|
||||
|
||||
sRGBColor stopColor2 = sRGBColor::FromABGR(stopColor);
|
||||
stopColor2.a *= stopOpacity * aGraphicOpacity;
|
||||
gradient->AddColorStop(offset, ToDeviceColor(stopColor2));
|
||||
}
|
||||
|
||||
return gradient.forget();
|
||||
@ -366,16 +351,15 @@ SVGGradientFrame* SVGGradientFrame::GetReferencedGradient() {
|
||||
return do_QueryFrame(SVGObserverUtils::GetAndObserveTemplate(this, GetHref));
|
||||
}
|
||||
|
||||
void SVGGradientFrame::GetStops(nsTArray<ColorStop>* aStops,
|
||||
float aGraphicOpacity) {
|
||||
float lastPosition = 0.0f;
|
||||
for (const auto* stopFrame : mFrames) {
|
||||
void SVGGradientFrame::GetStopFrames(nsTArray<nsIFrame*>* aStopFrames) {
|
||||
nsIFrame* stopFrame = nullptr;
|
||||
for (stopFrame = mFrames.FirstChild(); stopFrame;
|
||||
stopFrame = stopFrame->GetNextSibling()) {
|
||||
if (stopFrame->IsSVGStopFrame()) {
|
||||
aStops->AppendElement(
|
||||
GetStopInformation(stopFrame, aGraphicOpacity, lastPosition));
|
||||
aStopFrames->AppendElement(stopFrame);
|
||||
}
|
||||
}
|
||||
if (aStops->Length() > 0) {
|
||||
if (aStopFrames->Length() > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -393,7 +377,7 @@ void SVGGradientFrame::GetStops(nsTArray<ColorStop>* aStops,
|
||||
|
||||
SVGGradientFrame* next = GetReferencedGradient();
|
||||
if (next) {
|
||||
next->GetStops(aStops, aGraphicOpacity);
|
||||
next->GetStopFrames(aStopFrames);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "gfxMatrix.h"
|
||||
#include "gfxRect.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCSSRenderingGradients.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsLiteralString.h"
|
||||
|
||||
@ -73,7 +72,8 @@ class SVGGradientFrame : public SVGPaintServerFrame {
|
||||
*/
|
||||
SVGGradientFrame* GetReferencedGradient();
|
||||
|
||||
void GetStops(nsTArray<ColorStop>* aStops, float aGraphicOpacity);
|
||||
// Optionally get a stop frame (returns stop index/count)
|
||||
void GetStopFrames(nsTArray<nsIFrame*>* aStopFrames);
|
||||
|
||||
const SVGAnimatedTransformList* GetGradientTransformList(
|
||||
nsIContent* aDefault);
|
||||
|
@ -1,22 +0,0 @@
|
||||
<svg width="100%" height="100%"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml">
|
||||
<g id="testmeta">
|
||||
<title>Gradient with color-interpolation: linearRGB</title>
|
||||
<html:link rel="help"
|
||||
href="https://www.w3.org/TR/SVG2/pservers.html#LinearGradients"/>
|
||||
<html:link rel="match" href="reference/gradient-color-interpolation-ref.svg" />
|
||||
<html:meta name="fuzzy" content="maxDifference=0-20;totalPixels=0-29200" />
|
||||
</g>
|
||||
|
||||
<defs>
|
||||
<linearGradient id="gradientLinearRGB" gradientUnits="objectBoundingBox" color-interpolation="linearRGB">
|
||||
<stop offset="0" stop-color="white"/>
|
||||
<stop offset=".33" stop-color="blue"/>
|
||||
<stop offset=".66" stop-color="red"/>
|
||||
<stop offset="1" stop-color="yellow"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<rect x="20" y="20" width="200" height="200" style="fill:url(#gradientLinearRGB)" />
|
||||
</svg>
|
Before Width: | Height: | Size: 896 B |
@ -1,24 +0,0 @@
|
||||
<svg width="100%" height="100%"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<style>
|
||||
div {
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
};
|
||||
</style>
|
||||
<defs>
|
||||
<linearGradient id="gradientLinearRGB" gradientUnits="objectBoundingBox" color-interpolation="linearRGB">
|
||||
<stop offset="0" stop-color="white"/>
|
||||
<stop offset=".33" stop-color="blue"/>
|
||||
<stop offset=".66" stop-color="red"/>
|
||||
<stop offset="1" stop-color="yellow"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<foreignObject x="20" y="20" width="200" height="200">
|
||||
<html:div style="height:100%;width:100%;background: linear-gradient(90deg in srgb-linear, white 0%, blue 33%, red 66%, yellow 100%);"/>
|
||||
</foreignObject>
|
||||
</svg>
|
Before Width: | Height: | Size: 761 B |
Loading…
Reference in New Issue
Block a user