diff options
Diffstat (limited to 'layout')
77 files changed, 1406 insertions, 918 deletions
diff --git a/layout/base/nsArenaMemoryStats.h b/layout/base/nsArenaMemoryStats.h index ba09baaa4..2a872cfe8 100644 --- a/layout/base/nsArenaMemoryStats.h +++ b/layout/base/nsArenaMemoryStats.h @@ -18,7 +18,12 @@ public: Other // Everything else. }; - nsTabSizes() { mozilla::PodZero(this); } + nsTabSizes() + : mDom(0) + , mStyle(0) + , mOther(0) + { + } void add(Kind kind, size_t n) { 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 054632ad7..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(); } @@ -2516,7 +2610,6 @@ nsCSSRendering::PaintGradient(nsPresContext* aPresContext, PROFILER_LABEL("nsCSSRendering", "PaintGradient", js::ProfileEntry::Category::GRAPHICS); - Telemetry::AutoTimer<Telemetry::GRADIENT_DURATION, Telemetry::Microsecond> gradientTimer; if (aDest.IsEmpty() || aFillArea.IsEmpty()) { return; } @@ -3164,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)) { @@ -3240,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(), @@ -3257,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)) { @@ -3280,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; @@ -3326,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) { @@ -3335,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 @@ -3570,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) { @@ -3595,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()); } } @@ -3606,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, @@ -3651,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/nsCaret.cpp b/layout/base/nsCaret.cpp index 8ad435950..eca22f3ba 100644 --- a/layout/base/nsCaret.cpp +++ b/layout/base/nsCaret.cpp @@ -117,6 +117,12 @@ IsBidiUI() return Preferences::GetBool("bidi.browser.ui"); } +static bool +CjkThickCaret() +{ + return Preferences::GetBool("layout.cjkthickcaret"); +} + nsCaret::nsCaret() : mOverrideOffset(0) , mBlinkCount(-1) @@ -190,7 +196,7 @@ nsCaret::ComputeMetrics(nsIFrame* aFrame, int32_t aOffset, nscoord aCaretHeight) nsPresContext::CSSPixelsToAppUnits( LookAndFeel::GetInt(LookAndFeel::eIntID_CaretWidth, 1)); - if (DrawCJKCaret(aFrame, aOffset)) { + if (DrawCJKCaret(aFrame, aOffset) && CjkThickCaret()) { caretWidth += nsPresContext::CSSPixelsToAppUnits(1); } nscoord bidiIndicatorSize = nsPresContext::CSSPixelsToAppUnits(kMinBidiIndicatorPixels); diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index cb55bb2da..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,106 +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(); - - // Record the total time. - Telemetry::Accumulate(Telemetry::CONTENT_PAINT_TIME, static_cast<uint32_t>(totalMs)); - - // 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); - - nsDependentCString key(aKey); - Telemetry::Accumulate(Telemetry::CONTENT_LARGE_PAINT_PHASE_WEIGHT, key, amount); - }; - - 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/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index 7b8734928..5478c61b0 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -1206,11 +1206,8 @@ nsDocumentViewer::PermitUnloadInternal(bool *aShouldPrompt, nsIDocument::PageUnloadingEventTimeStamp timestamp(mDocument); mInPermitUnload = true; - { - Telemetry::AutoTimer<Telemetry::HANDLE_BEFOREUNLOAD_MS> telemetryTimer; - EventDispatcher::DispatchDOMEvent(window, nullptr, event, mPresContext, + EventDispatcher::DispatchDOMEvent(window, nullptr, event, mPresContext, nullptr); - } mInPermitUnload = false; } @@ -1275,7 +1272,6 @@ nsDocumentViewer::PermitUnloadInternal(bool *aShouldPrompt, nsAutoSyncOperation sync(mDocument); mInPermitUnloadPrompt = true; - mozilla::Telemetry::Accumulate(mozilla::Telemetry::ONBEFOREUNLOAD_PROMPT_COUNT, 1); rv = prompt->ConfirmEx(title, message, buttonFlags, leaveLabel, stayLabel, nullptr, nullptr, &dummy, &buttonPressed); @@ -1290,15 +1286,12 @@ nsDocumentViewer::PermitUnloadInternal(bool *aShouldPrompt, // XXX: Are there other cases where prompts can abort? Is it ok to // prevent unloading the page in those cases? if (NS_FAILED(rv)) { - mozilla::Telemetry::Accumulate(mozilla::Telemetry::ONBEFOREUNLOAD_PROMPT_ACTION, 2); *aPermitUnload = false; return NS_OK; } // Button 0 == leave, button 1 == stay *aPermitUnload = (buttonPressed == 0); - mozilla::Telemetry::Accumulate(mozilla::Telemetry::ONBEFOREUNLOAD_PROMPT_ACTION, - (*aPermitUnload ? 1 : 0)); // If the user decided to go ahead, make sure not to prompt the user again // by toggling the internal prompting bool to false: if (*aPermitUnload) { @@ -1393,10 +1386,7 @@ nsDocumentViewer::PageHide(bool aIsUnload) nsIDocument::PageUnloadingEventTimeStamp timestamp(mDocument); - { - Telemetry::AutoTimer<Telemetry::HANDLE_UNLOAD_MS> telemetryTimer; - EventDispatcher::Dispatch(window, mPresContext, &event, nullptr, &status); - } + EventDispatcher::Dispatch(window, mPresContext, &event, nullptr, &status); } #ifdef MOZ_XUL diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 062fbfe15..07befdc81 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" @@ -2681,6 +2681,10 @@ nsLayoutUtils::GetTransformToAncestorScaleExcludingAnimated(nsIFrame* aFrame) nsIFrame* nsLayoutUtils::FindNearestCommonAncestorFrame(nsIFrame* aFrame1, nsIFrame* aFrame2) { + if (!aFrame1 || !aFrame2) { + return nullptr; + } + AutoTArray<nsIFrame*,100> ancestors1; AutoTArray<nsIFrame*,100> ancestors2; nsIFrame* commonAncestor = nullptr; @@ -3423,7 +3427,6 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram return NS_OK; } - TimeStamp startBuildDisplayList = TimeStamp::Now(); nsDisplayListBuilder builder(aFrame, aBuilderMode, !(aFlags & PaintFrameFlags::PAINT_HIDE_CARET)); if (aFlags & PaintFrameFlags::PAINT_IN_TRANSFORM) { @@ -3535,8 +3538,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); } @@ -3569,8 +3570,6 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram } builder.LeavePresShell(aFrame, &list); - Telemetry::AccumulateTimeDelta(Telemetry::PAINT_BUILD_DISPLAYLIST_TIME, - startBuildDisplayList); bool profilerNeedsDisplayList = profiler_feature_active("displaylistdump"); bool consoleNeedsDisplayList = gfxUtils::DumpDisplayList() || gfxEnv::DumpPaint(); @@ -3651,8 +3650,6 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram TimeStamp paintStart = TimeStamp::Now(); RefPtr<LayerManager> layerManager = list.PaintRoot(&builder, aRenderingContext, flags); - Telemetry::AccumulateTimeDelta(Telemetry::PAINT_RASTERIZE_TIME, - paintStart); if (gfxPrefs::GfxLoggingPaintedPixelCountEnabled()) { TimeStamp now = TimeStamp::Now(); @@ -6943,7 +6940,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; } @@ -9301,3 +9298,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..0a82dbf6a 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. @@ -1437,13 +1439,14 @@ public: /** * This function increases an initial intrinsic size, 'aCurrent', according * to the given 'aPercent', such that the size-increase makes up exactly - * 'aPercent' percent of the returned value. If 'aPercent' is less than - * or equal to zero the original 'aCurrent' value is returned. If 'aPercent' - * is greater than or equal to 1.0 the value nscoord_MAX is returned. + * 'aPercent' percent of the returned value. If 'aPercent' or 'aCurrent' are + * less than or equal to zero the original 'aCurrent' value is returned. + * If 'aPercent' is greater than or equal to 1.0 the value nscoord_MAX is + * returned. */ static nscoord AddPercents(nscoord aCurrent, float aPercent) { - if (aPercent > 0.0f) { + if (aPercent > 0.0f && aCurrent > 0) { return MOZ_UNLIKELY(aPercent >= 1.0f) ? nscoord_MAX : NSToCoordRound(float(aCurrent) / (1.0f - aPercent)); } @@ -2870,6 +2873,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 3e5320c22..5dfbb8dba 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" @@ -1111,21 +1110,6 @@ PresShell::Destroy() LogTextPerfStats(tp, this, tp->cumulative, 0.0, eLog_totals, nullptr); } } - if (mPresContext) { - const bool mayFlushUserFontSet = false; - gfxUserFontSet* fs = mPresContext->GetUserFontSet(mayFlushUserFontSet); - if (fs) { - uint32_t fontCount; - uint64_t fontSize; - fs->GetLoadStatistics(fontCount, fontSize); - Telemetry::Accumulate(Telemetry::WEBFONT_PER_PAGE, fontCount); - Telemetry::Accumulate(Telemetry::WEBFONT_SIZE_PER_PAGE, - uint32_t(fontSize/1024)); - } else { - Telemetry::Accumulate(Telemetry::WEBFONT_PER_PAGE, 0); - Telemetry::Accumulate(Telemetry::WEBFONT_SIZE_PER_PAGE, 0); - } - } #ifdef MOZ_REFLOW_PERF DumpReflows(); @@ -2276,8 +2260,6 @@ PresShell::ScrollPage(bool aForward) nsIScrollableFrame* scrollFrame = GetFrameToScrollAsScrollable(nsIPresShell::eVertical); if (scrollFrame) { - mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS, - (uint32_t) ScrollInputMethod::MainThreadScrollPage); scrollFrame->ScrollBy(nsIntPoint(0, aForward ? 1 : -1), nsIScrollableFrame::PAGES, nsIScrollableFrame::SMOOTH, @@ -2294,9 +2276,6 @@ PresShell::ScrollLine(bool aForward) nsIScrollableFrame* scrollFrame = GetFrameToScrollAsScrollable(nsIPresShell::eVertical); if (scrollFrame) { - mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS, - (uint32_t) ScrollInputMethod::MainThreadScrollLine); - int32_t lineCount = Preferences::GetInt("toolkit.scrollbox.verticalScrollDistance", NS_DEFAULT_VERTICAL_SCROLL_DISTANCE); scrollFrame->ScrollBy(nsIntPoint(0, aForward ? lineCount : -lineCount), @@ -2315,8 +2294,6 @@ PresShell::ScrollCharacter(bool aRight) nsIScrollableFrame* scrollFrame = GetFrameToScrollAsScrollable(nsIPresShell::eHorizontal); if (scrollFrame) { - mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS, - (uint32_t) ScrollInputMethod::MainThreadScrollCharacter); int32_t h = Preferences::GetInt("toolkit.scrollbox.horizontalScrollDistance", NS_DEFAULT_HORIZONTAL_SCROLL_DISTANCE); scrollFrame->ScrollBy(nsIntPoint(aRight ? h : -h, 0), @@ -2335,8 +2312,6 @@ PresShell::CompleteScroll(bool aForward) nsIScrollableFrame* scrollFrame = GetFrameToScrollAsScrollable(nsIPresShell::eVertical); if (scrollFrame) { - mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS, - (uint32_t) ScrollInputMethod::MainThreadCompleteScroll); scrollFrame->ScrollBy(nsIntPoint(0, aForward ? 1 : -1), nsIScrollableFrame::WHOLE, nsIScrollableFrame::SMOOTH, @@ -7321,11 +7296,11 @@ PresShell::HandleEvent(nsIFrame* aFrame, return NS_OK; } - nsIContent* capturingContent = ((aEvent->mClass == ePointerEventClass || - aEvent->mClass == eWheelEventClass || - aEvent->HasMouseEventMessage()) - ? GetCapturingContent() - : nullptr); + nsCOMPtr<nsIContent> capturingContent = ((aEvent->mClass == ePointerEventClass || + aEvent->mClass == eWheelEventClass || + aEvent->HasMouseEventMessage()) + ? GetCapturingContent() + : nullptr); nsCOMPtr<nsIDocument> retargetEventDoc; if (!aDontRetargetEvents) { @@ -8231,16 +8206,6 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent, } } - if (Telemetry::CanRecordBase() && - !aEvent->mTimeStamp.IsNull() && - aEvent->AsInputEvent()) { - double millis = (TimeStamp::Now() - aEvent->mTimeStamp).ToMilliseconds(); - Telemetry::Accumulate(Telemetry::INPUT_EVENT_RESPONSE_MS, millis); - if (mDocument && mDocument->GetReadyStateEnum() != nsIDocument::READYSTATE_COMPLETE) { - Telemetry::Accumulate(Telemetry::LOAD_INPUT_EVENT_RESPONSE_MS, millis); - } - } - return rv; } @@ -9428,9 +9393,6 @@ PresShell::DoVerifyReflow() } #endif -// used with Telemetry metrics -#define NS_LONG_REFLOW_TIME_MS 5000 - bool PresShell::ProcessReflowCommands(bool aInterruptible) { @@ -9439,7 +9401,6 @@ PresShell::ProcessReflowCommands(bool aInterruptible) return true; } - mozilla::TimeStamp timerStart = mozilla::TimeStamp::Now(); bool interrupted = false; if (!mDirtyRoots.IsEmpty()) { @@ -9522,16 +9483,6 @@ PresShell::ProcessReflowCommands(bool aInterruptible) UnsuppressAndInvalidate(); } - if (mDocument->GetRootElement()) { - TimeDuration elapsed = TimeStamp::Now() - timerStart; - int32_t intElapsed = int32_t(elapsed.ToMilliseconds()); - - if (intElapsed > NS_LONG_REFLOW_TIME_MS) { - Telemetry::Accumulate(Telemetry::LONG_REFLOW_INTERRUPTIBLE, - aInterruptible ? 1 : 0); - } - } - return !interrupted; } diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index 6676bea97..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" @@ -143,11 +142,7 @@ public: { } - virtual ~RefreshDriverTimer() - { - MOZ_ASSERT(mContentRefreshDrivers.Length() == 0, "Should have removed all content refresh drivers from here by now!"); - MOZ_ASSERT(mRootRefreshDrivers.Length() == 0, "Should have removed all root refresh drivers from here by now!"); - } + NS_INLINE_DECL_REFCOUNTING(RefreshDriverTimer) virtual void AddRefreshDriver(nsRefreshDriver* aDriver) { @@ -253,6 +248,12 @@ public: } protected: + virtual ~RefreshDriverTimer() + { + MOZ_ASSERT(mContentRefreshDrivers.Length() == 0, "Should have removed all content refresh drivers from here by now!"); + MOZ_ASSERT(mRootRefreshDrivers.Length() == 0, "Should have removed all root refresh drivers from here by now!"); + } + virtual void StartTimer() = 0; virtual void StopTimer() = 0; virtual void ScheduleNextTick(TimeStamp aNowTime) = 0; @@ -335,10 +336,11 @@ protected: nsTArray<RefPtr<nsRefreshDriver> > mRootRefreshDrivers; // useful callback for nsITimer-based derived classes, here - // bacause of c++ protected shenanigans + // because of c++ protected shenanigans static void TimerTick(nsITimer* aTimer, void* aClosure) { - RefreshDriverTimer *timer = static_cast<RefreshDriverTimer*>(aClosure); + RefPtr<RefreshDriverTimer> timer = + static_cast<RefreshDriverTimer*>(aClosure); timer->Tick(); } }; @@ -459,9 +461,7 @@ public: private: // Since VsyncObservers are refCounted, but the RefreshDriverTimer are // explicitly shutdown. We create an inner class that has the VsyncObserver - // and is shutdown when the RefreshDriverTimer is deleted. The alternative is - // to (a) make all RefreshDriverTimer RefCounted or (b) use different - // VsyncObserver types. + // and is shutdown when the RefreshDriverTimer is deleted. class RefreshDriverVsyncObserver final : public VsyncObserver { public: @@ -478,6 +478,9 @@ private: bool NotifyVsync(TimeStamp aVsyncTimestamp) override { + // IMPORTANT: All paths through this method MUST hold a strong ref on + // |this| for the duration of the TickRefreshDriver callback. + if (!NS_IsMainThread()) { MOZ_ASSERT(XRE_IsParentProcess()); // Compress vsync notifications such that only 1 may run at a time @@ -498,6 +501,7 @@ private: aVsyncTimestamp); NS_DispatchToMainThread(vsyncEvent); } else { + RefPtr<RefreshDriverVsyncObserver> kungFuDeathGrip(this); TickRefreshDriver(aVsyncTimestamp); } @@ -519,54 +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(); - Telemetry::Accumulate(Telemetry::FX_REFRESH_DRIVER_CHROME_FRAME_DELAY_MS, - sample); - Telemetry::Accumulate(Telemetry::FX_REFRESH_DRIVER_SYNC_SCROLL_FRAME_DELAY_MS, - sample); - 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(); - Telemetry::Accumulate(Telemetry::FX_REFRESH_DRIVER_CONTENT_FRAME_DELAY_MS, - sample); - Telemetry::Accumulate(Telemetry::FX_REFRESH_DRIVER_SYNC_SCROLL_FRAME_DELAY_MS, - sample); - 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; @@ -580,7 +540,9 @@ private: // the scheduled TickRefreshDriver() runs. Check mVsyncRefreshDriverTimer // before use. if (mVsyncRefreshDriverTimer) { - mVsyncRefreshDriverTimer->RunRefreshDrivers(aVsyncTimestamp); + RefPtr<VsyncRefreshDriverTimer> timer = mVsyncRefreshDriverTimer; + timer->RunRefreshDrivers(aVsyncTimestamp); + // Note: mVsyncRefreshDriverTimer might be null now. } } @@ -833,7 +795,8 @@ protected: static void TimerTickOne(nsITimer* aTimer, void* aClosure) { - InactiveRefreshDriverTimer *timer = static_cast<InactiveRefreshDriverTimer*>(aClosure); + RefPtr<InactiveRefreshDriverTimer> timer = + static_cast<InactiveRefreshDriverTimer*>(aClosure); timer->TickOne(); } @@ -885,8 +848,8 @@ NS_IMPL_ISUPPORTS(VsyncChildCreateCallback, nsIIPCBackgroundChildCreateCallback) } // namespace mozilla -static RefreshDriverTimer* sRegularRateTimer; -static InactiveRefreshDriverTimer* sThrottledRateTimer; +static StaticRefPtr<RefreshDriverTimer> sRegularRateTimer; +static StaticRefPtr<InactiveRefreshDriverTimer> sThrottledRateTimer; #ifdef XP_WIN static int32_t sHighPrecisionTimerRequests = 0; @@ -968,8 +931,6 @@ GetFirstFrameDelay(imgIRequest* req) nsRefreshDriver::Shutdown() { // clean up our timers - delete sRegularRateTimer; - delete sThrottledRateTimer; sRegularRateTimer = nullptr; sThrottledRateTimer = nullptr; @@ -2008,7 +1969,6 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime) mViewManagerFlushIsPending = false; RefPtr<nsViewManager> vm = mPresContext->GetPresShell()->GetViewManager(); { - PaintTelemetry::AutoRecordPaint record; vm->ProcessPendingUpdates(); } @@ -2027,10 +1987,6 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime) notifyGC = true; } -#ifndef ANDROID /* bug 1142079 */ - mozilla::Telemetry::AccumulateTimeDelta(mozilla::Telemetry::REFRESH_DRIVER_TICK, mTickStart); -#endif - nsTObserverArray<nsAPostRefreshObserver*>::ForwardIterator iter(mPostRefreshObservers); while (iter.HasMore()) { nsAPostRefreshObserver* observer = iter.GetNext(); @@ -2237,16 +2193,15 @@ nsRefreshDriver::PVsyncActorCreated(VsyncChild* aVsyncChild) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!XRE_IsParentProcess()); - auto* vsyncRefreshDriverTimer = - new VsyncRefreshDriverTimer(aVsyncChild); + RefPtr<RefreshDriverTimer> vsyncRefreshDriverTimer = + new VsyncRefreshDriverTimer(aVsyncChild); // If we are using software timer, swap current timer to // VsyncRefreshDriverTimer. if (sRegularRateTimer) { sRegularRateTimer->SwapRefreshDrivers(vsyncRefreshDriverTimer); - delete sRegularRateTimer; } - sRegularRateTimer = vsyncRefreshDriverTimer; + sRegularRateTimer = vsyncRefreshDriverTimer.forget(); } void diff --git a/layout/build/nsLayoutCID.h b/layout/build/nsLayoutCID.h index 47a90d7d8..1b43c7592 100644 --- a/layout/build/nsLayoutCID.h +++ b/layout/build/nsLayoutCID.h @@ -82,7 +82,4 @@ #define SERVICEWORKERMANAGER_CID \ { 0xc74bde32, 0xbcc7, 0x4840, { 0x84, 0x30, 0xc7, 0x33, 0x35, 0x1b, 0x21, 0x2a } } -#define NOTIFICATIONTELEMETRYSERVICE_CID \ -{ 0x5995b782, 0x6a0e, 0x4066, { 0xaa, 0xc5, 0x27, 0x6f, 0x0a, 0x9a, 0xd8, 0xcf } } - #endif /* nsLayoutCID_h__ */ diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index 748bc11d8..8bb70f85c 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -204,7 +204,6 @@ using mozilla::dom::UDPSocketChild; using mozilla::dom::time::TimeService; using mozilla::net::StreamingProtocolControllerService; using mozilla::gmp::GeckoMediaPluginService; -using mozilla::dom::NotificationTelemetryService; #define NS_EDITORCOMMANDTABLE_CID \ { 0x4f5e62b8, 0xd659, 0x4156, \ @@ -292,7 +291,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(TextInputProcessor) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIPresentationService, NS_CreatePresentationService) NS_GENERIC_FACTORY_CONSTRUCTOR(PresentationTCPSessionTransport) -NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(NotificationTelemetryService, Init) NS_GENERIC_FACTORY_CONSTRUCTOR(PushNotifier) //----------------------------------------------------------------------------- @@ -657,7 +655,6 @@ NS_DEFINE_NAMED_CID(NS_TEXTEDITOR_CID); NS_DEFINE_NAMED_CID(DOMREQUEST_SERVICE_CID); NS_DEFINE_NAMED_CID(QUOTAMANAGER_SERVICE_CID); NS_DEFINE_NAMED_CID(SERVICEWORKERMANAGER_CID); -NS_DEFINE_NAMED_CID(NOTIFICATIONTELEMETRYSERVICE_CID); NS_DEFINE_NAMED_CID(PUSHNOTIFIER_CID); NS_DEFINE_NAMED_CID(WORKERDEBUGGERMANAGER_CID); @@ -925,7 +922,6 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = { { &kDOMREQUEST_SERVICE_CID, false, nullptr, DOMRequestServiceConstructor }, { &kQUOTAMANAGER_SERVICE_CID, false, nullptr, QuotaManagerServiceConstructor }, { &kSERVICEWORKERMANAGER_CID, false, nullptr, ServiceWorkerManagerConstructor }, - { &kNOTIFICATIONTELEMETRYSERVICE_CID, false, nullptr, NotificationTelemetryServiceConstructor }, { &kPUSHNOTIFIER_CID, false, nullptr, PushNotifierConstructor }, { &kWORKERDEBUGGERMANAGER_CID, true, nullptr, WorkerDebuggerManagerConstructor }, { &kNS_AUDIOCHANNELAGENT_CID, true, nullptr, AudioChannelAgentConstructor }, @@ -1057,7 +1053,6 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = { { DOMREQUEST_SERVICE_CONTRACTID, &kDOMREQUEST_SERVICE_CID }, { QUOTAMANAGER_SERVICE_CONTRACTID, &kQUOTAMANAGER_SERVICE_CID }, { SERVICEWORKERMANAGER_CONTRACTID, &kSERVICEWORKERMANAGER_CID }, - { NOTIFICATIONTELEMETRYSERVICE_CONTRACTID, &kNOTIFICATIONTELEMETRYSERVICE_CID }, { PUSHNOTIFIER_CONTRACTID, &kPUSHNOTIFIER_CID }, { WORKERDEBUGGERMANAGER_CONTRACTID, &kWORKERDEBUGGERMANAGER_CID }, { NS_AUDIOCHANNELAGENT_CONTRACTID, &kNS_AUDIOCHANNELAGENT_CID }, @@ -1132,7 +1127,6 @@ static const mozilla::Module::CategoryEntry kLayoutCategories[] = { CONTENTDLF_CATEGORIES { "profile-after-change", "PresentationDeviceManager", PRESENTATION_DEVICE_MANAGER_CONTRACTID }, { "profile-after-change", "PresentationService", PRESENTATION_SERVICE_CONTRACTID }, - { "profile-after-change", "Notification Telemetry Service", NOTIFICATIONTELEMETRYSERVICE_CONTRACTID }, { nullptr } }; diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index 0306626c4..0f4560afe 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -92,10 +92,6 @@ #include "nsSynthVoiceRegistry.h" #endif -#ifdef MOZ_ANDROID_OMX -#include "AndroidMediaPluginHost.h" -#endif - #include "CubebUtils.h" #include "Latency.h" #include "WebAudioUtils.h" @@ -381,11 +377,6 @@ nsLayoutStatics::Shutdown() nsAutoCopyListener::Shutdown(); FrameLayerBuilder::Shutdown(); - -#ifdef MOZ_ANDROID_OMX - AndroidMediaPluginHost::Shutdown(); -#endif - CubebUtils::ShutdownLibrary(); AsyncLatencyLogger::ShutdownLogger(); WebAudioUtils::Shutdown(); diff --git a/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp index f69198cc7..5a9438939 100644 --- a/layout/forms/nsComboboxControlFrame.cpp +++ b/layout/forms/nsComboboxControlFrame.cpp @@ -1040,6 +1040,9 @@ nsComboboxControlFrame::HandleRedisplayTextEvent() mRedisplayTextEvent.Forget(); ActuallyDisplayText(true); + if (!weakThis.IsAlive()) + return; + // XXXbz This should perhaps be eResize. Check. PresContext()->PresShell()->FrameNeedsReflow(mDisplayFrame, nsIPresShell::eStyleChange, diff --git a/layout/forms/nsNumberControlFrame.cpp b/layout/forms/nsNumberControlFrame.cpp index 74dec2bea..9724109cb 100644 --- a/layout/forms/nsNumberControlFrame.cpp +++ b/layout/forms/nsNumberControlFrame.cpp @@ -430,6 +430,8 @@ nsNumberControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements) nsContentUtils::AddScriptRunner(focusJob); } + SyncDisabledState(); + if (StyleDisplay()->mAppearance == NS_THEME_TEXTFIELD) { // The author has elected to hide the spinner by setting this // -moz-appearance. We will reframe if it changes. @@ -461,8 +463,6 @@ nsNumberControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements) CSSPseudoElementType::mozNumberSpinDown, spinBoxCI.mStyleContext); - SyncDisabledState(); - return rv; } diff --git a/layout/generic/nsAbsoluteContainingBlock.cpp b/layout/generic/nsAbsoluteContainingBlock.cpp index 7c48aae92..e3c847d01 100644 --- a/layout/generic/nsAbsoluteContainingBlock.cpp +++ b/layout/generic/nsAbsoluteContainingBlock.cpp @@ -409,14 +409,30 @@ OffsetToAlignedStaticPos(const ReflowInput& aKidReflowInput, ? GetOrthogonalAxis(aAbsPosCBAxis) : aAbsPosCBAxis); + const bool placeholderContainerIsContainingBlock = + aPlaceholderContainer == aKidReflowInput.mCBReflowInput->mFrame; + nsIAtom* parentType = aPlaceholderContainer->GetType(); LogicalSize alignAreaSize(pcWM); if (parentType == nsGkAtoms::flexContainerFrame) { - // The alignment container is the flex container's content box: - alignAreaSize = aPlaceholderContainer->GetLogicalSize(pcWM); - LogicalMargin pcBorderPadding = - aPlaceholderContainer->GetLogicalUsedBorderAndPadding(pcWM); - alignAreaSize -= pcBorderPadding.Size(pcWM); + // We store the frame rect in FinishAndStoreOverflow, which runs _after_ + // reflowing the absolute frames, so handle the special case of the frame + // being the actual containing block here, by getting the size from + // aAbsPosCBSize. + // + // The alignment container is the flex container's content box. + if (placeholderContainerIsContainingBlock) { + alignAreaSize = aAbsPosCBSize.ConvertTo(pcWM, aAbsPosCBWM); + // aAbsPosCBSize is the padding-box, so substract the padding to get the + // content box. + alignAreaSize -= + aPlaceholderContainer->GetLogicalUsedPadding(pcWM).Size(pcWM); + } else { + alignAreaSize = aPlaceholderContainer->GetLogicalSize(pcWM); + LogicalMargin pcBorderPadding = + aPlaceholderContainer->GetLogicalUsedBorderAndPadding(pcWM); + alignAreaSize -= pcBorderPadding.Size(pcWM); + } } else if (parentType == nsGkAtoms::gridContainerFrame) { // This abspos elem's parent is a grid container. Per CSS Grid 10.1 & 10.2: // - If the grid container *also* generates the abspos containing block (a @@ -424,7 +440,7 @@ OffsetToAlignedStaticPos(const ReflowInput& aKidReflowInput, // the alignment container, too. (And its size is aAbsPosCBSize.) // - Otherwise, we use the grid's padding box as the alignment container. // https://drafts.csswg.org/css-grid/#static-position - if (aPlaceholderContainer == aKidReflowInput.mCBReflowInput->mFrame) { + if (placeholderContainerIsContainingBlock) { // The alignment container is the grid area that we're using as the // absolute containing block. alignAreaSize = aAbsPosCBSize.ConvertTo(pcWM, aAbsPosCBWM); diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index ccdc3a0ce..3ed3b0bb3 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -1774,6 +1774,18 @@ public: return true; } + /** + * The mCallee holds a strong ref to us since the refresh driver doesn't. + * Our dtor and mCallee's Destroy() method both call RemoveObserver() - + * whichever comes first removes us from the refresh driver. + */ + void RemoveObserver() { + if (mCallee) { + RefreshDriver(mCallee)->RemoveRefreshObserver(this, Flush_Style); + mCallee = nullptr; + } + } + private: // Private destructor, to discourage deletion outside of Release(): ~AsyncSmoothMSDScroll() { @@ -1786,17 +1798,6 @@ private: return aCallee->mOuter->PresContext()->RefreshDriver(); } - /* - * The refresh driver doesn't hold a reference to its observers, - * so releasing this object can (and is) used to remove the observer on DTOR. - * Currently, this object is released once the scrolling ends. - */ - void RemoveObserver() { - if (mCallee) { - RefreshDriver(mCallee)->RemoveRefreshObserver(this, Flush_Style); - } - } - mozilla::layers::AxisPhysicsMSDModel mXAxisModel, mYAxisModel; nsRect mRange; mozilla::TimeStamp mLastRefreshTime; @@ -1875,24 +1876,25 @@ public: ScrollFrameHelper::AsyncScrollCallback(mCallee, aTime); } -private: - ScrollFrameHelper *mCallee; - - nsRefreshDriver* RefreshDriver(ScrollFrameHelper* aCallee) { - return aCallee->mOuter->PresContext()->RefreshDriver(); - } - - /* - * The refresh driver doesn't hold a reference to its observers, - * so releasing this object can (and is) used to remove the observer on DTOR. - * Currently, this object is released once the scrolling ends. + /** + * The mCallee holds a strong ref to us since the refresh driver doesn't. + * Our dtor and mCallee's Destroy() method both call RemoveObserver() - + * whichever comes first removes us from the refresh driver. */ void RemoveObserver() { if (mCallee) { RefreshDriver(mCallee)->RemoveRefreshObserver(this, Flush_Style); APZCCallbackHelper::SuppressDisplayport(false, mCallee->mOuter->PresContext()->PresShell()); + mCallee = nullptr; } } + +private: + ScrollFrameHelper *mCallee; + + nsRefreshDriver* RefreshDriver(ScrollFrameHelper* aCallee) { + return aCallee->mOuter->PresContext()->RefreshDriver(); + } }; /* @@ -2150,8 +2152,7 @@ void ScrollFrameHelper::CompleteAsyncScroll(const nsRect &aRange, nsIAtom* aOrigin) { // Apply desired destination range since this is the last step of scrolling. - mAsyncSmoothMSDScroll = nullptr; - mAsyncScroll = nullptr; + RemoveObservers(); nsWeakFrame weakFrame(mOuter); ScrollToImpl(mDestination, aRange, aOrigin); if (!weakFrame.IsAlive()) { @@ -4586,6 +4587,20 @@ ScrollFrameHelper::Destroy() mScrollActivityTimer->Cancel(); mScrollActivityTimer = nullptr; } + RemoveObservers(); +} + +void +ScrollFrameHelper::RemoveObservers() +{ + if (mAsyncScroll) { + mAsyncScroll->RemoveObserver(); + mAsyncScroll = nullptr; + } + if (mAsyncSmoothMSDScroll) { + mAsyncSmoothMSDScroll->RemoveObserver(); + mAsyncSmoothMSDScroll = nullptr; + } } /** diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index f1ef44ae8..81bbb358f 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -638,6 +638,9 @@ protected: bool HasBgAttachmentLocal() const; uint8_t GetScrolledFrameDir() const; + // Removes any RefreshDriver observers we might have registered. + void RemoveObservers(); + static void EnsureFrameVisPrefsCached(); static bool sFrameVisPrefsCached; // The number of scrollports wide/high to expand when tracking frame visibility. diff --git a/layout/generic/nsGridContainerFrame.cpp b/layout/generic/nsGridContainerFrame.cpp index 8f117b5ab..fbd61f783 100644 --- a/layout/generic/nsGridContainerFrame.cpp +++ b/layout/generic/nsGridContainerFrame.cpp @@ -3714,8 +3714,11 @@ MeasuringReflow(nsIFrame* aChild, parent->Properties().Set( nsContainerFrame::DebugReflowingWithInfiniteISize(), true); #endif - uint32_t riFlags = ReflowInput::COMPUTE_SIZE_SHRINK_WRAP | - ReflowInput::COMPUTE_SIZE_USE_AUTO_BSIZE; + auto wm = aChild->GetWritingMode(); + uint32_t riFlags = ReflowInput::COMPUTE_SIZE_USE_AUTO_BSIZE; + if (aAvailableSize.ISize(wm) == INFINITE_ISIZE_COORD) { + riFlags |= ReflowInput::COMPUTE_SIZE_SHRINK_WRAP; + } if (aIMinSizeClamp != NS_MAXSIZE) { riFlags |= ReflowInput::I_CLAMP_MARGIN_BOX_MIN_SIZE; } @@ -3730,7 +3733,6 @@ MeasuringReflow(nsIFrame* aChild, ReflowOutput childSize(childRI); nsReflowStatus childStatus; const uint32_t flags = NS_FRAME_NO_MOVE_FRAME | NS_FRAME_NO_SIZE_VIEW; - WritingMode wm = childRI.GetWritingMode(); parent->ReflowChild(aChild, pc, childSize, childRI, wm, LogicalPoint(wm), nsSize(), flags, childStatus); parent->FinishReflowChild(aChild, pc, childSize, &childRI, wm, diff --git a/layout/generic/nsLineBox.h b/layout/generic/nsLineBox.h index 8f42b9e93..962279df6 100644 --- a/layout/generic/nsLineBox.h +++ b/layout/generic/nsLineBox.h @@ -857,29 +857,47 @@ class nsLineList_iterator { return --copy; } - // Passing by value rather than by reference and reference to const - // to keep AIX happy. - bool operator==(const iterator_self_type aOther) const + bool operator==(const iterator_self_type& aOther) const { MOZ_ASSERT(mListLink == aOther.mListLink, "comparing iterators over different lists"); return mCurrent == aOther.mCurrent; } - bool operator!=(const iterator_self_type aOther) const + bool operator!=(const iterator_self_type& aOther) const { MOZ_ASSERT(mListLink == aOther.mListLink, "comparing iterators over different lists"); return mCurrent != aOther.mCurrent; } - bool operator==(const iterator_self_type aOther) + bool operator==(const iterator_self_type& aOther) { MOZ_ASSERT(mListLink == aOther.mListLink, "comparing iterators over different lists"); return mCurrent == aOther.mCurrent; } - bool operator!=(const iterator_self_type aOther) + bool operator!=(const iterator_self_type& aOther) { MOZ_ASSERT(mListLink == aOther.mListLink, "comparing iterators over different lists"); return mCurrent != aOther.mCurrent; } - + bool operator==(iterator_self_type& aOther) const + { + MOZ_ASSERT(mListLink == aOther.mListLink, "comparing iterators over different lists"); + return mCurrent == aOther.mCurrent; + } + bool operator!=(iterator_self_type& aOther) const + { + MOZ_ASSERT(mListLink == aOther.mListLink, "comparing iterators over different lists"); + return mCurrent != aOther.mCurrent; + } + bool operator==(iterator_self_type& aOther) + { + MOZ_ASSERT(mListLink == aOther.mListLink, "comparing iterators over different lists"); + return mCurrent == aOther.mCurrent; + } + bool operator!=(iterator_self_type& aOther) + { + MOZ_ASSERT(mListLink == aOther.mListLink, "comparing iterators over different lists"); + return mCurrent != aOther.mCurrent; + } + private: link_type *mCurrent; #ifdef DEBUG @@ -992,24 +1010,42 @@ class nsLineList_reverse_iterator { } #endif /* !__MWERKS__ */ - // Passing by value rather than by reference and reference to const - // to keep AIX happy. - bool operator==(const iterator_self_type aOther) const + bool operator==(const iterator_self_type& aOther) const { NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); return mCurrent == aOther.mCurrent; } - bool operator!=(const iterator_self_type aOther) const + bool operator!=(const iterator_self_type& aOther) const { NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); return mCurrent != aOther.mCurrent; } - bool operator==(const iterator_self_type aOther) + bool operator==(const iterator_self_type& aOther) { NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); return mCurrent == aOther.mCurrent; } - bool operator!=(const iterator_self_type aOther) + bool operator!=(const iterator_self_type& aOther) + { + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); + return mCurrent != aOther.mCurrent; + } + bool operator==(iterator_self_type& aOther) const + { + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); + return mCurrent == aOther.mCurrent; + } + bool operator!=(iterator_self_type& aOther) const + { + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); + return mCurrent != aOther.mCurrent; + } + bool operator==(iterator_self_type& aOther) + { + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); + return mCurrent == aOther.mCurrent; + } + bool operator!=(iterator_self_type& aOther) { NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); return mCurrent != aOther.mCurrent; @@ -1126,24 +1162,42 @@ class nsLineList_const_iterator { return --copy; } - // Passing by value rather than by reference and reference to const - // to keep AIX happy. - bool operator==(const iterator_self_type aOther) const + bool operator==(const iterator_self_type& aOther) const { NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); return mCurrent == aOther.mCurrent; } - bool operator!=(const iterator_self_type aOther) const + bool operator!=(const iterator_self_type& aOther) const { NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); return mCurrent != aOther.mCurrent; } - bool operator==(const iterator_self_type aOther) + bool operator==(const iterator_self_type& aOther) { NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); return mCurrent == aOther.mCurrent; } - bool operator!=(const iterator_self_type aOther) + bool operator!=(const iterator_self_type& aOther) + { + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); + return mCurrent != aOther.mCurrent; + } + bool operator==(iterator_self_type& aOther) const + { + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); + return mCurrent == aOther.mCurrent; + } + bool operator!=(iterator_self_type& aOther) const + { + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); + return mCurrent != aOther.mCurrent; + } + bool operator==(iterator_self_type& aOther) + { + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); + return mCurrent == aOther.mCurrent; + } + bool operator!=(iterator_self_type& aOther) { NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); return mCurrent != aOther.mCurrent; diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index a2227c39c..ff75ab85d 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -2201,8 +2201,6 @@ nsFrameSelection::CommonPageMove(bool aForward, return; // scroll one page - mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS, - (uint32_t) ScrollInputMethod::MainThreadScrollPage); aScrollableFrame->ScrollBy(nsIntPoint(0, aForward ? 1 : -1), nsIScrollableFrame::PAGES, nsIScrollableFrame::SMOOTH); @@ -3546,7 +3544,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Selection) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAnchorFocusRange) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameSelection) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelectionListeners) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Selection) @@ -6202,11 +6199,6 @@ Selection::ScrollIntoView(SelectionRegion aRegion, flags |= nsIPresShell::SCROLL_OVERFLOW_HIDDEN; } - if (aFlags & Selection::SCROLL_FOR_CARET_MOVE) { - mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS, - (uint32_t) ScrollInputMethod::MainThreadScrollCaretIntoView); - } - presShell->ScrollFrameRectIntoView(frame, rect, aVertical, aHorizontal, flags); return NS_OK; diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index fa31443fd..3288d3f2e 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -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; } } diff --git a/layout/inspector/inDOMUtils.cpp b/layout/inspector/inDOMUtils.cpp index 9f1dcaad3..e212e20df 100644 --- a/layout/inspector/inDOMUtils.cpp +++ b/layout/inspector/inDOMUtils.cpp @@ -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: diff --git a/layout/reftests/css-display/display-contents-dyn-insert-text-ref.html b/layout/reftests/css-display/display-contents-dyn-insert-text-ref.html new file mode 100644 index 000000000..a212e025e --- /dev/null +++ b/layout/reftests/css-display/display-contents-dyn-insert-text-ref.html @@ -0,0 +1,7 @@ +<!doctype html> +<meta charset="utf-8"> +<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io"> +<title>CSS Test reference - Bug 1338678</title> +<div style="display: contents"> + <div id="element">PASS</div> +</div> diff --git a/layout/reftests/css-display/display-contents-dyn-insert-text.html b/layout/reftests/css-display/display-contents-dyn-insert-text.html new file mode 100644 index 000000000..f3b0c0c95 --- /dev/null +++ b/layout/reftests/css-display/display-contents-dyn-insert-text.html @@ -0,0 +1,16 @@ +<!doctype html> +<meta charset="utf-8"> +<link rel="author" title="Markus Stange" href="mailto:mstange@themasta.com"> +<link rel="help" href="https://drafts.csswg.org/css-display/#box-generation"> +<title>Bug 1338678 - display:contents makes textContent disappear</title> +<div style="display: contents"> + <div id="element"></div> +</div> +<script> +window.onload = function() { + document.body.offsetTop; + var element = document.getElementById('element'); + element.textContent = "FAIL"; + element.textContent = "PASS"; +} +</script> diff --git a/layout/reftests/css-display/reftest.list b/layout/reftests/css-display/reftest.list index d310422bb..00f46a80b 100644 --- a/layout/reftests/css-display/reftest.list +++ b/layout/reftests/css-display/reftest.list @@ -24,5 +24,6 @@ skip pref(layout.css.display-contents.enabled,true) == display-contents-xbl-4.xu asserts(0-1) fuzzy-if(Android,8,3216) pref(layout.css.display-contents.enabled,true) == display-contents-fieldset.html display-contents-fieldset-ref.html # bug 1089223 asserts(1) pref(layout.css.display-contents.enabled,true) == display-contents-xbl-5.xul display-contents-xbl-3-ref.xul # bug 1089223 pref(layout.css.display-contents.enabled,true) == display-contents-list-item-child.html display-contents-list-item-child-ref.html +pref(layout.css.display-contents.enabled,true) == display-contents-dyn-insert-text.html display-contents-dyn-insert-text-ref.html pref(layout.css.display-contents.enabled,true) == display-contents-writing-mode-1.html display-contents-writing-mode-1-ref.html pref(layout.css.display-contents.enabled,true) == display-contents-writing-mode-2.html display-contents-writing-mode-2-ref.html diff --git a/layout/reftests/css-grid/bug1349571-ref.html b/layout/reftests/css-grid/bug1349571-ref.html new file mode 100644 index 000000000..42efd731a --- /dev/null +++ b/layout/reftests/css-grid/bug1349571-ref.html @@ -0,0 +1,90 @@ +<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Testcase for bug 1349571</title>
+ <style type="text/css">
+html,body {
+ color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
+}
+
+.container {
+ display: grid;
+ grid: 250px / 500px;
+ border: 3px solid;
+ width: 500px;
+}
+
+.responsive-container {
+ background: lightgrey;
+}
+
+ </style>
+<script>try {
+(function() {
+ var target = 'blur';
+ if ( target === '' || target === '{{1}}' ) { return; }
+ var needle = 'mz_str', reText = '.?';
+ if ( needle !== '' && needle !== '{{2}}' ) {
+ reText = /^\/.+\/$/.test(needle)
+ ? needle.slice(1,-1)
+ : needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+ }
+ var re = new RegExp(reText);
+ var chain = target.split('.');
+ var owner = window, prop;
+ for (;;) {
+ prop = chain.shift();
+ if ( chain.length === 0 ) { break; }
+ owner = owner[prop];
+ if ( owner instanceof Object === false ) { return; }
+ }
+ var desc = Object.getOwnPropertyDescriptor(owner, prop);
+ if ( desc && desc.get !== undefined ) { return; }
+ var magic = String.fromCharCode(Date.now() % 26 + 97) +
+ Math.floor(Math.random() * 982451653 + 982451653).toString(36);
+ var value = owner[prop];
+ var validate = function() {
+ var e = document.currentScript;
+ if ( e instanceof HTMLScriptElement && e.src === '' && re.test(e.textContent) ) {
+ throw new ReferenceError(magic);
+ }
+ };
+ Object.defineProperty(owner, prop, {
+ get: function() {
+ validate();
+ return value;
+ },
+ set: function(a) {
+ validate();
+ value = a;
+ }
+ });
+ var oe = window.onerror;
+ window.onerror = function(msg) {
+ if ( typeof msg === 'string' && msg.indexOf(magic) !== -1 ) {
+ return true;
+ }
+ if ( oe instanceof Function ) {
+ return oe.apply(this, arguments);
+ }
+ }.bind();
+})();
+} catch ( e ) { }
+(function() {
+ var c = document.currentScript, p = c && c.parentNode;
+ if ( p ) { p.removeChild(c); }
+})();</script></head>
+<body>
+
+<div class="container">
+ <div class="responsive-container"></div>
+</div>
+
+
+
+</body></html>
\ No newline at end of file diff --git a/layout/reftests/css-grid/bug1349571.html b/layout/reftests/css-grid/bug1349571.html new file mode 100644 index 000000000..f836fe36e --- /dev/null +++ b/layout/reftests/css-grid/bug1349571.html @@ -0,0 +1,94 @@ +<!DOCTYPE html>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <meta charset="utf-8">
+ <title>Testcase for bug 1349571</title>
+ <style type="text/css">
+html,body {
+ color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
+}
+
+.container {
+ display: grid;
+ grid-template-columns: 1fr;
+ border: 3px solid;
+ width: 500px;
+}
+
+.responsive-container {
+ padding-bottom: 50%;
+ height: 0;
+ background: lightgrey;
+}
+
+ </style>
+<script>try {
+(function() {
+ var target = 'blur';
+ if ( target === '' || target === '{{1}}' ) { return; }
+ var needle = 'mz_str', reText = '.?';
+ if ( needle !== '' && needle !== '{{2}}' ) {
+ reText = /^\/.+\/$/.test(needle)
+ ? needle.slice(1,-1)
+ : needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+ }
+ var re = new RegExp(reText);
+ var chain = target.split('.');
+ var owner = window, prop;
+ for (;;) {
+ prop = chain.shift();
+ if ( chain.length === 0 ) { break; }
+ owner = owner[prop];
+ if ( owner instanceof Object === false ) { return; }
+ }
+ var desc = Object.getOwnPropertyDescriptor(owner, prop);
+ if ( desc && desc.get !== undefined ) { return; }
+ var magic = String.fromCharCode(Date.now() % 26 + 97) +
+ Math.floor(Math.random() * 982451653 + 982451653).toString(36);
+ var value = owner[prop];
+ var validate = function() {
+ var e = document.currentScript;
+ if ( e instanceof HTMLScriptElement && e.src === '' && re.test(e.textContent) ) {
+ throw new ReferenceError(magic);
+ }
+ };
+ Object.defineProperty(owner, prop, {
+ get: function() {
+ validate();
+ return value;
+ },
+ set: function(a) {
+ validate();
+ value = a;
+ }
+ });
+ var oe = window.onerror;
+ window.onerror = function(msg) {
+ if ( typeof msg === 'string' && msg.indexOf(magic) !== -1 ) {
+ return true;
+ }
+ if ( oe instanceof Function ) {
+ return oe.apply(this, arguments);
+ }
+ }.bind();
+})();
+} catch ( e ) { }
+(function() {
+ var c = document.currentScript, p = c && c.parentNode;
+ if ( p ) { p.removeChild(c); }
+})();</script></head>
+<body>
+
+<div class="container">
+ <div>
+ <div class="responsive-container"></div>
+ </div>
+</div>
+
+
+
+</body></html>
\ No newline at end of file diff --git a/layout/reftests/css-grid/bug1356820-ref.html b/layout/reftests/css-grid/bug1356820-ref.html new file mode 100644 index 000000000..b203ba203 --- /dev/null +++ b/layout/reftests/css-grid/bug1356820-ref.html @@ -0,0 +1,81 @@ +<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8"><script>try {
+(function() {
+ var target = 'blur';
+ if ( target === '' || target === '{{1}}' ) { return; }
+ var needle = 'mz_str', reText = '.?';
+ if ( needle !== '' && needle !== '{{2}}' ) {
+ reText = /^\/.+\/$/.test(needle)
+ ? needle.slice(1,-1)
+ : needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+ }
+ var re = new RegExp(reText);
+ var chain = target.split('.');
+ var owner = window, prop;
+ for (;;) {
+ prop = chain.shift();
+ if ( chain.length === 0 ) { break; }
+ owner = owner[prop];
+ if ( owner instanceof Object === false ) { return; }
+ }
+ var desc = Object.getOwnPropertyDescriptor(owner, prop);
+ if ( desc && desc.get !== undefined ) { return; }
+ var magic = String.fromCharCode(Date.now() % 26 + 97) +
+ Math.floor(Math.random() * 982451653 + 982451653).toString(36);
+ var value = owner[prop];
+ var validate = function() {
+ var e = document.currentScript;
+ if ( e instanceof HTMLScriptElement && e.src === '' && re.test(e.textContent) ) {
+ throw new ReferenceError(magic);
+ }
+ };
+ Object.defineProperty(owner, prop, {
+ get: function() {
+ validate();
+ return value;
+ },
+ set: function(a) {
+ validate();
+ value = a;
+ }
+ });
+ var oe = window.onerror;
+ window.onerror = function(msg) {
+ if ( typeof msg === 'string' && msg.indexOf(magic) !== -1 ) {
+ return true;
+ }
+ if ( oe instanceof Function ) {
+ return oe.apply(this, arguments);
+ }
+ }.bind();
+})();
+} catch ( e ) { }
+(function() {
+ var c = document.currentScript, p = c && c.parentNode;
+ if ( p ) { p.removeChild(c); }
+})();</script></head><body><div style="display: grid; width: 5em;">
+ <div style="word-wrap: break-word; width: 5em; justify-self:start">
+ first item with a longlonglongword
+ </div>
+ <div>
+ second item
+ </div>
+</div>
+<div style="display: grid; width: 5em;">
+ <div style="width: 5em; justify-self:start">
+ first item with a longlonglongword
+ </div>
+ <div>
+ second item
+ </div>
+</div>
+<div style="display: grid; width: 5em;">
+ <div style="word-wrap: break-word; writing-mode:vertical-lr; justify-self:start">
+ first item with a longlonglongword
+ </div>
+ <div>
+ second item
+ </div>
+</div>
+</body></html>
\ No newline at end of file diff --git a/layout/reftests/css-grid/bug1356820.html b/layout/reftests/css-grid/bug1356820.html new file mode 100644 index 000000000..2f2f36014 --- /dev/null +++ b/layout/reftests/css-grid/bug1356820.html @@ -0,0 +1,81 @@ +<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8"><script>try {
+(function() {
+ var target = 'blur';
+ if ( target === '' || target === '{{1}}' ) { return; }
+ var needle = 'mz_str', reText = '.?';
+ if ( needle !== '' && needle !== '{{2}}' ) {
+ reText = /^\/.+\/$/.test(needle)
+ ? needle.slice(1,-1)
+ : needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+ }
+ var re = new RegExp(reText);
+ var chain = target.split('.');
+ var owner = window, prop;
+ for (;;) {
+ prop = chain.shift();
+ if ( chain.length === 0 ) { break; }
+ owner = owner[prop];
+ if ( owner instanceof Object === false ) { return; }
+ }
+ var desc = Object.getOwnPropertyDescriptor(owner, prop);
+ if ( desc && desc.get !== undefined ) { return; }
+ var magic = String.fromCharCode(Date.now() % 26 + 97) +
+ Math.floor(Math.random() * 982451653 + 982451653).toString(36);
+ var value = owner[prop];
+ var validate = function() {
+ var e = document.currentScript;
+ if ( e instanceof HTMLScriptElement && e.src === '' && re.test(e.textContent) ) {
+ throw new ReferenceError(magic);
+ }
+ };
+ Object.defineProperty(owner, prop, {
+ get: function() {
+ validate();
+ return value;
+ },
+ set: function(a) {
+ validate();
+ value = a;
+ }
+ });
+ var oe = window.onerror;
+ window.onerror = function(msg) {
+ if ( typeof msg === 'string' && msg.indexOf(magic) !== -1 ) {
+ return true;
+ }
+ if ( oe instanceof Function ) {
+ return oe.apply(this, arguments);
+ }
+ }.bind();
+})();
+} catch ( e ) { }
+(function() {
+ var c = document.currentScript, p = c && c.parentNode;
+ if ( p ) { p.removeChild(c); }
+})();</script></head><body><div style="display: grid; width: 5em;">
+ <div style="word-wrap: break-word; min-width: 0;">
+ first item with a longlonglongword
+ </div>
+ <div>
+ second item
+ </div>
+</div>
+<div style="display: grid; width: 5em;">
+ <div style="min-width: 0;">
+ first item with a longlonglongword
+ </div>
+ <div>
+ second item
+ </div>
+</div>
+<div style="display: grid; width: 5em;">
+ <div style="word-wrap: break-word; min-height: 0; writing-mode:vertical-lr">
+ first item with a longlonglongword
+ </div>
+ <div>
+ second item
+ </div>
+</div>
+</body></html>
\ No newline at end of file diff --git a/layout/reftests/css-grid/reftest.list b/layout/reftests/css-grid/reftest.list index c2ee57c1a..3087ca49b 100644 --- a/layout/reftests/css-grid/reftest.list +++ b/layout/reftests/css-grid/reftest.list @@ -280,3 +280,5 @@ asserts(1-10) == grid-fragmentation-dyn4-021.html grid-fragmentation-021-ref.htm == grid-fragmentation-dyn2-031.html grid-fragmentation-031-ref.html == bug1306106.html bug1306106-ref.html == grid-percent-intrinsic-sizing-001.html grid-percent-intrinsic-sizing-001-ref.html +== bug1349571.html bug1349571-ref.html +== bug1356820.html bug1356820-ref.html diff --git a/layout/reftests/svg/reftest.list b/layout/reftests/svg/reftest.list index 520adc9e6..096628681 100644 --- a/layout/reftests/svg/reftest.list +++ b/layout/reftests/svg/reftest.list @@ -396,6 +396,7 @@ fuzzy-if(skiaContent,1,300) == tspan-xy-05.svg tspan-xy-ref.svg # bug 773482 fuzzy-if(skiaContent,1,300) == tspan-xy-06.svg tspan-xy-ref.svg # bug 773482 fuzzy-if(skiaContent,1,100) == tspan-xy-anchor-middle-01.svg tspan-xy-anchor-middle-ref.svg # bug 773482 fuzzy-if(skiaContent,1,100) == tspan-xy-anchor-end-01.svg tspan-xy-anchor-end-ref.svg # bug 773482 +== use-localRef-link.html pass.svg == userSpaceOnUse-and-pattern-01.svg userSpaceOnUse-and-pattern-01-ref.svg == viewBox-and-pattern-01.svg pass.svg == viewBox-and-pattern-02.svg pass.svg diff --git a/layout/reftests/svg/use-localRef-link.html b/layout/reftests/svg/use-localRef-link.html new file mode 100644 index 000000000..672e9ffaa --- /dev/null +++ b/layout/reftests/svg/use-localRef-link.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<head> +<base href="/test"> +</head> +<body style="background-color: lime;"> + <svg width="100" height="100"> + <defs> + <rect id="a" x="0" y="0" width="50" height="50" fill="lime"/> + </defs> + <rect x="0" y="0" width="50" height="50" fill="red"/> + <use xlink:href="#a"/> + </svg> +</body> +</html> + + diff --git a/layout/reftests/w3c-css/submitted/flexbox/position-absolute-containing-block-001-ref.html b/layout/reftests/w3c-css/submitted/flexbox/position-absolute-containing-block-001-ref.html new file mode 100644 index 000000000..08eec8691 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/flexbox/position-absolute-containing-block-001-ref.html @@ -0,0 +1,27 @@ +<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>CSS Test Reference</title>
+<meta charset="utf-8">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<style>
+.parent {
+ position: fixed;
+ top: 0;
+ left: 0;
+ display: block;
+ width: 200px;
+ height: 200px;
+ background: yellow;
+}
+
+.child {
+ position: absolute;
+ left: 50px;
+ top: 50px;
+ width: 100px;
+ height: 100px;
+ background: green;
+}
+</style>
+</head><body><div class="parent"><div class="child"></div></div>
+</body></html>
\ No newline at end of file diff --git a/layout/reftests/w3c-css/submitted/flexbox/position-absolute-containing-block-001.html b/layout/reftests/w3c-css/submitted/flexbox/position-absolute-containing-block-001.html new file mode 100644 index 000000000..5f623cb84 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/flexbox/position-absolute-containing-block-001.html @@ -0,0 +1,30 @@ +<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>CSS Test: Absolutely positioned children of flex container with CSS align</title>
+<meta charset="utf-8">
+<link rel="help" href="https://drafts.csswg.org/css-flexbox/#abspos-items">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1386654">
+<link rel="match" href="https://hg.mozilla.org/mozilla-central/raw-file/6538de3b6137/layout/reftests/w3c-css/submitted/flexbox/position-absolute-containing-block-001-ref.html">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<style>
+.parent {
+ position: fixed;
+ top: 0;
+ left: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 200px;
+ height: 200px;
+ background: yellow;
+}
+
+.child {
+ position: absolute;
+ width: 100px;
+ height: 100px;
+ background: green;
+}
+</style>
+</head><body><div class="parent"><div class="child"></div></div>
+</body></html>
\ No newline at end of file diff --git a/layout/reftests/w3c-css/submitted/flexbox/position-absolute-containing-block-002-ref.html b/layout/reftests/w3c-css/submitted/flexbox/position-absolute-containing-block-002-ref.html new file mode 100644 index 000000000..df730047b --- /dev/null +++ b/layout/reftests/w3c-css/submitted/flexbox/position-absolute-containing-block-002-ref.html @@ -0,0 +1,27 @@ +<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>CSS Test Reference</title>
+<meta charset="utf-8">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<style>
+.parent {
+ position: fixed;
+ top: 0;
+ left: 0;
+ display: block;
+ width: 200px;
+ height: 200px;
+ background: yellow;
+}
+
+.child {
+ position: absolute;
+ left: 60px;
+ top: 60px;
+ width: 100px;
+ height: 100px;
+ background: green;
+}
+</style>
+</head><body><div class="parent"><div class="child"></div></div>
+</body></html>
\ No newline at end of file diff --git a/layout/reftests/w3c-css/submitted/flexbox/position-absolute-containing-block-002.html b/layout/reftests/w3c-css/submitted/flexbox/position-absolute-containing-block-002.html new file mode 100644 index 000000000..9e89c5ad0 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/flexbox/position-absolute-containing-block-002.html @@ -0,0 +1,38 @@ +<!DOCTYPE html>
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>CSS Test: Absolutely positioned children of flex container with CSS align</title>
+<meta charset="utf-8">
+<link rel="help" href="https://drafts.csswg.org/css-flexbox/#abspos-items">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1386654">
+<link rel="match" href="https://hg.mozilla.org/mozilla-central/raw-file/6538de3b6137/layout/reftests/w3c-css/submitted/flexbox/position-absolute-containing-block-002-ref.html">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<style>
+.parent {
+ position: fixed;
+ top: 0;
+ left: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 180px;
+ height: 180px;
+
+ /* Expand the background area to 200px, without touching the content-box,
+ which is what flex absolute children should be aligned relative to. */
+ border-top: 5px solid yellow;
+ padding-top: 15px;
+ border-left: 5px solid yellow;
+ padding-left: 15px;
+
+ background: yellow;
+}
+
+.child {
+ position: absolute;
+ width: 100px;
+ height: 100px;
+ background: green;
+}
+</style>
+</head><body><div class="parent"><div class="child"></div></div>
+</body></html>
\ No newline at end of file diff --git a/layout/reftests/w3c-css/submitted/flexbox/reftest.list b/layout/reftests/w3c-css/submitted/flexbox/reftest.list index fd8bfccc9..3df75aee6 100644 --- a/layout/reftests/w3c-css/submitted/flexbox/reftest.list +++ b/layout/reftests/w3c-css/submitted/flexbox/reftest.list @@ -211,3 +211,7 @@ fails == flexbox-min-height-auto-002b.html flexbox-min-height-auto-002-ref.html == flexbox-single-line-clamp-1.html flexbox-single-line-clamp-1-ref.html == flexbox-single-line-clamp-2.html flexbox-single-line-clamp-2-ref.html == flexbox-single-line-clamp-3.html flexbox-single-line-clamp-3-ref.html + +# Flexbox as an absolute containing block. +== position-absolute-containing-block-001.html position-absolute-containing-block-001-ref.html +== position-absolute-containing-block-002.html position-absolute-containing-block-002-ref.html diff --git a/layout/style/Declaration.cpp b/layout/style/Declaration.cpp index c67f6b2a2..b2de159ed 100644 --- a/layout/style/Declaration.cpp +++ b/layout/style/Declaration.cpp @@ -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 diff --git a/layout/style/FontFace.cpp b/layout/style/FontFace.cpp index 4558ab1a2..ab6781149 100644 --- a/layout/style/FontFace.cpp +++ b/layout/style/FontFace.cpp @@ -75,7 +75,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(FontFace) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRule) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFontFaceSet) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOtherFontFaceSets) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FontFace) diff --git a/layout/style/FontFaceSet.cpp b/layout/style/FontFaceSet.cpp index 550a7d71a..1645adfef 100644 --- a/layout/style/FontFaceSet.cpp +++ b/layout/style/FontFaceSet.cpp @@ -1762,18 +1762,10 @@ FontFaceSet::UserFontSet::RecordFontLoadDone(uint32_t aFontSize, { mDownloadCount++; mDownloadSize += aFontSize; - Telemetry::Accumulate(Telemetry::WEBFONT_SIZE, aFontSize / 1024); if (!mFontFaceSet) { return; } - - TimeStamp navStart = mFontFaceSet->GetNavigationStartTimeStamp(); - TimeStamp zero; - if (navStart != zero) { - Telemetry::AccumulateTimeDelta(Telemetry::WEBFONT_DOWNLOAD_TIME_AFTER_START, - navStart, aDoneTime); - } } /* virtual */ nsresult diff --git a/layout/style/ImageLoader.cpp b/layout/style/ImageLoader.cpp index 0a605abc9..a26a1741a 100644 --- a/layout/style/ImageLoader.cpp +++ b/layout/style/ImageLoader.cpp @@ -519,9 +519,6 @@ ImageLoader::FlushUseCounters() nsCOMPtr<imgIContainer> container; request->GetImage(getter_AddRefs(container)); - if (container) { - static_cast<image::Image*>(container.get())->ReportUseCounters(); - } } } diff --git a/layout/style/Loader.cpp b/layout/style/Loader.cpp index a1a0fcfd9..0ce337e29 100644 --- a/layout/style/Loader.cpp +++ b/layout/style/Loader.cpp @@ -1677,10 +1677,6 @@ Loader::LoadSheet(SheetLoadData* aLoadData, nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); if (httpChannel) { - // Send a minimal Accept header for text/css - httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"), - NS_LITERAL_CSTRING("text/css,*/*;q=0.1"), - false); nsCOMPtr<nsIURI> referrerURI = aLoadData->GetReferrerURI(); if (referrerURI) httpChannel->SetReferrerWithPolicy(referrerURI, diff --git a/layout/style/MediaQueryList.cpp b/layout/style/MediaQueryList.cpp index 069e049c4..db3781b76 100644 --- a/layout/style/MediaQueryList.cpp +++ b/layout/style/MediaQueryList.cpp @@ -39,7 +39,6 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(MediaQueryList) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(MediaQueryList) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallbacks) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(MediaQueryList) diff --git a/layout/style/StyleAnimationValue.cpp b/layout/style/StyleAnimationValue.cpp index eb34c3d83..a0f52b4ea 100644 --- a/layout/style/StyleAnimationValue.cpp +++ b/layout/style/StyleAnimationValue.cpp @@ -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 = diff --git a/layout/style/StyleRule.cpp b/layout/style/StyleRule.cpp index 6aade8897..598cb7c74 100644 --- a/layout/style/StyleRule.cpp +++ b/layout/style/StyleRule.cpp @@ -1275,10 +1275,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMCSSStyleRule) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMCSSStyleRule) - // Just NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS here: that will call - // into our Trace hook, where we do the right thing with declarations - // already. - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMETHODIMP diff --git a/layout/style/nsCSSDataBlock.cpp b/layout/style/nsCSSDataBlock.cpp index fe2dc621a..1dfdaed0e 100644 --- a/layout/style/nsCSSDataBlock.cpp +++ b/layout/style/nsCSSDataBlock.cpp @@ -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, diff --git a/layout/style/nsCSSKeywordList.h b/layout/style/nsCSSKeywordList.h index 94968faca..34a46ffce 100644 --- a/layout/style/nsCSSKeywordList.h +++ b/layout/style/nsCSSKeywordList.h @@ -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) diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index b361cf0c2..a8309314f 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -1549,6 +1549,9 @@ protected: // All data from successfully parsed properties are placed into |mData|. nsCSSExpandedDataBlock mData; + + // Value to make sure our resolved variable results stay within sane limits. + const uint32_t MAX_CSS_VAR_LENGTH = 10240; public: // Used from nsCSSParser constructors and destructors @@ -2802,6 +2805,12 @@ CSSParserImpl::ResolveValueWithVariableReferencesRec( // Invalid variable with no fallback. return false; } + // Make sure we are still using sane sizes for value and + // variableValue, and abort if OOB. + if (value.Length() > MAX_CSS_VAR_LENGTH || + variableValue.Length() > MAX_CSS_VAR_LENGTH) { + return false; + } // Valid variable with no fallback. AppendTokens(value, valueFirstToken, valueLastToken, varFirstToken, varLastToken, variableValue); @@ -11996,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: @@ -12009,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: @@ -12415,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, @@ -12428,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); @@ -12453,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 @@ -12522,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; @@ -12538,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]); diff --git a/layout/style/nsCSSPropAliasList.h b/layout/style/nsCSSPropAliasList.h index 2699549ff..f7938af9e 100644 --- a/layout/style/nsCSSPropAliasList.h +++ b/layout/style/nsCSSPropAliasList.h @@ -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 diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index b04921dcb..2049f70e8 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -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, diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp index 9805eae14..ac2978c27 100644 --- a/layout/style/nsCSSProps.cpp +++ b/layout/style/nsCSSProps.cpp @@ -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. diff --git a/layout/style/nsCSSProps.h b/layout/style/nsCSSProps.h index dfe35afd8..e67e1d41d 100644 --- a/layout/style/nsCSSProps.h +++ b/layout/style/nsCSSProps.h @@ -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[]; diff --git a/layout/style/nsCSSRules.cpp b/layout/style/nsCSSRules.cpp index a08d8af34..4b90b6f0c 100644 --- a/layout/style/nsCSSRules.cpp +++ b/layout/style/nsCSSRules.cpp @@ -1552,9 +1552,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCSSFontFaceRule) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCSSFontFaceRule) - // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS will call into our - // Trace hook, where we do the right thing with declarations already. - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END // QueryInterface implementation for nsCSSFontFaceRule diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index 4f8d3edf6..65c1d698c 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -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. @@ -280,7 +304,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsComputedDOMStyle) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContent) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsComputedDOMStyle) @@ -1803,24 +1826,6 @@ nsComputedDOMStyle::DoGetFontVariantPosition() } 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() { return GetBackgroundList(&nsStyleImageLayers::Layer::mAttachment, @@ -2367,7 +2372,7 @@ nsComputedDOMStyle::DoGetBackgroundOrigin() return GetBackgroundList(&nsStyleImageLayers::Layer::mOrigin, &nsStyleImageLayers::mOriginCount, StyleBackground()->mImage, - nsCSSProps::kImageLayerOriginKTable); + nsCSSProps::kBackgroundOriginKTable); } void @@ -5013,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) { @@ -6180,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( @@ -6200,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> @@ -6241,7 +6239,7 @@ nsComputedDOMStyle::DoGetMaskOrigin() return GetBackgroundList(&nsStyleImageLayers::Layer::mOrigin, &nsStyleImageLayers::mOriginCount, StyleSVGReset()->mMask, - nsCSSProps::kImageLayerOriginKTable); + nsCSSProps::kMaskOriginKTable); } already_AddRefed<CSSValue> @@ -6278,7 +6276,6 @@ nsComputedDOMStyle::DoGetMaskSize() const nsStyleImageLayers& layers = StyleSVGReset()->mMask; return DoGetImageLayerSize(layers); } -#endif already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetMaskType() diff --git a/layout/style/nsComputedDOMStyle.h b/layout/style/nsComputedDOMStyle.h index 27e2086e9..77df71ec8 100644 --- a/layout/style/nsComputedDOMStyle.h +++ b/layout/style/nsComputedDOMStyle.h @@ -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, diff --git a/layout/style/nsComputedDOMStylePropertyList.h b/layout/style/nsComputedDOMStylePropertyList.h index 1983208ac..825976b58 100644 --- a/layout/style/nsComputedDOMStylePropertyList.h +++ b/layout/style/nsComputedDOMStylePropertyList.h @@ -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) diff --git a/layout/style/nsFontFaceLoader.cpp b/layout/style/nsFontFaceLoader.cpp index f5a0a9f34..3082bbf87 100644 --- a/layout/style/nsFontFaceLoader.cpp +++ b/layout/style/nsFontFaceLoader.cpp @@ -205,7 +205,6 @@ nsFontFaceLoader::OnStreamComplete(nsIStreamLoader* aLoader, TimeStamp doneTime = TimeStamp::Now(); TimeDuration downloadTime = doneTime - mStartTime; uint32_t downloadTimeMS = uint32_t(downloadTime.ToMilliseconds()); - Telemetry::Accumulate(Telemetry::WEBFONT_DOWNLOAD_TIME, downloadTimeMS); if (GetFontDisplay() == NS_FONT_DISPLAY_FALLBACK) { uint32_t loadTimeout = GetFallbackDelay(); diff --git a/layout/style/nsROCSSPrimitiveValue.cpp b/layout/style/nsROCSSPrimitiveValue.cpp index cbc715eb2..2721bd609 100644 --- a/layout/style/nsROCSSPrimitiveValue.cpp +++ b/layout/style/nsROCSSPrimitiveValue.cpp @@ -52,7 +52,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsROCSSPrimitiveValue) } else if (tmp->mType == CSS_RECT) { NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mValue.mRect) } - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsROCSSPrimitiveValue) diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 9b9fc3948..08400635b 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -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" @@ -66,9 +67,6 @@ #define alloca _alloca #endif #endif -#ifdef SOLARIS -#include <alloca.h> -#endif using std::max; using std::min; @@ -6800,6 +6798,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 +7366,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 +7385,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 +10018,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 +10055,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 +10065,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 +10125,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) } diff --git a/layout/style/nsStyleConsts.h b/layout/style/nsStyleConsts.h index be588113e..6d207aec9 100644 --- a/layout/style/nsStyleConsts.h +++ b/layout/style/nsStyleConsts.h @@ -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 @@ -375,12 +386,6 @@ enum class FillMode : uint32_t; #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) #define NS_STYLE_IMAGELAYER_POSITION_TOP (1<<1) diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 52491a288..72c103724 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -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; } } diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 1cadea840..c8182b8f1 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -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 diff --git a/layout/svg/nsCSSClipPathInstance.cpp b/layout/svg/nsCSSClipPathInstance.cpp index 828b10eac..01f7de248 100644 --- a/layout/svg/nsCSSClipPathInstance.cpp +++ b/layout/svg/nsCSSClipPathInstance.cpp @@ -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 diff --git a/layout/svg/nsCSSClipPathInstance.h b/layout/svg/nsCSSClipPathInstance.h index 3b0724dbd..33d92e738 100644 --- a/layout/svg/nsCSSClipPathInstance.h +++ b/layout/svg/nsCSSClipPathInstance.h @@ -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. */ diff --git a/layout/svg/nsSVGEffects.cpp b/layout/svg/nsSVGEffects.cpp index eac094a91..e75c973c8 100644 --- a/layout/svg/nsSVGEffects.cpp +++ b/layout/svg/nsSVGEffects.cpp @@ -888,24 +888,13 @@ nsSVGEffects::InvalidateDirectRenderingObservers(nsIFrame* aFrame, uint32_t aFla } } -static already_AddRefed<nsIURI> -ResolveURLUsingLocalRef(nsIFrame* aFrame, const css::URLValueData* aURL) +already_AddRefed<nsIURI> +nsSVGEffects::GetBaseURLForLocalRef(nsIContent* content, nsIURI* aDocURI) { - MOZ_ASSERT(aFrame); - - if (!aURL) { - return nullptr; - } - - // Non-local-reference URL. - if (!aURL->IsLocalRef()) { - nsCOMPtr<nsIURI> result = aURL->GetURI(); - return result.forget(); - } + MOZ_ASSERT(content); // For a local-reference URL, resolve that fragment against the current // document that relative URLs are resolved against. - nsIContent* content = aFrame->GetContent(); nsCOMPtr<nsIURI> baseURI = content->OwnerDoc()->GetDocumentURI(); if (content->IsInAnonymousSubtree()) { @@ -933,12 +922,37 @@ ResolveURLUsingLocalRef(nsIFrame* aFrame, const css::URLValueData* aURL) } } - if (originalURI && aURL->EqualsExceptRef(originalURI)) { - baseURI = originalURI; + if (originalURI) { + bool isEqualsExceptRef = false; + aDocURI->EqualsExceptRef(originalURI, &isEqualsExceptRef); + if (isEqualsExceptRef) { + baseURI = originalURI; + } } } } + return baseURI.forget(); +} + +static already_AddRefed<nsIURI> +ResolveURLUsingLocalRef(nsIFrame* aFrame, const css::URLValueData* aURL) +{ + MOZ_ASSERT(aFrame); + + if (!aURL) { + return nullptr; + } + + // Non-local-reference URL. + if (!aURL->IsLocalRef()) { + nsCOMPtr<nsIURI> result = aURL->GetURI(); + return result.forget(); + } + + nsCOMPtr<nsIURI> baseURI = + nsSVGEffects::GetBaseURLForLocalRef(aFrame->GetContent(), aURL->GetURI()); + return aURL->ResolveLocalRef(baseURI); } diff --git a/layout/svg/nsSVGEffects.h b/layout/svg/nsSVGEffects.h index 9dd92fd31..0cf9b1500 100644 --- a/layout/svg/nsSVGEffects.h +++ b/layout/svg/nsSVGEffects.h @@ -626,11 +626,23 @@ public: static already_AddRefed<nsIURI> GetPaintURI(nsIFrame* aFrame, nsStyleSVGPaint nsStyleSVG::* aPaint); - /** + /** * A helper function to resolve SVG mask URL. */ static already_AddRefed<nsIURI> GetMaskURI(nsIFrame* aFrame, uint32_t aIndex); + + /** + * Return a baseURL for resolving a local-ref URL. + * + * @param aContent an element which uses a local-ref property. Here are some + * examples: + * <rect fill=url(#foo)> + * <circle clip-path=url(#foo)> + * <use xlink:href="#foo"> + */ + static already_AddRefed<nsIURI> + GetBaseURLForLocalRef(nsIContent* aContent, nsIURI* aDocURI); }; #endif /*NSSVGEFFECTS_H_*/ diff --git a/layout/svg/nsSVGIntegrationUtils.cpp b/layout/svg/nsSVGIntegrationUtils.cpp index 498f69393..0003e1a73 100644 --- a/layout/svg/nsSVGIntegrationUtils.cpp +++ b/layout/svg/nsSVGIntegrationUtils.cpp @@ -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; - } - - aOutMaskTransform = ToMatrix(maskSurfaceMatrix); - if (!aOutMaskTransform.Invert()) { - return DrawResult::SUCCESS; + 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; } - 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(); } diff --git a/layout/svg/nsSVGMaskFrame.cpp b/layout/svg/nsSVGMaskFrame.cpp index b8e4b32ae..a22833d61 100644 --- a/layout/svg/nsSVGMaskFrame.cpp +++ b/layout/svg/nsSVGMaskFrame.cpp @@ -274,7 +274,8 @@ nsSVGMaskFrame::GetMaskForMaskedFrame(gfxContext* aContext, } RefPtr<DataSourceSurface> maskSurface = maskSnapshot->GetDataSurface(); DataSourceSurface::MappedSurface map; - if (!maskSurface->Map(DataSourceSurface::MapType::READ, &map)) { + if (!maskSurface || + !maskSurface->Map(DataSourceSurface::MapType::READ, &map)) { return nullptr; } diff --git a/layout/svg/nsSVGOuterSVGFrame.cpp b/layout/svg/nsSVGOuterSVGFrame.cpp index aeadccbc5..e1b97bb40 100644 --- a/layout/svg/nsSVGOuterSVGFrame.cpp +++ b/layout/svg/nsSVGOuterSVGFrame.cpp @@ -241,8 +241,9 @@ nsSVGOuterSVGFrame::GetIntrinsicRatio() nsSVGLength2 &height = content->mLengthAttributes[SVGSVGElement::ATTR_HEIGHT]; if (!width.IsPercentage() && !height.IsPercentage()) { - nsSize ratio(NSToCoordRoundWithClamp(width.GetAnimValue(content)), - NSToCoordRoundWithClamp(height.GetAnimValue(content))); + nsSize ratio( + nsPresContext::CSSPixelsToAppUnits(width.GetAnimValue(content)), + nsPresContext::CSSPixelsToAppUnits(height.GetAnimValue(content))); if (ratio.width < 0) { ratio.width = 0; } @@ -272,8 +273,8 @@ nsSVGOuterSVGFrame::GetIntrinsicRatio() if (viewBoxHeight < 0.0f) { viewBoxHeight = 0.0f; } - return nsSize(NSToCoordRoundWithClamp(viewBoxWidth), - NSToCoordRoundWithClamp(viewBoxHeight)); + return nsSize(nsPresContext::CSSPixelsToAppUnits(viewBoxWidth), + nsPresContext::CSSPixelsToAppUnits(viewBoxHeight)); } return nsSVGDisplayContainerFrame::GetIntrinsicRatio(); diff --git a/layout/svg/nsSVGUtils.cpp b/layout/svg/nsSVGUtils.cpp index 344ebf645..98e5f9b5f 100644 --- a/layout/svg/nsSVGUtils.cpp +++ b/layout/svg/nsSVGUtils.cpp @@ -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); @@ -753,9 +734,12 @@ nsSVGUtils::PaintFrameWithEffects(nsIFrame *aFrame, RefPtr<SourceSurface> maskSurface; if (maskUsage.shouldGenerateMaskLayer) { - maskSurface = - maskFrame->GetMaskForMaskedFrame(&aContext, aFrame, aTransform, - maskUsage.opacity, &maskTransform); + // Make sure we have a mask frame. + if (maskFrame) { + maskSurface = + maskFrame->GetMaskForMaskedFrame(&aContext, aFrame, aTransform, + maskUsage.opacity, &maskTransform); + } if (!maskSurface) { // Entire surface is clipped out. diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index 5030804ed..4c11d2704 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -2681,14 +2681,14 @@ nsTableFrame::GetOuterBCBorder(const WritingMode aWM) const const_cast<nsTableFrame*>(this)->CalcBCBorders(); } - int32_t p2t = nsPresContext::AppUnitsPerCSSPixel(); + int32_t d2a = PresContext()->AppUnitsPerDevPixel(); BCPropertyData* propData = GetBCProperty(); if (propData) { return LogicalMargin(aWM, - BC_BORDER_START_HALF_COORD(p2t, propData->mBStartBorderWidth), - BC_BORDER_END_HALF_COORD(p2t, propData->mIEndBorderWidth), - BC_BORDER_END_HALF_COORD(p2t, propData->mBEndBorderWidth), - BC_BORDER_START_HALF_COORD(p2t, propData->mIStartBorderWidth)); + BC_BORDER_START_HALF_COORD(d2a, propData->mBStartBorderWidth), + BC_BORDER_END_HALF_COORD(d2a, propData->mIEndBorderWidth), + BC_BORDER_END_HALF_COORD(d2a, propData->mBEndBorderWidth), + BC_BORDER_START_HALF_COORD(d2a, propData->mIStartBorderWidth)); } return LogicalMargin(aWM); } @@ -2700,14 +2700,14 @@ nsTableFrame::GetIncludedOuterBCBorder(const WritingMode aWM) const const_cast<nsTableFrame*>(this)->CalcBCBorders(); } - int32_t p2t = nsPresContext::AppUnitsPerCSSPixel(); + int32_t d2a = PresContext()->AppUnitsPerDevPixel(); BCPropertyData* propData = GetBCProperty(); if (propData) { return LogicalMargin(aWM, - BC_BORDER_START_HALF_COORD(p2t, propData->mBStartBorderWidth), - BC_BORDER_END_HALF_COORD(p2t, propData->mIEndCellBorderWidth), - BC_BORDER_END_HALF_COORD(p2t, propData->mBEndBorderWidth), - BC_BORDER_START_HALF_COORD(p2t, propData->mIStartCellBorderWidth)); + BC_BORDER_START_HALF_COORD(d2a, propData->mBStartBorderWidth), + BC_BORDER_END_HALF_COORD(d2a, propData->mIEndCellBorderWidth), + BC_BORDER_END_HALF_COORD(d2a, propData->mBEndBorderWidth), + BC_BORDER_START_HALF_COORD(d2a, propData->mIStartCellBorderWidth)); } return LogicalMargin(aWM); } @@ -4791,7 +4791,7 @@ GetColorAndStyle(const nsIFrame* aFrame, if (aWidth) { nscoord width = styleData->GetComputedBorderWidth(physicalSide); - *aWidth = nsPresContext::AppUnitsToIntCSSPixels(width); + *aWidth = aFrame->PresContext()->AppUnitsToDevPixels(width); } } @@ -6476,8 +6476,8 @@ BCPaintBorderIterator::SetDamageArea(const nsRect& aDirtyRect) nscoord rowBSize = rowFrame->BSize(mTableWM); if (haveIntersect) { // conservatively estimate the half border widths outside the row - nscoord borderHalf = mTable->GetPrevInFlow() ? 0 : nsPresContext:: - CSSPixelsToAppUnits(rowFrame->GetBStartBCBorderWidth() + 1); + nscoord borderHalf = mTable->GetPrevInFlow() ? 0 : + mTable->PresContext()->DevPixelsToAppUnits(rowFrame->GetBStartBCBorderWidth() + 1); if (dirtyRect.BEnd(mTableWM) >= rowB - borderHalf) { nsTableRowFrame* fifRow = static_cast<nsTableRowFrame*>(rowFrame->FirstInFlow()); @@ -6487,8 +6487,8 @@ BCPaintBorderIterator::SetDamageArea(const nsRect& aDirtyRect) } else { // conservatively estimate the half border widths outside the row - nscoord borderHalf = mTable->GetNextInFlow() ? 0 : nsPresContext:: - CSSPixelsToAppUnits(rowFrame->GetBEndBCBorderWidth() + 1); + nscoord borderHalf = mTable->GetNextInFlow() ? 0 : + mTable->PresContext()->DevPixelsToAppUnits(rowFrame->GetBEndBCBorderWidth() + 1); if (rowB + rowBSize + borderHalf >= dirtyRect.BStart(mTableWM)) { mStartRg = rgFrame; mStartRow = rowFrame; @@ -6532,8 +6532,8 @@ BCPaintBorderIterator::SetDamageArea(const nsRect& aDirtyRect) nscoord colISize = colFrame->ISize(mTableWM); if (haveIntersect) { // conservatively estimate the iStart half border width outside the col - nscoord iStartBorderHalf = nsPresContext:: - CSSPixelsToAppUnits(colFrame->GetIStartBorderWidth() + 1); + nscoord iStartBorderHalf = + mTable->PresContext()->DevPixelsToAppUnits(colFrame->GetIStartBorderWidth() + 1); if (dirtyRect.IEnd(mTableWM) >= x - iStartBorderHalf) { endColIndex = colIdx; } @@ -6541,8 +6541,8 @@ BCPaintBorderIterator::SetDamageArea(const nsRect& aDirtyRect) } else { // conservatively estimate the iEnd half border width outside the col - nscoord iEndBorderHalf = nsPresContext:: - CSSPixelsToAppUnits(colFrame->GetIEndBorderWidth() + 1); + nscoord iEndBorderHalf = + mTable->PresContext()->DevPixelsToAppUnits(colFrame->GetIEndBorderWidth() + 1); if (x + colISize + iEndBorderHalf >= dirtyRect.IStart(mTableWM)) { startColIndex = endColIndex = colIdx; haveIntersect = true; @@ -6785,7 +6785,8 @@ CalcVerCornerOffset(LogicalSide aCornerOwnerSide, BCPixelSize aCornerSubWidth, BCPixelSize aHorWidth, bool aIsStartOfSeg, - bool aIsBevel) + bool aIsBevel, + nsPresContext* aPresContext) { nscoord offset = 0; // XXX These should be replaced with appropriate side-specific macros (which?) @@ -6808,7 +6809,7 @@ CalcVerCornerOffset(LogicalSide aCornerOwnerSide, offset = (aIsStartOfSeg) ? smallHalf : -largeHalf; } } - return nsPresContext::CSSPixelsToAppUnits(offset); + return aPresContext->DevPixelsToAppUnits(offset); } /** Compute the horizontal offset of a horizontal border segment @@ -6824,7 +6825,8 @@ CalcHorCornerOffset(LogicalSide aCornerOwnerSide, BCPixelSize aCornerSubWidth, BCPixelSize aVerWidth, bool aIsStartOfSeg, - bool aIsBevel) + bool aIsBevel, + nsPresContext* aPresContext) { nscoord offset = 0; // XXX These should be replaced with appropriate side-specific macros (which?) @@ -6847,7 +6849,7 @@ CalcHorCornerOffset(LogicalSide aCornerOwnerSide, offset = (aIsStartOfSeg) ? smallHalf : -largeHalf; } } - return nsPresContext::CSSPixelsToAppUnits(offset); + return aPresContext->DevPixelsToAppUnits(offset); } BCBlockDirSeg::BCBlockDirSeg() @@ -6883,10 +6885,10 @@ BCBlockDirSeg::Start(BCPaintBorderIterator& aIter, BCPixelSize maxInlineSegBSize = std::max(aIter.mPrevInlineSegBSize, aInlineSegBSize); nscoord offset = CalcVerCornerOffset(ownerSide, cornerSubWidth, maxInlineSegBSize, true, - bStartBevel); + bStartBevel, aIter.mTable->PresContext()); mBStartBevelOffset = bStartBevel ? - nsPresContext::CSSPixelsToAppUnits(maxInlineSegBSize): 0; + aIter.mTable->PresContext()->DevPixelsToAppUnits(maxInlineSegBSize): 0; // XXX this assumes that only corners where 2 segments join can be beveled mBStartBevelSide = (aInlineSegBSize > 0) ? eLogicalSideIEnd : eLogicalSideIStart; mOffsetB += offset; @@ -6944,8 +6946,8 @@ BCBlockDirSeg::GetBEndCorner(BCPaintBorderIterator& aIter, mIsBEndBevel = (mWidth > 0) ? bevel : false; mBEndInlineSegBSize = std::max(aIter.mPrevInlineSegBSize, aInlineSegBSize); mBEndOffset = CalcVerCornerOffset(ownerSide, cornerSubWidth, - mBEndInlineSegBSize, - false, mIsBEndBevel); + mBEndInlineSegBSize, false, + mIsBEndBevel, aIter.mTable->PresContext()); mLength += mBEndOffset; } @@ -7029,11 +7031,11 @@ BCBlockDirSeg::Paint(BCPaintBorderIterator& aIter, BCPixelSize smallHalf, largeHalf; DivideBCBorderSize(mWidth, smallHalf, largeHalf); LogicalRect segRect(aIter.mTableWM, - mOffsetI - nsPresContext::CSSPixelsToAppUnits(largeHalf), + mOffsetI - aIter.mTable->PresContext()->DevPixelsToAppUnits(largeHalf), mOffsetB, - nsPresContext::CSSPixelsToAppUnits(mWidth), mLength); + aIter.mTable->PresContext()->DevPixelsToAppUnits(mWidth), mLength); nscoord bEndBevelOffset = (mIsBEndBevel) ? - nsPresContext::CSSPixelsToAppUnits(mBEndInlineSegBSize) : 0; + aIter.mTable->PresContext()->DevPixelsToAppUnits(mBEndInlineSegBSize) : 0; LogicalSide bEndBevelSide = (aInlineSegBSize > 0) ? eLogicalSideIEnd : eLogicalSideIStart; @@ -7067,7 +7069,7 @@ BCBlockDirSeg::Paint(BCPaintBorderIterator& aIter, nsCSSRendering::DrawTableBorderSegment(aDrawTarget, style, color, aIter.mTableBgColor, physicalRect, appUnitsPerDevPixel, - nsPresContext::AppUnitsPerCSSPixel(), + aIter.mTable->PresContext()->AppUnitsPerDevPixel(), startBevelSide, startBevelOffset, endBevelSide, endBevelOffset); } @@ -7123,7 +7125,8 @@ BCInlineDirSeg::Start(BCPaintBorderIterator& aIter, nscoord maxBlockSegISize = std::max(aIter.mBlockDirInfo[relColIndex].mWidth, aBEndBlockSegISize); nscoord offset = CalcHorCornerOffset(cornerOwnerSide, cornerSubWidth, - maxBlockSegISize, true, iStartBevel); + maxBlockSegISize, true, iStartBevel, + aIter.mTable->PresContext()); mIStartBevelOffset = (iStartBevel && (aInlineSegBSize > 0)) ? maxBlockSegISize : 0; // XXX this assumes that only corners where 2 segments join can be beveled mIStartBevelSide = (aBEndBlockSegISize > 0) ? eLogicalSideBEnd : eLogicalSideBStart; @@ -7157,10 +7160,10 @@ BCInlineDirSeg::GetIEndCorner(BCPaintBorderIterator& aIter, nscoord verWidth = std::max(aIter.mBlockDirInfo[relColIndex].mWidth, aIStartSegISize); mEndOffset = CalcHorCornerOffset(ownerSide, cornerSubWidth, verWidth, - false, mIsIEndBevel); + false, mIsIEndBevel, aIter.mTable->PresContext()); mLength += mEndOffset; mIEndBevelOffset = (mIsIEndBevel) ? - nsPresContext::CSSPixelsToAppUnits(verWidth) : 0; + aIter.mTable->PresContext()->DevPixelsToAppUnits(verWidth) : 0; mIEndBevelSide = (aIStartSegISize > 0) ? eLogicalSideBEnd : eLogicalSideBStart; } @@ -7240,9 +7243,9 @@ BCInlineDirSeg::Paint(BCPaintBorderIterator& aIter, DrawTarget& aDrawTarget) BCPixelSize smallHalf, largeHalf; DivideBCBorderSize(mWidth, smallHalf, largeHalf); LogicalRect segRect(aIter.mTableWM, mOffsetI, - mOffsetB - nsPresContext::CSSPixelsToAppUnits(largeHalf), + mOffsetB - aIter.mTable->PresContext()->DevPixelsToAppUnits(largeHalf), mLength, - nsPresContext::CSSPixelsToAppUnits(mWidth)); + aIter.mTable->PresContext()->DevPixelsToAppUnits(mWidth)); // Convert logical to physical sides/coordinates for DrawTableBorderSegment. nsRect physicalRect = segRect.GetPhysicalRect(aIter.mTableWM, @@ -7250,7 +7253,7 @@ BCInlineDirSeg::Paint(BCPaintBorderIterator& aIter, DrawTarget& aDrawTarget) uint8_t startBevelSide = aIter.mTableWM.PhysicalSide(mIStartBevelSide); uint8_t endBevelSide = aIter.mTableWM.PhysicalSide(mIEndBevelSide); nscoord startBevelOffset = - nsPresContext::CSSPixelsToAppUnits(mIStartBevelOffset); + aIter.mTable->PresContext()->DevPixelsToAppUnits(mIStartBevelOffset); nscoord endBevelOffset = mIEndBevelOffset; // With inline-RTL directionality, the 'start' and 'end' of the inline-dir // border segment need to be swapped because DrawTableBorderSegment will @@ -7271,7 +7274,7 @@ BCInlineDirSeg::Paint(BCPaintBorderIterator& aIter, DrawTarget& aDrawTarget) nsCSSRendering::DrawTableBorderSegment(aDrawTarget, style, color, aIter.mTableBgColor, physicalRect, appUnitsPerDevPixel, - nsPresContext::AppUnitsPerCSSPixel(), + aIter.mTable->PresContext()->AppUnitsPerDevPixel(), startBevelSide, startBevelOffset, endBevelSide, endBevelOffset); } diff --git a/layout/xul/BoxObject.cpp b/layout/xul/BoxObject.cpp index 6636a6d62..347205fff 100644 --- a/layout/xul/BoxObject.cpp +++ b/layout/xul/BoxObject.cpp @@ -53,7 +53,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BoxObject) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BoxObject) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS if (tmp->mPropertyTable) { for (auto iter = tmp->mPropertyTable->Iter(); !iter.Done(); iter.Next()) { cb.NoteXPCOMChild(iter.UserData()); diff --git a/layout/xul/nsScrollbarButtonFrame.cpp b/layout/xul/nsScrollbarButtonFrame.cpp index 206d9717f..ff757a65f 100644 --- a/layout/xul/nsScrollbarButtonFrame.cpp +++ b/layout/xul/nsScrollbarButtonFrame.cpp @@ -171,9 +171,6 @@ nsScrollbarButtonFrame::HandleButtonPress(nsPresContext* aPresContext, return false; } - mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS, - (uint32_t) ScrollInputMethod::MainThreadScrollbarButtonClick); - if (!m) { sb->MoveToNewPosition(); if (!weakFrame.IsAlive()) { diff --git a/layout/xul/nsSliderFrame.cpp b/layout/xul/nsSliderFrame.cpp index 8e083f20c..3c1f9ef91 100644 --- a/layout/xul/nsSliderFrame.cpp +++ b/layout/xul/nsSliderFrame.cpp @@ -529,9 +529,6 @@ nsSliderFrame::HandleEvent(nsPresContext* aPresContext, return NS_OK; } - mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS, - (uint32_t) ScrollInputMethod::MainThreadScrollbarDrag); - // take our current position and subtract the start location pos -= mDragStart; bool isMouseOutsideThumb = false; @@ -598,9 +595,6 @@ nsSliderFrame::HandleEvent(nsPresContext* aPresContext, nsSize thumbSize = thumbFrame->GetSize(); nscoord thumbLength = isHorizontal ? thumbSize.width : thumbSize.height; - mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS, - (uint32_t) ScrollInputMethod::MainThreadScrollbarTrackClick); - // set it nsWeakFrame weakFrame(this); // should aMaySnap be true here? diff --git a/layout/xul/tree/nsTreeColumns.cpp b/layout/xul/tree/nsTreeColumns.cpp index c6ee19342..ee8577f92 100644 --- a/layout/xul/tree/nsTreeColumns.cpp +++ b/layout/xul/tree/nsTreeColumns.cpp @@ -54,7 +54,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsTreeColumn) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContent) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNext) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsTreeColumn) |