summaryrefslogtreecommitdiffstats
path: root/layout/base
diff options
context:
space:
mode:
Diffstat (limited to 'layout/base')
-rw-r--r--layout/base/nsCSSFrameConstructor.cpp16
-rw-r--r--layout/base/nsCSSRendering.cpp215
-rw-r--r--layout/base/nsDisplayList.cpp121
-rw-r--r--layout/base/nsDisplayList.h47
-rw-r--r--layout/base/nsLayoutUtils.cpp130
-rw-r--r--layout/base/nsLayoutUtils.h5
-rw-r--r--layout/base/nsPresShell.cpp4
-rw-r--r--layout/base/nsRefreshDriver.cpp38
8 files changed, 329 insertions, 247 deletions
diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp
index c63374541..07a5b80e7 100644
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -7021,8 +7021,11 @@ nsCSSFrameConstructor::MaybeConstructLazily(Operation aOperation,
nsIContent* aContainer,
nsIContent* aChild)
{
+ // XXXmats no lazy frames for display:contents direct descendants yet
+ // (Mozilla bug 979782).
if (mPresShell->GetPresContext()->IsChrome() || !aContainer ||
- aContainer->IsInNativeAnonymousSubtree() || aContainer->IsXULElement()) {
+ aContainer->IsInNativeAnonymousSubtree() || aContainer->IsXULElement() ||
+ GetDisplayContentsStyleFor(aContainer)) {
return false;
}
@@ -7056,6 +7059,10 @@ nsCSSFrameConstructor::MaybeConstructLazily(Operation aOperation,
// ignore anonymous children (eg framesets) make this complicated. So we set
// these two booleans if we encounter these situations and unset them if we
// hit a node with a leaf frame.
+ //
+ // Also, it's fine if one of the nodes without primary frame is a display:
+ // contents node except if it's the direct ancestor of the children we're
+ // recreating frames for.
bool noPrimaryFrame = false;
bool needsFrameBitSet = false;
#endif
@@ -7065,17 +7072,14 @@ nsCSSFrameConstructor::MaybeConstructLazily(Operation aOperation,
if (content->GetPrimaryFrame() && content->GetPrimaryFrame()->IsLeaf()) {
noPrimaryFrame = needsFrameBitSet = false;
}
- if (!noPrimaryFrame && !content->GetPrimaryFrame()) {
+ if (!noPrimaryFrame && !content->GetPrimaryFrame() &&
+ !GetDisplayContentsStyleFor(content)) {
noPrimaryFrame = true;
}
if (!needsFrameBitSet && content->HasFlag(NODE_NEEDS_FRAME)) {
needsFrameBitSet = true;
}
#endif
- // XXXmats no lazy frames for display:contents descendants yet (bug 979782).
- if (GetDisplayContentsStyleFor(content)) {
- return false;
- }
content->SetFlags(NODE_DESCENDANTS_NEED_FRAMES);
content = content->GetFlattenedTreeParent();
}
diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp
index 71ebfad22..ff9edf742 100644
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -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;
diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp
index 2bf20144a..d619576ba 100644
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -61,7 +61,6 @@
#include "mozilla/OperatorNewExtensions.h"
#include "mozilla/PendingAnimationTracker.h"
#include "mozilla/Preferences.h"
-#include "mozilla/Telemetry.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Unused.h"
#include "mozilla/gfx/gfxVars.h"
@@ -1857,7 +1856,6 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot(nsDisplayListBuilder* aB
RefPtr<ContainerLayer> root;
{
- PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::Layerization);
root = layerBuilder->
BuildContainerLayerFor(aBuilder, layerManager, frame, nullptr, this,
containerParameters, nullptr);
@@ -3016,7 +3014,7 @@ nsDisplayBackgroundImage::ComputeVisibility(nsDisplayListBuilder* aBuilder,
/* static */ nsRegion
nsDisplayBackgroundImage::GetInsideClipRegion(nsDisplayItem* aItem,
- uint8_t aClip,
+ StyleGeometryBox aClip,
const nsRect& aRect,
const nsRect& aBackgroundRect)
{
@@ -3030,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());
@@ -3066,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);
}
}
@@ -3145,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;
}
@@ -3163,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();
}
@@ -3585,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;
}
@@ -3620,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();
}
@@ -7453,100 +7451,3 @@ nsDisplayFilter::PrintEffects(nsACString& aTo)
aTo += ")";
}
#endif
-
-namespace mozilla {
-
-uint32_t PaintTelemetry::sPaintLevel = 0;
-uint32_t PaintTelemetry::sMetricLevel = 0;
-EnumeratedArray<PaintTelemetry::Metric,
- PaintTelemetry::Metric::COUNT,
- double> PaintTelemetry::sMetrics;
-
-PaintTelemetry::AutoRecordPaint::AutoRecordPaint()
-{
- // Don't record nested paints.
- if (sPaintLevel++ > 0) {
- return;
- }
-
- // Reset metrics for a new paint.
- for (auto& metric : sMetrics) {
- metric = 0.0;
- }
- mStart = TimeStamp::Now();
-}
-
-PaintTelemetry::AutoRecordPaint::~AutoRecordPaint()
-{
- MOZ_ASSERT(sPaintLevel != 0);
- if (--sPaintLevel > 0) {
- return;
- }
-
- // If we're in multi-process mode, don't include paint times for the parent
- // process.
- if (gfxVars::BrowserTabsRemoteAutostart() && XRE_IsParentProcess()) {
- return;
- }
-
- double totalMs = (TimeStamp::Now() - mStart).ToMilliseconds();
-
- // If the total time was >= 16ms, then it's likely we missed a frame due to
- // painting. In this case we'll gather some detailed metrics below.
- if (totalMs <= 16.0) {
- return;
- }
-
- auto record = [=](const char* aKey, double aDurationMs) -> void {
- MOZ_ASSERT(aDurationMs <= totalMs);
-
- uint32_t amount = static_cast<int32_t>((aDurationMs / totalMs) * 100.0);
- };
-
- double dlMs = sMetrics[Metric::DisplayList];
- double flbMs = sMetrics[Metric::Layerization];
- double rMs = sMetrics[Metric::Rasterization];
-
- // Record all permutations since aggregation makes it difficult to
- // correlate. For example we can't derive "flb+r" from "dl" because we
- // don't know the total time associated with a bucket entry. So we just
- // play it safe and include everything. We can however derive "other" time
- // from the final permutation.
- record("dl", dlMs);
- record("flb", flbMs);
- record("r", rMs);
- record("dl,flb", dlMs + flbMs);
- record("dl,r", dlMs + rMs);
- record("flb,r", flbMs + rMs);
- record("dl,flb,r", dlMs + flbMs + rMs);
-}
-
-PaintTelemetry::AutoRecord::AutoRecord(Metric aMetric)
- : mMetric(aMetric)
-{
- // Don't double-record anything nested.
- if (sMetricLevel++ > 0) {
- return;
- }
-
- // Don't record inside nested paints, or outside of paints.
- if (sPaintLevel != 1) {
- return;
- }
-
- mStart = TimeStamp::Now();
-}
-
-PaintTelemetry::AutoRecord::~AutoRecord()
-{
- MOZ_ASSERT(sMetricLevel != 0);
-
- sMetricLevel--;
- if (mStart.IsNull()) {
- return;
- }
-
- sMetrics[mMetric] += (TimeStamp::Now() - mStart).ToMilliseconds();
-}
-
-} // namespace mozilla
diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h
index df584b489..c9f773f5b 100644
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -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;
@@ -4508,43 +4512,4 @@ public:
mutable mozilla::Maybe<bool> mIsFrameSelected;
};
-namespace mozilla {
-
-class PaintTelemetry
-{
- public:
- enum class Metric {
- DisplayList,
- Layerization,
- Rasterization,
- COUNT,
- };
-
- class AutoRecord
- {
- public:
- explicit AutoRecord(Metric aMetric);
- ~AutoRecord();
- private:
- Metric mMetric;
- mozilla::TimeStamp mStart;
- };
-
- class AutoRecordPaint
- {
- public:
- AutoRecordPaint();
- ~AutoRecordPaint();
- private:
- mozilla::TimeStamp mStart;
- };
-
- private:
- static uint32_t sPaintLevel;
- static uint32_t sMetricLevel;
- static mozilla::EnumeratedArray<Metric, Metric::COUNT, double> sMetrics;
-};
-
-} // namespace mozilla
-
#endif /*NSDISPLAYLIST_H_*/
diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp
index c1f4ad372..f0341f9ef 100644
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -111,13 +111,13 @@
#include "FrameLayerBuilder.h"
#include "mozilla/layers/APZCTreeManager.h"
#include "mozilla/layers/CompositorBridgeChild.h"
-#include "mozilla/Telemetry.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/EventStateManager.h"
#include "mozilla/RuleNodeCacheConditions.h"
#include "mozilla/StyleSetHandle.h"
#include "mozilla/StyleSetHandleInlines.h"
#include "RegionBuilder.h"
+#include "SVGSVGElement.h"
#ifdef MOZ_XUL
#include "nsXULPopupManager.h"
@@ -3534,8 +3534,6 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
PROFILER_LABEL("nsLayoutUtils", "PaintFrame::BuildDisplayList",
js::ProfileEntry::Category::GRAPHICS);
-
- PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::DisplayList);
aFrame->BuildDisplayListForStackingContext(&builder, dirtyRect, &list);
}
@@ -6938,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;
}
@@ -9296,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;
+}
diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h
index 97fc410b0..63253fd10 100644
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -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;
diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp
index 340042b46..969ebc962 100644
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -170,7 +170,6 @@
#include "mozilla/css/ImageLoader.h"
#include "mozilla/dom/DocumentTimeline.h"
#include "mozilla/Preferences.h"
-#include "mozilla/Telemetry.h"
#include "nsCanvasFrame.h"
#include "nsIImageLoadingContent.h"
#include "nsImageFrame.h"
@@ -9394,9 +9393,6 @@ PresShell::DoVerifyReflow()
}
#endif
-// used with Telemetry metrics
-#define NS_LONG_REFLOW_TIME_MS 5000
-
bool
PresShell::ProcessReflowCommands(bool aInterruptible)
{
diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp
index b975a69dd..5ea7a0188 100644
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -55,7 +55,6 @@
#include "nsDocShell.h"
#include "nsISimpleEnumerator.h"
#include "nsJSEnvironment.h"
-#include "mozilla/Telemetry.h"
#include "gfxPrefs.h"
#include "BackgroundChild.h"
#include "mozilla/ipc/PBackgroundChild.h"
@@ -524,46 +523,10 @@ private:
private:
~RefreshDriverVsyncObserver() = default;
- void RecordTelemetryProbes(TimeStamp aVsyncTimestamp)
- {
- MOZ_ASSERT(NS_IsMainThread());
- #ifndef ANDROID /* bug 1142079 */
- if (XRE_IsParentProcess()) {
- TimeDuration vsyncLatency = TimeStamp::Now() - aVsyncTimestamp;
- uint32_t sample = (uint32_t)vsyncLatency.ToMilliseconds();
- RecordJank(sample);
- } else if (mVsyncRate != TimeDuration::Forever()) {
- TimeDuration contentDelay = (TimeStamp::Now() - mLastChildTick) - mVsyncRate;
- if (contentDelay.ToMilliseconds() < 0 ){
- // Vsyncs are noisy and some can come at a rate quicker than
- // the reported hardware rate. In those cases, consider that we have 0 delay.
- contentDelay = TimeDuration::FromMilliseconds(0);
- }
- uint32_t sample = (uint32_t)contentDelay.ToMilliseconds();
- RecordJank(sample);
- } else {
- // Request the vsync rate from the parent process. Might be a few vsyncs
- // until the parent responds.
- mVsyncRate = mVsyncRefreshDriverTimer->mVsyncChild->GetVsyncRate();
- }
- #endif
- }
-
- void RecordJank(uint32_t aJankMS)
- {
- uint32_t duration = 1 /* ms */;
- for (size_t i = 0;
- i < mozilla::ArrayLength(sJankLevels) && duration < aJankMS;
- ++i, duration *= 2) {
- sJankLevels[i]++;
- }
- }
-
void TickRefreshDriver(TimeStamp aVsyncTimestamp)
{
MOZ_ASSERT(NS_IsMainThread());
- RecordTelemetryProbes(aVsyncTimestamp);
if (XRE_IsParentProcess()) {
MonitorAutoLock lock(mRefreshTickLock);
aVsyncTimestamp = mRecentVsync;
@@ -2006,7 +1969,6 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
mViewManagerFlushIsPending = false;
RefPtr<nsViewManager> vm = mPresContext->GetPresShell()->GetViewManager();
{
- PaintTelemetry::AutoRecordPaint record;
vm->ProcessPendingUpdates();
}