Set inflation container to null during parts of intrinsic sizing that should not have inflation applied. (Bug 706609, patch 4) r=roc

This is the first of two patches to honor inflation during intrinsic
width calculation (which we need to do to make some form controls
inflate correctly).
This commit is contained in:
L. David Baron
2012-01-24 17:21:29 -08:00
parent ccb7b28d3f
commit 1d98076bbe
22 changed files with 338 additions and 2 deletions

View File

@@ -121,6 +121,7 @@
using namespace mozilla; using namespace mozilla;
using namespace mozilla::layers; using namespace mozilla::layers;
using namespace mozilla::dom; using namespace mozilla::dom;
using namespace mozilla::layout;
#ifdef DEBUG #ifdef DEBUG
// TODO: remove, see bug 598468. // TODO: remove, see bug 598468.
@@ -2328,6 +2329,11 @@ GetIntrinsicCoord(const nsStyleCoord& aStyle,
NS_ASSERTION(val == NS_STYLE_WIDTH_MAX_CONTENT || NS_ASSERTION(val == NS_STYLE_WIDTH_MAX_CONTENT ||
val == NS_STYLE_WIDTH_MIN_CONTENT, val == NS_STYLE_WIDTH_MIN_CONTENT,
"should have reduced everything remaining to one of these"); "should have reduced everything remaining to one of these");
// If aFrame is a container for font size inflation, then shrink
// wrapping inside of it should not apply font size inflation.
AutoMaybeNullInflationContainer an(aFrame);
if (val == NS_STYLE_WIDTH_MAX_CONTENT) if (val == NS_STYLE_WIDTH_MAX_CONTENT)
aResult = aFrame->GetPrefWidth(aRenderingContext); aResult = aFrame->GetPrefWidth(aRenderingContext);
else else
@@ -2356,6 +2362,10 @@ nsLayoutUtils::IntrinsicForContainer(nsRenderingContext *aRenderingContext,
aType == MIN_WIDTH ? "min" : "pref"); aType == MIN_WIDTH ? "min" : "pref");
#endif #endif
// If aFrame is a container for font size inflation, then shrink
// wrapping inside of it should not apply font size inflation.
AutoMaybeNullInflationContainer an(aFrame);
nsIFrame::IntrinsicWidthOffsetData offsets = nsIFrame::IntrinsicWidthOffsetData offsets =
aFrame->IntrinsicWidthOffsets(aRenderingContext); aFrame->IntrinsicWidthOffsets(aRenderingContext);
@@ -2611,6 +2621,10 @@ nsLayoutUtils::ComputeWidthValue(
// are less than 0 have already been dropped by the parser.) // are less than 0 have already been dropped by the parser.)
result -= aContentEdgeToBoxSizing; result -= aContentEdgeToBoxSizing;
} else if (eStyleUnit_Enumerated == aCoord.GetUnit()) { } else if (eStyleUnit_Enumerated == aCoord.GetUnit()) {
// If aFrame is a container for font size inflation, then shrink
// wrapping inside of it should not apply font size inflation.
AutoMaybeNullInflationContainer an(aFrame);
PRInt32 val = aCoord.GetIntValue(); PRInt32 val = aCoord.GetIntValue();
switch (val) { switch (val) {
case NS_STYLE_WIDTH_MAX_CONTENT: case NS_STYLE_WIDTH_MAX_CONTENT:
@@ -2957,6 +2971,9 @@ nsLayoutUtils::ComputeAutoSizeWithIntrinsicDimensions(nscoord minWidth, nscoord
nsLayoutUtils::MinWidthFromInline(nsIFrame* aFrame, nsLayoutUtils::MinWidthFromInline(nsIFrame* aFrame,
nsRenderingContext* aRenderingContext) nsRenderingContext* aRenderingContext)
{ {
NS_ASSERTION(!nsLayoutUtils::IsContainerForFontSizeInflation(aFrame),
"should not be container for font size inflation");
nsIFrame::InlineMinWidthData data; nsIFrame::InlineMinWidthData data;
DISPLAY_MIN_WIDTH(aFrame, data.prevLines); DISPLAY_MIN_WIDTH(aFrame, data.prevLines);
aFrame->AddInlineMinWidth(aRenderingContext, &data); aFrame->AddInlineMinWidth(aRenderingContext, &data);
@@ -2968,6 +2985,9 @@ nsLayoutUtils::MinWidthFromInline(nsIFrame* aFrame,
nsLayoutUtils::PrefWidthFromInline(nsIFrame* aFrame, nsLayoutUtils::PrefWidthFromInline(nsIFrame* aFrame,
nsRenderingContext* aRenderingContext) nsRenderingContext* aRenderingContext)
{ {
NS_ASSERTION(!nsLayoutUtils::IsContainerForFontSizeInflation(aFrame),
"should not be container for font size inflation");
nsIFrame::InlinePrefWidthData data; nsIFrame::InlinePrefWidthData data;
DISPLAY_PREF_WIDTH(aFrame, data.prevLines); DISPLAY_PREF_WIDTH(aFrame, data.prevLines);
aFrame->AddInlinePrefWidth(aRenderingContext, &data); aFrame->AddInlinePrefWidth(aRenderingContext, &data);

View File

@@ -1638,6 +1638,43 @@ public:
#endif #endif
}; };
namespace mozilla {
namespace layout {
/**
* An RAII class which will, for the duration of its lifetime,
* **if** the frame given is a container for font size inflation,
* set the current inflation container on the pres context to null
* (and then, in its destructor, restore the old value).
*/
class AutoMaybeNullInflationContainer {
public:
AutoMaybeNullInflationContainer(nsIFrame *aFrame)
{
if (nsLayoutUtils::IsContainerForFontSizeInflation(aFrame)) {
mPresContext = aFrame->PresContext();
mOldValue = mPresContext->mCurrentInflationContainer;
mPresContext->mCurrentInflationContainer = nsnull;
} else {
// indicate we have nothing to restore
mPresContext = nsnull;
}
}
~AutoMaybeNullInflationContainer()
{
if (mPresContext) {
mPresContext->mCurrentInflationContainer = mOldValue;
}
}
private:
nsPresContext *mPresContext;
nsIFrame *mOldValue;
};
}
}
class nsSetAttrRunnable : public nsRunnable class nsSetAttrRunnable : public nsRunnable
{ {
public: public:

View File

@@ -383,6 +383,7 @@ _BROWSER_FILES = \
_INFLATION_REFTEST_FILES = \ _INFLATION_REFTEST_FILES = \
$(shell find $(srcdir)/font-inflation/ -name '*.html' -o -name '*.xhtml') \ $(shell find $(srcdir)/font-inflation/ -name '*.html' -o -name '*.xhtml') \
$(srcdir)/../../reftests/webm-video/black140x100.webm \ $(srcdir)/../../reftests/webm-video/black140x100.webm \
$(srcdir)/../../reftests/fonts/Ahem.ttf \
$(NULL) $(NULL)
libs:: $(_TEST_FILES) libs:: $(_TEST_FILES)

View File

@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<style>
@font-face { font-family: Ahem; src: url(Ahem.ttf); }
html, body { margin: 0; padding: 0; }
body { width: 10px }
p {
margin: 0;
background: yellow;
color: blue;
width: 60px;
font: 12px Ahem;
}
</style>
<!--
In a 60px container, the minimum font size at 15em per line is 4px.
-->
<p>This is tiny bit of text.</p>

View File

@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<style>
@font-face { font-family: Ahem; src: url(Ahem.ttf); }
html, body { margin: 0; padding: 0; }
body { width: 10px }
p {
margin: 0;
background: yellow;
color: blue;
width: -moz-fit-content; /* computes to 60px */
font: 12px Ahem;
}
</style>
<!--
In a 60px container, the minimum font size at 15em per line is 4px.
-->
<p>This is tiny bit of text.</p>

View File

@@ -0,0 +1,18 @@
<!DOCTYPE HTML>
<style>
@font-face { font-family: Ahem; src: url(Ahem.ttf); }
html, body { margin: 0; padding: 0; }
body { width: 450px }
p {
margin: 0;
background: yellow;
color: blue;
width: 300px;
font: 24px Ahem;
}
</style>
<!--
In a 300px container, the minimum font size at 15em per line is 20px.
This means we map 0px-30px into 20px-30px, so 12px gets mapped to 24px.
-->
<p>This is tiny bit of text.</p>

View File

@@ -0,0 +1,18 @@
<!DOCTYPE HTML>
<style>
@font-face { font-family: Ahem; src: url(Ahem.ttf); }
html, body { margin: 0; padding: 0; }
body { width: 450px }
p {
margin: 0;
background: yellow;
color: blue;
width: -moz-fit-content; /* computes to 300px */
font: 12px Ahem;
}
</style>
<!--
In a 300px container, the minimum font size at 15em per line is 20px.
This means we map 0px-30px into 20px-30px, so 12px gets mapped to 24px.
-->
<p>This is tiny bit of text.</p>

View File

@@ -0,0 +1,18 @@
<!DOCTYPE HTML>
<style>
@font-face { font-family: Ahem; src: url(Ahem.ttf); }
html, body { margin: 0; padding: 0; }
body { width: 150px }
p {
margin: 0;
background: yellow;
color: blue;
width: 150px;
font: 14px Ahem;
}
</style>
<!--
In a 150px container, the minimum font size at 15em per line is 10px.
This means we map 0px-15px into 10px-15px, so 12px gets mapped to 14px.
-->
<p>This is tiny bit of text.</p>

View File

@@ -0,0 +1,18 @@
<!DOCTYPE HTML>
<style>
@font-face { font-family: Ahem; src: url(Ahem.ttf); }
html, body { margin: 0; padding: 0; }
body { width: 150px }
p {
margin: 0;
background: yellow;
color: blue;
width: -moz-fit-content; /* computes to 150px */
font: 12px Ahem;
}
</style>
<!--
In a 150px container, the minimum font size at 15em per line is 10px.
This means we map 0px-15px into 10px-15px, so 12px gets mapped to 14px.
-->
<p>This is tiny bit of text.</p>

View File

@@ -0,0 +1,18 @@
<!DOCTYPE HTML>
<style>
@font-face { font-family: Ahem; src: url(Ahem.ttf); }
html, body { margin: 0; padding: 0; }
body { width: 10px }
p {
margin: 0;
background: yellow;
color: blue;
float: left;
width: auto; /* computes to 60px */
font: 12px Ahem;
}
</style>
<!--
In a 60px container, the minimum font size at 15em per line is 4px.
-->
<p>This is tiny bit of text.</p>

View File

@@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<style>
@font-face { font-family: Ahem; src: url(Ahem.ttf); }
html, body { margin: 0; padding: 0; }
body { width: 450px }
p {
margin: 0;
background: yellow;
color: blue;
float: left;
width: auto; /* computes to 300px */
font: 12px Ahem;
}
</style>
<!--
In a 300px container, the minimum font size at 15em per line is 20px.
This means we map 0px-30px into 20px-30px, so 12px gets mapped to 24px.
-->
<p>This is tiny bit of text.</p>

View File

@@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<style>
@font-face { font-family: Ahem; src: url(Ahem.ttf); }
html, body { margin: 0; padding: 0; }
body { width: 150px }
p {
margin: 0;
background: yellow;
color: blue;
float: left;
width: auto; /* computes to 150px */
font: 12px Ahem;
}
</style>
<!--
In a 150px container, the minimum font size at 15em per line is 10px.
This means we map 0px-15px into 10px-15px, so 12px gets mapped to 14px.
-->
<p>This is tiny bit of text.</p>

View File

@@ -0,0 +1,14 @@
<!DOCTYPE HTML>
<style>
@font-face { font-family: Ahem; src: url(Ahem.ttf); }
html, body { margin: 0; padding: 0; }
body { width: 450px }
p {
margin: 0;
background: yellow;
color: blue;
width: 300px;
font: 24px Ahem;
}
</style>
<p>This is tiny bit of text.</p>

View File

@@ -0,0 +1,18 @@
<!DOCTYPE HTML>
<style>
@font-face { font-family: Ahem; src: url(Ahem.ttf); }
html, body { margin: 0; padding: 0; }
body { width: 450px }
p {
margin: 0;
background: yellow;
color: blue;
width: -moz-max-content; /* computes to 300px */
font: 12px Ahem;
}
</style>
<!--
In a 300px container, the minimum font size at 15em per line is 20px.
This means we map 0px-30px into 20px-30px, so 12px gets mapped to 24px.
-->
<p>This is tiny bit of text.</p>

View File

@@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<style>
@font-face { font-family: Ahem; src: url(Ahem.ttf); }
html, body { margin: 0; padding: 0; }
body { width: 450px }
p {
margin: 0;
background: yellow;
color: blue;
width: 60px;
font: 12px Ahem;
}
</style>
<!--
In a 60px container, the minimum font size at 15em per line is 4px.
-->
<p>This is some text.</p>

View File

@@ -0,0 +1,14 @@
<!DOCTYPE HTML>
<style>
@font-face { font-family: Ahem; src: url(Ahem.ttf); }
html, body { margin: 0; padding: 0; }
body { width: 450px }
p {
margin: 0;
background: yellow;
color: blue;
width: -moz-min-content; /* computes to 60px */
font: 12px Ahem;
}
</style>
<p>This is some text.</p>

View File

@@ -47,6 +47,14 @@ var gTests = [
"== css-transform-2.html css-transform-2-ref.html", "== css-transform-2.html css-transform-2-ref.html",
"== container-with-clamping.html container-with-clamping-ref.html", "== container-with-clamping.html container-with-clamping-ref.html",
"!= video-1.html about:blank", // crashtest "!= video-1.html about:blank", // crashtest
"== intrinsic-min-1.html intrinsic-min-1-ref.html",
"== intrinsic-max-1.html intrinsic-max-1-ref.html",
"== intrinsic-fit-1a.html intrinsic-fit-1a-ref.html",
"== intrinsic-fit-1b.html intrinsic-fit-1b-ref.html",
"== intrinsic-fit-1c.html intrinsic-fit-1c-ref.html",
"== intrinsic-fit-2a.html intrinsic-fit-1a-ref.html",
"== intrinsic-fit-2b.html intrinsic-fit-1b-ref.html",
"== intrinsic-fit-2c.html intrinsic-fit-1c-ref.html",
]; ];
// Maintain a reference count of how many things we're waiting for until // Maintain a reference count of how many things we're waiting for until

View File

@@ -63,6 +63,9 @@
#include "nsDisplayList.h" #include "nsDisplayList.h"
#include "nsRenderingContext.h" #include "nsRenderingContext.h"
using namespace mozilla;
using namespace mozilla::layout;
class nsLegendFrame; class nsLegendFrame;
class nsFieldSetFrame : public nsContainerFrame { class nsFieldSetFrame : public nsContainerFrame {
@@ -403,6 +406,11 @@ nsFieldSetFrame::ComputeSize(nsRenderingContext *aRenderingContext,
aMargin, aBorder, aPadding, aShrinkWrap); aMargin, aBorder, aPadding, aShrinkWrap);
// Fieldsets never shrink below their min width. // Fieldsets never shrink below their min width.
// If we're a container for font size inflation, then shrink
// wrapping inside of us should not apply font size inflation.
AutoMaybeNullInflationContainer an(this);
nscoord minWidth = GetMinWidth(aRenderingContext); nscoord minWidth = GetMinWidth(aRenderingContext);
if (minWidth > result.width) if (minWidth > result.width)
result.width = minWidth; result.width = minWidth;

View File

@@ -132,6 +132,7 @@
using namespace mozilla; using namespace mozilla;
using namespace mozilla::layers; using namespace mozilla::layers;
using namespace mozilla::layout;
// Struct containing cached metrics for box-wrapped frames. // Struct containing cached metrics for box-wrapped frames.
struct nsBoxLayoutMetrics struct nsBoxLayoutMetrics
@@ -3852,6 +3853,10 @@ nscoord
nsFrame::ShrinkWidthToFit(nsRenderingContext *aRenderingContext, nsFrame::ShrinkWidthToFit(nsRenderingContext *aRenderingContext,
nscoord aWidthInCB) nscoord aWidthInCB)
{ {
// If we're a container for font size inflation, then shrink
// wrapping inside of us should not apply font size inflation.
AutoMaybeNullInflationContainer an(this);
nscoord result; nscoord result;
nscoord minWidth = GetMinWidth(aRenderingContext); nscoord minWidth = GetMinWidth(aRenderingContext);
if (minWidth > aWidthInCB) { if (minWidth > aWidthInCB) {
@@ -7239,8 +7244,16 @@ nsFrame::RefreshSizeCache(nsBoxLayoutState& aState)
nsMargin bp(0,0,0,0); nsMargin bp(0,0,0,0);
GetBorderAndPadding(bp); GetBorderAndPadding(bp);
metrics->mBlockPrefSize.width = GetPrefWidth(rendContext) + bp.LeftRight(); {
metrics->mBlockMinSize.width = GetMinWidth(rendContext) + bp.LeftRight(); // If we're a container for font size inflation, then shrink
// wrapping inside of us should not apply font size inflation.
AutoMaybeNullInflationContainer an(this);
metrics->mBlockPrefSize.width =
GetPrefWidth(rendContext) + bp.LeftRight();
metrics->mBlockMinSize.width =
GetMinWidth(rendContext) + bp.LeftRight();
}
// do the nasty. // do the nasty.
nsHTMLReflowMetrics desiredSize; nsHTMLReflowMetrics desiredSize;

View File

@@ -48,6 +48,9 @@
#include "nsGkAtoms.h" #include "nsGkAtoms.h"
#include "SpanningCellSorter.h" #include "SpanningCellSorter.h"
using namespace mozilla;
using namespace mozilla::layout;
namespace css = mozilla::css; namespace css = mozilla::css;
#undef DEBUG_TABLE_STRATEGY #undef DEBUG_TABLE_STRATEGY
@@ -110,6 +113,10 @@ GetWidthInfo(nsRenderingContext *aRenderingContext,
{ {
nscoord minCoord, prefCoord; nscoord minCoord, prefCoord;
if (aIsCell) { if (aIsCell) {
// If aFrame is a container for font size inflation, then shrink
// wrapping inside of it should not apply font size inflation.
AutoMaybeNullInflationContainer an(aFrame);
minCoord = aFrame->GetMinWidth(aRenderingContext); minCoord = aFrame->GetMinWidth(aRenderingContext);
prefCoord = aFrame->GetPrefWidth(aRenderingContext); prefCoord = aFrame->GetPrefWidth(aRenderingContext);
} else { } else {

View File

@@ -76,6 +76,7 @@
#include "nsCSSProps.h" #include "nsCSSProps.h"
using namespace mozilla; using namespace mozilla;
using namespace mozilla::layout;
/******************************************************************************** /********************************************************************************
** nsTableReflowState ** ** nsTableReflowState **
@@ -1512,6 +1513,10 @@ nsTableFrame::ComputeSize(nsRenderingContext *aRenderingContext,
nsContainerFrame::ComputeSize(aRenderingContext, aCBSize, aAvailableWidth, nsContainerFrame::ComputeSize(aRenderingContext, aCBSize, aAvailableWidth,
aMargin, aBorder, aPadding, aShrinkWrap); aMargin, aBorder, aPadding, aShrinkWrap);
// If we're a container for font size inflation, then shrink
// wrapping inside of us should not apply font size inflation.
AutoMaybeNullInflationContainer an(this);
// Tables never shrink below their min width. // Tables never shrink below their min width.
nscoord minWidth = GetMinWidth(aRenderingContext); nscoord minWidth = GetMinWidth(aRenderingContext);
if (minWidth > result.width) if (minWidth > result.width)
@@ -1524,6 +1529,10 @@ nscoord
nsTableFrame::TableShrinkWidthToFit(nsRenderingContext *aRenderingContext, nsTableFrame::TableShrinkWidthToFit(nsRenderingContext *aRenderingContext,
nscoord aWidthInCB) nscoord aWidthInCB)
{ {
// If we're a container for font size inflation, then shrink
// wrapping inside of us should not apply font size inflation.
AutoMaybeNullInflationContainer an(this);
nscoord result; nscoord result;
nscoord minWidth = GetMinWidth(aRenderingContext); nscoord minWidth = GetMinWidth(aRenderingContext);
if (minWidth > aWidthInCB) { if (minWidth > aWidthInCB) {

View File

@@ -54,6 +54,9 @@
#include "nsDisplayList.h" #include "nsDisplayList.h"
#include "nsLayoutUtils.h" #include "nsLayoutUtils.h"
using namespace mozilla;
using namespace mozilla::layout;
/* ----------- nsTableCaptionFrame ---------- */ /* ----------- nsTableCaptionFrame ---------- */
#define NS_TABLE_FRAME_CAPTION_LIST_INDEX 1 #define NS_TABLE_FRAME_CAPTION_LIST_INDEX 1
@@ -97,6 +100,11 @@ nsTableCaptionFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
{ {
nsSize result = nsBlockFrame::ComputeAutoSize(aRenderingContext, aCBSize, nsSize result = nsBlockFrame::ComputeAutoSize(aRenderingContext, aCBSize,
aAvailableWidth, aMargin, aBorder, aPadding, aShrinkWrap); aAvailableWidth, aMargin, aBorder, aPadding, aShrinkWrap);
// If we're a container for font size inflation, then shrink
// wrapping inside of us should not apply font size inflation.
AutoMaybeNullInflationContainer an(this);
PRUint8 captionSide = GetStyleTableBorder()->mCaptionSide; PRUint8 captionSide = GetStyleTableBorder()->mCaptionSide;
if (captionSide == NS_STYLE_CAPTION_SIDE_LEFT || if (captionSide == NS_STYLE_CAPTION_SIDE_LEFT ||
captionSide == NS_STYLE_CAPTION_SIDE_RIGHT) { captionSide == NS_STYLE_CAPTION_SIDE_RIGHT) {