зеркало из https://github.com/mozilla/gecko-dev.git
Bug 841601 - Add background-blend-mode implementation. r=roc
This commit is contained in:
Родитель
56504fb58d
Коммит
b360983fd3
|
@ -320,6 +320,30 @@ static nscolor MakeBevelColor(mozilla::css::Side whichSide, uint8_t style,
|
|||
nscolor aBackgroundColor,
|
||||
nscolor aBorderColor);
|
||||
|
||||
static gfxContext::GraphicsOperator GetGFXBlendMode(uint8_t mBlendMode)
|
||||
{
|
||||
switch (mBlendMode) {
|
||||
case NS_STYLE_BLEND_NORMAL: return gfxContext::OPERATOR_OVER;
|
||||
case NS_STYLE_BLEND_MULTIPLY: return gfxContext::OPERATOR_MULTIPLY;
|
||||
case NS_STYLE_BLEND_SCREEN: return gfxContext::OPERATOR_SCREEN;
|
||||
case NS_STYLE_BLEND_OVERLAY: return gfxContext::OPERATOR_OVERLAY;
|
||||
case NS_STYLE_BLEND_DARKEN: return gfxContext::OPERATOR_DARKEN;
|
||||
case NS_STYLE_BLEND_LIGHTEN: return gfxContext::OPERATOR_LIGHTEN;
|
||||
case NS_STYLE_BLEND_COLOR_DODGE: return gfxContext::OPERATOR_COLOR_DODGE;
|
||||
case NS_STYLE_BLEND_COLOR_BURN: return gfxContext::OPERATOR_COLOR_BURN;
|
||||
case NS_STYLE_BLEND_HARD_LIGHT: return gfxContext::OPERATOR_HARD_LIGHT;
|
||||
case NS_STYLE_BLEND_SOFT_LIGHT: return gfxContext::OPERATOR_SOFT_LIGHT;
|
||||
case NS_STYLE_BLEND_DIFFERENCE: return gfxContext::OPERATOR_DIFFERENCE;
|
||||
case NS_STYLE_BLEND_EXCLUSION: return gfxContext::OPERATOR_EXCLUSION;
|
||||
case NS_STYLE_BLEND_HUE: return gfxContext::OPERATOR_HUE;
|
||||
case NS_STYLE_BLEND_SATURATION: return gfxContext::OPERATOR_SATURATION;
|
||||
case NS_STYLE_BLEND_COLOR: return gfxContext::OPERATOR_COLOR;
|
||||
case NS_STYLE_BLEND_LUMINOSITY: return gfxContext::OPERATOR_LUMINOSITY;
|
||||
}
|
||||
|
||||
return gfxContext::OPERATOR_OVER;
|
||||
}
|
||||
|
||||
static InlineBackgroundData* gInlineBGData = nullptr;
|
||||
|
||||
// Initialize any static variables used by nsCSSRendering.
|
||||
|
@ -2561,10 +2585,18 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
|
|||
nsBackgroundLayerState state = PrepareBackgroundLayer(aPresContext, aForFrame,
|
||||
aFlags, aBorderArea, clipState.mBGClipArea, *bg, layer);
|
||||
if (!state.mFillArea.IsEmpty()) {
|
||||
if (state.mCompositingOp != gfxContext::OPERATOR_OVER) {
|
||||
NS_ASSERTION(ctx->CurrentOperator() == gfxContext::OPERATOR_OVER,
|
||||
"It is assumed the initial operator is OPERATOR_OVER, when it is restored later");
|
||||
ctx->SetOperator(state.mCompositingOp);
|
||||
}
|
||||
state.mImageRenderer.DrawBackground(aPresContext, aRenderingContext,
|
||||
state.mDestArea, state.mFillArea,
|
||||
state.mAnchor + aBorderArea.TopLeft(),
|
||||
clipState.mDirtyRect);
|
||||
if (state.mCompositingOp != gfxContext::OPERATOR_OVER) {
|
||||
ctx->SetOperator(gfxContext::OPERATOR_OVER);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2856,6 +2888,7 @@ nsCSSRendering::PrepareBackgroundLayer(nsPresContext* aPresContext,
|
|||
* background-origin
|
||||
* background-size
|
||||
* background-break (-moz-background-inline-policy)
|
||||
* background-blend-mode
|
||||
*
|
||||
* (background-color applies to the entire element and not to individual
|
||||
* layers, so it is irrelevant to this method.)
|
||||
|
@ -2978,6 +3011,9 @@ nsCSSRendering::PrepareBackgroundLayer(nsPresContext* aPresContext,
|
|||
state.mFillArea.height = bgClipRect.height;
|
||||
}
|
||||
state.mFillArea.IntersectRect(state.mFillArea, bgClipRect);
|
||||
|
||||
state.mCompositingOp = GetGFXBlendMode(aLayer.mBlendMode);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
|
|
@ -213,7 +213,7 @@ struct nsBackgroundLayerState {
|
|||
* @param aFlags some combination of nsCSSRendering::PAINTBG_* flags
|
||||
*/
|
||||
nsBackgroundLayerState(nsIFrame* aForFrame, const nsStyleImage* aImage, uint32_t aFlags)
|
||||
: mImageRenderer(aForFrame, aImage, aFlags) {}
|
||||
: mImageRenderer(aForFrame, aImage, aFlags), mCompositingOp(gfxContext::OPERATOR_OVER) {}
|
||||
|
||||
/**
|
||||
* The nsImageRenderer that will be used to draw the background.
|
||||
|
@ -237,6 +237,10 @@ struct nsBackgroundLayerState {
|
|||
* PrepareBackgroundLayer.
|
||||
*/
|
||||
nsPoint mAnchor;
|
||||
/**
|
||||
* The compositing operation that the image should use
|
||||
*/
|
||||
gfxContext::GraphicsOperator mCompositingOp;
|
||||
};
|
||||
|
||||
struct nsCSSRendering {
|
||||
|
|
|
@ -1739,11 +1739,15 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
|
|||
drawBackgroundImage, drawBackgroundColor);
|
||||
}
|
||||
|
||||
// An auxiliary list is necessary in case we have background blending; if that
|
||||
// is the case, background items need to be wrapped by a blend container to
|
||||
// isolate blending to the background
|
||||
nsDisplayList bgItemList;
|
||||
// Even if we don't actually have a background color to paint, we may still need
|
||||
// to create an item for hit testing.
|
||||
if ((drawBackgroundColor && color != NS_RGBA(0,0,0,0)) ||
|
||||
aBuilder->IsForEventDelivery()) {
|
||||
aList->AppendNewToTop(
|
||||
bgItemList.AppendNewToTop(
|
||||
new (aBuilder) nsDisplayBackgroundColor(aBuilder, aFrame, bg,
|
||||
drawBackgroundColor ? color : NS_RGBA(0, 0, 0, 0)));
|
||||
}
|
||||
|
@ -1751,25 +1755,40 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
|
|||
if (isThemed) {
|
||||
nsDisplayThemedBackground* bgItem =
|
||||
new (aBuilder) nsDisplayThemedBackground(aBuilder, aFrame);
|
||||
aList->AppendNewToTop(bgItem);
|
||||
bgItemList.AppendNewToTop(bgItem);
|
||||
aList->AppendToTop(&bgItemList);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!bg) {
|
||||
aList->AppendToTop(&bgItemList);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool needBlendContainer = false;
|
||||
|
||||
// Passing bg == nullptr in this macro will result in one iteration with
|
||||
// i = 0.
|
||||
NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
|
||||
if (bg->mLayers[i].mImage.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bg->mLayers[i].mBlendMode != NS_STYLE_BLEND_NORMAL) {
|
||||
needBlendContainer = true;
|
||||
}
|
||||
|
||||
nsDisplayBackgroundImage* bgItem =
|
||||
new (aBuilder) nsDisplayBackgroundImage(aBuilder, aFrame, i, bg);
|
||||
aList->AppendNewToTop(bgItem);
|
||||
bgItemList.AppendNewToTop(bgItem);
|
||||
}
|
||||
|
||||
if (needBlendContainer) {
|
||||
bgItemList.AppendNewToTop(
|
||||
new (aBuilder) nsDisplayBlendContainer(aBuilder, aFrame, &bgItemList));
|
||||
}
|
||||
|
||||
aList->AppendToTop(&bgItemList);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2091,7 +2110,7 @@ nsDisplayBackgroundImage::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
|||
if (mBackgroundStyle->mBackgroundInlinePolicy == NS_STYLE_BG_INLINE_POLICY_EACH_BOX ||
|
||||
(!mFrame->GetPrevContinuation() && !mFrame->GetNextContinuation())) {
|
||||
const nsStyleBackground::Layer& layer = mBackgroundStyle->mLayers[mLayer];
|
||||
if (layer.mImage.IsOpaque()) {
|
||||
if (layer.mImage.IsOpaque() && layer.mBlendMode == NS_STYLE_BLEND_NORMAL) {
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
result = GetInsideClipRegion(this, presContext, layer.mClip, mBounds, aSnap);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче