Implement correct intrinsic width calculation (for container) for elements with specified height properties and an intrinsic ratio. b=364066 r+sr=bzbarsky

This commit is contained in:
dbaron@dbaron.org 2007-06-12 11:27:09 -07:00
Родитель 1a71565259
Коммит 01e481e23d
12 изменённых файлов: 283 добавлений и 3 удалений

Просмотреть файл

@ -1253,6 +1253,67 @@ nsLayoutUtils::GetAbsoluteCoord(const nsStyleCoord& aStyle,
return PR_FALSE;
}
static PRBool
GetPercentHeight(const nsStyleCoord& aStyle,
nsIRenderingContext* aRenderingContext,
nsIFrame* aFrame,
nscoord& aResult)
{
if (eStyleUnit_Percent != aStyle.GetUnit())
return PR_FALSE;
nsIFrame *f;
for (f = aFrame->GetParent(); f && !f->IsContainingBlock();
f = f->GetParent())
;
if (!f) {
NS_NOTREACHED("top of frame tree not a containing block");
return PR_FALSE;
}
const nsStylePosition *pos = f->GetStylePosition();
nscoord h;
if (!nsLayoutUtils::
GetAbsoluteCoord(pos->mHeight, aRenderingContext, f, h) &&
!GetPercentHeight(pos->mHeight, aRenderingContext, f, h)) {
NS_ASSERTION(pos->mHeight.GetUnit() == eStyleUnit_Auto ||
pos->mHeight.GetUnit() == eStyleUnit_Percent,
"unknown height unit");
// There's no basis for the percentage height, so it acts like auto.
// Should we consider a max-height < min-height pair a basis for
// percentage heights? The spec is somewhat unclear, and not doing
// so is simpler and avoids troubling discontinuities in behavior,
// so I'll choose not to. -LDB
return PR_FALSE;
}
nscoord maxh;
if (nsLayoutUtils::
GetAbsoluteCoord(pos->mMaxHeight, aRenderingContext, f, maxh) ||
GetPercentHeight(pos->mMaxHeight, aRenderingContext, f, maxh)) {
if (maxh < h)
h = maxh;
} else {
NS_ASSERTION(pos->mMaxHeight.GetUnit() == eStyleUnit_None ||
pos->mMaxHeight.GetUnit() == eStyleUnit_Percent,
"unknown max-height unit");
}
nscoord minh;
if (nsLayoutUtils::
GetAbsoluteCoord(pos->mMinHeight, aRenderingContext, f, minh) ||
GetPercentHeight(pos->mMinHeight, aRenderingContext, f, minh)) {
if (minh > h)
h = minh;
} else {
NS_ASSERTION(pos->mMaxHeight.GetUnit() == eStyleUnit_Percent,
"unknown min-height unit");
}
aResult = NSToCoordRound(aStyle.GetPercentValue() * h);
return PR_TRUE;
}
// Handles only -moz-intrinsic and -moz-min-intrinsic, and
// -moz-shrink-wrap for min-width and max-width, since the others
// (-moz-shrink-wrap for width, and -moz-fill) have no effect on
@ -1369,6 +1430,43 @@ nsLayoutUtils::IntrinsicForContainer(nsIRenderingContext *aRenderingContext,
printf(" %s intrinsic width from frame is %d.\n",
aType == MIN_WIDTH ? "min" : "pref", result);
#endif
// Handle elements with an intrinsic ratio (or size) and a specified
// height, min-height, or max-height.
const nsStyleCoord &styleHeight = stylePos->mHeight;
const nsStyleCoord &styleMinHeight = stylePos->mMinHeight;
const nsStyleCoord &styleMaxHeight = stylePos->mMaxHeight;
if (styleHeight.GetUnit() != eStyleUnit_Auto ||
!(styleMinHeight.GetUnit() == eStyleUnit_Coord &&
styleMinHeight.GetCoordValue() == 0) ||
styleMaxHeight.GetUnit() != eStyleUnit_None) {
nsSize ratio = aFrame->GetIntrinsicRatio();
if (ratio.height != 0) {
nscoord h;
if (GetAbsoluteCoord(styleHeight, aRenderingContext, aFrame, h) ||
GetPercentHeight(styleHeight, aRenderingContext, aFrame, h)) {
result =
NSToCoordRound(h * (float(ratio.width) / float(ratio.height)));
}
if (GetAbsoluteCoord(styleMaxHeight, aRenderingContext, aFrame, h) ||
GetPercentHeight(styleMaxHeight, aRenderingContext, aFrame, h)) {
h = NSToCoordRound(h * (float(ratio.width) / float(ratio.height)));
if (h < result)
result = h;
}
if (GetAbsoluteCoord(styleMinHeight, aRenderingContext, aFrame, h) ||
GetPercentHeight(styleMinHeight, aRenderingContext, aFrame, h)) {
h = NSToCoordRound(h * (float(ratio.width) / float(ratio.height)));
if (h > result)
result = h;
}
}
}
}
if (aFrame->GetType() == nsGkAtoms::tableFrame) {

Просмотреть файл

@ -3099,6 +3099,12 @@ nsFrame::IntrinsicWidthOffsets(nsIRenderingContext* aRenderingContext)
return result;
}
/* virtual */ nsSize
nsFrame::GetIntrinsicRatio()
{
return nsSize(0, 0);
}
inline PRBool
IsAutoHeight(const nsStyleCoord &aCoord, nscoord aCBHeight)
{

Просмотреть файл

@ -279,6 +279,7 @@ public:
InlinePrefWidthData *aData);
virtual IntrinsicWidthOffsetData
IntrinsicWidthOffsets(nsIRenderingContext* aRenderingContext);
virtual nsSize GetIntrinsicRatio();
virtual nsSize ComputeSize(nsIRenderingContext *aRenderingContext,
nsSize aCBSize, nscoord aAvailableWidth,

Просмотреть файл

@ -99,6 +99,12 @@ nsHTMLCanvasFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
return result;
}
/* virtual */ nsSize
nsHTMLCanvasFrame::GetIntrinsicRatio()
{
return GetCanvasSize();
}
/* virtual */ nsSize
nsHTMLCanvasFrame::ComputeSize(nsIRenderingContext *aRenderingContext,
nsSize aCBSize, nscoord aAvailableWidth,

Просмотреть файл

@ -65,6 +65,7 @@ public:
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
virtual nsSize GetIntrinsicRatio();
virtual nsSize ComputeSize(nsIRenderingContext *aRenderingContext,
nsSize aCBSize, nscoord aAvailableWidth,

Просмотреть файл

@ -100,10 +100,10 @@ struct nsMargin;
typedef class nsIFrame nsIBox;
// IID for the nsIFrame interface
// 902aaa17-6433-4d96-86b3-fe1f4af41159
// 4c0cfb5b-864d-46c5-ad78-b1b4de35a4c3
#define NS_IFRAME_IID \
{ 0x902aaa17, 0x6433, 0x4d96, \
{ 0x86, 0xb3, 0xfe, 0x1f, 0x4a, 0xf4, 0x11, 0x59 } }
{ 0x4c0cfb5b, 0x864d, 0x46c5, \
{ 0xad, 0x78, 0xb1, 0xb4, 0xde, 0x35, 0xa4, 0xc3 } }
/**
* Indication of how the frame can be split. This is used when doing runaround
@ -1186,6 +1186,17 @@ public:
virtual IntrinsicWidthOffsetData
IntrinsicWidthOffsets(nsIRenderingContext* aRenderingContext) = 0;
/*
* Get the intrinsic ratio of this element, or nsSize(0,0) if it has
* no intrinsic ratio. The intrinsic ratio is the ratio of the
* height/width of a box with an intrinsic size or the intrinsic
* aspect ratio of a scalable vector image without an intrinsic size.
*
* Either one of the sides may be zero, indicating a zero or infinite
* ratio.
*/
virtual nsSize GetIntrinsicRatio() = 0;
/**
* Compute the size that a frame will occupy. Called while
* constructing the nsHTMLReflowState to be used to Reflow the frame,

Просмотреть файл

@ -769,6 +769,13 @@ nsImageFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
return result;
}
/* virtual */ nsSize
nsImageFrame::GetIntrinsicRatio()
{
EnsureIntrinsicSize(PresContext());
return mIntrinsicSize;
}
NS_IMETHODIMP
nsImageFrame::Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aMetrics,

Просмотреть файл

@ -108,6 +108,7 @@ public:
const nsDisplayListSet& aLists);
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
virtual nsSize GetIntrinsicRatio();
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,

Просмотреть файл

@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<title>Testcase, bug 364066</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css">
table { margin: 1px 0; border-spacing: 0; }
td { padding: 0; border: 1px solid; }
</style>
</head>
<body>
<!-- solidblue.png is a 16x16 image -->
<table border><tr>
<td width="200">
<table><tr><td>
<div style="height: 16px; width: 16px"></div>
</td></tr></table>
<table><tr><td>
<div style="height: 32px; width: 32px"></div>
</td></tr></table>
<table><tr><td>
<div style="height: 32px; width: 32px"></div>
</td></tr></table>
<table><tr><td>
<div style="height: 8px; width: 8px"></div>
</td></tr></table>
<table><tr><td>
<div style="height: 8px; width: 8px"></div>
</td></tr></table>
<table><tr><td>
<div style="height: 8px; width: 8px"></div>
</td></tr></table>
<table><tr><td>
<div style="height: 8px; width: 8px"></div>
</td></tr></table>
<table><tr><td>
<div style="height: 40px; width: 32px"></div>
</td></tr></table>
<table><tr><td>
<div style="height: 40px; width: 32px"></div>
</td></tr></table>
<table><tr><td>
<div style="height: 40px; width: 32px"></div>
</td></tr></table>
</td><td width="200">
<table><tr><td>
<div style="height: 40px; width: 32px"></div>
</td></tr></table>
<table><tr><td>
<div style="height: 40px; width: 32px"></div>
</td></tr></table>
<table><tr><td>
<div style="height: 40px; width: 32px"></div>
</td></tr></table>
<table><tr><td>
<div style="height: 40px; width: 32px"></div>
</td></tr></table>
</td>
</tr></table>
</body>
</html>

Просмотреть файл

@ -0,0 +1,72 @@
<!DOCTYPE html>
<html>
<head>
<title>Testcase, bug 364066</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css">
table { margin: 1px 0; border-spacing: 0; }
td { padding: 0; border: 1px solid; line-height: 1px; }
img { visibility: hidden; vertical-align: bottom; }
</style>
</head>
<body>
<!-- solidblue.png is a 16x16 image -->
<table border><tr>
<td width="200">
<table><tr><td><img src="solidblue.png"></td></tr></table>
<table><tr><td>
<img src="solidblue.png" style="height: 32px">
</td></tr></table>
<table><tr><td>
<img src="solidblue.png" style="min-height: 32px">
</td></tr></table>
<table><tr><td>
<img src="solidblue.png" style="max-height: 8px">
</td></tr></table>
<table><tr><td>
<img src="solidblue.png" style="height: 4px;min-height:8px">
</td></tr></table>
<table><tr><td>
<img src="solidblue.png" style="max-height: 4px;min-height:8px">
</td></tr></table>
<table><tr><td>
<img src="solidblue.png" style="height: 12px;max-height:8px">
</td></tr></table>
<table><tr><td><div style="height: 40px">
<img src="solidblue.png" style="height: 80%">
</div></td></tr></table>
<table><tr><td><div style="height: 40px">
<img src="solidblue.png" style="min-height: 80%">
</div></td></tr></table>
<table><tr><td><div style="height: 40px">
<img src="solidblue.png" style="height: 60px; max-height: 80%">
</div></td></tr></table>
</td><td width="200">
<table><tr><td><div style="height: 40px"><div style="height:100%"><div style="height:100%">
<img src="solidblue.png" style="height: 80%">
</div></div></div></td></tr></table>
<table><tr><td><div style="height: 64px; max-height: 40px">
<img src="solidblue.png" style="height: 80%">
</div></td></tr></table>
<table><tr><td><div style="height: 20px;min-height: 40px">
<img src="solidblue.png" style="height: 80%">
</div></td></tr></table>
<table><tr><td><div style="height: 40px"><div style="height:20px; min-height:100%"><div style="height:100px;max-height:100%">
<img src="solidblue.png" style="height: 80%">
</div></div></div></td></tr></table>
</td>
</tr></table>
</body>
</html>

Просмотреть файл

@ -174,6 +174,7 @@ fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == 362901-1.html 362901-1-ref.html # mac b
== 363637-1.html 363637-1-ref.html
== 363874.html 363874-ref.html
== 363874-max-width.html 363874-max-width-ref.html
== 364066-1.html 364066-1-ref.html
== 364079-1.html 364079-1-ref.html
== 364861-1.html 364861-1-ref.html
== 364862-1.html 364862-1-ref.html

Просмотреть файл

@ -67,6 +67,9 @@ private:
public:
// nsIFrame:
// XXX Should this implement intrinsic width methods (esp.
// GetIntrinsicRatio)?
NS_IMETHOD Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,