mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 21:35:39 +00:00
Bug 1347469 - Add support for gradient border. r=mattwoodrow
MozReview-Commit-ID: 7RfVsPFWhlo
This commit is contained in:
parent
d4a7aaf673
commit
5cb5800c6b
@ -1011,27 +1011,42 @@ nsCSSGradientRenderer::Paint(gfxContext& aContext,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsCSSGradientRenderer::BuildWebRenderParameters(float aOpacity,
|
||||
WrGradientExtendMode& aMode,
|
||||
nsTArray<WrGradientStop>& aStops,
|
||||
LayoutDevicePoint& aLineStart,
|
||||
LayoutDevicePoint& aLineEnd,
|
||||
LayoutDeviceSize& aGradientRadius)
|
||||
{
|
||||
bool isRepeat = mGradient->mRepeating || mForceRepeatToCoverTiles;
|
||||
aMode = isRepeat ? WrGradientExtendMode::Repeat : WrGradientExtendMode::Clamp;
|
||||
|
||||
aStops.SetLength(mStops.Length());
|
||||
for(uint32_t i = 0; i < mStops.Length(); i++) {
|
||||
aStops[i].color.r = mStops[i].mColor.r;
|
||||
aStops[i].color.g = mStops[i].mColor.g;
|
||||
aStops[i].color.b = mStops[i].mColor.b;
|
||||
aStops[i].color.a = mStops[i].mColor.a * aOpacity;
|
||||
aStops[i].offset = mStops[i].mPosition;
|
||||
}
|
||||
|
||||
aLineStart = LayoutDevicePoint(mLineStart.x, mLineStart.y);
|
||||
aLineEnd = LayoutDevicePoint(mLineEnd.x, mLineEnd.y);
|
||||
aGradientRadius = LayoutDeviceSize(mRadiusX, mRadiusY);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
LayoutDevicePoint lineStart = LayoutDevicePoint(mLineStart.x, mLineStart.y);
|
||||
LayoutDevicePoint lineEnd = LayoutDevicePoint(mLineEnd.x, mLineEnd.y);
|
||||
LayoutDeviceSize gradientRadius = LayoutDeviceSize(mRadiusX, mRadiusY);
|
||||
WrGradientExtendMode extendMode;
|
||||
nsTArray<WrGradientStop> stops;
|
||||
LayoutDevicePoint lineStart;
|
||||
LayoutDevicePoint lineEnd;
|
||||
LayoutDeviceSize gradientRadius;
|
||||
BuildWebRenderParameters(aOpacity, extendMode, stops, lineStart, lineEnd, gradientRadius);
|
||||
|
||||
// Do a naive tiling of the gradient by making multiple display items
|
||||
// TODO: this should be done on the WebRender side eventually
|
||||
|
@ -57,6 +57,13 @@ public:
|
||||
const nsRect& aDirtyRect,
|
||||
float aOpacity = 1.0);
|
||||
|
||||
void BuildWebRenderParameters(float aOpacity,
|
||||
WrGradientExtendMode& aMode,
|
||||
nsTArray<WrGradientStop>& aStops,
|
||||
LayoutDevicePoint& aLineStart,
|
||||
LayoutDevicePoint& aLineEnd,
|
||||
LayoutDeviceSize& aGradientRadius);
|
||||
|
||||
void BuildWebRenderDisplayItems(wr::DisplayListBuilder& aBuilder,
|
||||
layers::WebRenderDisplayItemLayer* aLayer,
|
||||
float aOpacity = 1.0);
|
||||
|
@ -4610,7 +4610,9 @@ nsDisplayBorder::GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
const nsStyleImage* image = &styleBorder->mBorderImageSource;
|
||||
mBorderRenderer = Nothing();
|
||||
mBorderImageRenderer = Nothing();
|
||||
if ((!image || image->GetType() != eStyleImageType_Image) && !br) {
|
||||
if ((!image ||
|
||||
image->GetType() != eStyleImageType_Image ||
|
||||
image->GetType() != eStyleImageType_Gradient) && !br) {
|
||||
return LAYER_NONE;
|
||||
}
|
||||
|
||||
@ -4728,29 +4730,21 @@ nsDisplayBorder::CreateBorderImageWebRenderCommands(mozilla::wr::DisplayListBuil
|
||||
nsTArray<WebRenderParentCommand>& aParentCommands,
|
||||
WebRenderDisplayItemLayer* aLayer)
|
||||
{
|
||||
// Only support border-image currently
|
||||
MOZ_ASSERT(mBorderImageRenderer);
|
||||
if (!mBorderImageRenderer->mImageRenderer.IsReady()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsDisplayListBuilder* builder = aLayer->GetDisplayListBuilder();
|
||||
uint32_t flags = builder->ShouldSyncDecodeImages() ?
|
||||
imgIContainer::FLAG_SYNC_DECODE :
|
||||
imgIContainer::FLAG_NONE;
|
||||
|
||||
RefPtr<imgIContainer> img = mBorderImageRenderer->mImageRenderer.GetImage();
|
||||
RefPtr<layers::ImageContainer> container = img->GetImageContainer(aLayer->WrManager(), flags);
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t externalImageId = aLayer->SendImageContainer(container);
|
||||
if (!externalImageId) {
|
||||
return;
|
||||
}
|
||||
|
||||
float widths[4];
|
||||
float slice[4];
|
||||
float outset[4];
|
||||
const int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
NS_FOR_CSS_SIDES(i) {
|
||||
slice[i] = (float)(mBorderImageRenderer->mSlice.Side(i)) / appUnitsPerDevPixel;
|
||||
widths[i] = (float)(mBorderImageRenderer->mWidths.Side(i)) / appUnitsPerDevPixel;
|
||||
outset[i] = (float)(mBorderImageRenderer->mImageOutset.Side(i)) / appUnitsPerDevPixel;
|
||||
}
|
||||
|
||||
Rect destRect =
|
||||
NSRectToRect(mBorderImageRenderer->mArea, appUnitsPerDevPixel);
|
||||
Rect destRectTransformed = aLayer->RelativeToParent(destRect);
|
||||
@ -4764,30 +4758,89 @@ nsDisplayBorder::CreateBorderImageWebRenderCommands(mozilla::wr::DisplayListBuil
|
||||
clip = RoundedToInt(clipRectTransformed);
|
||||
}
|
||||
|
||||
float widths[4];
|
||||
float slice[4];
|
||||
float outset[4];
|
||||
NS_FOR_CSS_SIDES(i) {
|
||||
slice[i] = (float)(mBorderImageRenderer->mSlice.Side(i)) / appUnitsPerDevPixel;
|
||||
widths[i] = (float)(mBorderImageRenderer->mWidths.Side(i)) / appUnitsPerDevPixel;
|
||||
outset[i] = (float)(mBorderImageRenderer->mImageOutset.Side(i)) / appUnitsPerDevPixel;
|
||||
}
|
||||
switch (mBorderImageRenderer->mImageRenderer.GetType()) {
|
||||
case eStyleImageType_Image:
|
||||
{
|
||||
nsDisplayListBuilder* builder = aLayer->GetDisplayListBuilder();
|
||||
uint32_t flags = builder->ShouldSyncDecodeImages() ?
|
||||
imgIContainer::FLAG_SYNC_DECODE :
|
||||
imgIContainer::FLAG_NONE;
|
||||
|
||||
WrImageKey key;
|
||||
key.mNamespace = aLayer->WrBridge()->GetNamespace();
|
||||
key.mHandle = aLayer->WrBridge()->GetNextResourceId();
|
||||
aParentCommands.AppendElement(OpAddExternalImage(externalImageId, key));
|
||||
aBuilder.PushBorderImage(wr::ToWrRect(dest),
|
||||
aBuilder.BuildClipRegion(wr::ToWrRect(clip)),
|
||||
wr::ToWrBorderWidths(widths[0], widths[1], widths[2], widths[3]),
|
||||
key,
|
||||
wr::ToWrNinePatchDescriptor(
|
||||
(float)(mBorderImageRenderer->mImageSize.width) / appUnitsPerDevPixel,
|
||||
(float)(mBorderImageRenderer->mImageSize.height) / appUnitsPerDevPixel,
|
||||
wr::ToWrSideOffsets2Du32(slice[0], slice[1], slice[2], slice[3])),
|
||||
wr::ToWrSideOffsets2Df32(outset[0], outset[1], outset[2], outset[3]),
|
||||
wr::ToWrRepeatMode(mBorderImageRenderer->mRepeatModeHorizontal),
|
||||
wr::ToWrRepeatMode(mBorderImageRenderer->mRepeatModeVertical));
|
||||
RefPtr<imgIContainer> img = mBorderImageRenderer->mImageRenderer.GetImage();
|
||||
RefPtr<layers::ImageContainer> container = img->GetImageContainer(aLayer->WrManager(), flags);
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t externalImageId = aLayer->SendImageContainer(container);
|
||||
if (!externalImageId) {
|
||||
return;
|
||||
}
|
||||
|
||||
WrImageKey key;
|
||||
key.mNamespace = aLayer->WrBridge()->GetNamespace();
|
||||
key.mHandle = aLayer->WrBridge()->GetNextResourceId();
|
||||
aParentCommands.AppendElement(OpAddExternalImage(externalImageId, key));
|
||||
aBuilder.PushBorderImage(wr::ToWrRect(dest),
|
||||
aBuilder.BuildClipRegion(wr::ToWrRect(clip)),
|
||||
wr::ToWrBorderWidths(widths[0], widths[1], widths[2], widths[3]),
|
||||
key,
|
||||
wr::ToWrNinePatchDescriptor(
|
||||
(float)(mBorderImageRenderer->mImageSize.width) / appUnitsPerDevPixel,
|
||||
(float)(mBorderImageRenderer->mImageSize.height) / appUnitsPerDevPixel,
|
||||
wr::ToWrSideOffsets2Du32(slice[0], slice[1], slice[2], slice[3])),
|
||||
wr::ToWrSideOffsets2Df32(outset[0], outset[1], outset[2], outset[3]),
|
||||
wr::ToWrRepeatMode(mBorderImageRenderer->mRepeatModeHorizontal),
|
||||
wr::ToWrRepeatMode(mBorderImageRenderer->mRepeatModeVertical));
|
||||
break;
|
||||
}
|
||||
case eStyleImageType_Gradient:
|
||||
{
|
||||
RefPtr<nsStyleGradient> gradientData = mBorderImageRenderer->mImageRenderer.GetGradientData();
|
||||
Maybe<nsCSSGradientRenderer> renderer =
|
||||
nsCSSGradientRenderer::Create(mFrame->PresContext(), gradientData,
|
||||
mBorderImageRenderer->mArea,
|
||||
mBorderImageRenderer->mArea,
|
||||
mBorderImageRenderer->mArea.Size(),
|
||||
CSSIntRect(),
|
||||
mBorderImageRenderer->mImageSize);
|
||||
|
||||
WrGradientExtendMode extendMode;
|
||||
nsTArray<WrGradientStop> stops;
|
||||
LayoutDevicePoint lineStart;
|
||||
LayoutDevicePoint lineEnd;
|
||||
LayoutDeviceSize gradientRadius;
|
||||
renderer->BuildWebRenderParameters(1.0, extendMode, stops, lineStart, lineEnd, gradientRadius);
|
||||
|
||||
if (gradientData->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR) {
|
||||
Point startPoint = dest.TopLeft();
|
||||
startPoint = startPoint + Point(lineStart.x, lineStart.y);
|
||||
Point endPoint = dest.TopLeft();
|
||||
endPoint = endPoint + Point(lineEnd.x, lineEnd.y);
|
||||
|
||||
aBuilder.PushBorderGradient(wr::ToWrRect(dest),
|
||||
aBuilder.BuildClipRegion(wr::ToWrRect(clip)),
|
||||
wr::ToWrBorderWidths(widths[0], widths[1], widths[2], widths[3]),
|
||||
wr::ToWrPoint(startPoint),
|
||||
wr::ToWrPoint(endPoint),
|
||||
stops,
|
||||
extendMode,
|
||||
wr::ToWrSideOffsets2Df32(outset[0], outset[1], outset[2], outset[3]));
|
||||
} else {
|
||||
aBuilder.PushBorderRadialGradient(wr::ToWrRect(dest),
|
||||
aBuilder.BuildClipRegion(wr::ToWrRect(clip)),
|
||||
wr::ToWrBorderWidths(widths[0], widths[1], widths[2], widths[3]),
|
||||
wr::ToWrPoint(lineStart),
|
||||
wr::ToWrSize(gradientRadius),
|
||||
stops,
|
||||
extendMode,
|
||||
wr::ToWrSideOffsets2Df32(outset[0], outset[1], outset[2], outset[3]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unsupport border image type");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -999,3 +999,10 @@ nsImageRenderer::PurgeCacheForViewportChange(
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<nsStyleGradient>
|
||||
nsImageRenderer::GetGradientData()
|
||||
{
|
||||
RefPtr<nsStyleGradient> res = mGradientData;
|
||||
return res.forget();
|
||||
}
|
||||
|
||||
|
@ -262,6 +262,8 @@ public:
|
||||
void SetMaskOp(uint8_t aMaskOp) { mMaskOp = aMaskOp; }
|
||||
void PurgeCacheForViewportChange(const mozilla::Maybe<nsSize>& aSVGViewportSize,
|
||||
const bool aHasRatio);
|
||||
nsStyleImageType GetType() const { return mType; }
|
||||
already_AddRefed<nsStyleGradient> GetGradientData();
|
||||
|
||||
private:
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user