Bug 1341101 part 3 - Support building WR gradients in nsCSSGradientRenderer r=mattwoodrow

MozReview-Commit-ID: HLSmseHj5Si

--HG--
extra : rebase_source : b8e39ba51c6ab28a2c9ed7b694e5098e50bf022c
This commit is contained in:
Ryan Hunt 2017-03-15 03:20:02 -04:00
Родитель 6e1c6e32b8
Коммит cfc9025674
3 изменённых файлов: 153 добавлений и 42 удалений

Просмотреть файл

@ -162,6 +162,61 @@ static inline WrColor ToWrColor(const gfx::Color& color)
return c;
}
template<class T>
static inline WrPoint ToWrPoint(const gfx::PointTyped<T>& point)
{
WrPoint p;
p.x = point.x;
p.y = point.y;
return p;
}
template<class T>
static inline WrPoint ToWrPoint(const gfx::IntPointTyped<T>& point)
{
return ToWrPoint(IntPointToPoint(point));
}
static inline WrPoint ToWrPoint(const gfx::Point& point)
{
WrPoint p;
p.x = point.x;
p.y = point.y;
return p;
}
template<class T>
static inline WrRect ToWrRect(const gfx::RectTyped<T>& rect)
{
WrRect r;
r.x = rect.x;
r.y = rect.y;
r.width = rect.width;
r.height = rect.height;
return r;
}
template<class T>
static inline WrRect ToWrRect(const gfx::IntRectTyped<T>& rect)
{
return ToWrRect(IntRectToRect(rect));
}
template<class T>
static inline WrSize ToWrSize(const gfx::SizeTyped<T>& size)
{
WrSize ls;
ls.width = size.width;
ls.height = size.height;
return ls;
}
template<class T>
static inline WrSize ToWrSize(const gfx::IntSizeTyped<T>& size)
{
return ToWrSize(IntSizeToSize(size));
}
static inline WrBorderStyle ToWrBorderStyle(const uint8_t& style)
{
switch (style) {
@ -199,22 +254,6 @@ static inline WrBorderSide ToWrBorderSide(const gfx::Color& color, const uint8_t
return bs;
}
static inline WrPoint ToWrPoint(const LayerPoint point)
{
WrPoint lp;
lp.x = point.x;
lp.y = point.y;
return lp;
}
static inline WrSize ToWrSize(const LayerSize size)
{
WrSize ls;
ls.width = size.width;
ls.height = size.height;
return ls;
}
static inline WrBorderRadius ToWrUniformBorderRadius(const LayerSize& aSize)
{
WrBorderRadius br;
@ -294,23 +333,6 @@ static inline WrRepeatMode ToWrRepeatMode(uint8_t repeatMode)
return WrRepeatMode::Stretch;
}
template<class T>
static inline WrRect ToWrRect(const gfx::RectTyped<T>& rect)
{
WrRect r;
r.x = rect.x;
r.y = rect.y;
r.width = rect.width;
r.height = rect.height;
return r;
}
template<class T>
static inline WrRect ToWrRect(const gfx::IntRectTyped<T>& rect)
{
return ToWrRect(IntRectToRect(rect));
}
template<class T>
static inline WrComplexClipRegion ToWrComplexClipRegion(const gfx::RectTyped<T>& rect,
const LayerSize& size)
@ -321,14 +343,6 @@ static inline WrComplexClipRegion ToWrComplexClipRegion(const gfx::RectTyped<T>&
return complex_clip;
}
static inline WrPoint ToWrPoint(const gfx::Point& point)
{
WrPoint p;
p.x = point.x;
p.y = point.y;
return p;
}
static inline WrExternalImageId ToWrExternalImageId(uint64_t aID)
{
WrExternalImageId id;

Просмотреть файл

@ -29,6 +29,11 @@
#include "gfxUtils.h"
#include "gfxGradientCache.h"
#include "mozilla/layers/WebRenderLayerManager.h"
#include "mozilla/webrender/WebRenderTypes.h"
#include "mozilla/webrender/WebRenderAPI.h"
#include "Units.h"
using namespace mozilla;
using namespace mozilla::gfx;
@ -1003,4 +1008,84 @@ nsCSSGradientRenderer::Paint(gfxContext& aContext,
}
}
void
nsCSSGradientRenderer::BuildWebRenderDisplayItems(wr::DisplayListBuilder& aBuilder,
layers::WebRenderDisplayItemLayer* aLayer,
float aOpacity)
{
bool isRepeat = mGradient->mRepeating || mForceRepeatToCoverTiles;
WrGradientExtendMode extendMode = isRepeat ? WrGradientExtendMode::Repeat : WrGradientExtendMode::Clamp;
nsTArray<WrGradientStop> stops(mStops.Length());
stops.SetLength(mStops.Length());
for(uint32_t i = 0; i < mStops.Length(); i++) {
stops[i].color.r = mStops[i].mColor.r;
stops[i].color.g = mStops[i].mColor.g;
stops[i].color.b = mStops[i].mColor.b;
stops[i].color.a = mStops[i].mColor.a * aOpacity;
stops[i].offset = mStops[i].mPosition;
}
double firstStop = mStops[0].mPosition;
double lastStop = mStops[mStops.Length() - 1].mPosition;
LayoutDevicePoint lineStart = LayoutDevicePoint(mLineStart.x, mLineStart.y);
LayoutDevicePoint lineEnd = LayoutDevicePoint(mLineEnd.x, mLineEnd.y);
// Do a naive tiling of the gradient by making multiple display items
// TODO: this should be done on the WebRender side eventually
nscoord appUnitsPerDevPixel = mPresContext->AppUnitsPerDevPixel();
LayoutDeviceRect firstTileBounds = LayoutDevicePixel::FromAppUnits(mDest, appUnitsPerDevPixel);
LayoutDeviceRect clipBounds = LayoutDevicePixel::FromAppUnits(mFillArea, appUnitsPerDevPixel);
// Make the units relative to the parent stacking context
firstTileBounds = LayoutDeviceRect::FromUnknownRect(aLayer->RelativeToParent(firstTileBounds.ToUnknownRect()));
clipBounds = LayoutDeviceRect::FromUnknownRect(aLayer->RelativeToParent(clipBounds.ToUnknownRect()));
float xStart = 0;
float yStart = 0;
float xEnd = (mFillArea.XMost() - mDest.X()) / appUnitsPerDevPixel;
float yEnd = (mFillArea.YMost() - mDest.Y()) / appUnitsPerDevPixel;
float stepX = mRepeatSize.width / appUnitsPerDevPixel;
float stepY = mRepeatSize.height / appUnitsPerDevPixel;
for (float y = yStart; y < yEnd; y += stepY) {
for (float x = xStart; x < xEnd; x += stepX) {
LayoutDevicePoint tileOffset = firstTileBounds.TopLeft() + LayoutDevicePoint(x, y);
LayoutDeviceRect tileRect = LayoutDeviceRect(tileOffset, firstTileBounds.Size());
if (mGradient->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR) {
LayoutDevicePoint relativeGradientStart = lineStart + tileOffset;
LayoutDevicePoint relativeGradientEnd = lineEnd + tileOffset;
aBuilder.PushLinearGradient(
mozilla::wr::ToWrRect(tileRect),
aBuilder.BuildClipRegion(mozilla::wr::ToWrRect(clipBounds)),
mozilla::wr::ToWrPoint(relativeGradientStart),
mozilla::wr::ToWrPoint(relativeGradientEnd),
stops,
extendMode);
} else {
LayoutDevicePoint relativeGradientCenter = lineStart + tileOffset;
// TODO: ellipse gradients
double innerRadius = mRadiusX * firstStop;
double outerRadius = mRadiusX * lastStop;
aBuilder.PushRadialGradient(
mozilla::wr::ToWrRect(tileRect),
aBuilder.BuildClipRegion(mozilla::wr::ToWrRect(clipBounds)),
mozilla::wr::ToWrPoint(relativeGradientCenter),
mozilla::wr::ToWrPoint(relativeGradientCenter),
innerRadius,
outerRadius,
stops,
extendMode);
}
}
}
}
} // namespace mozilla

Просмотреть файл

@ -13,6 +13,14 @@
namespace mozilla {
namespace layers {
class WebRenderDisplayItemLayer;
} // namespace layers
namespace wr {
class DisplayListBuilder;
}
// A resolved color stop, with a specific position along the gradient line and
// a color.
struct ColorStop {
@ -48,6 +56,10 @@ public:
const nsRect& aDirtyRect,
float aOpacity = 1.0);
void BuildWebRenderDisplayItems(wr::DisplayListBuilder& aBuilder,
layers::WebRenderDisplayItemLayer* aLayer,
float aOpacity = 1.0);
private:
nsCSSGradientRenderer() {}
@ -60,7 +72,7 @@ private:
nsSize mRepeatSize;
nsTArray<ColorStop> mStops;
gfxPoint mLineStart, mLineEnd;
double mRadiusX, mRadiusY; // for radial gradients only
double mRadiusX, mRadiusY;
bool mForceRepeatToCoverTiles;
bool mForceRepeatToCoverTilesFlip;
};