b=453827 block-height line-height r=bz sr=dbaron a=ss

git-svn-id: svn://10.0.0.236/trunk@258087 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
karlt+%karlt.net 2009-08-12 21:31:55 +00:00
parent 57a764d0ea
commit 4f43733aa9
19 changed files with 151 additions and 66 deletions

View File

@ -2303,6 +2303,19 @@ nsLayoutUtils::GetStringWidth(const nsIFrame* aFrame,
return width;
}
/* static */ nscoord
nsLayoutUtils::GetCenteredFontBaseline(nsIFontMetrics* aFontMetrics,
nscoord aLineHeight)
{
nscoord fontAscent, fontHeight;
aFontMetrics->GetMaxAscent(fontAscent);
aFontMetrics->GetHeight(fontHeight);
nscoord leading = aLineHeight - fontHeight;
return fontAscent + leading/2;
}
/* static */ PRBool
nsLayoutUtils::GetFirstLineBaseline(const nsIFrame* aFrame, nscoord* aResult)
{

View File

@ -685,6 +685,15 @@ public:
const PRUnichar* aString,
PRInt32 aLength);
/**
* Gets the baseline to vertically center text from a font within a
* line of specified height.
*
* Returns the baseline position relative to the top of the line.
*/
static nscoord GetCenteredFontBaseline(nsIFontMetrics* aFontMetrics,
nscoord aLineHeight);
/**
* Derive a baseline of |aFrame| (measured from its top border edge)
* from its first in-flow line box (not descending into anything with

View File

@ -595,6 +595,9 @@
#define NS_STYLE_WHITESPACE_NOWRAP 2
#define NS_STYLE_WHITESPACE_PRE_WRAP 3
// See nsStyleText
#define NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT 0
// See nsStyleText
#define NS_STYLE_UNICODE_BIDI_NORMAL 0
#define NS_STYLE_UNICODE_BIDI_EMBED 1

View File

@ -1309,7 +1309,8 @@ nsTextControlFrame::CalcIntrinsicSize(nsIRenderingContext* aRenderingContext,
aRenderingContext->SetFont(fontMet);
lineHeight = nsHTMLReflowState::CalcLineHeight(aRenderingContext,
this);
GetStyleContext(),
NS_AUTOHEIGHT);
fontMet->GetAveCharWidth(charWidth);
fontMet->GetMaxAdvance(charMaxAdvance);

View File

@ -149,14 +149,10 @@ BRFrame::Reflow(nsPresContext* aPresContext,
nsCOMPtr<nsIFontMetrics> fm;
aReflowState.rendContext->GetFontMetrics(*getter_AddRefs(fm));
if (fm) {
nscoord ascent, descent;
fm->GetMaxAscent(ascent);
fm->GetMaxDescent(descent);
nscoord logicalHeight =
aReflowState.CalcLineHeight(aReflowState.rendContext, this);
nscoord leading = logicalHeight - ascent - descent;
nscoord logicalHeight = aReflowState.CalcLineHeight();
aMetrics.height = logicalHeight;
aMetrics.ascent = ascent + (leading/2);
aMetrics.ascent =
nsLayoutUtils::GetCenteredFontBaseline(fm, logicalHeight);
}
else {
aMetrics.ascent = aMetrics.height = 0;

View File

@ -139,8 +139,7 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
mPrevChild = nsnull;
mCurrentLine = aFrame->end_lines();
mMinLineHeight = nsHTMLReflowState::CalcLineHeight(aReflowState.rendContext,
aReflowState.frame);
mMinLineHeight = aReflowState.CalcLineHeight();
// Calculate mOutsideBulletX
GetAvailableSpace();

View File

@ -396,7 +396,7 @@ nsHTMLReflowState::InitResizeFlags(nsPresContext* aPresContext)
mComputedHeight + mComputedBorderPadding.TopBottom();
}
const PRBool dependsOnCBHeight =
PRBool dependsOnCBHeight =
mStylePosition->mHeight.GetUnit() == eStyleUnit_Percent ||
mStylePosition->mMinHeight.GetUnit() == eStyleUnit_Percent ||
mStylePosition->mMaxHeight.GetUnit() == eStyleUnit_Percent ||
@ -406,6 +406,17 @@ nsHTMLReflowState::InitResizeFlags(nsPresContext* aPresContext)
(mStylePosition->mHeight.GetUnit() == eStyleUnit_Auto &&
frame->GetIntrinsicSize().height.GetUnit() == eStyleUnit_Percent);
if (mStyleText->mLineHeight.GetUnit() == eStyleUnit_Enumerated) {
NS_ASSERTION(mStyleText->mLineHeight.GetIntValue() ==
NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT,
"bad line-height value");
// line-height depends on block height
frame->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT);
// but only on containing blocks if this frame is not a suitable block
dependsOnCBHeight |= !frame->IsContainingBlock();
}
// If we're the descendant of a table cell that performs special height
// reflows and we could be the child that requires them, always set
// the vertical resize in case this is the first pass before the
@ -2030,40 +2041,62 @@ GetNormalLineHeight(nsIFontMetrics* aFontMetrics)
// Need only one of aRenderingContext and aDeviceContext
static nscoord
ComputeLineHeight(nsIRenderingContext* aRenderingContext,
nsStyleContext* aStyleContext)
nsStyleContext* aStyleContext,
nscoord aBlockHeight)
{
nscoord lineHeight;
const nsStyleCoord& lhCoord = aStyleContext->GetStyleText()->mLineHeight;
if (!nsLayoutUtils::GetAbsoluteCoord(lhCoord, aRenderingContext,
aStyleContext, lineHeight)) {
nscoord lineHeight;
if (nsLayoutUtils::GetAbsoluteCoord(lhCoord, aRenderingContext,
aStyleContext, lineHeight))
return lineHeight;
if (lhCoord.GetUnit() == eStyleUnit_Factor) {
// For factor units the computed value of the line-height property
// is found by multiplying the factor by the font's computed size
// (adjusted for min-size prefs and text zoom).
float factor = lhCoord.GetFactorValue();
const nsStyleFont* font = aStyleContext->GetStyleFont();
if (lhCoord.GetUnit() == eStyleUnit_Factor) {
// For factor units the computed value of the line-height property
// is found by multiplying the factor by the font's computed size
// (adjusted for min-size prefs and text zoom).
float factor = lhCoord.GetFactorValue();
lineHeight = NSToCoordRound(factor * font->mFont.size);
} else {
NS_ASSERTION(eStyleUnit_Normal == lhCoord.GetUnit(), "bad unit");
nsCOMPtr<nsIFontMetrics> fm;
nsLayoutUtils::GetFontMetricsForStyleContext(aStyleContext,
getter_AddRefs(fm));
lineHeight = GetNormalLineHeight(fm);
}
return NSToCoordRound(factor * font->mFont.size);
}
return lineHeight;
NS_ASSERTION(lhCoord.GetUnit() == eStyleUnit_Normal ||
lhCoord.GetUnit() == eStyleUnit_Enumerated,
"bad line-height unit");
if (lhCoord.GetUnit() == eStyleUnit_Enumerated) {
NS_ASSERTION(lhCoord.GetIntValue() == NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT,
"bad line-height value");
if (aBlockHeight != NS_AUTOHEIGHT)
return aBlockHeight;
}
nsCOMPtr<nsIFontMetrics> fm;
nsLayoutUtils::GetFontMetricsForStyleContext(aStyleContext,
getter_AddRefs(fm));
return GetNormalLineHeight(fm);
}
nscoord
nsHTMLReflowState::CalcLineHeight() const
{
nscoord blockHeight =
frame->IsContainingBlock() ? mComputedHeight :
(mCBReflowState ? mCBReflowState->mComputedHeight : NS_AUTOHEIGHT);
return CalcLineHeight(rendContext, frame->GetStyleContext(), blockHeight);
}
/* static */ nscoord
nsHTMLReflowState::CalcLineHeight(nsIRenderingContext* aRenderingContext,
nsStyleContext* aStyleContext)
nsStyleContext* aStyleContext,
nscoord aBlockHeight)
{
NS_PRECONDITION(aRenderingContext, "Must have a rendering context");
NS_PRECONDITION(aStyleContext, "Must have a style context");
nscoord lineHeight = ComputeLineHeight(aRenderingContext, aStyleContext);
nscoord lineHeight = ComputeLineHeight(aRenderingContext, aStyleContext,
aBlockHeight);
NS_ASSERTION(lineHeight >= 0, "ComputeLineHeight screwed up");

View File

@ -419,20 +419,22 @@ public:
static nsIFrame* GetContainingBlockFor(const nsIFrame* aFrame);
/**
* Calculate the raw line-height property for the given frame. The return
* value will be >= 0.
* Calculate the used line-height property. The return value will be >= 0.
*/
static nscoord CalcLineHeight(nsIRenderingContext* aRenderingContext,
nsIFrame* aFrame)
{
return CalcLineHeight(aRenderingContext, aFrame->GetStyleContext());
}
nscoord CalcLineHeight() const;
/**
* Same as above, but doesn't need a frame.
* Same as CalcLineHeight() above, but doesn't need a reflow state.
*
* @param aBlockHeight The computed height of the content rect of the block
* that the line should fill.
* Only used with line-height:-moz-block-height.
* NS_AUTOHEIGHT results in a normal line-height for
* line-height:-moz-block-height.
*/
static nscoord CalcLineHeight(nsIRenderingContext* aRenderingContext,
nsStyleContext* aStyleContext);
nsStyleContext* aStyleContext,
nscoord aBlockHeight);
void ComputeContainingBlockRectangle(nsPresContext* aPresContext,

View File

@ -1725,7 +1725,9 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd)
// Compute the logical height for this span. The logical height
// is based on the line-height value, not the font-size. Also
// compute the top leading.
nscoord logicalHeight = nsHTMLReflowState::CalcLineHeight(rc, spanFrame);
nscoord logicalHeight = nsHTMLReflowState::
CalcLineHeight(rc, spanFrame->GetStyleContext(),
mBlockReflowState->ComputedHeight());
nscoord contentHeight = spanFramePFD->mBounds.height -
spanFramePFD->mBorderPadding.top - spanFramePFD->mBorderPadding.bottom;
@ -1955,7 +1957,9 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd)
case eStyleUnit_Percent:
// Similar to a length value (eStyleUnit_Coord) except that the
// percentage is a function of the elements line-height value.
elementLineHeight = nsHTMLReflowState::CalcLineHeight(rc, frame);
elementLineHeight = nsHTMLReflowState::
CalcLineHeight(rc, frame->GetStyleContext(),
mBlockReflowState->ComputedHeight());
percentOffset = nscoord(
textStyle->mVerticalAlign.GetPercentValue() * elementLineHeight
);
@ -2082,13 +2086,10 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd)
printf(" [span]==> adjusting min/maxY: currentValues: %d,%d", minY, maxY);
#endif
nscoord minimumLineHeight = mMinLineHeight;
nscoord fontAscent, fontHeight;
fm->GetMaxAscent(fontAscent);
fm->GetHeight(fontHeight);
nscoord leading = minimumLineHeight - fontHeight;
nscoord yTop = -fontAscent - leading/2;
nscoord yTop =
-nsLayoutUtils::GetCenteredFontBaseline(fm, minimumLineHeight);
nscoord yBottom = yTop + minimumLineHeight;
if (yTop < minY) minY = yTop;
if (yBottom > maxY) maxY = yBottom;

View File

@ -87,6 +87,7 @@ CSS_KEY(-moz-center, _moz_center)
CSS_KEY(-moz-cjk-earthly-branch, _moz_cjk_earthly_branch)
CSS_KEY(-moz-cjk-heavenly-stem, _moz_cjk_heavenly_stem)
CSS_KEY(-moz-compact, _moz_compact) // Disabled because not supported.
CSS_KEY(-moz-block-height, _moz_block_height)
CSS_KEY(-moz-context-menu, _moz_context_menu)
CSS_KEY(-moz-copy, _moz_copy)
CSS_KEY(-moz-deck, _moz_deck)

View File

@ -4841,7 +4841,7 @@ PRBool CSSParserImpl::ParseSingleValueProperty(nsresult& aErrorCode,
case eCSSProperty_word_spacing:
return ParseVariant(aErrorCode, aValue, VARIANT_HL | VARIANT_NORMAL, nsnull);
case eCSSProperty_line_height:
return ParsePositiveVariant(aErrorCode, aValue, VARIANT_HLPN | VARIANT_NORMAL | VARIANT_SYSFONT, nsnull);
return ParsePositiveVariant(aErrorCode, aValue, VARIANT_HLPN | VARIANT_KEYWORD | VARIANT_NORMAL | VARIANT_SYSFONT, nsCSSProps::kLineHeightKTable);
case eCSSProperty_list_style_image:
return ParseVariant(aErrorCode, aValue, VARIANT_HUO, nsnull);
case eCSSProperty_list_style_position:

View File

@ -401,7 +401,7 @@ CSS_PROP_LIST(-moz-image-region, image_region, MozImageRegion, List, mImageRegio
CSS_PROP_UIRESET(ime-mode, ime_mode, ImeMode, UserInterface, mIMEMode, eCSSType_Value, kIMEModeKTable)
CSS_PROP_POSITION(left, left, Left, Position, mOffset.mLeft, eCSSType_Value, nsnull)
CSS_PROP_TEXT(letter-spacing, letter_spacing, LetterSpacing, Text, mLetterSpacing, eCSSType_Value, nsnull)
CSS_PROP_TEXT(line-height, line_height, LineHeight, Text, mLineHeight, eCSSType_Value, nsnull)
CSS_PROP_TEXT(line-height, line_height, LineHeight, Text, mLineHeight, eCSSType_Value, kLineHeightKTable)
CSS_PROP_SHORTHAND(list-style, list_style, ListStyle)
CSS_PROP_LIST(list-style-image, list_style_image, ListStyleImage, List, mImage, eCSSType_Value, nsnull)
CSS_PROP_LIST(list-style-position, list_style_position, ListStylePosition, List, mPosition, eCSSType_Value, kListStylePositionKTable)

View File

@ -676,8 +676,9 @@ const PRInt32 nsCSSProps::kIMEModeKTable[] = {
eCSSKeyword_UNKNOWN,-1
};
// XXX What's the point?
const PRInt32 nsCSSProps::kKeyEquivalentKTable[] = {
const PRInt32 nsCSSProps::kLineHeightKTable[] = {
// -moz- prefixed, intended for internal use for single-line controls
eCSSKeyword__moz_block_height, NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT,
eCSSKeyword_UNKNOWN,-1
};

View File

@ -158,8 +158,8 @@ public:
static const PRInt32 kFontStyleKTable[];
static const PRInt32 kFontVariantKTable[];
static const PRInt32 kFontWeightKTable[];
static const PRInt32 kKeyEquivalentKTable[];
static const PRInt32 kIMEModeKTable[];
static const PRInt32 kLineHeightKTable[];
static const PRInt32 kListStylePositionKTable[];
static const PRInt32 kListStyleKTable[];
static const PRInt32 kOutlineStyleKTable[];

View File

@ -1690,8 +1690,12 @@ nsComputedDOMStyle::GetLineHeight(nsIDOMCSSValue** aValue)
NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY);
nscoord lineHeight;
GetLineHeightCoord(lineHeight);
val->SetAppUnits(lineHeight);
if (GetLineHeightCoord(lineHeight)) {
val->SetAppUnits(lineHeight);
} else {
SetValueToCoord(val, GetStyleText()->mLineHeight,
nsnull, nsCSSProps::kLineHeightKTable);
}
return CallQueryInterface(val, aValue);
}
@ -2761,6 +2765,8 @@ nsComputedDOMStyle::GetPaddingWidthFor(PRUint8 aSide, nsIDOMCSSValue** aValue)
PRBool
nsComputedDOMStyle::GetLineHeightCoord(nscoord& aCoord)
{
AssertFlushedPendingReflows();
// Get a rendering context
nsCOMPtr<nsIRenderingContext> cx;
nsIFrame* frame = mPresShell->FrameManager()->GetRootFrame();
@ -2773,7 +2779,20 @@ nsComputedDOMStyle::GetLineHeightCoord(nscoord& aCoord)
return PR_FALSE;
}
aCoord = nsHTMLReflowState::CalcLineHeight(cx, mStyleContextHolder);
nscoord blockHeight = NS_AUTOHEIGHT;
if (GetStyleText()->mLineHeight.GetUnit() == eStyleUnit_Enumerated) {
if (!mInnerFrame)
return PR_FALSE;
if (mInnerFrame->IsContainingBlock()) {
blockHeight = mInnerFrame->GetContentRect().height;
} else {
GetCBContentHeight(blockHeight);
}
}
aCoord = nsHTMLReflowState::CalcLineHeight(cx, mStyleContextHolder,
blockHeight);
// CalcLineHeight uses font->mFont.size, but we want to use
// font->mSize as the font size. Adjust for that. Also adjust for
@ -3703,7 +3722,7 @@ nsComputedDOMStyle::GetQueryablePropertyMap(PRUint32* aLength)
COMPUTED_STYLE_MAP_ENTRY_LAYOUT(height, Height),
COMPUTED_STYLE_MAP_ENTRY_LAYOUT(left, Left),
COMPUTED_STYLE_MAP_ENTRY(letter_spacing, LetterSpacing),
COMPUTED_STYLE_MAP_ENTRY(line_height, LineHeight),
COMPUTED_STYLE_MAP_ENTRY_LAYOUT(line_height, LineHeight),
//// COMPUTED_STYLE_MAP_ENTRY(list_style, ListStyle),
COMPUTED_STYLE_MAP_ENTRY(list_style_image, ListStyleImage),
COMPUTED_STYLE_MAP_ENTRY(list_style_position, ListStylePosition),
@ -3763,7 +3782,7 @@ nsComputedDOMStyle::GetQueryablePropertyMap(PRUint32* aLength)
COMPUTED_STYLE_MAP_ENTRY(text_transform, TextTransform),
COMPUTED_STYLE_MAP_ENTRY_LAYOUT(top, Top),
COMPUTED_STYLE_MAP_ENTRY(unicode_bidi, UnicodeBidi),
COMPUTED_STYLE_MAP_ENTRY(vertical_align, VerticalAlign),
COMPUTED_STYLE_MAP_ENTRY_LAYOUT(vertical_align, VerticalAlign),
COMPUTED_STYLE_MAP_ENTRY(visibility, Visibility),
// COMPUTED_STYLE_MAP_ENTRY(voice_family, VoiceFamily),
// COMPUTED_STYLE_MAP_ENTRY(volume, Volume),

View File

@ -2651,7 +2651,7 @@ nsRuleNode::ComputeTextData(void* aStartStruct,
}
else {
SetCoord(textData.mLineHeight, text->mLineHeight, parentText->mLineHeight,
SETCOORD_LH | SETCOORD_FACTOR | SETCOORD_NORMAL,
SETCOORD_LEH | SETCOORD_FACTOR | SETCOORD_NORMAL,
aContext, mPresContext, inherited);
if (textData.mLineHeight.IsFixedLengthUnit() ||
textData.mLineHeight.GetUnit() == eCSSUnit_Pixel) {

View File

@ -993,11 +993,12 @@ var gCSSProperties = {
* getComputedStyle (which uses the CSS2 computed value, or
* CSS2.1 used value) doesn't match what the CSS2.1 computed
* value is. And they even require consistent font metrics for
* computation of 'normal'.
* computation of 'normal'. -moz-block-height requires height
* on a block.
*/
prerequisites: { "font-size": "19px", "font-size-adjust": "none", "font-family": "serif", "font-weight": "normal", "font-style": "normal" },
prerequisites: { "font-size": "19px", "font-size-adjust": "none", "font-family": "serif", "font-weight": "normal", "font-style": "normal", "height": "18px", "display": "block"},
initial_values: [ "normal" ],
other_values: [ "1.0", "1", "1em", "47px" ],
other_values: [ "1.0", "1", "1em", "47px", "-moz-block-height" ],
invalid_values: []
},
"list-style": {

View File

@ -183,10 +183,10 @@ function test_value(property, val, is_initial)
} else {
(xfail_value(property, val, is_initial, false) ? todo_isnot : isnot)(
val_computed_n, initial_computed_n,
"should not get initial value for '" + property + ":" + val + "'");
"should not get initial value for '" + property + ":" + val + "' on elementn.");
(xfail_value(property, val, is_initial, true) ? todo_isnot : isnot)(
val_computed_f, initial_computed_f,
"should not get initial value for '" + property + ":" + val + "'");
"should not get initial value for '" + property + ":" + val + "' on elementf.");
}
if (is_initial)
gRule1.style.removeProperty(property);

View File

@ -787,6 +787,12 @@ panel[type="autocomplete-richlistbox"] {
-moz-binding: url("chrome://global/content/bindings/autocomplete.xml#history-dropmarker");
}
/* Bug 453827 */
toolbaritem.chromeclass-location > textbox > hbox > hbox > html|*.textbox-input > html|*.anonymous-div {
/* Make the line-height equal to the available height */
line-height: -moz-block-height;
}
%endif