mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-08 16:58:38 +09:00
issue #908 - implement missing parts of CSS mask
This commit is contained in:
parent
7b5e5f85de
commit
b5376e63c5
28 changed files with 574 additions and 449 deletions
|
|
@ -1803,6 +1803,44 @@ SetupDirtyRects(const nsRect& aBGClipArea, const nsRect& aCallerDirtyRect,
|
|||
"second should be empty if first is");
|
||||
}
|
||||
|
||||
static bool
|
||||
IsSVGStyleGeometryBox(StyleGeometryBox aBox)
|
||||
{
|
||||
return (aBox == StyleGeometryBox::Fill || aBox == StyleGeometryBox::Stroke ||
|
||||
aBox == StyleGeometryBox::View);
|
||||
}
|
||||
|
||||
static bool
|
||||
IsHTMLStyleGeometryBox(StyleGeometryBox aBox)
|
||||
{
|
||||
return (aBox == StyleGeometryBox::Content ||
|
||||
aBox == StyleGeometryBox::Padding ||
|
||||
aBox == StyleGeometryBox::Border ||
|
||||
aBox == StyleGeometryBox::Margin);
|
||||
}
|
||||
|
||||
static StyleGeometryBox
|
||||
ComputeBoxValue(nsIFrame* aForFrame, StyleGeometryBox aBox)
|
||||
{
|
||||
// Except <svg>, all svg elements are not associate with CSS layout box.
|
||||
if (aForFrame->IsFrameOfType(nsIFrame::eSVG) &&
|
||||
(aForFrame->GetType() != nsGkAtoms::svgOuterSVGFrame)) {
|
||||
// For SVG elements without associated CSS layout box, the values
|
||||
// content-box, padding-box, border-box and margin-box compute to fill-box.
|
||||
if (IsHTMLStyleGeometryBox(aBox)) {
|
||||
return StyleGeometryBox::Fill;
|
||||
}
|
||||
} else {
|
||||
// For elements with associated CSS layout box, the values fill-box,
|
||||
// stroke-box and view-box compute to the initial value of mask-clip.
|
||||
if (IsSVGStyleGeometryBox(aBox)) {
|
||||
return StyleGeometryBox::Border;
|
||||
}
|
||||
}
|
||||
|
||||
return aBox;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsCSSRendering::GetImageLayerClip(const nsStyleImageLayers::Layer& aLayer,
|
||||
nsIFrame* aForFrame, const nsStyleBorder& aBorder,
|
||||
|
|
@ -1810,6 +1848,55 @@ nsCSSRendering::GetImageLayerClip(const nsStyleImageLayers::Layer& aLayer,
|
|||
bool aWillPaintBorder, nscoord aAppUnitsPerPixel,
|
||||
/* out */ ImageLayerClipState* aClipState)
|
||||
{
|
||||
StyleGeometryBox layerClip = ComputeBoxValue(aForFrame, aLayer.mClip);
|
||||
|
||||
if (IsSVGStyleGeometryBox(layerClip)) {
|
||||
MOZ_ASSERT(aForFrame->IsFrameOfType(nsIFrame::eSVG) &&
|
||||
(aForFrame->GetType() != nsGkAtoms::svgOuterSVGFrame));
|
||||
|
||||
aClipState->mHasAdditionalBGClipArea = false;
|
||||
aClipState->mCustomClip = false;
|
||||
|
||||
// The coordinate space of clipArea is svg user space.
|
||||
nsRect clipArea =
|
||||
nsLayoutUtils::ComputeGeometryBox(aForFrame, layerClip);
|
||||
|
||||
nsRect strokeBox = (layerClip == StyleGeometryBox::Stroke)
|
||||
? clipArea
|
||||
: nsLayoutUtils::ComputeGeometryBox(aForFrame, StyleGeometryBox::Stroke);
|
||||
nsRect clipAreaRelativeToStrokeBox = clipArea - strokeBox.TopLeft();
|
||||
|
||||
// aBorderArea is the stroke-box area in a coordinate space defined by
|
||||
// the caller. This coordinate space can be svg user space of aForFrame,
|
||||
// the space of aForFrame's reference-frame, or anything else.
|
||||
//
|
||||
// Which coordinate space chosen for aBorderArea is not matter. What
|
||||
// matter is to ensure returning aClipState->mBGClipArea in the consistent
|
||||
// coordiante space with aBorderArea. So we evaluate the position of clip
|
||||
// area base on the position of aBorderArea here.
|
||||
aClipState->mBGClipArea =
|
||||
clipAreaRelativeToStrokeBox + aBorderArea.TopLeft();
|
||||
|
||||
SetupDirtyRects(aClipState->mBGClipArea, aCallerDirtyRect,
|
||||
aAppUnitsPerPixel, &aClipState->mDirtyRect,
|
||||
&aClipState->mDirtyRectGfx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (layerClip == StyleGeometryBox::NoClip) {
|
||||
aClipState->mBGClipArea = aCallerDirtyRect;
|
||||
aClipState->mHasAdditionalBGClipArea = false;
|
||||
aClipState->mCustomClip = false;
|
||||
|
||||
SetupDirtyRects(aClipState->mBGClipArea, aCallerDirtyRect,
|
||||
aAppUnitsPerPixel, &aClipState->mDirtyRect,
|
||||
&aClipState->mDirtyRectGfx);
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!aForFrame->IsFrameOfType(nsIFrame::eSVG) ||
|
||||
aForFrame->GetType() == nsGkAtoms::svgOuterSVGFrame);
|
||||
|
||||
// Compute the outermost boundary of the area that might be painted.
|
||||
// Same coordinate space as aBorderArea.
|
||||
Sides skipSides = aForFrame->GetSkipSides();
|
||||
|
|
@ -1819,16 +1906,15 @@ nsCSSRendering::GetImageLayerClip(const nsStyleImageLayers::Layer& aLayer,
|
|||
bool haveRoundedCorners = GetRadii(aForFrame, aBorder, aBorderArea,
|
||||
clipBorderArea, aClipState->mRadii);
|
||||
|
||||
uint8_t backgroundClip = aLayer.mClip;
|
||||
|
||||
bool isSolidBorder =
|
||||
aWillPaintBorder && IsOpaqueBorder(aBorder);
|
||||
if (isSolidBorder && backgroundClip == NS_STYLE_IMAGELAYER_CLIP_BORDER) {
|
||||
if (isSolidBorder && layerClip == StyleGeometryBox::Border) {
|
||||
// If we have rounded corners, we need to inflate the background
|
||||
// drawing area a bit to avoid seams between the border and
|
||||
// background.
|
||||
backgroundClip = haveRoundedCorners ?
|
||||
NS_STYLE_IMAGELAYER_CLIP_MOZ_ALMOST_PADDING : NS_STYLE_IMAGELAYER_CLIP_PADDING;
|
||||
layerClip = haveRoundedCorners
|
||||
? StyleGeometryBox::MozAlmostPadding
|
||||
: StyleGeometryBox::Padding;
|
||||
}
|
||||
|
||||
aClipState->mBGClipArea = clipBorderArea;
|
||||
|
|
@ -1844,7 +1930,7 @@ nsCSSRendering::GetImageLayerClip(const nsStyleImageLayers::Layer& aLayer,
|
|||
// but the background is also clipped at a non-scrolling 'padding-box'
|
||||
// like the content. (See below.)
|
||||
// Therefore, only 'content-box' makes a difference here.
|
||||
if (backgroundClip == NS_STYLE_IMAGELAYER_CLIP_CONTENT) {
|
||||
if (layerClip == StyleGeometryBox::Content) {
|
||||
nsIScrollableFrame* scrollableFrame = do_QueryFrame(aForFrame);
|
||||
// Clip at a rectangle attached to the scrolled content.
|
||||
aClipState->mHasAdditionalBGClipArea = true;
|
||||
|
|
@ -1864,22 +1950,30 @@ nsCSSRendering::GetImageLayerClip(const nsStyleImageLayers::Layer& aLayer,
|
|||
|
||||
// Also clip at a non-scrolling, rounded-corner 'padding-box',
|
||||
// same as the scrolled content because of the 'overflow' property.
|
||||
backgroundClip = NS_STYLE_IMAGELAYER_CLIP_PADDING;
|
||||
layerClip = StyleGeometryBox::Padding;
|
||||
}
|
||||
|
||||
if (backgroundClip != NS_STYLE_IMAGELAYER_CLIP_BORDER &&
|
||||
backgroundClip != NS_STYLE_IMAGELAYER_CLIP_TEXT) {
|
||||
// See the comment of StyleGeometryBox::Margin.
|
||||
// Hitting this assertion means we decide to turn on margin-box support for
|
||||
// positioned mask from CSS parser and style system. In this case, you
|
||||
// should *inflate* mBGClipArea by the margin returning from
|
||||
// aForFrame->GetUsedMargin() in the code chunk bellow.
|
||||
MOZ_ASSERT(layerClip != StyleGeometryBox::Margin,
|
||||
"StyleGeometryBox::Margin rendering is not supported yet.\n");
|
||||
|
||||
if (layerClip != StyleGeometryBox::Border &&
|
||||
layerClip != StyleGeometryBox::Text) {
|
||||
nsMargin border = aForFrame->GetUsedBorder();
|
||||
if (backgroundClip == NS_STYLE_IMAGELAYER_CLIP_MOZ_ALMOST_PADDING) {
|
||||
if (layerClip == StyleGeometryBox::MozAlmostPadding) {
|
||||
// Reduce |border| by 1px (device pixels) on all sides, if
|
||||
// possible, so that we don't get antialiasing seams between the
|
||||
// background and border.
|
||||
// {background|mask} and border.
|
||||
border.top = std::max(0, border.top - aAppUnitsPerPixel);
|
||||
border.right = std::max(0, border.right - aAppUnitsPerPixel);
|
||||
border.bottom = std::max(0, border.bottom - aAppUnitsPerPixel);
|
||||
border.left = std::max(0, border.left - aAppUnitsPerPixel);
|
||||
} else if (backgroundClip != NS_STYLE_IMAGELAYER_CLIP_PADDING) {
|
||||
NS_ASSERTION(backgroundClip == NS_STYLE_IMAGELAYER_CLIP_CONTENT,
|
||||
} else if (layerClip != StyleGeometryBox::Padding) {
|
||||
NS_ASSERTION(layerClip == StyleGeometryBox::Content,
|
||||
"unexpected background-clip");
|
||||
border += aForFrame->GetUsedPadding();
|
||||
}
|
||||
|
|
@ -3163,7 +3257,7 @@ nsCSSRendering::PaintBackgroundWithSC(const PaintBGParams& aParams,
|
|||
|
||||
if (drawBackgroundImage) {
|
||||
bool clipSet = false;
|
||||
uint8_t currentBackgroundClip = NS_STYLE_IMAGELAYER_CLIP_BORDER;
|
||||
StyleGeometryBox currentBackgroundClip = StyleGeometryBox::Border;
|
||||
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT_WITH_RANGE(i, layers, layers.mImageCount - 1,
|
||||
nLayers + (layers.mImageCount -
|
||||
startLayer - 1)) {
|
||||
|
|
@ -3239,16 +3333,43 @@ nsCSSRendering::ComputeImageLayerPositioningArea(nsPresContext* aPresContext,
|
|||
nsIFrame** aAttachedToFrame,
|
||||
bool* aOutIsTransformedFixed)
|
||||
{
|
||||
// Compute background origin area relative to aBorderArea now as we may need
|
||||
// it to compute the effective image size for a CSS gradient.
|
||||
nsRect bgPositioningArea;
|
||||
// Compute {background|mask} origin area relative to aBorderArea now as we
|
||||
// may need it to compute the effective image size for a CSS gradient.
|
||||
nsRect positionArea;
|
||||
|
||||
StyleGeometryBox layerOrigin =
|
||||
ComputeBoxValue(aForFrame, aLayer.mOrigin);
|
||||
|
||||
if (IsSVGStyleGeometryBox(layerOrigin)) {
|
||||
MOZ_ASSERT(aForFrame->IsFrameOfType(nsIFrame::eSVG) &&
|
||||
(aForFrame->GetType() != nsGkAtoms::svgOuterSVGFrame));
|
||||
*aAttachedToFrame = aForFrame;
|
||||
|
||||
positionArea =
|
||||
nsLayoutUtils::ComputeGeometryBox(aForFrame, layerOrigin);
|
||||
|
||||
nsPoint toStrokeBoxOffset = nsPoint(0, 0);
|
||||
if (layerOrigin != StyleGeometryBox::Stroke) {
|
||||
nsRect strokeBox =
|
||||
nsLayoutUtils::ComputeGeometryBox(aForFrame,
|
||||
StyleGeometryBox::Stroke);
|
||||
toStrokeBoxOffset = positionArea.TopLeft() - strokeBox.TopLeft();
|
||||
}
|
||||
|
||||
// For SVG frames, the return value is relative to the stroke box
|
||||
return nsRect(toStrokeBoxOffset, positionArea.Size());
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!aForFrame->IsFrameOfType(nsIFrame::eSVG) ||
|
||||
aForFrame->GetType() == nsGkAtoms::svgOuterSVGFrame);
|
||||
|
||||
|
||||
nsIAtom* frameType = aForFrame->GetType();
|
||||
nsIFrame* geometryFrame = aForFrame;
|
||||
if (MOZ_UNLIKELY(frameType == nsGkAtoms::scrollFrame &&
|
||||
NS_STYLE_IMAGELAYER_ATTACHMENT_LOCAL == aLayer.mAttachment)) {
|
||||
nsIScrollableFrame* scrollableFrame = do_QueryFrame(aForFrame);
|
||||
bgPositioningArea = nsRect(
|
||||
positionArea = nsRect(
|
||||
scrollableFrame->GetScrolledFrame()->GetPosition()
|
||||
// For the dir=rtl case:
|
||||
+ scrollableFrame->GetScrollRange().TopLeft(),
|
||||
|
|
@ -3256,20 +3377,20 @@ nsCSSRendering::ComputeImageLayerPositioningArea(nsPresContext* aPresContext,
|
|||
// The ScrolledRect’s size does not include the borders or scrollbars,
|
||||
// reverse the handling of background-origin
|
||||
// compared to the common case below.
|
||||
if (aLayer.mOrigin == NS_STYLE_IMAGELAYER_ORIGIN_BORDER) {
|
||||
if (layerOrigin == StyleGeometryBox::Border) {
|
||||
nsMargin border = geometryFrame->GetUsedBorder();
|
||||
border.ApplySkipSides(geometryFrame->GetSkipSides());
|
||||
bgPositioningArea.Inflate(border);
|
||||
bgPositioningArea.Inflate(scrollableFrame->GetActualScrollbarSizes());
|
||||
} else if (aLayer.mOrigin != NS_STYLE_IMAGELAYER_ORIGIN_PADDING) {
|
||||
positionArea.Inflate(border);
|
||||
positionArea.Inflate(scrollableFrame->GetActualScrollbarSizes());
|
||||
} else if (layerOrigin != StyleGeometryBox::Padding) {
|
||||
nsMargin padding = geometryFrame->GetUsedPadding();
|
||||
padding.ApplySkipSides(geometryFrame->GetSkipSides());
|
||||
bgPositioningArea.Deflate(padding);
|
||||
NS_ASSERTION(aLayer.mOrigin == NS_STYLE_IMAGELAYER_ORIGIN_CONTENT,
|
||||
positionArea.Deflate(padding);
|
||||
NS_ASSERTION(layerOrigin == StyleGeometryBox::Content,
|
||||
"unknown background-origin value");
|
||||
}
|
||||
*aAttachedToFrame = aForFrame;
|
||||
return bgPositioningArea;
|
||||
return positionArea;
|
||||
}
|
||||
|
||||
if (MOZ_UNLIKELY(frameType == nsGkAtoms::canvasFrame)) {
|
||||
|
|
@ -3279,25 +3400,31 @@ nsCSSRendering::ComputeImageLayerPositioningArea(nsPresContext* aPresContext,
|
|||
// finished and this page only displays the continuations of
|
||||
// absolutely positioned content).
|
||||
if (geometryFrame) {
|
||||
bgPositioningArea = geometryFrame->GetRect();
|
||||
positionArea = geometryFrame->GetRect();
|
||||
}
|
||||
} else {
|
||||
bgPositioningArea = nsRect(nsPoint(0,0), aBorderArea.Size());
|
||||
positionArea = nsRect(nsPoint(0,0), aBorderArea.Size());
|
||||
}
|
||||
|
||||
// Background images are tiled over the 'background-clip' area
|
||||
// but the origin of the tiling is based on the 'background-origin' area
|
||||
// XXX: Bug 1303623 will bring in new origin value, we should iterate from
|
||||
// NS_STYLE_IMAGELAYER_ORIGIN_MARGIN instead of
|
||||
// NS_STYLE_IMAGELAYER_ORIGIN_BORDER.
|
||||
if (aLayer.mOrigin != NS_STYLE_IMAGELAYER_ORIGIN_BORDER && geometryFrame) {
|
||||
// See the comment of StyleGeometryBox::Margin.
|
||||
// Hitting this assertion means we decide to turn on margin-box support for
|
||||
// positioned mask from CSS parser and style system. In this case, you
|
||||
// should *inflate* positionArea by the margin returning from
|
||||
// geometryFrame->GetUsedMargin() in the code chunk bellow.
|
||||
MOZ_ASSERT(aLayer.mOrigin != StyleGeometryBox::Margin,
|
||||
"StyleGeometryBox::Margin rendering is not supported yet.\n");
|
||||
|
||||
// {background|mask} images are tiled over the '{background|mask}-clip' area
|
||||
// but the origin of the tiling is based on the '{background|mask}-origin'
|
||||
// area.
|
||||
if (layerOrigin != StyleGeometryBox::Border && geometryFrame) {
|
||||
nsMargin border = geometryFrame->GetUsedBorder();
|
||||
if (aLayer.mOrigin != NS_STYLE_IMAGELAYER_ORIGIN_PADDING) {
|
||||
if (layerOrigin != StyleGeometryBox::Padding) {
|
||||
border += geometryFrame->GetUsedPadding();
|
||||
NS_ASSERTION(aLayer.mOrigin == NS_STYLE_IMAGELAYER_ORIGIN_CONTENT,
|
||||
NS_ASSERTION(layerOrigin == StyleGeometryBox::Content,
|
||||
"unknown background-origin value");
|
||||
}
|
||||
bgPositioningArea.Deflate(border);
|
||||
positionArea.Deflate(border);
|
||||
}
|
||||
|
||||
nsIFrame* attachedToFrame = aForFrame;
|
||||
|
|
@ -3325,7 +3452,7 @@ nsCSSRendering::ComputeImageLayerPositioningArea(nsPresContext* aPresContext,
|
|||
} else {
|
||||
// Set the background positioning area to the viewport's area
|
||||
// (relative to aForFrame)
|
||||
bgPositioningArea =
|
||||
positionArea =
|
||||
nsRect(-aForFrame->GetOffsetTo(attachedToFrame), attachedToFrame->GetSize());
|
||||
|
||||
if (!pageContentFrame) {
|
||||
|
|
@ -3334,14 +3461,14 @@ nsCSSRendering::ComputeImageLayerPositioningArea(nsPresContext* aPresContext,
|
|||
aPresContext->PresShell()->GetRootScrollFrameAsScrollable();
|
||||
if (scrollableFrame) {
|
||||
nsMargin scrollbars = scrollableFrame->GetActualScrollbarSizes();
|
||||
bgPositioningArea.Deflate(scrollbars);
|
||||
positionArea.Deflate(scrollbars);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*aAttachedToFrame = attachedToFrame;
|
||||
|
||||
return bgPositioningArea;
|
||||
return positionArea;
|
||||
}
|
||||
|
||||
// Implementation of the formula for computation of background-repeat round
|
||||
|
|
@ -3569,7 +3696,7 @@ nsCSSRendering::PrepareImageLayer(nsPresContext* aPresContext,
|
|||
bool transformedFixed = false;
|
||||
// Compute background origin area relative to aBorderArea now as we may need
|
||||
// it to compute the effective image size for a CSS gradient.
|
||||
nsRect bgPositioningArea =
|
||||
nsRect positionArea =
|
||||
ComputeImageLayerPositioningArea(aPresContext, aForFrame, aBorderArea,
|
||||
aLayer, &attachedToFrame, &transformedFixed);
|
||||
if (aOutIsTransformedFixed) {
|
||||
|
|
@ -3594,7 +3721,7 @@ nsCSSRendering::PrepareImageLayer(nsPresContext* aPresContext,
|
|||
// not a pure optimization since it can affect the values of pixels at the
|
||||
// edge of the viewport --- whether they're sampled from a putative "next
|
||||
// tile" or not.)
|
||||
bgClipRect.IntersectRect(bgClipRect, bgPositioningArea + aBorderArea.TopLeft());
|
||||
bgClipRect.IntersectRect(bgClipRect, positionArea + aBorderArea.TopLeft());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3605,7 +3732,7 @@ nsCSSRendering::PrepareImageLayer(nsPresContext* aPresContext,
|
|||
// Also as required for proper background positioning when background-position
|
||||
// is defined with percentages.
|
||||
CSSSizeOrRatio intrinsicSize = state.mImageRenderer.ComputeIntrinsicSize();
|
||||
nsSize bgPositionSize = bgPositioningArea.Size();
|
||||
nsSize bgPositionSize = positionArea.Size();
|
||||
nsSize imageSize = ComputeDrawnSizeForBackground(intrinsicSize,
|
||||
bgPositionSize,
|
||||
aLayer.mSize,
|
||||
|
|
@ -3650,8 +3777,8 @@ nsCSSRendering::PrepareImageLayer(nsPresContext* aPresContext,
|
|||
}
|
||||
}
|
||||
|
||||
imageTopLeft += bgPositioningArea.TopLeft();
|
||||
state.mAnchor += bgPositioningArea.TopLeft();
|
||||
imageTopLeft += positionArea.TopLeft();
|
||||
state.mAnchor += positionArea.TopLeft();
|
||||
state.mDestArea = nsRect(imageTopLeft + aBorderArea.TopLeft(), imageSize);
|
||||
state.mFillArea = state.mDestArea;
|
||||
|
||||
|
|
|
|||
|
|
@ -3014,7 +3014,7 @@ nsDisplayBackgroundImage::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
/* static */ nsRegion
|
||||
nsDisplayBackgroundImage::GetInsideClipRegion(nsDisplayItem* aItem,
|
||||
uint8_t aClip,
|
||||
StyleGeometryBox aClip,
|
||||
const nsRect& aRect,
|
||||
const nsRect& aBackgroundRect)
|
||||
{
|
||||
|
|
@ -3028,10 +3028,10 @@ nsDisplayBackgroundImage::GetInsideClipRegion(nsDisplayItem* aItem,
|
|||
if (frame->GetType() == nsGkAtoms::canvasFrame) {
|
||||
nsCanvasFrame* canvasFrame = static_cast<nsCanvasFrame*>(frame);
|
||||
clipRect = canvasFrame->CanvasArea() + aItem->ToReferenceFrame();
|
||||
} else if (aClip == NS_STYLE_IMAGELAYER_CLIP_PADDING ||
|
||||
aClip == NS_STYLE_IMAGELAYER_CLIP_CONTENT) {
|
||||
} else if (aClip == StyleGeometryBox::Padding ||
|
||||
aClip == StyleGeometryBox::Content) {
|
||||
nsMargin border = frame->GetUsedBorder();
|
||||
if (aClip == NS_STYLE_IMAGELAYER_CLIP_CONTENT) {
|
||||
if (aClip == StyleGeometryBox::Content) {
|
||||
border += frame->GetUsedPadding();
|
||||
}
|
||||
border.ApplySkipSides(frame->GetSkipSides());
|
||||
|
|
@ -3064,7 +3064,7 @@ nsDisplayBackgroundImage::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
|||
if (layer.mImage.IsOpaque() && layer.mBlendMode == NS_STYLE_BLEND_NORMAL &&
|
||||
layer.mRepeat.mXRepeat != NS_STYLE_IMAGELAYER_REPEAT_SPACE &&
|
||||
layer.mRepeat.mYRepeat != NS_STYLE_IMAGELAYER_REPEAT_SPACE &&
|
||||
layer.mClip != NS_STYLE_IMAGELAYER_CLIP_TEXT) {
|
||||
layer.mClip != StyleGeometryBox::Text) {
|
||||
result = GetInsideClipRegion(this, layer.mClip, mBounds, mBackgroundRect);
|
||||
}
|
||||
}
|
||||
|
|
@ -3143,9 +3143,9 @@ nsDisplayBackgroundImage::PaintInternal(nsDisplayListBuilder* aBuilder,
|
|||
CheckForBorderItem(this, flags);
|
||||
|
||||
gfxContext* ctx = aCtx->ThebesContext();
|
||||
uint8_t clip = mBackgroundStyle->mImage.mLayers[mLayer].mClip;
|
||||
StyleGeometryBox clip = mBackgroundStyle->mImage.mLayers[mLayer].mClip;
|
||||
|
||||
if (clip == NS_STYLE_IMAGELAYER_CLIP_TEXT) {
|
||||
if (clip == StyleGeometryBox::Text) {
|
||||
if (!GenerateAndPushTextMask(mFrame, aCtx, mBackgroundRect, aBuilder)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -3161,7 +3161,7 @@ nsDisplayBackgroundImage::PaintInternal(nsDisplayListBuilder* aBuilder,
|
|||
image::DrawResult result =
|
||||
nsCSSRendering::PaintBackground(params);
|
||||
|
||||
if (clip == NS_STYLE_IMAGELAYER_CLIP_TEXT) {
|
||||
if (clip == StyleGeometryBox::Text) {
|
||||
ctx->PopGroupAndBlend();
|
||||
}
|
||||
|
||||
|
|
@ -3583,8 +3583,8 @@ nsDisplayBackgroundColor::Paint(nsDisplayListBuilder* aBuilder,
|
|||
nsLayoutUtils::RectToGfxRect(mBackgroundRect,
|
||||
mFrame->PresContext()->AppUnitsPerDevPixel());
|
||||
|
||||
uint8_t clip = mBackgroundStyle->mImage.mLayers[0].mClip;
|
||||
if (clip == NS_STYLE_IMAGELAYER_CLIP_TEXT) {
|
||||
StyleGeometryBox clip = mBackgroundStyle->mImage.mLayers[0].mClip;
|
||||
if (clip == StyleGeometryBox::Text) {
|
||||
if (!GenerateAndPushTextMask(mFrame, aCtx, mBackgroundRect, aBuilder)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -3618,7 +3618,7 @@ nsDisplayBackgroundColor::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
|
||||
const nsStyleImageLayers::Layer& bottomLayer = mBackgroundStyle->BottomLayer();
|
||||
if (bottomLayer.mClip == NS_STYLE_IMAGELAYER_CLIP_TEXT) {
|
||||
if (bottomLayer.mClip == StyleGeometryBox::Text) {
|
||||
return nsRegion();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2713,6 +2713,8 @@ private:
|
|||
*/
|
||||
class nsDisplayBackgroundImage : public nsDisplayImageContainer {
|
||||
public:
|
||||
typedef mozilla::StyleGeometryBox StyleGeometryBox;
|
||||
|
||||
/**
|
||||
* aLayer signifies which background layer this item represents.
|
||||
* aIsThemed should be the value of aFrame->IsThemed.
|
||||
|
|
@ -2790,8 +2792,10 @@ public:
|
|||
virtual already_AddRefed<imgIContainer> GetImage() override;
|
||||
virtual nsRect GetDestRect() override;
|
||||
|
||||
static nsRegion GetInsideClipRegion(nsDisplayItem* aItem, uint8_t aClip,
|
||||
const nsRect& aRect, const nsRect& aBackgroundRect);
|
||||
static nsRegion GetInsideClipRegion(nsDisplayItem* aItem,
|
||||
StyleGeometryBox aClip,
|
||||
const nsRect& aRect,
|
||||
const nsRect& aBackgroundRect);
|
||||
|
||||
virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@
|
|||
#include "mozilla/StyleSetHandle.h"
|
||||
#include "mozilla/StyleSetHandleInlines.h"
|
||||
#include "RegionBuilder.h"
|
||||
#include "SVGSVGElement.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsXULPopupManager.h"
|
||||
|
|
@ -6935,7 +6936,7 @@ nsLayoutUtils::GetFrameTransparency(nsIFrame* aBackgroundFrame,
|
|||
const nsStyleBackground* bg = bgSC->StyleBackground();
|
||||
if (NS_GET_A(bg->mBackgroundColor) < 255 ||
|
||||
// bottom layer's clip is used for the color
|
||||
bg->BottomLayer().mClip != NS_STYLE_IMAGELAYER_CLIP_BORDER)
|
||||
bg->BottomLayer().mClip != StyleGeometryBox::Border)
|
||||
return eTransparencyTransparent;
|
||||
return eTransparencyOpaque;
|
||||
}
|
||||
|
|
@ -9293,3 +9294,127 @@ nsLayoutUtils::IsInvisibleBreak(nsINode* aNode, nsIFrame** aNextLineFrame)
|
|||
|
||||
return lineNonEmpty;
|
||||
}
|
||||
|
||||
static nsRect
|
||||
ComputeSVGReferenceRect(nsIFrame* aFrame,
|
||||
StyleGeometryBox aGeometryBox)
|
||||
{
|
||||
MOZ_ASSERT(aFrame->GetContent()->IsSVGElement());
|
||||
nsRect r;
|
||||
|
||||
// For SVG elements without associated CSS layout box, the used value for
|
||||
// content-box, padding-box, border-box and margin-box is fill-box.
|
||||
switch (aGeometryBox) {
|
||||
case StyleGeometryBox::Stroke: {
|
||||
// XXX Bug 1299876
|
||||
// The size of srtoke-box is not correct if this graphic element has
|
||||
// specific stroke-linejoin or stroke-linecap.
|
||||
gfxRect bbox = nsSVGUtils::GetBBox(aFrame,
|
||||
nsSVGUtils::eBBoxIncludeFill | nsSVGUtils::eBBoxIncludeStroke);
|
||||
r = nsLayoutUtils::RoundGfxRectToAppRect(bbox,
|
||||
nsPresContext::AppUnitsPerCSSPixel());
|
||||
break;
|
||||
}
|
||||
case StyleGeometryBox::View: {
|
||||
nsIContent* content = aFrame->GetContent();
|
||||
nsSVGElement* element = static_cast<nsSVGElement*>(content);
|
||||
SVGSVGElement* svgElement = element->GetCtx();
|
||||
MOZ_ASSERT(svgElement);
|
||||
|
||||
if (svgElement && svgElement->HasViewBoxRect()) {
|
||||
// If a ‘viewBox‘ attribute is specified for the SVG viewport creating
|
||||
// element:
|
||||
// 1. The reference box is positioned at the origin of the coordinate
|
||||
// system established by the ‘viewBox‘ attribute.
|
||||
// 2. The dimension of the reference box is set to the width and height
|
||||
// values of the ‘viewBox‘ attribute.
|
||||
nsSVGViewBox* viewBox = svgElement->GetViewBox();
|
||||
const nsSVGViewBoxRect& value = viewBox->GetAnimValue();
|
||||
r = nsRect(nsPresContext::CSSPixelsToAppUnits(value.x),
|
||||
nsPresContext::CSSPixelsToAppUnits(value.y),
|
||||
nsPresContext::CSSPixelsToAppUnits(value.width),
|
||||
nsPresContext::CSSPixelsToAppUnits(value.height));
|
||||
} else {
|
||||
// No viewBox is specified, uses the nearest SVG viewport as reference
|
||||
// box.
|
||||
svgFloatSize viewportSize = svgElement->GetViewportSize();
|
||||
r = nsRect(0, 0,
|
||||
nsPresContext::CSSPixelsToAppUnits(viewportSize.width),
|
||||
nsPresContext::CSSPixelsToAppUnits(viewportSize.height));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case StyleGeometryBox::NoBox:
|
||||
case StyleGeometryBox::Border:
|
||||
case StyleGeometryBox::Content:
|
||||
case StyleGeometryBox::Padding:
|
||||
case StyleGeometryBox::Margin:
|
||||
case StyleGeometryBox::Fill: {
|
||||
gfxRect bbox = nsSVGUtils::GetBBox(aFrame,
|
||||
nsSVGUtils::eBBoxIncludeFill);
|
||||
r = nsLayoutUtils::RoundGfxRectToAppRect(bbox,
|
||||
nsPresContext::AppUnitsPerCSSPixel());
|
||||
break;
|
||||
}
|
||||
default:{
|
||||
MOZ_ASSERT_UNREACHABLE("unknown StyleGeometryBox type");
|
||||
gfxRect bbox = nsSVGUtils::GetBBox(aFrame,
|
||||
nsSVGUtils::eBBoxIncludeFill);
|
||||
r = nsLayoutUtils::RoundGfxRectToAppRect(bbox,
|
||||
nsPresContext::AppUnitsPerCSSPixel());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static nsRect
|
||||
ComputeHTMLReferenceRect(nsIFrame* aFrame,
|
||||
StyleGeometryBox aGeometryBox)
|
||||
{
|
||||
nsRect r;
|
||||
|
||||
// For elements with associated CSS layout box, the used value for fill-box,
|
||||
// stroke-box and view-box is border-box.
|
||||
switch (aGeometryBox) {
|
||||
case StyleGeometryBox::Content:
|
||||
r = aFrame->GetContentRectRelativeToSelf();
|
||||
break;
|
||||
case StyleGeometryBox::Padding:
|
||||
r = aFrame->GetPaddingRectRelativeToSelf();
|
||||
break;
|
||||
case StyleGeometryBox::Margin:
|
||||
r = aFrame->GetMarginRectRelativeToSelf();
|
||||
break;
|
||||
case StyleGeometryBox::NoBox:
|
||||
case StyleGeometryBox::Border:
|
||||
case StyleGeometryBox::Fill:
|
||||
case StyleGeometryBox::Stroke:
|
||||
case StyleGeometryBox::View:
|
||||
r = aFrame->GetRectRelativeToSelf();
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("unknown StyleGeometryBox type");
|
||||
r = aFrame->GetRectRelativeToSelf();
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* static */ nsRect
|
||||
nsLayoutUtils::ComputeGeometryBox(nsIFrame* aFrame,
|
||||
StyleGeometryBox aGeometryBox)
|
||||
{
|
||||
// We use ComputeSVGReferenceRect for all SVG elements, except <svg>
|
||||
// element, which does have an associated CSS layout box. In this case we
|
||||
// should still use ComputeHTMLReferenceRect for region computing.
|
||||
nsRect r = aFrame->IsFrameOfType(nsIFrame::eSVG) &&
|
||||
(aFrame->GetType() != nsGkAtoms::svgOuterSVGFrame)
|
||||
? ComputeSVGReferenceRect(aFrame, aGeometryBox)
|
||||
: ComputeHTMLReferenceRect(aFrame, aGeometryBox);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "mozilla/ReflowOutput.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "nsStyleConsts.h"
|
||||
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
|
|
@ -152,6 +153,7 @@ public:
|
|||
typedef mozilla::CSSRect CSSRect;
|
||||
typedef mozilla::ScreenMargin ScreenMargin;
|
||||
typedef mozilla::LayoutDeviceIntSize LayoutDeviceIntSize;
|
||||
typedef mozilla::StyleGeometryBox StyleGeometryBox;
|
||||
|
||||
/**
|
||||
* Finds previously assigned ViewID for the given content element, if any.
|
||||
|
|
@ -2870,6 +2872,9 @@ public:
|
|||
*/
|
||||
static bool IsInvisibleBreak(nsINode* aNode, nsIFrame** aNextLineFrame = nullptr);
|
||||
|
||||
static nsRect ComputeGeometryBox(nsIFrame* aFrame,
|
||||
StyleGeometryBox aGeometryBox);
|
||||
|
||||
private:
|
||||
static uint32_t sFontSizeInflationEmPerLine;
|
||||
static uint32_t sFontSizeInflationMinTwips;
|
||||
|
|
|
|||
|
|
@ -6715,7 +6715,7 @@ ShouldDrawSelection(const nsIFrame* aFrame)
|
|||
const nsStyleBackground* bg = aFrame->StyleContext()->StyleBackground();
|
||||
const nsStyleImageLayers& layers = bg->mImage;
|
||||
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, layers) {
|
||||
if (layers.mLayers[i].mClip == NS_STYLE_IMAGELAYER_CLIP_TEXT) {
|
||||
if (layers.mLayers[i].mClip == StyleGeometryBox::Text) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -784,12 +784,10 @@ PropertySupportsVariant(nsCSSPropertyID aPropertyID, uint32_t aVariant)
|
|||
case eCSSProperty_background_position_x:
|
||||
case eCSSProperty_background_position_y:
|
||||
case eCSSProperty_background_size:
|
||||
#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
|
||||
case eCSSProperty_mask_position:
|
||||
case eCSSProperty_mask_position_x:
|
||||
case eCSSProperty_mask_position_y:
|
||||
case eCSSProperty_mask_size:
|
||||
#endif
|
||||
case eCSSProperty_grid_auto_columns:
|
||||
case eCSSProperty_grid_auto_rows:
|
||||
case eCSSProperty_grid_template_columns:
|
||||
|
|
|
|||
|
|
@ -395,28 +395,25 @@ Declaration::GetImageLayerValue(
|
|||
origin->mValue.GetUnit() == eCSSUnit_Enumerated,
|
||||
"should not have inherit/initial within list");
|
||||
|
||||
int32_t originDefaultValue =
|
||||
StyleGeometryBox originDefaultValue =
|
||||
(aTable == nsStyleImageLayers::kBackgroundLayerTable)
|
||||
? NS_STYLE_IMAGELAYER_ORIGIN_PADDING : NS_STYLE_IMAGELAYER_ORIGIN_BORDER;
|
||||
if (clip->mValue.GetIntValue() != NS_STYLE_IMAGELAYER_CLIP_BORDER ||
|
||||
origin->mValue.GetIntValue() != originDefaultValue) {
|
||||
? StyleGeometryBox::Padding : StyleGeometryBox::Border;
|
||||
if (static_cast<StyleGeometryBox>(clip->mValue.GetIntValue()) !=
|
||||
StyleGeometryBox::Border ||
|
||||
static_cast<StyleGeometryBox>(origin->mValue.GetIntValue()) !=
|
||||
originDefaultValue) {
|
||||
#ifdef DEBUG
|
||||
for (size_t i = 0; nsCSSProps::kImageLayerOriginKTable[i].mValue != -1; i++) {
|
||||
const nsCSSProps::KTableEntry* originTable =
|
||||
nsCSSProps::kKeywordTableTable[aTable[nsStyleImageLayers::origin]];
|
||||
const nsCSSProps::KTableEntry* clipTable =
|
||||
nsCSSProps::kKeywordTableTable[aTable[nsStyleImageLayers::clip]];
|
||||
for (size_t i = 0; originTable[i].mValue != -1; i++) {
|
||||
// For each keyword & value in kOriginKTable, ensure that
|
||||
// kBackgroundKTable has a matching entry at the same position.
|
||||
MOZ_ASSERT(nsCSSProps::kImageLayerOriginKTable[i].mKeyword ==
|
||||
nsCSSProps::kBackgroundClipKTable[i].mKeyword);
|
||||
MOZ_ASSERT(nsCSSProps::kImageLayerOriginKTable[i].mValue ==
|
||||
nsCSSProps::kBackgroundClipKTable[i].mValue);
|
||||
MOZ_ASSERT(originTable[i].mKeyword == clipTable[i].mKeyword);
|
||||
MOZ_ASSERT(originTable[i].mValue == clipTable[i].mValue);
|
||||
}
|
||||
#endif
|
||||
static_assert(NS_STYLE_IMAGELAYER_CLIP_BORDER ==
|
||||
NS_STYLE_IMAGELAYER_ORIGIN_BORDER &&
|
||||
NS_STYLE_IMAGELAYER_CLIP_PADDING ==
|
||||
NS_STYLE_IMAGELAYER_ORIGIN_PADDING &&
|
||||
NS_STYLE_IMAGELAYER_CLIP_CONTENT ==
|
||||
NS_STYLE_IMAGELAYER_ORIGIN_CONTENT,
|
||||
"mask-clip and mask-origin style constants must agree");
|
||||
aValue.Append(char16_t(' '));
|
||||
origin->mValue.AppendToString(aTable[nsStyleImageLayers::origin], aValue,
|
||||
aSerialization);
|
||||
|
|
@ -462,11 +459,7 @@ Declaration::GetImageLayerValue(
|
|||
}
|
||||
// This layer is an mask layer
|
||||
} else {
|
||||
#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
|
||||
MOZ_ASSERT(aTable == nsStyleImageLayers::kMaskLayerTable);
|
||||
#else
|
||||
MOZ_ASSERT_UNREACHABLE("Should never get here when mask-as-shorthand is disable");
|
||||
#endif
|
||||
if (repeat || positionX || positionY || clip || origin || size ||
|
||||
composite || mode) {
|
||||
// Uneven length lists, so can't be serialized as shorthand.
|
||||
|
|
@ -487,11 +480,7 @@ Declaration::GetImageLayerValue(
|
|||
}
|
||||
// This layer is an mask layer
|
||||
} else {
|
||||
#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
|
||||
MOZ_ASSERT(aTable == nsStyleImageLayers::kMaskLayerTable);
|
||||
#else
|
||||
MOZ_ASSERT_UNREACHABLE("Should never get here when mask-as-shorthand is disable");
|
||||
#endif
|
||||
if (!repeat || !positionX || !positionY || !clip || !origin || !size ||
|
||||
!composite || !mode) {
|
||||
// Uneven length lists, so can't be serialized as shorthand.
|
||||
|
|
@ -817,7 +806,6 @@ Declaration::GetPropertyValueInternal(
|
|||
nsStyleImageLayers::kBackgroundLayerTable);
|
||||
break;
|
||||
}
|
||||
#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
|
||||
case eCSSProperty_mask: {
|
||||
GetImageLayerValue(data, aValue, aSerialization,
|
||||
nsStyleImageLayers::kMaskLayerTable);
|
||||
|
|
@ -828,7 +816,6 @@ Declaration::GetPropertyValueInternal(
|
|||
nsStyleImageLayers::kMaskLayerTable);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case eCSSProperty_font: {
|
||||
// systemFont might not be present; other values are guaranteed to be
|
||||
// available based on the shorthand check at the beginning of the
|
||||
|
|
|
|||
|
|
@ -4255,7 +4255,6 @@ StyleAnimationValue::ExtractComputedValue(nsCSSPropertyID aProperty,
|
|||
|
||||
|
||||
}
|
||||
#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
|
||||
case eCSSProperty_mask_position_x: {
|
||||
const nsStyleImageLayers& layers =
|
||||
static_cast<const nsStyleSVGReset*>(styleStruct)->mMask;
|
||||
|
|
@ -4269,21 +4268,18 @@ StyleAnimationValue::ExtractComputedValue(nsCSSPropertyID aProperty,
|
|||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case eCSSProperty_background_size: {
|
||||
const nsStyleImageLayers& layers =
|
||||
static_cast<const nsStyleBackground*>(styleStruct)->mImage;
|
||||
ExtractImageLayerSizePairList(layers, aComputedValue);
|
||||
break;
|
||||
}
|
||||
#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
|
||||
case eCSSProperty_mask_size: {
|
||||
const nsStyleImageLayers& layers =
|
||||
static_cast<const nsStyleSVGReset*>(styleStruct)->mMask;
|
||||
ExtractImageLayerSizePairList(layers, aComputedValue);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case eCSSProperty_clip_path: {
|
||||
const nsStyleSVGReset* svgReset =
|
||||
|
|
|
|||
|
|
@ -61,7 +61,6 @@ TryToStartImageLoadOnValue(const nsCSSValue& aValue, nsIDocument* aDocument,
|
|||
MOZ_ASSERT(aDocument);
|
||||
|
||||
if (aValue.GetUnit() == eCSSUnit_URL) {
|
||||
#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
|
||||
// The 'mask-image' property accepts local reference URIs.
|
||||
// For example,
|
||||
// mask-image: url(#mask_id); // refer to a SVG mask element, whose id is
|
||||
|
|
@ -94,7 +93,6 @@ TryToStartImageLoadOnValue(const nsCSSValue& aValue, nsIDocument* aDocument,
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
aValue.StartImageLoad(aDocument);
|
||||
if (aForTokenStream && aContext) {
|
||||
CSSVariableImageTable::Add(aContext, aProperty,
|
||||
|
|
|
|||
|
|
@ -405,6 +405,7 @@ CSS_KEY(n-resize, n_resize)
|
|||
CSS_KEY(narrower, narrower)
|
||||
CSS_KEY(ne-resize, ne_resize)
|
||||
CSS_KEY(nesw-resize, nesw_resize)
|
||||
CSS_KEY(no-clip, no_clip)
|
||||
CSS_KEY(no-close-quote, no_close_quote)
|
||||
CSS_KEY(no-common-ligatures, no_common_ligatures)
|
||||
CSS_KEY(no-contextual, no_contextual)
|
||||
|
|
|
|||
|
|
@ -12005,7 +12005,6 @@ CSSParserImpl::ParsePropertyByFunction(nsCSSPropertyID aPropID)
|
|||
return ParsePaintOrder();
|
||||
case eCSSProperty_scroll_snap_type:
|
||||
return ParseScrollSnapType();
|
||||
#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
|
||||
case eCSSProperty_mask:
|
||||
return ParseImageLayers(nsStyleImageLayers::kMaskLayerTable);
|
||||
case eCSSProperty_mask_repeat:
|
||||
|
|
@ -12018,7 +12017,6 @@ CSSParserImpl::ParsePropertyByFunction(nsCSSPropertyID aPropID)
|
|||
aPropID == eCSSProperty_mask_position_x);
|
||||
case eCSSProperty_mask_size:
|
||||
return ParseImageLayerSize(eCSSProperty_mask_size);
|
||||
#endif
|
||||
case eCSSProperty__webkit_text_stroke:
|
||||
return ParseWebkitTextStroke();
|
||||
case eCSSProperty_all:
|
||||
|
|
@ -12424,7 +12422,7 @@ CSSParserImpl::ParseImageLayersItem(
|
|||
aState.mImage->mValue.SetNoneValue();
|
||||
aState.mAttachment->mValue.SetIntValue(NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL,
|
||||
eCSSUnit_Enumerated);
|
||||
aState.mClip->mValue.SetIntValue(NS_STYLE_IMAGELAYER_CLIP_BORDER,
|
||||
aState.mClip->mValue.SetIntValue(StyleGeometryBox::Border,
|
||||
eCSSUnit_Enumerated);
|
||||
|
||||
aState.mRepeat->mXValue.SetIntValue(NS_STYLE_IMAGELAYER_REPEAT_REPEAT,
|
||||
|
|
@ -12437,10 +12435,10 @@ CSSParserImpl::ParseImageLayersItem(
|
|||
aState.mPositionY->mValue.SetArrayValue(positionYArr, eCSSUnit_Array);
|
||||
|
||||
if (eCSSProperty_mask == aTable[nsStyleImageLayers::shorthand]) {
|
||||
aState.mOrigin->mValue.SetIntValue(NS_STYLE_IMAGELAYER_ORIGIN_BORDER,
|
||||
aState.mOrigin->mValue.SetIntValue(StyleGeometryBox::Border,
|
||||
eCSSUnit_Enumerated);
|
||||
} else {
|
||||
aState.mOrigin->mValue.SetIntValue(NS_STYLE_IMAGELAYER_ORIGIN_PADDING,
|
||||
aState.mOrigin->mValue.SetIntValue(StyleGeometryBox::Padding,
|
||||
eCSSUnit_Enumerated);
|
||||
}
|
||||
positionXArr->Item(1).SetPercentValue(0.0f);
|
||||
|
|
@ -12462,6 +12460,8 @@ CSSParserImpl::ParseImageLayersItem(
|
|||
haveMode = false,
|
||||
haveSomething = false;
|
||||
|
||||
const KTableEntry* originTable =
|
||||
nsCSSProps::kKeywordTableTable[aTable[nsStyleImageLayers::origin]];
|
||||
while (GetToken(true)) {
|
||||
nsCSSTokenType tt = mToken.mType;
|
||||
UngetToken(); // ...but we'll still cheat and use mToken
|
||||
|
|
@ -12531,8 +12531,7 @@ CSSParserImpl::ParseImageLayersItem(
|
|||
aState.mSize->mXValue = scratch.mXValue;
|
||||
aState.mSize->mYValue = scratch.mYValue;
|
||||
}
|
||||
} else if (nsCSSProps::FindKeyword(keyword,
|
||||
nsCSSProps::kImageLayerOriginKTable, dummy)) {
|
||||
} else if (nsCSSProps::FindKeyword(keyword, originTable, dummy)) {
|
||||
if (haveOrigin)
|
||||
return false;
|
||||
haveOrigin = true;
|
||||
|
|
@ -12547,23 +12546,15 @@ CSSParserImpl::ParseImageLayersItem(
|
|||
// immediately following the first one (for background-origin).
|
||||
|
||||
#ifdef DEBUG
|
||||
for (size_t i = 0; nsCSSProps::kImageLayerOriginKTable[i].mValue != -1; i++) {
|
||||
const KTableEntry* clipTable =
|
||||
nsCSSProps::kKeywordTableTable[aTable[nsStyleImageLayers::clip]];
|
||||
for (size_t i = 0; originTable[i].mValue != -1; i++) {
|
||||
// For each keyword & value in kOriginKTable, ensure that
|
||||
// kBackgroundKTable has a matching entry at the same position.
|
||||
MOZ_ASSERT(nsCSSProps::kImageLayerOriginKTable[i].mKeyword ==
|
||||
nsCSSProps::kBackgroundClipKTable[i].mKeyword);
|
||||
MOZ_ASSERT(nsCSSProps::kImageLayerOriginKTable[i].mValue ==
|
||||
nsCSSProps::kBackgroundClipKTable[i].mValue);
|
||||
MOZ_ASSERT(originTable[i].mKeyword == clipTable[i].mKeyword);
|
||||
MOZ_ASSERT(originTable[i].mValue == clipTable[i].mValue);
|
||||
}
|
||||
#endif
|
||||
static_assert(NS_STYLE_IMAGELAYER_CLIP_BORDER ==
|
||||
NS_STYLE_IMAGELAYER_ORIGIN_BORDER &&
|
||||
NS_STYLE_IMAGELAYER_CLIP_PADDING ==
|
||||
NS_STYLE_IMAGELAYER_ORIGIN_PADDING &&
|
||||
NS_STYLE_IMAGELAYER_CLIP_CONTENT ==
|
||||
NS_STYLE_IMAGELAYER_ORIGIN_CONTENT,
|
||||
"bg-clip and bg-origin style constants must agree");
|
||||
|
||||
CSSParseResult result =
|
||||
ParseSingleValueProperty(aState.mClip->mValue,
|
||||
aTable[nsStyleImageLayers::clip]);
|
||||
|
|
|
|||
|
|
@ -453,7 +453,6 @@ CSS_PROP_ALIAS(-webkit-user-select,
|
|||
WebkitUserSelect,
|
||||
WEBKIT_PREFIX_PREF)
|
||||
|
||||
#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
|
||||
CSS_PROP_ALIAS(-webkit-mask,
|
||||
mask,
|
||||
WebkitMask,
|
||||
|
|
@ -494,5 +493,4 @@ CSS_PROP_ALIAS(-webkit-mask-size,
|
|||
mask_size,
|
||||
WebkitMaskSize,
|
||||
WEBKIT_PREFIX_PREF)
|
||||
#endif
|
||||
#undef WEBKIT_PREFIX_PREF
|
||||
|
|
|
|||
|
|
@ -564,7 +564,7 @@ CSS_PROP_BACKGROUND(
|
|||
CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
|
||||
"",
|
||||
VARIANT_KEYWORD, // used by list parsing
|
||||
kImageLayerOriginKTable,
|
||||
kBackgroundOriginKTable,
|
||||
CSS_PROP_NO_OFFSET,
|
||||
eStyleAnimType_Discrete)
|
||||
CSS_PROP_SHORTHAND(
|
||||
|
|
@ -2645,19 +2645,6 @@ CSS_PROP_SVG(
|
|||
nullptr,
|
||||
CSS_PROP_NO_OFFSET,
|
||||
eStyleAnimType_Discrete)
|
||||
#ifndef MOZ_ENABLE_MASK_AS_SHORTHAND
|
||||
CSS_PROP_SVGRESET(
|
||||
mask,
|
||||
mask,
|
||||
Mask,
|
||||
CSS_PROPERTY_PARSE_VALUE |
|
||||
CSS_PROPERTY_CREATES_STACKING_CONTEXT,
|
||||
"",
|
||||
VARIANT_HUO,
|
||||
nullptr,
|
||||
CSS_PROP_NO_OFFSET,
|
||||
eStyleAnimType_Discrete)
|
||||
#else
|
||||
CSS_PROP_SHORTHAND(
|
||||
mask,
|
||||
mask,
|
||||
|
|
@ -2672,7 +2659,7 @@ CSS_PROP_SVGRESET(
|
|||
CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
|
||||
"",
|
||||
VARIANT_KEYWORD, // used by list parsing
|
||||
kImageLayerOriginKTable,
|
||||
kMaskClipKTable,
|
||||
CSS_PROP_NO_OFFSET,
|
||||
eStyleAnimType_Discrete)
|
||||
CSS_PROP_SVGRESET(
|
||||
|
|
@ -2718,7 +2705,7 @@ CSS_PROP_SVGRESET(
|
|||
CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
|
||||
"",
|
||||
VARIANT_KEYWORD, // used by list parsing
|
||||
kImageLayerOriginKTable,
|
||||
kMaskOriginKTable,
|
||||
CSS_PROP_NO_OFFSET,
|
||||
eStyleAnimType_Discrete)
|
||||
CSS_PROP_SHORTHAND(
|
||||
|
|
@ -2776,7 +2763,6 @@ CSS_PROP_SVGRESET(
|
|||
kImageLayerSizeKTable,
|
||||
CSS_PROP_NO_OFFSET,
|
||||
eStyleAnimType_Custom)
|
||||
#endif // MOZ_ENABLE_MASK_AS_SHORTHAND
|
||||
CSS_PROP_SVGRESET(
|
||||
mask-type,
|
||||
mask_type,
|
||||
|
|
|
|||
|
|
@ -932,33 +932,43 @@ const KTableEntry nsCSSProps::kImageLayerAttachmentKTable[] = {
|
|||
{ eCSSKeyword_UNKNOWN, -1 }
|
||||
};
|
||||
|
||||
static_assert(NS_STYLE_IMAGELAYER_CLIP_BORDER == NS_STYLE_IMAGELAYER_ORIGIN_BORDER &&
|
||||
NS_STYLE_IMAGELAYER_CLIP_PADDING == NS_STYLE_IMAGELAYER_ORIGIN_PADDING &&
|
||||
NS_STYLE_IMAGELAYER_CLIP_CONTENT == NS_STYLE_IMAGELAYER_ORIGIN_CONTENT,
|
||||
"Except background-clip:text, all {background,mask}-clip and "
|
||||
"{background,mask}-origin style constants must agree");
|
||||
|
||||
const KTableEntry nsCSSProps::kImageLayerOriginKTable[] = {
|
||||
{ eCSSKeyword_border_box, NS_STYLE_IMAGELAYER_ORIGIN_BORDER },
|
||||
{ eCSSKeyword_padding_box, NS_STYLE_IMAGELAYER_ORIGIN_PADDING },
|
||||
{ eCSSKeyword_content_box, NS_STYLE_IMAGELAYER_ORIGIN_CONTENT },
|
||||
const KTableEntry nsCSSProps::kBackgroundOriginKTable[] = {
|
||||
{ eCSSKeyword_border_box, StyleGeometryBox::Border },
|
||||
{ eCSSKeyword_padding_box, StyleGeometryBox::Padding },
|
||||
{ eCSSKeyword_content_box, StyleGeometryBox::Content },
|
||||
{ eCSSKeyword_UNKNOWN, -1 }
|
||||
};
|
||||
|
||||
KTableEntry nsCSSProps::kBackgroundClipKTable[] = {
|
||||
{ eCSSKeyword_border_box, NS_STYLE_IMAGELAYER_CLIP_BORDER },
|
||||
{ eCSSKeyword_padding_box, NS_STYLE_IMAGELAYER_CLIP_PADDING },
|
||||
{ eCSSKeyword_content_box, NS_STYLE_IMAGELAYER_CLIP_CONTENT },
|
||||
{ eCSSKeyword_border_box, StyleGeometryBox::Border },
|
||||
{ eCSSKeyword_padding_box, StyleGeometryBox::Padding },
|
||||
{ eCSSKeyword_content_box, StyleGeometryBox::Content },
|
||||
// The next entry is controlled by the layout.css.background-clip-text.enabled
|
||||
// pref.
|
||||
{ eCSSKeyword_text, NS_STYLE_IMAGELAYER_CLIP_TEXT },
|
||||
{ eCSSKeyword_text, StyleGeometryBox::Text },
|
||||
{ eCSSKeyword_UNKNOWN, -1 }
|
||||
};
|
||||
|
||||
static_assert(MOZ_ARRAY_LENGTH(nsCSSProps::kImageLayerOriginKTable) ==
|
||||
MOZ_ARRAY_LENGTH(nsCSSProps::kBackgroundClipKTable) - 1,
|
||||
"background-clip has one extra value, which is text, compared"
|
||||
"to {background,mask}-origin");
|
||||
const KTableEntry nsCSSProps::kMaskOriginKTable[] = {
|
||||
{ eCSSKeyword_border_box, StyleGeometryBox::Border },
|
||||
{ eCSSKeyword_padding_box, StyleGeometryBox::Padding },
|
||||
{ eCSSKeyword_content_box, StyleGeometryBox::Content },
|
||||
{ eCSSKeyword_fill_box, StyleGeometryBox::Fill },
|
||||
{ eCSSKeyword_stroke_box, StyleGeometryBox::Stroke },
|
||||
{ eCSSKeyword_view_box, StyleGeometryBox::View },
|
||||
{ eCSSKeyword_UNKNOWN, -1 }
|
||||
};
|
||||
|
||||
const KTableEntry nsCSSProps::kMaskClipKTable[] = {
|
||||
{ eCSSKeyword_border_box, StyleGeometryBox::Border },
|
||||
{ eCSSKeyword_padding_box, StyleGeometryBox::Padding },
|
||||
{ eCSSKeyword_content_box, StyleGeometryBox::Content },
|
||||
{ eCSSKeyword_fill_box, StyleGeometryBox::Fill },
|
||||
{ eCSSKeyword_stroke_box, StyleGeometryBox::Stroke },
|
||||
{ eCSSKeyword_view_box, StyleGeometryBox::View },
|
||||
{ eCSSKeyword_no_clip, StyleGeometryBox::NoClip },
|
||||
{ eCSSKeyword_UNKNOWN, -1 }
|
||||
};
|
||||
|
||||
// Note: Don't change this table unless you update
|
||||
// ParseImageLayerPosition!
|
||||
|
|
@ -2346,13 +2356,13 @@ const KTableEntry nsCSSProps::kFillRuleKTable[] = {
|
|||
};
|
||||
|
||||
const KTableEntry nsCSSProps::kClipPathGeometryBoxKTable[] = {
|
||||
{ eCSSKeyword_content_box, StyleClipPathGeometryBox::Content },
|
||||
{ eCSSKeyword_padding_box, StyleClipPathGeometryBox::Padding },
|
||||
{ eCSSKeyword_border_box, StyleClipPathGeometryBox::Border },
|
||||
{ eCSSKeyword_margin_box, StyleClipPathGeometryBox::Margin },
|
||||
{ eCSSKeyword_fill_box, StyleClipPathGeometryBox::Fill },
|
||||
{ eCSSKeyword_stroke_box, StyleClipPathGeometryBox::Stroke },
|
||||
{ eCSSKeyword_view_box, StyleClipPathGeometryBox::View },
|
||||
{ eCSSKeyword_content_box, StyleGeometryBox::Content },
|
||||
{ eCSSKeyword_padding_box, StyleGeometryBox::Padding },
|
||||
{ eCSSKeyword_border_box, StyleGeometryBox::Border },
|
||||
{ eCSSKeyword_margin_box, StyleGeometryBox::Margin },
|
||||
{ eCSSKeyword_fill_box, StyleGeometryBox::Fill },
|
||||
{ eCSSKeyword_stroke_box, StyleGeometryBox::Stroke },
|
||||
{ eCSSKeyword_view_box, StyleGeometryBox::View },
|
||||
{ eCSSKeyword_UNKNOWN, -1 }
|
||||
};
|
||||
|
||||
|
|
@ -3051,7 +3061,6 @@ static const nsCSSPropertyID gScrollSnapTypeSubpropTable[] = {
|
|||
eCSSProperty_scroll_snap_type_y,
|
||||
eCSSProperty_UNKNOWN
|
||||
};
|
||||
#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
|
||||
static const nsCSSPropertyID gMaskSubpropTable[] = {
|
||||
eCSSProperty_mask_image,
|
||||
eCSSProperty_mask_repeat,
|
||||
|
|
@ -3069,7 +3078,6 @@ static const nsCSSPropertyID gMaskPositionSubpropTable[] = {
|
|||
eCSSProperty_mask_position_y,
|
||||
eCSSProperty_UNKNOWN
|
||||
};
|
||||
#endif
|
||||
// FIXME: mask-border tables should be added when we implement
|
||||
// mask-border properties.
|
||||
|
||||
|
|
|
|||
|
|
@ -717,6 +717,8 @@ public:
|
|||
static const KTableEntry kTransformStyleKTable[];
|
||||
static const KTableEntry kImageLayerAttachmentKTable[];
|
||||
static const KTableEntry kImageLayerOriginKTable[];
|
||||
static const KTableEntry kBackgroundOriginKTable[];
|
||||
static const KTableEntry kMaskOriginKTable[];
|
||||
static const KTableEntry kImageLayerPositionKTable[];
|
||||
static const KTableEntry kImageLayerRepeatKTable[];
|
||||
static const KTableEntry kImageLayerRepeatPartKTable[];
|
||||
|
|
@ -726,6 +728,7 @@ public:
|
|||
// Not const because we modify its entries when the pref
|
||||
// "layout.css.background-clip.text" changes:
|
||||
static KTableEntry kBackgroundClipKTable[];
|
||||
static const KTableEntry kMaskClipKTable[];
|
||||
static const KTableEntry kBlendModeKTable[];
|
||||
static const KTableEntry kBorderCollapseKTable[];
|
||||
static const KTableEntry kBorderImageRepeatKTable[];
|
||||
|
|
|
|||
|
|
@ -74,6 +74,30 @@ NS_NewComputedDOMStyle(dom::Element* aElement, const nsAString& aPseudoElt,
|
|||
return computedStyle.forget();
|
||||
}
|
||||
|
||||
static nsDOMCSSValueList*
|
||||
GetROCSSValueList(bool aCommaDelimited)
|
||||
{
|
||||
return new nsDOMCSSValueList(aCommaDelimited, true);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
already_AddRefed<CSSValue>
|
||||
GetBackgroundList(T nsStyleImageLayers::Layer::* aMember,
|
||||
uint32_t nsStyleImageLayers::* aCount,
|
||||
const nsStyleImageLayers& aLayers,
|
||||
const KTableEntry aTable[])
|
||||
{
|
||||
RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
|
||||
|
||||
for (uint32_t i = 0, i_end = aLayers.*aCount; i < i_end; ++i) {
|
||||
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
|
||||
val->SetIdent(nsCSSProps::ValueToKeywordEnum(aLayers.mLayers[i].*aMember, aTable));
|
||||
valueList->AppendCSSValue(val.forget());
|
||||
}
|
||||
|
||||
return valueList.forget();
|
||||
}
|
||||
|
||||
/**
|
||||
* An object that represents the ordered set of properties that are exposed on
|
||||
* an nsComputedDOMStyle object and how their computed values can be obtained.
|
||||
|
|
@ -1801,24 +1825,6 @@ nsComputedDOMStyle::DoGetFontVariantPosition()
|
|||
return val.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<CSSValue>
|
||||
nsComputedDOMStyle::GetBackgroundList(uint8_t nsStyleImageLayers::Layer::* aMember,
|
||||
uint32_t nsStyleImageLayers::* aCount,
|
||||
const nsStyleImageLayers& aLayers,
|
||||
const KTableEntry aTable[])
|
||||
{
|
||||
RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
|
||||
|
||||
for (uint32_t i = 0, i_end = aLayers.*aCount; i < i_end; ++i) {
|
||||
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
|
||||
val->SetIdent(nsCSSProps::ValueToKeywordEnum(aLayers.mLayers[i].*aMember,
|
||||
aTable));
|
||||
valueList->AppendCSSValue(val.forget());
|
||||
}
|
||||
|
||||
return valueList.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<CSSValue>
|
||||
nsComputedDOMStyle::DoGetBackgroundAttachment()
|
||||
{
|
||||
|
|
@ -2366,7 +2372,7 @@ nsComputedDOMStyle::DoGetBackgroundOrigin()
|
|||
return GetBackgroundList(&nsStyleImageLayers::Layer::mOrigin,
|
||||
&nsStyleImageLayers::mOriginCount,
|
||||
StyleBackground()->mImage,
|
||||
nsCSSProps::kImageLayerOriginKTable);
|
||||
nsCSSProps::kBackgroundOriginKTable);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -5012,12 +5018,6 @@ nsComputedDOMStyle::DoGetTop()
|
|||
return GetOffsetWidthFor(NS_SIDE_TOP);
|
||||
}
|
||||
|
||||
nsDOMCSSValueList*
|
||||
nsComputedDOMStyle::GetROCSSValueList(bool aCommaDelimited)
|
||||
{
|
||||
return new nsDOMCSSValueList(aCommaDelimited, true);
|
||||
}
|
||||
|
||||
already_AddRefed<CSSValue>
|
||||
nsComputedDOMStyle::GetOffsetWidthFor(mozilla::css::Side aSide)
|
||||
{
|
||||
|
|
@ -6179,8 +6179,8 @@ nsComputedDOMStyle::DoGetMask()
|
|||
// need to support computed style for the cases where it used to be
|
||||
// a longhand.
|
||||
if (svg->mMask.mImageCount > 1 ||
|
||||
firstLayer.mClip != NS_STYLE_IMAGELAYER_CLIP_BORDER ||
|
||||
firstLayer.mOrigin != NS_STYLE_IMAGELAYER_ORIGIN_BORDER ||
|
||||
firstLayer.mClip != StyleGeometryBox::Border ||
|
||||
firstLayer.mOrigin != StyleGeometryBox::Border ||
|
||||
firstLayer.mComposite != NS_STYLE_MASK_COMPOSITE_ADD ||
|
||||
firstLayer.mMaskMode != NS_STYLE_MASK_MODE_MATCH_SOURCE ||
|
||||
!nsStyleImageLayers::IsInitialPositionForLayerType(
|
||||
|
|
@ -6199,14 +6199,13 @@ nsComputedDOMStyle::DoGetMask()
|
|||
return val.forget();
|
||||
}
|
||||
|
||||
#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
|
||||
already_AddRefed<CSSValue>
|
||||
nsComputedDOMStyle::DoGetMaskClip()
|
||||
{
|
||||
return GetBackgroundList(&nsStyleImageLayers::Layer::mClip,
|
||||
&nsStyleImageLayers::mClipCount,
|
||||
StyleSVGReset()->mMask,
|
||||
nsCSSProps::kImageLayerOriginKTable);
|
||||
nsCSSProps::kMaskClipKTable);
|
||||
}
|
||||
|
||||
already_AddRefed<CSSValue>
|
||||
|
|
@ -6240,7 +6239,7 @@ nsComputedDOMStyle::DoGetMaskOrigin()
|
|||
return GetBackgroundList(&nsStyleImageLayers::Layer::mOrigin,
|
||||
&nsStyleImageLayers::mOriginCount,
|
||||
StyleSVGReset()->mMask,
|
||||
nsCSSProps::kImageLayerOriginKTable);
|
||||
nsCSSProps::kMaskOriginKTable);
|
||||
}
|
||||
|
||||
already_AddRefed<CSSValue>
|
||||
|
|
@ -6277,7 +6276,6 @@ nsComputedDOMStyle::DoGetMaskSize()
|
|||
const nsStyleImageLayers& layers = StyleSVGReset()->mMask;
|
||||
return DoGetImageLayerSize(layers);
|
||||
}
|
||||
#endif
|
||||
|
||||
already_AddRefed<CSSValue>
|
||||
nsComputedDOMStyle::DoGetMaskType()
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ private:
|
|||
// Convenience typedefs:
|
||||
typedef nsCSSProps::KTableEntry KTableEntry;
|
||||
typedef mozilla::dom::CSSValue CSSValue;
|
||||
typedef mozilla::StyleGeometryBox StyleGeometryBox;
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
|
@ -202,12 +203,6 @@ private:
|
|||
const nscolor& aDefaultColor,
|
||||
bool aIsBoxShadow);
|
||||
|
||||
already_AddRefed<CSSValue> GetBackgroundList(
|
||||
uint8_t nsStyleImageLayers::Layer::* aMember,
|
||||
uint32_t nsStyleImageLayers::* aCount,
|
||||
const nsStyleImageLayers& aLayers,
|
||||
const KTableEntry aTable[]);
|
||||
|
||||
void GetCSSGradientString(const nsStyleGradient* aGradient,
|
||||
nsAString& aString);
|
||||
void GetImageRectString(nsIURI* aURI,
|
||||
|
|
@ -310,7 +305,6 @@ private:
|
|||
|
||||
/* Mask properties */
|
||||
already_AddRefed<CSSValue> DoGetMask();
|
||||
#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
|
||||
already_AddRefed<CSSValue> DoGetMaskImage();
|
||||
already_AddRefed<CSSValue> DoGetMaskPosition();
|
||||
already_AddRefed<CSSValue> DoGetMaskPositionX();
|
||||
|
|
@ -321,7 +315,7 @@ private:
|
|||
already_AddRefed<CSSValue> DoGetMaskSize();
|
||||
already_AddRefed<CSSValue> DoGetMaskMode();
|
||||
already_AddRefed<CSSValue> DoGetMaskComposite();
|
||||
#endif
|
||||
|
||||
/* Padding properties */
|
||||
already_AddRefed<CSSValue> DoGetPaddingTop();
|
||||
already_AddRefed<CSSValue> DoGetPaddingBottom();
|
||||
|
|
@ -582,8 +576,6 @@ private:
|
|||
/* Custom properties */
|
||||
already_AddRefed<CSSValue> DoGetCustomProperty(const nsAString& aPropertyName);
|
||||
|
||||
nsDOMCSSValueList* GetROCSSValueList(bool aCommaDelimited);
|
||||
|
||||
/* Helper functions */
|
||||
void SetToRGBAColor(nsROCSSPrimitiveValue* aValue, nscolor aColor);
|
||||
void SetValueFromComplexColor(nsROCSSPrimitiveValue* aValue,
|
||||
|
|
|
|||
|
|
@ -332,7 +332,6 @@ COMPUTED_STYLE_PROP(marker_end, MarkerEnd)
|
|||
COMPUTED_STYLE_PROP(marker_mid, MarkerMid)
|
||||
COMPUTED_STYLE_PROP(marker_start, MarkerStart)
|
||||
COMPUTED_STYLE_PROP(mask, Mask)
|
||||
#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
|
||||
COMPUTED_STYLE_PROP(mask_clip, MaskClip)
|
||||
COMPUTED_STYLE_PROP(mask_composite, MaskComposite)
|
||||
COMPUTED_STYLE_PROP(mask_image, MaskImage)
|
||||
|
|
@ -343,7 +342,6 @@ COMPUTED_STYLE_PROP(mask_position_x, MaskPositionX)
|
|||
COMPUTED_STYLE_PROP(mask_position_y, MaskPositionY)
|
||||
COMPUTED_STYLE_PROP(mask_repeat, MaskRepeat)
|
||||
COMPUTED_STYLE_PROP(mask_size, MaskSize)
|
||||
#endif
|
||||
COMPUTED_STYLE_PROP(mask_type, MaskType)
|
||||
COMPUTED_STYLE_PROP(paint_order, PaintOrder)
|
||||
COMPUTED_STYLE_PROP(shape_rendering, ShapeRendering)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "mozilla/Unused.h"
|
||||
|
||||
#include "mozilla/css/Declaration.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include "nsAlgorithm.h" // for clamped()
|
||||
#include "nsRuleNode.h"
|
||||
|
|
@ -6800,6 +6801,21 @@ struct BackgroundItemComputer<nsCSSValueList, RefPtr<css::URLValueData>>
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct BackgroundItemComputer<nsCSSValueList, T>
|
||||
{
|
||||
typedef typename EnableIf<IsEnum<T>::value, T>::Type ComputedType;
|
||||
|
||||
static void ComputeValue(nsStyleContext* aStyleContext,
|
||||
const nsCSSValueList* aSpecifiedValue,
|
||||
ComputedType& aComputedValue,
|
||||
RuleNodeCacheConditions& aConditions)
|
||||
{
|
||||
aComputedValue =
|
||||
static_cast<T>(aSpecifiedValue->mValue.GetIntValue());
|
||||
}
|
||||
};
|
||||
|
||||
/* Helper function for ComputePositionValue.
|
||||
* This function computes a single PositionCoord from two nsCSSValue objects,
|
||||
* which represent an edge and an offset from that edge.
|
||||
|
|
@ -7353,7 +7369,7 @@ nsRuleNode::ComputeBackgroundData(void* aStartStruct,
|
|||
bg->mImage.mLayers,
|
||||
parentBG->mImage.mLayers,
|
||||
&nsStyleImageLayers::Layer::mClip,
|
||||
uint8_t(NS_STYLE_IMAGELAYER_CLIP_BORDER),
|
||||
StyleGeometryBox::Border,
|
||||
parentBG->mImage.mClipCount,
|
||||
bg->mImage.mClipCount, maxItemCount, rebuild, conditions);
|
||||
|
||||
|
|
@ -7372,7 +7388,7 @@ nsRuleNode::ComputeBackgroundData(void* aStartStruct,
|
|||
bg->mImage.mLayers,
|
||||
parentBG->mImage.mLayers,
|
||||
&nsStyleImageLayers::Layer::mOrigin,
|
||||
uint8_t(NS_STYLE_IMAGELAYER_ORIGIN_PADDING),
|
||||
StyleGeometryBox::Padding,
|
||||
parentBG->mImage.mOriginCount,
|
||||
bg->mImage.mOriginCount, maxItemCount, rebuild,
|
||||
conditions);
|
||||
|
|
@ -10005,7 +10021,6 @@ nsRuleNode::ComputeSVGResetData(void* aStartStruct,
|
|||
parentSVGReset->mMaskType,
|
||||
NS_STYLE_MASK_TYPE_LUMINANCE);
|
||||
|
||||
#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
|
||||
uint32_t maxItemCount = 1;
|
||||
bool rebuild = false;
|
||||
|
||||
|
|
@ -10043,7 +10058,7 @@ nsRuleNode::ComputeSVGResetData(void* aStartStruct,
|
|||
svgReset->mMask.mLayers,
|
||||
parentSVGReset->mMask.mLayers,
|
||||
&nsStyleImageLayers::Layer::mClip,
|
||||
uint8_t(NS_STYLE_IMAGELAYER_CLIP_BORDER),
|
||||
StyleGeometryBox::Border,
|
||||
parentSVGReset->mMask.mClipCount,
|
||||
svgReset->mMask.mClipCount, maxItemCount, rebuild,
|
||||
conditions);
|
||||
|
|
@ -10053,7 +10068,7 @@ nsRuleNode::ComputeSVGResetData(void* aStartStruct,
|
|||
svgReset->mMask.mLayers,
|
||||
parentSVGReset->mMask.mLayers,
|
||||
&nsStyleImageLayers::Layer::mOrigin,
|
||||
uint8_t(NS_STYLE_IMAGELAYER_ORIGIN_BORDER),
|
||||
StyleGeometryBox::Border,
|
||||
parentSVGReset->mMask.mOriginCount,
|
||||
svgReset->mMask.mOriginCount, maxItemCount, rebuild,
|
||||
conditions);
|
||||
|
|
@ -10113,21 +10128,6 @@ nsRuleNode::ComputeSVGResetData(void* aStartStruct,
|
|||
if (rebuild) {
|
||||
FillAllBackgroundLists(svgReset->mMask, maxItemCount);
|
||||
}
|
||||
#else
|
||||
// mask: none | <url>
|
||||
const nsCSSValue* maskValue = aRuleData->ValueForMask();
|
||||
if (eCSSUnit_URL == maskValue->GetUnit()) {
|
||||
svgReset->mMask.mLayers[0].mSourceURI = maskValue->GetURLStructValue();
|
||||
} else if (eCSSUnit_None == maskValue->GetUnit() ||
|
||||
eCSSUnit_Initial == maskValue->GetUnit() ||
|
||||
eCSSUnit_Unset == maskValue->GetUnit()) {
|
||||
svgReset->mMask.mLayers[0].mSourceURI = nullptr;
|
||||
} else if (eCSSUnit_Inherit == maskValue->GetUnit()) {
|
||||
conditions.SetUncacheable();
|
||||
svgReset->mMask.mLayers[0].mSourceURI =
|
||||
parentSVGReset->mMask.mLayers[0].mSourceURI;
|
||||
}
|
||||
#endif
|
||||
|
||||
COMPUTE_END_RESET(SVGReset, svgReset)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,16 +134,35 @@ enum class StyleClear : uint8_t {
|
|||
Max = 13 // Max = (Both | Line)
|
||||
};
|
||||
|
||||
// clip-path geometry box
|
||||
enum class StyleClipPathGeometryBox : uint8_t {
|
||||
NoBox,
|
||||
// Define geometry box for clip-path's reference-box, background-clip,
|
||||
// background-origin, mask-clip and mask-origin.
|
||||
enum class StyleGeometryBox : uint8_t {
|
||||
Content,
|
||||
Padding,
|
||||
Border,
|
||||
Margin,
|
||||
Fill,
|
||||
Stroke,
|
||||
View,
|
||||
Margin, // XXX Bug 1260094 comment 9.
|
||||
// Although margin-box is required by mask-origin and mask-clip, we
|
||||
// do not implement that due to lack of support in other browsers.
|
||||
// clip-path reference-box only.
|
||||
Fill, // mask-clip, mask-origin and clip-path reference-box only.
|
||||
Stroke, // mask-clip, mask-origin and clip-path reference-box only.
|
||||
View, // mask-clip, mask-origin and clip-path reference-box only.
|
||||
NoClip, // mask-clip only.
|
||||
Text, // background-clip only.
|
||||
NoBox, // Depending on which kind of element this style value applied on,
|
||||
// the default value of a reference-box can be different.
|
||||
// For an HTML element, the default value of reference-box is
|
||||
// border-box; for an SVG element, the default value is fill-box.
|
||||
// Since we can not determine the default value at parsing time,
|
||||
// set it as NoBox so that we make a decision later.
|
||||
// clip-path reference-box only.
|
||||
MozAlmostPadding = 127 // A magic value that we use for our "pretend that
|
||||
// background-clip is 'padding' when we have a solid
|
||||
// border" optimization. This isn't actually equal
|
||||
// to StyleGeometryBox::Padding because using that
|
||||
// causes antialiasing seams between the background
|
||||
// and border.
|
||||
// background-clip only.
|
||||
};
|
||||
|
||||
// fill-rule
|
||||
|
|
@ -359,14 +378,6 @@ enum class FillMode : uint32_t;
|
|||
#define NS_STYLE_IMAGELAYER_ATTACHMENT_FIXED 1
|
||||
#define NS_STYLE_IMAGELAYER_ATTACHMENT_LOCAL 2
|
||||
|
||||
// See nsStyleImageLayers
|
||||
// Code depends on these constants having the same values as IMAGELAYER_ORIGIN_*
|
||||
#define NS_STYLE_IMAGELAYER_CLIP_BORDER 0
|
||||
#define NS_STYLE_IMAGELAYER_CLIP_PADDING 1
|
||||
#define NS_STYLE_IMAGELAYER_CLIP_CONTENT 2
|
||||
// One extra constant which does not exist in IMAGELAYER_ORIGIN_*
|
||||
#define NS_STYLE_IMAGELAYER_CLIP_TEXT 3
|
||||
|
||||
// A magic value that we use for our "pretend that background-clip is
|
||||
// 'padding' when we have a solid border" optimization. This isn't
|
||||
// actually equal to NS_STYLE_IMAGELAYER_CLIP_PADDING because using that
|
||||
|
|
@ -374,12 +385,6 @@ enum class FillMode : uint32_t;
|
|||
// is a backend-only value.
|
||||
#define NS_STYLE_IMAGELAYER_CLIP_MOZ_ALMOST_PADDING 127
|
||||
|
||||
// See nsStyleImageLayers
|
||||
// Code depends on these constants having the same values as BG_CLIP_*
|
||||
#define NS_STYLE_IMAGELAYER_ORIGIN_BORDER 0
|
||||
#define NS_STYLE_IMAGELAYER_ORIGIN_PADDING 1
|
||||
#define NS_STYLE_IMAGELAYER_ORIGIN_CONTENT 2
|
||||
|
||||
// See nsStyleImageLayers
|
||||
// The parser code depends on |ing these values together.
|
||||
#define NS_STYLE_IMAGELAYER_POSITION_CENTER (1<<0)
|
||||
|
|
|
|||
|
|
@ -2465,7 +2465,6 @@ const nsCSSPropertyID nsStyleImageLayers::kBackgroundLayerTable[] = {
|
|||
eCSSProperty_UNKNOWN // composite
|
||||
};
|
||||
|
||||
#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
|
||||
const nsCSSPropertyID nsStyleImageLayers::kMaskLayerTable[] = {
|
||||
eCSSProperty_mask, // shorthand
|
||||
eCSSProperty_UNKNOWN, // color
|
||||
|
|
@ -2480,7 +2479,6 @@ const nsCSSPropertyID nsStyleImageLayers::kMaskLayerTable[] = {
|
|||
eCSSProperty_mask_mode, // maskMode
|
||||
eCSSProperty_mask_composite // composite
|
||||
};
|
||||
#endif
|
||||
|
||||
nsStyleImageLayers::nsStyleImageLayers(nsStyleImageLayers::LayerType aType)
|
||||
: mAttachmentCount(1)
|
||||
|
|
@ -2787,7 +2785,7 @@ nsStyleImageLayers::Size::operator==(const Size& aOther) const
|
|||
}
|
||||
|
||||
nsStyleImageLayers::Layer::Layer()
|
||||
: mClip(NS_STYLE_IMAGELAYER_CLIP_BORDER)
|
||||
: mClip(StyleGeometryBox::Border)
|
||||
, mAttachment(NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL)
|
||||
, mBlendMode(NS_STYLE_BLEND_NORMAL)
|
||||
, mComposite(NS_STYLE_MASK_COMPOSITE_ADD)
|
||||
|
|
@ -2809,10 +2807,10 @@ nsStyleImageLayers::Layer::Initialize(nsStyleImageLayers::LayerType aType)
|
|||
mPosition.SetInitialPercentValues(0.0f);
|
||||
|
||||
if (aType == LayerType::Background) {
|
||||
mOrigin = NS_STYLE_IMAGELAYER_ORIGIN_PADDING;
|
||||
mOrigin = StyleGeometryBox::Padding;
|
||||
} else {
|
||||
MOZ_ASSERT(aType == LayerType::Mask, "unsupported layer type.");
|
||||
mOrigin = NS_STYLE_IMAGELAYER_ORIGIN_BORDER;
|
||||
mOrigin = StyleGeometryBox::Border;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -782,6 +782,8 @@ struct nsStyleImageLayers {
|
|||
struct Layer;
|
||||
friend struct Layer;
|
||||
struct Layer {
|
||||
typedef mozilla::StyleGeometryBox StyleGeometryBox;
|
||||
|
||||
nsStyleImage mImage; // [reset]
|
||||
RefPtr<mozilla::css::URLValueData> mSourceURI; // [reset]
|
||||
// mask-only property
|
||||
|
|
@ -793,9 +795,9 @@ struct nsStyleImageLayers {
|
|||
// or an ImageValue.)
|
||||
mozilla::Position mPosition; // [reset]
|
||||
Size mSize; // [reset]
|
||||
uint8_t mClip; // [reset] See nsStyleConsts.h
|
||||
StyleGeometryBox mClip; // [reset] See nsStyleConsts.h
|
||||
MOZ_INIT_OUTSIDE_CTOR
|
||||
uint8_t mOrigin; // [reset] See nsStyleConsts.h
|
||||
StyleGeometryBox mOrigin; // [reset] See nsStyleConsts.h
|
||||
uint8_t mAttachment; // [reset] See nsStyleConsts.h
|
||||
// background-only property
|
||||
// This property is used for background layer
|
||||
|
|
@ -2755,7 +2757,7 @@ private:
|
|||
ReferenceBox mReferenceBox = ReferenceBox::NoBox;
|
||||
};
|
||||
|
||||
using StyleClipPath = StyleShapeSource<StyleClipPathGeometryBox>;
|
||||
using StyleClipPath = StyleShapeSource<StyleGeometryBox>;
|
||||
using StyleShapeOutside = StyleShapeSource<StyleShapeOutsideShapeBox>;
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
|||
|
|
@ -62,122 +62,12 @@ nsCSSClipPathInstance::HitTestBasicShapeClip(nsIFrame* aFrame,
|
|||
return path->ContainsPoint(ToPoint(aPoint) * pixelRatio, Matrix());
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsCSSClipPathInstance::ComputeSVGReferenceRect()
|
||||
{
|
||||
MOZ_ASSERT(mTargetFrame->GetContent()->IsSVGElement());
|
||||
nsRect r;
|
||||
|
||||
// For SVG elements without associated CSS layout box, the used value for
|
||||
// content-box, padding-box, border-box and margin-box is fill-box.
|
||||
switch (mClipPathStyle.GetReferenceBox()) {
|
||||
case StyleClipPathGeometryBox::Stroke: {
|
||||
// XXX Bug 1299876
|
||||
// The size of srtoke-box is not correct if this graphic element has
|
||||
// specific stroke-linejoin or stroke-linecap.
|
||||
gfxRect bbox = nsSVGUtils::GetBBox(mTargetFrame,
|
||||
nsSVGUtils::eBBoxIncludeFill | nsSVGUtils::eBBoxIncludeStroke);
|
||||
r = nsLayoutUtils::RoundGfxRectToAppRect(bbox,
|
||||
nsPresContext::AppUnitsPerCSSPixel());
|
||||
break;
|
||||
}
|
||||
case StyleClipPathGeometryBox::View: {
|
||||
nsIContent* content = mTargetFrame->GetContent();
|
||||
nsSVGElement* element = static_cast<nsSVGElement*>(content);
|
||||
SVGSVGElement* svgElement = element->GetCtx();
|
||||
MOZ_ASSERT(svgElement);
|
||||
|
||||
if (svgElement && svgElement->HasViewBoxRect()) {
|
||||
// If a ‘viewBox‘ attribute is specified for the SVG viewport creating
|
||||
// element:
|
||||
// 1. The reference box is positioned at the origin of the coordinate
|
||||
// system established by the ‘viewBox‘ attribute.
|
||||
// 2. The dimension of the reference box is set to the width and height
|
||||
// values of the ‘viewBox‘ attribute.
|
||||
nsSVGViewBox* viewBox = svgElement->GetViewBox();
|
||||
const nsSVGViewBoxRect& value = viewBox->GetAnimValue();
|
||||
r = nsRect(nsPresContext::CSSPixelsToAppUnits(value.x),
|
||||
nsPresContext::CSSPixelsToAppUnits(value.y),
|
||||
nsPresContext::CSSPixelsToAppUnits(value.width),
|
||||
nsPresContext::CSSPixelsToAppUnits(value.height));
|
||||
} else {
|
||||
// No viewBox is specified, uses the nearest SVG viewport as reference
|
||||
// box.
|
||||
svgFloatSize viewportSize = svgElement->GetViewportSize();
|
||||
r = nsRect(0, 0,
|
||||
nsPresContext::CSSPixelsToAppUnits(viewportSize.width),
|
||||
nsPresContext::CSSPixelsToAppUnits(viewportSize.height));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case StyleClipPathGeometryBox::NoBox:
|
||||
case StyleClipPathGeometryBox::Border:
|
||||
case StyleClipPathGeometryBox::Content:
|
||||
case StyleClipPathGeometryBox::Padding:
|
||||
case StyleClipPathGeometryBox::Margin:
|
||||
case StyleClipPathGeometryBox::Fill: {
|
||||
gfxRect bbox = nsSVGUtils::GetBBox(mTargetFrame,
|
||||
nsSVGUtils::eBBoxIncludeFill);
|
||||
r = nsLayoutUtils::RoundGfxRectToAppRect(bbox,
|
||||
nsPresContext::AppUnitsPerCSSPixel());
|
||||
break;
|
||||
}
|
||||
default:{
|
||||
MOZ_ASSERT_UNREACHABLE("unknown StyleClipPathGeometryBox type");
|
||||
gfxRect bbox = nsSVGUtils::GetBBox(mTargetFrame,
|
||||
nsSVGUtils::eBBoxIncludeFill);
|
||||
r = nsLayoutUtils::RoundGfxRectToAppRect(bbox,
|
||||
nsPresContext::AppUnitsPerCSSPixel());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsCSSClipPathInstance::ComputeHTMLReferenceRect()
|
||||
{
|
||||
nsRect r;
|
||||
|
||||
// For elements with associated CSS layout box, the used value for fill-box,
|
||||
// stroke-box and view-box is border-box.
|
||||
switch (mClipPathStyle.GetReferenceBox()) {
|
||||
case StyleClipPathGeometryBox::Content:
|
||||
r = mTargetFrame->GetContentRectRelativeToSelf();
|
||||
break;
|
||||
case StyleClipPathGeometryBox::Padding:
|
||||
r = mTargetFrame->GetPaddingRectRelativeToSelf();
|
||||
break;
|
||||
case StyleClipPathGeometryBox::Margin:
|
||||
r = mTargetFrame->GetMarginRectRelativeToSelf();
|
||||
break;
|
||||
case StyleClipPathGeometryBox::NoBox:
|
||||
case StyleClipPathGeometryBox::Border:
|
||||
case StyleClipPathGeometryBox::Fill:
|
||||
case StyleClipPathGeometryBox::Stroke:
|
||||
case StyleClipPathGeometryBox::View:
|
||||
r = mTargetFrame->GetRectRelativeToSelf();
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("unknown StyleClipPathGeometryBox type");
|
||||
r = mTargetFrame->GetRectRelativeToSelf();
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
already_AddRefed<Path>
|
||||
nsCSSClipPathInstance::CreateClipPath(DrawTarget* aDrawTarget)
|
||||
{
|
||||
// We use ComputeSVGReferenceRect for all SVG elements, except <svg>
|
||||
// element, which does have an associated CSS layout box. In this case we
|
||||
// should still use ComputeHTMLReferenceRect for region computing.
|
||||
nsRect r = mTargetFrame->IsFrameOfType(nsIFrame::eSVG) &&
|
||||
(mTargetFrame->GetType() != nsGkAtoms::svgOuterSVGFrame)
|
||||
? ComputeSVGReferenceRect() : ComputeHTMLReferenceRect();
|
||||
nsRect r =
|
||||
nsLayoutUtils::ComputeGeometryBox(mTargetFrame,
|
||||
mClipPathStyle.GetReferenceBox());
|
||||
|
||||
if (mClipPathStyle.GetType() != StyleShapeSourceType::Shape) {
|
||||
// TODO Clip to border-radius/reference box if no shape
|
||||
|
|
|
|||
|
|
@ -48,10 +48,6 @@ private:
|
|||
already_AddRefed<Path> CreateClipPathInset(DrawTarget* aDrawTarget,
|
||||
const nsRect& aRefBox);
|
||||
|
||||
|
||||
nsRect ComputeHTMLReferenceRect();
|
||||
nsRect ComputeSVGReferenceRect();
|
||||
|
||||
/**
|
||||
* The frame for the element that is currently being clipped.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -509,71 +509,108 @@ PaintMaskSurface(const PaintFramesParams& aParams,
|
|||
return DrawResult::SUCCESS;
|
||||
}
|
||||
|
||||
static DrawResult
|
||||
struct MaskPaintResult {
|
||||
RefPtr<SourceSurface> maskSurface;
|
||||
Matrix maskTransform;
|
||||
DrawResult result;
|
||||
bool transparentBlackMask;
|
||||
bool opacityApplied;
|
||||
|
||||
MaskPaintResult()
|
||||
: result(DrawResult::SUCCESS), transparentBlackMask(false),
|
||||
opacityApplied(false)
|
||||
{}
|
||||
};
|
||||
|
||||
static MaskPaintResult
|
||||
CreateAndPaintMaskSurface(const PaintFramesParams& aParams,
|
||||
float aOpacity, nsStyleContext* aSC,
|
||||
const nsTArray<nsSVGMaskFrame*>& aMaskFrames,
|
||||
const nsPoint& aOffsetToUserSpace,
|
||||
Matrix& aOutMaskTransform,
|
||||
RefPtr<SourceSurface>& aOutMaskSurface,
|
||||
bool& aOpacityApplied)
|
||||
const nsPoint& aOffsetToUserSpace)
|
||||
{
|
||||
const nsStyleSVGReset *svgReset = aSC->StyleSVGReset();
|
||||
MOZ_ASSERT(aMaskFrames.Length() > 0);
|
||||
MaskPaintResult paintResult;
|
||||
|
||||
gfxContext& ctx = aParams.ctx;
|
||||
|
||||
// There is only one SVG mask.
|
||||
// Optimization for single SVG mask.
|
||||
if (((aMaskFrames.Length() == 1) && aMaskFrames[0])) {
|
||||
gfxMatrix cssPxToDevPxMatrix =
|
||||
nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(aParams.frame);
|
||||
paintResult.opacityApplied = true;
|
||||
|
||||
aOpacityApplied = true;
|
||||
aOutMaskSurface =
|
||||
paintResult.maskSurface =
|
||||
aMaskFrames[0]->GetMaskForMaskedFrame(&ctx, aParams.frame,
|
||||
cssPxToDevPxMatrix, aOpacity,
|
||||
&aOutMaskTransform,
|
||||
&paintResult.maskTransform,
|
||||
svgReset->mMask.mLayers[0].mMaskMode);
|
||||
return DrawResult::SUCCESS;
|
||||
if (!paintResult.maskSurface) {
|
||||
paintResult.transparentBlackMask = true;
|
||||
}
|
||||
|
||||
return paintResult;
|
||||
}
|
||||
|
||||
const IntRect& maskSurfaceRect = aParams.maskRect;
|
||||
if (maskSurfaceRect.IsEmpty()) {
|
||||
return DrawResult::SUCCESS;
|
||||
paintResult.transparentBlackMask = true;
|
||||
return paintResult;
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget> maskDT =
|
||||
ctx.GetDrawTarget()->CreateSimilarDrawTarget(maskSurfaceRect.Size(),
|
||||
SurfaceFormat::A8);
|
||||
if (!maskDT || !maskDT->IsValid()) {
|
||||
return DrawResult::TEMPORARY_ERROR;
|
||||
paintResult.result = DrawResult::TEMPORARY_ERROR;
|
||||
return paintResult;
|
||||
}
|
||||
|
||||
// Set aAppliedOpacity as true only if all mask layers are svg mask.
|
||||
// In this case, we will apply opacity into the final mask surface, so the
|
||||
// caller does not need to apply it again.
|
||||
aOpacityApplied = !HasNonSVGMask(aMaskFrames);
|
||||
paintResult.opacityApplied = !HasNonSVGMask(aMaskFrames);
|
||||
|
||||
// Set context's matrix on maskContext, offset by the maskSurfaceRect's
|
||||
// position. This makes sure that we combine the masks in device space.
|
||||
gfxMatrix maskSurfaceMatrix =
|
||||
ctx.CurrentMatrix() * gfxMatrix::Translation(-aParams.maskRect.TopLeft());
|
||||
|
||||
DrawResult result = PaintMaskSurface(aParams, maskDT,
|
||||
aOpacityApplied ? aOpacity : 1.0,
|
||||
aSC, aMaskFrames, maskSurfaceMatrix,
|
||||
aOffsetToUserSpace);
|
||||
if (result != DrawResult::SUCCESS) {
|
||||
return result;
|
||||
paintResult.result = PaintMaskSurface(aParams, maskDT,
|
||||
paintResult.opacityApplied
|
||||
? aOpacity : 1.0,
|
||||
aSC, aMaskFrames, maskSurfaceMatrix,
|
||||
aOffsetToUserSpace);
|
||||
if (paintResult.result != DrawResult::SUCCESS) {
|
||||
// Now we know the status of mask resource since we used it while painting.
|
||||
// According to the return value of PaintMaskSurface, we know whether mask
|
||||
// resource is resolvable or not.
|
||||
//
|
||||
// For a HTML doc:
|
||||
// According to css-masking spec, always create a mask surface when
|
||||
// we have any item in maskFrame even if all of those items are
|
||||
// non-resolvable <mask-sources> or <images>.
|
||||
// Set paintResult.transparentBlackMask as true, the caller should stop
|
||||
// painting masked content as if this mask is a transparent black one.
|
||||
// For a SVG doc:
|
||||
// SVG 1.1 say that if we fail to resolve a mask, we should draw the
|
||||
// object unmasked.
|
||||
// Left patinResult.maskSurface empty, the caller should paint all
|
||||
// masked content as if this mask is an opaque white one(no mask).
|
||||
paintResult.transparentBlackMask =
|
||||
!(aParams.frame->GetStateBits() & NS_FRAME_SVG_LAYOUT);
|
||||
|
||||
MOZ_ASSERT(!paintResult.maskSurface);
|
||||
return paintResult;
|
||||
}
|
||||
|
||||
paintResult.maskTransform = ToMatrix(maskSurfaceMatrix);
|
||||
if (!paintResult.maskTransform.Invert()) {
|
||||
return paintResult;
|
||||
}
|
||||
|
||||
aOutMaskTransform = ToMatrix(maskSurfaceMatrix);
|
||||
if (!aOutMaskTransform.Invert()) {
|
||||
return DrawResult::SUCCESS;
|
||||
}
|
||||
|
||||
aOutMaskSurface = maskDT->Snapshot();
|
||||
return DrawResult::SUCCESS;
|
||||
paintResult.maskSurface = maskDT->Snapshot();
|
||||
return paintResult;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
@ -783,6 +820,8 @@ nsSVGIntegrationUtils::PaintMaskAndClipPath(const PaintFramesParams& aParams)
|
|||
maskUsage.shouldGenerateClipMaskLayer ||
|
||||
maskUsage.shouldGenerateMaskLayer);
|
||||
|
||||
bool shouldPushMask = false;
|
||||
|
||||
/* Check if we need to do additional operations on this child's
|
||||
* rendering, which necessitates rendering into another surface. */
|
||||
if (shouldGenerateMask) {
|
||||
|
|
@ -800,14 +839,23 @@ nsSVGIntegrationUtils::PaintMaskAndClipPath(const PaintFramesParams& aParams)
|
|||
// instead of the first continuation frame.
|
||||
SetupContextMatrix(frame, aParams, offsetToBoundingBox,
|
||||
offsetToUserSpace);
|
||||
result = CreateAndPaintMaskSurface(aParams, maskUsage.opacity,
|
||||
firstFrame->StyleContext(),
|
||||
maskFrames, offsetToUserSpace,
|
||||
maskTransform, maskSurface,
|
||||
opacityApplied);
|
||||
if (!maskSurface) {
|
||||
// Entire surface is clipped out.
|
||||
return result;
|
||||
MaskPaintResult paintResult =
|
||||
CreateAndPaintMaskSurface(aParams, maskUsage.opacity,
|
||||
firstFrame->StyleContext(),
|
||||
maskFrames, offsetToUserSpace);
|
||||
|
||||
if (paintResult.transparentBlackMask) {
|
||||
MOZ_ASSERT(paintResult.result != DrawResult::SUCCESS);
|
||||
return paintResult.result;
|
||||
}
|
||||
|
||||
result &= paintResult.result;
|
||||
maskSurface = paintResult.maskSurface;
|
||||
if (maskSurface) {
|
||||
MOZ_ASSERT(paintResult.result == DrawResult::SUCCESS);
|
||||
shouldPushMask = true;
|
||||
maskTransform = paintResult.maskTransform;
|
||||
opacityApplied = paintResult.opacityApplied;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -831,6 +879,8 @@ nsSVGIntegrationUtils::PaintMaskAndClipPath(const PaintFramesParams& aParams)
|
|||
// failure in nsSVGClipPathFrame::GetClipMask.
|
||||
return result;
|
||||
}
|
||||
|
||||
shouldPushMask = true;
|
||||
}
|
||||
|
||||
// opacity != 1.0f.
|
||||
|
|
@ -841,18 +891,22 @@ nsSVGIntegrationUtils::PaintMaskAndClipPath(const PaintFramesParams& aParams)
|
|||
matSR.SetContext(&context);
|
||||
SetupContextMatrix(firstFrame, aParams, offsetToBoundingBox,
|
||||
offsetToUserSpace);
|
||||
shouldPushMask = true;
|
||||
}
|
||||
|
||||
if (aParams.layerManager->GetRoot()->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA) {
|
||||
context.PushGroupAndCopyBackground(gfxContentType::COLOR_ALPHA,
|
||||
opacityApplied
|
||||
? 1.0
|
||||
: maskUsage.opacity,
|
||||
maskSurface, maskTransform);
|
||||
} else {
|
||||
context.PushGroupForBlendBack(gfxContentType::COLOR_ALPHA,
|
||||
opacityApplied ? 1.0 : maskUsage.opacity,
|
||||
maskSurface, maskTransform);
|
||||
if (shouldPushMask) {
|
||||
if (aParams.layerManager->GetRoot()->GetContentFlags() &
|
||||
Layer::CONTENT_COMPONENT_ALPHA) {
|
||||
context.PushGroupAndCopyBackground(gfxContentType::COLOR_ALPHA,
|
||||
opacityApplied
|
||||
? 1.0
|
||||
: maskUsage.opacity,
|
||||
maskSurface, maskTransform);
|
||||
} else {
|
||||
context.PushGroupForBlendBack(gfxContentType::COLOR_ALPHA,
|
||||
opacityApplied ? 1.0 : maskUsage.opacity,
|
||||
maskSurface, maskTransform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -899,7 +953,7 @@ nsSVGIntegrationUtils::PaintMaskAndClipPath(const PaintFramesParams& aParams)
|
|||
context.PopClip();
|
||||
}
|
||||
|
||||
if (shouldGenerateMask) {
|
||||
if (shouldPushMask) {
|
||||
context.PopGroupAndBlend();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -514,26 +514,7 @@ nsSVGUtils::DetermineMaskUsage(nsIFrame* aFrame, bool aHandleOpacity,
|
|||
|
||||
nsTArray<nsSVGMaskFrame*> maskFrames = effectProperties.GetMaskFrames();
|
||||
|
||||
#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
|
||||
// For a HTML doc:
|
||||
// According to css-masking spec, always create a mask surface when we
|
||||
// have any item in maskFrame even if all of those items are
|
||||
// non-resolvable <mask-sources> or <images>, we still need to create a
|
||||
// transparent black mask layer under this condition.
|
||||
// For a SVG doc:
|
||||
// SVG 1.1 say that if we fail to resolve a mask, we should draw the
|
||||
// object unmasked.
|
||||
aUsage.shouldGenerateMaskLayer =
|
||||
(aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)
|
||||
? maskFrames.Length() == 1 && maskFrames[0]
|
||||
: maskFrames.Length() > 0;
|
||||
#else
|
||||
// Since we do not support image mask so far, we should treat any
|
||||
// unresolvable mask as no mask. Otherwise, any object with a valid image
|
||||
// mask, e.g. url("xxx.png"), will become invisible just because we can not
|
||||
// handle image mask correctly. (See bug 1294171)
|
||||
aUsage.shouldGenerateMaskLayer = maskFrames.Length() == 1 && maskFrames[0];
|
||||
#endif
|
||||
aUsage.shouldGenerateMaskLayer = (maskFrames.Length() > 0);
|
||||
|
||||
bool isOK = effectProperties.HasNoFilterOrHasValidFilter();
|
||||
nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame(&isOK);
|
||||
|
|
|
|||
|
|
@ -5680,22 +5680,6 @@ fi
|
|||
|
||||
AC_SUBST(PREPROCESS_OPTION)
|
||||
|
||||
dnl ========================================================
|
||||
dnl mask as shorthand property
|
||||
dnl ========================================================
|
||||
|
||||
# The control structure code will be removed as soon as the feature is stable
|
||||
# Refer to bug 1281101 for more details.
|
||||
|
||||
# Enable mask-as-shorthand property by default for nightly and aurora channels
|
||||
if test -z "$RELEASE_OR_BETA"; then
|
||||
dnl mask as shorthand property enabled
|
||||
MOZ_ENABLE_MASK_AS_SHORTHAND=1
|
||||
AC_DEFINE(MOZ_ENABLE_MASK_AS_SHORTHAND)
|
||||
fi
|
||||
|
||||
AC_SUBST(MOZ_ENABLE_MASK_AS_SHORTHAND)
|
||||
|
||||
# Avoid using obsolete NSPR features
|
||||
AC_DEFINE(NO_NSPR_10_SUPPORT)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue