summaryrefslogtreecommitdiffstats
path: root/layout/base
diff options
context:
space:
mode:
authorwolfbeast <mcwerewolf@wolfbeast.com>2019-12-06 23:39:47 +0100
committerwolfbeast <mcwerewolf@wolfbeast.com>2019-12-06 23:39:47 +0100
commit642032029f65e9dc0d38fbb6d35ef656c73a292c (patch)
tree78a22bd12d679ab532db490d631ee69fa085aec1 /layout/base
parent50ef259a2df60d020ccb02d76dc5aa4835ee319e (diff)
parent2529b2edece0a0ed86553d1e73eef13c3848bf64 (diff)
downloadUXP-642032029f65e9dc0d38fbb6d35ef656c73a292c.tar
UXP-642032029f65e9dc0d38fbb6d35ef656c73a292c.tar.gz
UXP-642032029f65e9dc0d38fbb6d35ef656c73a292c.tar.lz
UXP-642032029f65e9dc0d38fbb6d35ef656c73a292c.tar.xz
UXP-642032029f65e9dc0d38fbb6d35ef656c73a292c.zip
Merge branch 'master' into release
Diffstat (limited to 'layout/base')
-rw-r--r--layout/base/LayoutConstants.h31
-rw-r--r--layout/base/RestyleManagerBase.cpp9
-rw-r--r--layout/base/moz.build4
-rw-r--r--layout/base/nsDisplayItemTypesList.h4
-rw-r--r--layout/base/nsDisplayList.cpp132
-rw-r--r--layout/base/nsDisplayList.h104
-rw-r--r--layout/base/nsLayoutUtils.cpp76
-rw-r--r--layout/base/nsLayoutUtils.h95
8 files changed, 355 insertions, 100 deletions
diff --git a/layout/base/LayoutConstants.h b/layout/base/LayoutConstants.h
new file mode 100644
index 000000000..cd6e1c3f5
--- /dev/null
+++ b/layout/base/LayoutConstants.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* constants used throughout the Layout module */
+
+#ifndef LayoutConstants_h___
+#define LayoutConstants_h___
+
+#include "nsSize.h" // for NS_MAXSIZE
+
+/**
+ * Constant used to indicate an unconstrained size.
+ */
+#define NS_UNCONSTRAINEDSIZE NS_MAXSIZE
+
+// NOTE: There are assumptions all over that these have the same value,
+// namely NS_UNCONSTRAINEDSIZE.
+#define NS_INTRINSICSIZE NS_UNCONSTRAINEDSIZE
+#define NS_AUTOHEIGHT NS_UNCONSTRAINEDSIZE
+#define NS_AUTOOFFSET NS_UNCONSTRAINEDSIZE
+
+// +1 is to avoid clamped huge margin values being processed as auto margins
+#define NS_AUTOMARGIN (NS_UNCONSTRAINEDSIZE + 1)
+
+#define NS_INTRINSIC_WIDTH_UNKNOWN nscoord_MIN
+
+
+#endif // LayoutConstants_h___
diff --git a/layout/base/RestyleManagerBase.cpp b/layout/base/RestyleManagerBase.cpp
index 6770f9464..6ef048a19 100644
--- a/layout/base/RestyleManagerBase.cpp
+++ b/layout/base/RestyleManagerBase.cpp
@@ -474,15 +474,6 @@ RecomputePosition(nsIFrame* aFrame)
if (display->IsRelativelyPositionedStyle()) {
// Move the frame
if (display->mPosition == NS_STYLE_POSITION_STICKY) {
- if (display->IsInnerTableStyle()) {
- // We don't currently support sticky positioning of inner table
- // elements (bug 975644). Bail.
- //
- // When this is fixed, remove the null-check for the computed
- // offsets in nsTableRowFrame::ReflowChildren.
- return true;
- }
-
// Update sticky positioning for an entire element at once, starting with
// the first continuation or ib-split sibling.
// It's rare that the frame we already have isn't already the first
diff --git a/layout/base/moz.build b/layout/base/moz.build
index 4308a6e4d..afc683665 100644
--- a/layout/base/moz.build
+++ b/layout/base/moz.build
@@ -13,6 +13,9 @@ with Files('Display*'):
with Files('FrameLayerBuilder.*'):
BUG_COMPONENT = ('Core', 'Layout: View Rendering')
+with Files('LayoutConstants.*'):
+ BUG_COMPONENT = ('Core', 'Layout: View Rendering')
+
with Files('LayerState.*'):
BUG_COMPONENT = ('Core', 'Layout: View Rendering')
@@ -63,6 +66,7 @@ EXPORTS += [
'FrameLayerBuilder.h',
'FrameProperties.h',
'LayerState.h',
+ 'LayoutConstants.h',
'LayoutLogging.h',
'nsArenaMemoryStats.h',
'nsBidi.h',
diff --git a/layout/base/nsDisplayItemTypesList.h b/layout/base/nsDisplayItemTypesList.h
index 9865395a7..cf809817f 100644
--- a/layout/base/nsDisplayItemTypesList.h
+++ b/layout/base/nsDisplayItemTypesList.h
@@ -56,9 +56,7 @@ DECLARE_DISPLAY_ITEM_TYPE(SVG_PATH_GEOMETRY)
DECLARE_DISPLAY_ITEM_TYPE(SVG_TEXT)
DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_BACKGROUND)
DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_SELECTION)
-DECLARE_DISPLAY_ITEM_TYPE(TABLE_ROW_BACKGROUND)
-DECLARE_DISPLAY_ITEM_TYPE(TABLE_ROW_GROUP_BACKGROUND)
-DECLARE_DISPLAY_ITEM_TYPE(TABLE_BORDER_BACKGROUND)
+DECLARE_DISPLAY_ITEM_TYPE(TABLE_BORDER_COLLAPSE)
DECLARE_DISPLAY_ITEM_TYPE(TEXT)
DECLARE_DISPLAY_ITEM_TYPE(TEXT_OVERFLOW)
DECLARE_DISPLAY_ITEM_TYPE_FLAGS(TRANSFORM,TYPE_RENDERS_NO_IMAGES)
diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp
index e22230b41..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)
diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h
index c81d34fac..9cee7b517 100644
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -2737,7 +2737,9 @@ public:
const nsRect& aBackgroundRect,
nsDisplayList* aList,
bool aAllowWillPaintBorderOptimization = true,
- nsStyleContext* aStyleContext = nullptr);
+ nsStyleContext* aStyleContext = nullptr,
+ const nsRect& aBackgroundOriginRect = nsRect(),
+ nsIFrame* aSecondaryReferenceFrame = nullptr);
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
@@ -2812,6 +2814,8 @@ protected:
void PaintInternal(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
const nsRect& aBounds, nsRect* aClipRect);
+ virtual nsIFrame* StyleFrame() { return mFrame; }
+
// Determine whether we want to be separated into our own layer, independent
// of whether this item can actually be layerized.
enum ImageLayerization {
@@ -2837,6 +2841,60 @@ protected:
bool mShouldTreatAsFixed;
};
+enum class TableType : uint8_t {
+ TABLE,
+ TABLE_COL,
+ TABLE_COL_GROUP,
+ TABLE_ROW,
+ TABLE_ROW_GROUP,
+ TABLE_CELL,
+
+ TABLE_TYPE_MAX
+};
+
+enum class TableTypeBits : uint8_t {
+ COUNT = 3
+};
+
+static_assert(
+ static_cast<uint8_t>(TableType::TABLE_TYPE_MAX) < (1 << (static_cast<uint8_t>(TableTypeBits::COUNT) + 1)),
+ "TableType cannot fit with TableTypeBits::COUNT");
+TableType GetTableTypeFromFrame(nsIFrame* aFrame);
+
+/**
+ * A display item to paint background image for table. For table parts, such
+ * as row, row group, col, col group, when drawing its background, we'll
+ * create separate background image display item for its containning cell.
+ * Those background image display items will reference to same DisplayItemData
+ * if we keep the mFrame point to cell's ancestor frame. We don't want to this
+ * happened bacause share same DisplatItemData will cause many bugs. So that
+ * we let mFrame point to cell frame and store the table type of the ancestor
+ * frame. And use mFrame and table type as key to generate DisplayItemData to
+ * avoid sharing DisplayItemData.
+ *
+ * Also store ancestor frame as mStyleFrame for all rendering informations.
+ */
+class nsDisplayTableBackgroundImage : public nsDisplayBackgroundImage {
+public:
+ nsDisplayTableBackgroundImage(nsDisplayListBuilder* aBuilder,
+ nsIFrame* aFrame,
+ uint32_t aLayer,
+ const nsRect& aBackgroundRect,
+ const nsStyleBackground* aBackgroundStyle,
+ nsIFrame* aCellFrame);
+
+ virtual uint32_t GetPerFrameKey() override {
+ return (static_cast<uint8_t>(mTableType) << nsDisplayItem::TYPE_BITS) |
+ nsDisplayItem::GetPerFrameKey();
+ }
+
+ virtual bool IsInvalid(nsRect& aRect) override;
+protected:
+ virtual nsIFrame* StyleFrame() override { return mStyleFrame; }
+
+ nsIFrame* mStyleFrame;
+ TableType mTableType;
+};
/**
* A display item to paint the native theme background for a frame.
@@ -2957,6 +3015,27 @@ protected:
mozilla::gfx::Color mColor;
};
+class nsDisplayTableBackgroundColor : public nsDisplayBackgroundColor
+{
+public:
+ nsDisplayTableBackgroundColor(nsDisplayListBuilder* aBuilder,
+ nsIFrame* aFrame,
+ const nsRect& aBackgroundRect,
+ const nsStyleBackground* aBackgroundStyle,
+ nscolor aColor,
+ nsIFrame* aAncestorFrame)
+ : nsDisplayBackgroundColor(aBuilder, aFrame, aBackgroundRect, aBackgroundStyle, aColor)
+ , mTableType(GetTableTypeFromFrame(aAncestorFrame))
+ { }
+
+ virtual uint32_t GetPerFrameKey() override {
+ return (static_cast<uint8_t>(mTableType) << nsDisplayItem::TYPE_BITS) |
+ nsDisplayItem::GetPerFrameKey();
+ }
+protected:
+ TableType mTableType;
+};
+
class nsDisplayClearBackground : public nsDisplayItem
{
public:
@@ -3735,7 +3814,7 @@ public:
return mAnimatedGeometryRootForScrollMetadata;
}
-private:
+protected:
// For background-attachment:fixed
nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList, uint32_t aIndex);
@@ -3746,6 +3825,27 @@ private:
bool mIsFixedBackground;
};
+class nsDisplayTableFixedPosition : public nsDisplayFixedPosition
+{
+public:
+ static nsDisplayTableFixedPosition* CreateForFixedBackground(nsDisplayListBuilder* aBuilder,
+ nsIFrame* aFrame,
+ nsDisplayBackgroundImage* aImage,
+ uint32_t aIndex,
+ nsIFrame* aAncestorFrame);
+
+ virtual uint32_t GetPerFrameKey() override {
+ return (mIndex << (nsDisplayItem::TYPE_BITS + static_cast<uint8_t>(TableTypeBits::COUNT))) |
+ (static_cast<uint8_t>(mTableType) << nsDisplayItem::TYPE_BITS) |
+ nsDisplayItem::GetPerFrameKey();
+ }
+protected:
+ nsDisplayTableFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
+ nsDisplayList* aList, uint32_t aIndex, nsIFrame* aAncestorFrame);
+
+ TableType mTableType;
+};
+
/**
* This creates an empty scrollable layer. It has no child layers.
* It is used to record the existence of a scrollable frame in the layer
diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp
index 06690b208..21d20c69f 100644
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -4671,8 +4671,6 @@ GetDefiniteSize(const nsStyleCoord& aStyle,
nscoord pb = aIsInlineAxis ? aPercentageBasis.value().ISize(wm)
: aPercentageBasis.value().BSize(wm);
if (pb == NS_UNCONSTRAINEDSIZE) {
- // XXXmats given that we're calculating an intrinsic size here,
- // maybe we should back-compute the calc-size using AddPercents?
return false;
}
*aResult = std::max(0, calc->mLength +
@@ -4916,12 +4914,9 @@ AddIntrinsicSizeOffset(nsRenderingContext* aRenderingContext,
nscoord result = aContentSize;
nscoord min = aContentMinSize;
nscoord coordOutsideSize = 0;
- float pctOutsideSize = 0;
- float pctTotal = 0.0f;
if (!(aFlags & nsLayoutUtils::IGNORE_PADDING)) {
coordOutsideSize += aOffsets.hPadding;
- pctOutsideSize += aOffsets.hPctPadding;
}
coordOutsideSize += aOffsets.hBorder;
@@ -4929,21 +4924,15 @@ AddIntrinsicSizeOffset(nsRenderingContext* aRenderingContext,
if (aBoxSizing == StyleBoxSizing::Border) {
min += coordOutsideSize;
result = NSCoordSaturatingAdd(result, coordOutsideSize);
- pctTotal += pctOutsideSize;
coordOutsideSize = 0;
- pctOutsideSize = 0.0f;
}
coordOutsideSize += aOffsets.hMargin;
- pctOutsideSize += aOffsets.hPctMargin;
min += coordOutsideSize;
result = NSCoordSaturatingAdd(result, coordOutsideSize);
- pctTotal += pctOutsideSize;
- const bool shouldAddPercent = aType == nsLayoutUtils::PREF_ISIZE ||
- (aFlags & nsLayoutUtils::ADD_PERCENTS);
nscoord size;
if (aType == nsLayoutUtils::MIN_ISIZE &&
(((aStyleSize.HasPercent() || aStyleMaxSize.HasPercent()) &&
@@ -4961,18 +4950,6 @@ AddIntrinsicSizeOffset(nsRenderingContext* aRenderingContext,
GetIntrinsicCoord(aStyleSize, aRenderingContext, aFrame,
PROP_WIDTH, size)) {
result = size + coordOutsideSize;
- if (shouldAddPercent) {
- result = nsLayoutUtils::AddPercents(result, pctOutsideSize);
- }
- } else {
- // NOTE: We could really do a lot better for percents and for some
- // cases of calc() containing percent (certainly including any where
- // the coefficient on the percent is positive and there are no max()
- // expressions). However, doing better for percents wouldn't be
- // backwards compatible.
- if (shouldAddPercent) {
- result = nsLayoutUtils::AddPercents(result, pctTotal);
- }
}
nscoord maxSize = aFixedMaxSize ? *aFixedMaxSize : 0;
@@ -4980,9 +4957,6 @@ AddIntrinsicSizeOffset(nsRenderingContext* aRenderingContext,
GetIntrinsicCoord(aStyleMaxSize, aRenderingContext, aFrame,
PROP_MAX_WIDTH, maxSize)) {
maxSize += coordOutsideSize;
- if (shouldAddPercent) {
- maxSize = nsLayoutUtils::AddPercents(maxSize, pctOutsideSize);
- }
if (result > maxSize) {
result = maxSize;
}
@@ -4993,17 +4967,11 @@ AddIntrinsicSizeOffset(nsRenderingContext* aRenderingContext,
GetIntrinsicCoord(aStyleMinSize, aRenderingContext, aFrame,
PROP_MIN_WIDTH, minSize)) {
minSize += coordOutsideSize;
- if (shouldAddPercent) {
- minSize = nsLayoutUtils::AddPercents(minSize, pctOutsideSize);
- }
if (result < minSize) {
result = minSize;
}
}
- if (shouldAddPercent) {
- min = nsLayoutUtils::AddPercents(min, pctTotal);
- }
if (result < min) {
result = min;
}
@@ -5020,9 +4988,6 @@ AddIntrinsicSizeOffset(nsRenderingContext* aRenderingContext,
: devSize.width);
// GetMinimumWidgetSize() returns a border-box width.
themeSize += aOffsets.hMargin;
- if (shouldAddPercent) {
- themeSize = nsLayoutUtils::AddPercents(themeSize, aOffsets.hPctMargin);
- }
if (themeSize > result || !canOverride) {
result = themeSize;
}
@@ -5267,9 +5232,19 @@ nsLayoutUtils::IntrinsicForAxis(PhysicalAxis aAxis,
min = aFrame->GetMinISize(aRenderingContext);
}
+ nscoord pmPercentageBasis = NS_UNCONSTRAINEDSIZE;
+ if (aPercentageBasis.isSome()) {
+ // The padding/margin percentage basis is the inline-size in the parent's
+ // writing-mode.
+ auto childWM = aFrame->GetWritingMode();
+ pmPercentageBasis =
+ aFrame->GetParent()->GetWritingMode().IsOrthogonalTo(childWM) ?
+ aPercentageBasis->BSize(childWM) :
+ aPercentageBasis->ISize(childWM);
+ }
nsIFrame::IntrinsicISizeOffsetData offsets =
- MOZ_LIKELY(isInlineAxis) ? aFrame->IntrinsicISizeOffsets()
- : aFrame->IntrinsicBSizeOffsets();
+ MOZ_LIKELY(isInlineAxis) ? aFrame->IntrinsicISizeOffsets(pmPercentageBasis)
+ : aFrame->IntrinsicBSizeOffsets(pmPercentageBasis);
nscoord contentBoxSize = result;
result = AddIntrinsicSizeOffset(aRenderingContext, aFrame, offsets, aType,
boxSizing, result, min, styleISize,
@@ -5310,11 +5285,12 @@ nsLayoutUtils::IntrinsicForContainer(nsRenderingContext* aRenderingContext,
}
/* static */ nscoord
-nsLayoutUtils::MinSizeContributionForAxis(PhysicalAxis aAxis,
+nsLayoutUtils::MinSizeContributionForAxis(PhysicalAxis aAxis,
nsRenderingContext* aRC,
- nsIFrame* aFrame,
- IntrinsicISizeType aType,
- uint32_t aFlags)
+ nsIFrame* aFrame,
+ IntrinsicISizeType aType,
+ const LogicalSize& aPercentageBasis,
+ uint32_t aFlags)
{
MOZ_ASSERT(aFrame);
MOZ_ASSERT(aFrame->IsFlexOrGridItem(),
@@ -5328,9 +5304,7 @@ nsLayoutUtils::MinSizeContributionForAxis(PhysicalAxis aAxis,
aWM.IsVertical() ? "vertical" : "horizontal");
#endif
- // Note: this method is only meant for grid/flex items which always
- // include percentages in their intrinsic size.
- aFlags |= nsLayoutUtils::ADD_PERCENTS;
+ // Note: this method is only meant for grid/flex items.
const nsStylePosition* const stylePos = aFrame->StylePosition();
const nsStyleCoord* style = aAxis == eAxisHorizontal ? &stylePos->mMinWidth
: &stylePos->mMinHeight;
@@ -5375,11 +5349,17 @@ nsLayoutUtils::MinSizeContributionForAxis(PhysicalAxis aAxis,
// wrapping inside of it should not apply font size inflation.
AutoMaybeDisableFontInflation an(aFrame);
- PhysicalAxis ourInlineAxis =
- aFrame->GetWritingMode().PhysicalAxis(eLogicalAxisInline);
+ // The padding/margin percentage basis is the inline-size in the parent's
+ // writing-mode.
+ auto childWM = aFrame->GetWritingMode();
+ nscoord pmPercentageBasis =
+ aFrame->GetParent()->GetWritingMode().IsOrthogonalTo(childWM) ?
+ aPercentageBasis.BSize(childWM) :
+ aPercentageBasis.ISize(childWM);
+ PhysicalAxis ourInlineAxis = childWM.PhysicalAxis(eLogicalAxisInline);
nsIFrame::IntrinsicISizeOffsetData offsets =
- ourInlineAxis == aAxis ? aFrame->IntrinsicISizeOffsets()
- : aFrame->IntrinsicBSizeOffsets();
+ ourInlineAxis == aAxis ? aFrame->IntrinsicISizeOffsets(pmPercentageBasis)
+ : aFrame->IntrinsicBSizeOffsets(pmPercentageBasis);
nscoord result = 0;
nscoord min = 0;
diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h
index 0a82dbf6a..bba1f3265 100644
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -6,6 +6,7 @@
#ifndef nsLayoutUtils_h__
#define nsLayoutUtils_h__
+#include "LayoutConstants.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Maybe.h"
@@ -154,6 +155,7 @@ public:
typedef mozilla::ScreenMargin ScreenMargin;
typedef mozilla::LayoutDeviceIntSize LayoutDeviceIntSize;
typedef mozilla::StyleGeometryBox StyleGeometryBox;
+ typedef mozilla::LogicalSize LogicalSize;
/**
* Finds previously assigned ViewID for the given content element, if any.
@@ -1381,7 +1383,8 @@ public:
* variations if that's what matches aAxis) and its padding, border and margin
* in the corresponding dimension.
* @param aPercentageBasis an optional percentage basis (in aFrame's WM).
- * Pass NS_UNCONSTRAINEDSIZE if the basis is indefinite in either/both axes.
+ * If the basis is indefinite in a given axis, pass a size with
+ * NS_UNCONSTRAINEDSIZE in that component.
* If you pass Nothing() a percentage basis will be calculated from aFrame's
* ancestors' computed size in the relevant axis, if needed.
* @param aMarginBoxMinSizeClamp make the result fit within this margin-box
@@ -1395,14 +1398,13 @@ public:
IGNORE_PADDING = 0x01,
BAIL_IF_REFLOW_NEEDED = 0x02, // returns NS_INTRINSIC_WIDTH_UNKNOWN if so
MIN_INTRINSIC_ISIZE = 0x04, // use min-width/height instead of width/height
- ADD_PERCENTS = 0x08, // apply AddPercents also for MIN_ISIZE
};
static nscoord
IntrinsicForAxis(mozilla::PhysicalAxis aAxis,
nsRenderingContext* aRenderingContext,
nsIFrame* aFrame,
IntrinsicISizeType aType,
- const mozilla::Maybe<mozilla::LogicalSize>& aPercentageBasis = mozilla::Nothing(),
+ const mozilla::Maybe<LogicalSize>& aPercentageBasis = mozilla::Nothing(),
uint32_t aFlags = 0,
nscoord aMarginBoxMinSizeClamp = NS_MAXSIZE);
/**
@@ -1427,31 +1429,18 @@ public:
* calculates the result as if the 'min-' computed value is zero.
* Otherwise, return NS_UNCONSTRAINEDSIZE.
*
+ * @param aPercentageBasis the percentage basis (in aFrame's WM).
+ * Pass NS_UNCONSTRAINEDSIZE if the basis is indefinite in either/both axes.
* @note this behavior is specific to Grid/Flexbox (currently) so aFrame
* should be a grid/flex item.
*/
- static nscoord MinSizeContributionForAxis(mozilla::PhysicalAxis aAxis,
- nsRenderingContext* aRC,
- nsIFrame* aFrame,
- IntrinsicISizeType aType,
- uint32_t aFlags = 0);
-
- /**
- * 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' 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 && aCurrent > 0) {
- return MOZ_UNLIKELY(aPercent >= 1.0f) ? nscoord_MAX
- : NSToCoordRound(float(aCurrent) / (1.0f - aPercent));
- }
- return aCurrent;
- }
+ static nscoord
+ MinSizeContributionForAxis(mozilla::PhysicalAxis aAxis,
+ nsRenderingContext* aRC,
+ nsIFrame* aFrame,
+ IntrinsicISizeType aType,
+ const LogicalSize& aPercentageBasis,
+ uint32_t aFlags = 0);
/*
* Convert nsStyleCoord to nscoord when percentages depend on the
@@ -2876,6 +2865,62 @@ public:
static nsRect ComputeGeometryBox(nsIFrame* aFrame,
StyleGeometryBox aGeometryBox);
+ /**
+ * Resolve a CSS <length-percentage> value to a definite size.
+ */
+ template<bool clampNegativeResultToZero>
+ static nscoord ResolveToLength(const nsStyleCoord& aCoord,
+ nscoord aPercentageBasis)
+ {
+ NS_WARNING_ASSERTION(aPercentageBasis >= nscoord(0), "nscoord overflow?");
+
+ switch (aCoord.GetUnit()) {
+ case eStyleUnit_Coord:
+ MOZ_ASSERT(!clampNegativeResultToZero || aCoord.GetCoordValue() >= 0,
+ "This value should have been rejected by the style system");
+ return aCoord.GetCoordValue();
+ case eStyleUnit_Percent:
+ if (aPercentageBasis == NS_UNCONSTRAINEDSIZE) {
+ return nscoord(0);
+ }
+ MOZ_ASSERT(!clampNegativeResultToZero || aCoord.GetPercentValue() >= 0,
+ "This value should have been rejected by the style system");
+ return NSToCoordFloorClamped(aPercentageBasis *
+ aCoord.GetPercentValue());
+ case eStyleUnit_Calc: {
+ nsStyleCoord::Calc* calc = aCoord.GetCalcValue();
+ nscoord result;
+ if (aPercentageBasis == NS_UNCONSTRAINEDSIZE) {
+ result = calc->mLength;
+ } else {
+ result = calc->mLength +
+ NSToCoordFloorClamped(aPercentageBasis * calc->mPercent);
+ }
+ if (clampNegativeResultToZero && result < 0) {
+ return nscoord(0);
+ }
+ return result;
+ }
+ default:
+ MOZ_ASSERT_UNREACHABLE("Unexpected unit!");
+ return nscoord(0);
+ }
+ }
+
+ /**
+ * Resolve a column-gap/row-gap to a definite size.
+ * @note This method resolves 'normal' to zero.
+ * Callers who want different behavior should handle 'normal' on their own.
+ */
+ static nscoord ResolveGapToLength(const nsStyleCoord& aGap,
+ nscoord aPercentageBasis)
+ {
+ if (aGap.GetUnit() == eStyleUnit_Normal) {
+ return nscoord(0);
+ }
+ return ResolveToLength<true>(aGap, aPercentageBasis);
+ }
+
private:
static uint32_t sFontSizeInflationEmPerLine;
static uint32_t sFontSizeInflationMinTwips;