diff options
Diffstat (limited to 'layout/base/nsDisplayList.cpp')
-rw-r--r-- | layout/base/nsDisplayList.cpp | 173 |
1 files changed, 145 insertions, 28 deletions
diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index e35e027e3..8a34d108f 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -80,6 +80,8 @@ #include "nsPluginFrame.h" #include "DisplayItemScrollClip.h" #include "nsSVGMaskFrame.h" +#include "nsTableCellFrame.h" +#include "nsTableColFrame.h" // GetCurrentTime is defined in winbase.h as zero argument macro forwarding to // GetTickCount(). @@ -2631,11 +2633,17 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil const nsRect& aBackgroundRect, nsDisplayList* aList, bool aAllowWillPaintBorderOptimization, - nsStyleContext* aStyleContext) + nsStyleContext* aStyleContext, + const nsRect& aBackgroundOriginRect, + nsIFrame* aSecondaryReferenceFrame) { nsStyleContext* bgSC = aStyleContext; const nsStyleBackground* bg = nullptr; nsRect bgRect = aBackgroundRect + aBuilder->ToReferenceFrame(aFrame); + nsRect bgOriginRect = bgRect; + if (!aBackgroundOriginRect.IsEmpty()) { + bgOriginRect = aBackgroundOriginRect + aBuilder->ToReferenceFrame(aFrame); + } nsPresContext* presContext = aFrame->PresContext(); bool isThemed = aFrame->IsThemed(); if (!isThemed) { @@ -2695,9 +2703,22 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil bg->BottomLayer(), bgRect, useWillPaintBorderOptimization); } - bgItemList.AppendNewToTop( - new (aBuilder) nsDisplayBackgroundColor(aBuilder, aFrame, bgRect, bg, - drawBackgroundColor ? color : NS_RGBA(0, 0, 0, 0))); + if (aSecondaryReferenceFrame) { + bgItemList.AppendNewToTop( + new (aBuilder) nsDisplayTableBackgroundColor(aBuilder, + aSecondaryReferenceFrame, + bgRect, + bg, + drawBackgroundColor ? color : NS_RGBA(0, 0, 0, 0), + aFrame)); + } else { + bgItemList.AppendNewToTop( + new (aBuilder) nsDisplayBackgroundColor(aBuilder, + aFrame, + bgRect, + bg, + drawBackgroundColor ? color : NS_RGBA(0, 0, 0, 0))); + } } if (isThemed) { @@ -2743,12 +2764,31 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil } nsDisplayList thisItemList; - nsDisplayBackgroundImage* bgItem = - new (aBuilder) nsDisplayBackgroundImage(aBuilder, aFrame, i, bgRect, bg); - + nsDisplayBackgroundImage* bgItem; + if (aSecondaryReferenceFrame) { + bgItem = + new (aBuilder) nsDisplayTableBackgroundImage(aBuilder, + aFrame, + i, + bgOriginRect, + bg, + aSecondaryReferenceFrame); + } else { + bgItem = + new (aBuilder) nsDisplayBackgroundImage(aBuilder, aFrame, i, bgOriginRect, bg); + } if (bgItem->ShouldFixToViewport(aBuilder)) { - thisItemList.AppendNewToTop( - nsDisplayFixedPosition::CreateForFixedBackground(aBuilder, aFrame, bgItem, i)); + if (aSecondaryReferenceFrame) { + thisItemList.AppendNewToTop( + nsDisplayTableFixedPosition::CreateForFixedBackground(aBuilder, + aSecondaryReferenceFrame, + bgItem, + i, + aFrame)); + } else { + thisItemList.AppendNewToTop( + nsDisplayFixedPosition::CreateForFixedBackground(aBuilder, aFrame, bgItem, i)); + } } else { thisItemList.AppendNewToTop(bgItem); } @@ -2889,7 +2929,7 @@ nsDisplayBackgroundImage::ImageLayerization nsDisplayBackgroundImage::ShouldCreateOwnLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager) { - nsIFrame* backgroundStyleFrame = nsCSSRendering::FindBackgroundStyleFrame(mFrame); + nsIFrame* backgroundStyleFrame = nsCSSRendering::FindBackgroundStyleFrame(StyleFrame()); if (ActiveLayerTracker::IsBackgroundPositionAnimated(aBuilder, backgroundStyleFrame)) { return WHENEVER_POSSIBLE; @@ -3144,16 +3184,16 @@ nsDisplayBackgroundImage::PaintInternal(nsDisplayListBuilder* aBuilder, StyleGeometryBox clip = mBackgroundStyle->mImage.mLayers[mLayer].mClip; if (clip == StyleGeometryBox::Text) { - if (!GenerateAndPushTextMask(mFrame, aCtx, mBackgroundRect, aBuilder)) { + if (!GenerateAndPushTextMask(StyleFrame(), aCtx, mBackgroundRect, aBuilder)) { return; } } nsCSSRendering::PaintBGParams params = - nsCSSRendering::PaintBGParams::ForSingleLayer(*mFrame->PresContext(), + nsCSSRendering::PaintBGParams::ForSingleLayer(*StyleFrame()->PresContext(), *aCtx, aBounds, mBackgroundRect, - mFrame, flags, mLayer, + StyleFrame(), flags, mLayer, CompositionOp::OP_OVER); params.bgClipRect = aClipRect; image::DrawResult result = @@ -3255,6 +3295,27 @@ nsDisplayBackgroundImage::GetPerFrameKey() nsDisplayItem::GetPerFrameKey(); } +nsDisplayTableBackgroundImage::nsDisplayTableBackgroundImage(nsDisplayListBuilder* aBuilder, + nsIFrame* aFrame, + uint32_t aLayer, + const nsRect& aBackgroundRect, + const nsStyleBackground* aBackgroundStyle, + nsIFrame* aCellFrame) + : nsDisplayBackgroundImage(aBuilder, aFrame, aLayer, aBackgroundRect, aBackgroundStyle) + , mStyleFrame(aFrame) + , mTableType(GetTableTypeFromFrame(mStyleFrame)) +{ + mFrame = aCellFrame; +} + +bool +nsDisplayTableBackgroundImage::IsInvalid(nsRect& aRect) +{ + bool result = mStyleFrame ? mStyleFrame->IsInvalid(aRect) : false; + aRect += ToReferenceFrame(); + return result; +} + nsDisplayThemedBackground::nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, const nsRect& aBackgroundRect) @@ -5272,6 +5333,51 @@ bool nsDisplayFixedPosition::TryMerge(nsDisplayItem* aItem) { return true; } +TableType +GetTableTypeFromFrame(nsIFrame* aFrame) +{ + nsIAtom* type = aFrame->GetType(); + if (type == nsGkAtoms::tableFrame) { + return TableType::TABLE; + } else if (type == nsGkAtoms::tableColFrame) { + return TableType::TABLE_COL; + } else if (type == nsGkAtoms::tableColGroupFrame) { + return TableType::TABLE_COL_GROUP; + } else if (type == nsGkAtoms::tableRowFrame) { + return TableType::TABLE_ROW; + } else if (type == nsGkAtoms::tableRowGroupFrame) { + return TableType::TABLE_ROW_GROUP; + } else if (type == nsGkAtoms::tableCellFrame) { + return TableType::TABLE_CELL; + } else { + MOZ_ASSERT_UNREACHABLE("Invalid frame."); + return TableType::TABLE; + } +} + +nsDisplayTableFixedPosition::nsDisplayTableFixedPosition(nsDisplayListBuilder* aBuilder, + nsIFrame* aFrame, + nsDisplayList* aList, + uint32_t aIndex, + nsIFrame* aAncestorFrame) + : nsDisplayFixedPosition(aBuilder, aFrame, aList, aIndex) + , mTableType(GetTableTypeFromFrame(aAncestorFrame)) +{ +} + +/* static */ nsDisplayTableFixedPosition* +nsDisplayTableFixedPosition::CreateForFixedBackground(nsDisplayListBuilder* aBuilder, + nsIFrame* aFrame, + nsDisplayBackgroundImage* aImage, + uint32_t aIndex, + nsIFrame* aAncestorFrame) +{ + nsDisplayList temp; + temp.AppendToTop(aImage); + + return new (aBuilder) nsDisplayTableFixedPosition(aBuilder, aFrame, &temp, aIndex + 1, aAncestorFrame); +} + nsDisplayStickyPosition::nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsDisplayList* aList) @@ -5708,7 +5814,7 @@ nsDisplayTransform::GetDeltaToTransformOrigin(const nsIFrame* aFrame, } /* Allows us to access dimension getters by index. */ - float coords[2]; + float transformOrigin[2]; TransformReferenceBox::DimensionGetter dimensionGetter[] = { &TransformReferenceBox::Width, &TransformReferenceBox::Height }; TransformReferenceBox::DimensionGetter offsetGetter[] = @@ -5718,33 +5824,33 @@ nsDisplayTransform::GetDeltaToTransformOrigin(const nsIFrame* aFrame, /* If the transform-origin specifies a percentage, take the percentage * of the size of the box. */ - const nsStyleCoord &coord = display->mTransformOrigin[index]; - if (coord.GetUnit() == eStyleUnit_Calc) { - const nsStyleCoord::Calc *calc = coord.GetCalcValue(); - coords[index] = + const nsStyleCoord &originValue = display->mTransformOrigin[index]; + if (originValue.GetUnit() == eStyleUnit_Calc) { + const nsStyleCoord::Calc *calc = originValue.GetCalcValue(); + transformOrigin[index] = NSAppUnitsToFloatPixels((refBox.*dimensionGetter[index])(), aAppUnitsPerPixel) * calc->mPercent + NSAppUnitsToFloatPixels(calc->mLength, aAppUnitsPerPixel); - } else if (coord.GetUnit() == eStyleUnit_Percent) { - coords[index] = + } else if (originValue.GetUnit() == eStyleUnit_Percent) { + transformOrigin[index] = NSAppUnitsToFloatPixels((refBox.*dimensionGetter[index])(), aAppUnitsPerPixel) * - coord.GetPercentValue(); + originValue.GetPercentValue(); } else { - MOZ_ASSERT(coord.GetUnit() == eStyleUnit_Coord, "unexpected unit"); - coords[index] = - NSAppUnitsToFloatPixels(coord.GetCoordValue(), aAppUnitsPerPixel); + MOZ_ASSERT(originValue.GetUnit() == eStyleUnit_Coord, "unexpected unit"); + transformOrigin[index] = + NSAppUnitsToFloatPixels(originValue.GetCoordValue(), aAppUnitsPerPixel); } if (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) { // SVG frames (unlike other frames) have a reference box that can be (and // typically is) offset from the TopLeft() of the frame. We need to // account for that here. - coords[index] += + transformOrigin[index] += NSAppUnitsToFloatPixels((refBox.*offsetGetter[index])(), aAppUnitsPerPixel); } } - return Point3D(coords[0], coords[1], + return Point3D(transformOrigin[0], transformOrigin[1], NSAppUnitsToFloatPixels(display->mTransformOrigin[2].GetCoordValue(), aAppUnitsPerPixel)); } @@ -5917,6 +6023,17 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProp frame && frame->IsSVGTransformed(&svgTransform, &transformFromSVGParent); bool hasTransformFromSVGParent = hasSVGTransforms && !transformFromSVGParent.IsIdentity(); + + bool shouldRound = true; + + // An SVG frame should not have its translation rounded. + // Note it's possible that the SVG frame doesn't have an SVG + // transform but only has a CSS transform. + if (frame && frame->HasAnyStateBits(NS_FRAME_SVG_LAYOUT) && + !(frame->GetType() == nsGkAtoms::svgOuterSVGAnonChildFrame)) { + shouldRound = false; + } + /* Transformed frames always have a transform, or are preserving 3d (and might still have perspective!) */ if (aProperties.mTransformList) { result = nsStyleTransformMatrix::ReadTransforms(aProperties.mTransformList->mHead, @@ -5994,7 +6111,7 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProp // Otherwise we need to manually translate into our parent's coordinate // space. if (frame->IsTransformed()) { - nsLayoutUtils::PostTranslate(result, frame->GetPosition(), aAppUnitsPerPixel, !hasSVGTransforms); + nsLayoutUtils::PostTranslate(result, frame->GetPosition(), aAppUnitsPerPixel, shouldRound); } Matrix4x4 parent = GetResultingTransformMatrixInternal(props, @@ -6005,7 +6122,7 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProp } if (aFlags & OFFSET_BY_ORIGIN) { - nsLayoutUtils::PostTranslate(result, aOrigin, aAppUnitsPerPixel, !hasSVGTransforms); + nsLayoutUtils::PostTranslate(result, aOrigin, aAppUnitsPerPixel, shouldRound); } return result; |