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::layers;
using namespace mozilla::dom;
using namespace mozilla::layout;
#ifdef DEBUG
// TODO: remove, see bug 598468.
@@ -2328,6 +2329,11 @@ GetIntrinsicCoord(const nsStyleCoord& aStyle,
NS_ASSERTION(val == NS_STYLE_WIDTH_MAX_CONTENT ||
val == NS_STYLE_WIDTH_MIN_CONTENT,
"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)
aResult = aFrame->GetPrefWidth(aRenderingContext);
else
@@ -2356,6 +2362,10 @@ nsLayoutUtils::IntrinsicForContainer(nsRenderingContext *aRenderingContext,
aType == MIN_WIDTH ? "min" : "pref");
#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 =
aFrame->IntrinsicWidthOffsets(aRenderingContext);
@@ -2611,6 +2621,10 @@ nsLayoutUtils::ComputeWidthValue(
// are less than 0 have already been dropped by the parser.)
result -= aContentEdgeToBoxSizing;
} 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();
switch (val) {
case NS_STYLE_WIDTH_MAX_CONTENT:
@@ -2957,6 +2971,9 @@ nsLayoutUtils::ComputeAutoSizeWithIntrinsicDimensions(nscoord minWidth, nscoord
nsLayoutUtils::MinWidthFromInline(nsIFrame* aFrame,
nsRenderingContext* aRenderingContext)
{
NS_ASSERTION(!nsLayoutUtils::IsContainerForFontSizeInflation(aFrame),
"should not be container for font size inflation");
nsIFrame::InlineMinWidthData data;
DISPLAY_MIN_WIDTH(aFrame, data.prevLines);
aFrame->AddInlineMinWidth(aRenderingContext, &data);
@@ -2968,6 +2985,9 @@ nsLayoutUtils::MinWidthFromInline(nsIFrame* aFrame,
nsLayoutUtils::PrefWidthFromInline(nsIFrame* aFrame,
nsRenderingContext* aRenderingContext)
{
NS_ASSERTION(!nsLayoutUtils::IsContainerForFontSizeInflation(aFrame),
"should not be container for font size inflation");
nsIFrame::InlinePrefWidthData data;
DISPLAY_PREF_WIDTH(aFrame, data.prevLines);
aFrame->AddInlinePrefWidth(aRenderingContext, &data);

View File

@@ -1638,6 +1638,43 @@ public:
#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
{
public:

View File

@@ -383,6 +383,7 @@ _BROWSER_FILES = \
_INFLATION_REFTEST_FILES = \
$(shell find $(srcdir)/font-inflation/ -name '*.html' -o -name '*.xhtml') \
$(srcdir)/../../reftests/webm-video/black140x100.webm \
$(srcdir)/../../reftests/fonts/Ahem.ttf \
$(NULL)
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",
"== container-with-clamping.html container-with-clamping-ref.html",
"!= 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

View File

@@ -63,6 +63,9 @@
#include "nsDisplayList.h"
#include "nsRenderingContext.h"
using namespace mozilla;
using namespace mozilla::layout;
class nsLegendFrame;
class nsFieldSetFrame : public nsContainerFrame {
@@ -403,6 +406,11 @@ nsFieldSetFrame::ComputeSize(nsRenderingContext *aRenderingContext,
aMargin, aBorder, aPadding, aShrinkWrap);
// 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);
if (minWidth > result.width)
result.width = minWidth;

View File

@@ -132,6 +132,7 @@
using namespace mozilla;
using namespace mozilla::layers;
using namespace mozilla::layout;
// Struct containing cached metrics for box-wrapped frames.
struct nsBoxLayoutMetrics
@@ -3852,6 +3853,10 @@ nscoord
nsFrame::ShrinkWidthToFit(nsRenderingContext *aRenderingContext,
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 minWidth = GetMinWidth(aRenderingContext);
if (minWidth > aWidthInCB) {
@@ -7239,8 +7244,16 @@ nsFrame::RefreshSizeCache(nsBoxLayoutState& aState)
nsMargin bp(0,0,0,0);
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.
nsHTMLReflowMetrics desiredSize;

View File

@@ -48,6 +48,9 @@
#include "nsGkAtoms.h"
#include "SpanningCellSorter.h"
using namespace mozilla;
using namespace mozilla::layout;
namespace css = mozilla::css;
#undef DEBUG_TABLE_STRATEGY
@@ -110,6 +113,10 @@ GetWidthInfo(nsRenderingContext *aRenderingContext,
{
nscoord minCoord, prefCoord;
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);
prefCoord = aFrame->GetPrefWidth(aRenderingContext);
} else {

View File

@@ -76,6 +76,7 @@
#include "nsCSSProps.h"
using namespace mozilla;
using namespace mozilla::layout;
/********************************************************************************
** nsTableReflowState **
@@ -1512,6 +1513,10 @@ nsTableFrame::ComputeSize(nsRenderingContext *aRenderingContext,
nsContainerFrame::ComputeSize(aRenderingContext, aCBSize, 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);
// Tables never shrink below their min width.
nscoord minWidth = GetMinWidth(aRenderingContext);
if (minWidth > result.width)
@@ -1524,6 +1529,10 @@ nscoord
nsTableFrame::TableShrinkWidthToFit(nsRenderingContext *aRenderingContext,
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 minWidth = GetMinWidth(aRenderingContext);
if (minWidth > aWidthInCB) {

View File

@@ -54,6 +54,9 @@
#include "nsDisplayList.h"
#include "nsLayoutUtils.h"
using namespace mozilla;
using namespace mozilla::layout;
/* ----------- nsTableCaptionFrame ---------- */
#define NS_TABLE_FRAME_CAPTION_LIST_INDEX 1
@@ -97,6 +100,11 @@ nsTableCaptionFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
{
nsSize result = nsBlockFrame::ComputeAutoSize(aRenderingContext, aCBSize,
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;
if (captionSide == NS_STYLE_CAPTION_SIDE_LEFT ||
captionSide == NS_STYLE_CAPTION_SIDE_RIGHT) {