author | Mats Palmgren <matspal@gmail.com> |
Wed, 12 Oct 2011 18:20:46 +0200 | |
changeset 78629 | b4b895684f7e35b1b2473fe38dbeab13651b1606 |
parent 78628 | 3d5eee785f85fee1045d290dc3b1c3a8b21031a7 |
child 78630 | d45de3d261516152349ad2c590435499279dde50 |
push id | 21321 |
push user | mak77@bonardo.net |
push date | Thu, 13 Oct 2011 13:50:30 +0000 |
treeherder | mozilla-central@d6d3a1f90e2e [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bzbarsky, roc |
bugs | 684266 |
milestone | 10.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/layout/generic/TextOverflow.cpp +++ b/layout/generic/TextOverflow.cpp @@ -272,21 +272,21 @@ TextOverflow::WillProcessLines(nsDisplay nsIScrollableFrame* scroll = nsLayoutUtils::GetScrollableFrameFor(aBlockFrame); textOverflow->mCanHaveHorizontalScrollbar = false; if (scroll) { textOverflow->mCanHaveHorizontalScrollbar = scroll->GetScrollbarStyles().mHorizontal != NS_STYLE_OVERFLOW_HIDDEN; textOverflow->mContentArea.MoveBy(scroll->GetScrollPosition()); } - textOverflow->mBlockIsRTL = - aBlockFrame->GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL; + PRUint8 direction = aBlockFrame->GetStyleVisibility()->mDirection; + textOverflow->mBlockIsRTL = direction == NS_STYLE_DIRECTION_RTL; const nsStyleTextReset* style = aBlockFrame->GetStyleTextReset(); - textOverflow->mLeft.Init(style->mTextOverflow.mLeft); - textOverflow->mRight.Init(style->mTextOverflow.mRight); + textOverflow->mLeft.Init(*style->mTextOverflow.GetLeft(direction)); + textOverflow->mRight.Init(*style->mTextOverflow.GetRight(direction)); // The left/right marker string is setup in ExamineLineFrames when a line // has overflow on that side. return textOverflow.forget(); } void TextOverflow::DidProcessLines() @@ -397,41 +397,41 @@ TextOverflow::AnalyzeMarkerEdges(nsIFram } } void TextOverflow::ExamineLineFrames(nsLineBox* aLine, FrameHashtable* aFramesToHide, AlignmentEdges* aAlignmentEdges) { + // No ellipsing for 'clip' style. + bool suppressLeft = mLeft.mStyle->mType == NS_STYLE_TEXT_OVERFLOW_CLIP; + bool suppressRight = mRight.mStyle->mType == NS_STYLE_TEXT_OVERFLOW_CLIP; + // Scrolling to the end position can leave some text still overflowing due to // pixel snapping behaviour in our scrolling code so we move the edges 1px // outward to avoid triggering a text-overflow marker for such overflow. nsRect contentArea = mContentArea; const nscoord scrollAdjust = mCanHaveHorizontalScrollbar ? mBlock->PresContext()->AppUnitsPerDevPixel() : 0; - InflateLeft(&contentArea, - mLeft.mStyle->mType == NS_STYLE_TEXT_OVERFLOW_CLIP, - scrollAdjust); - InflateRight(&contentArea, - mRight.mStyle->mType == NS_STYLE_TEXT_OVERFLOW_CLIP, - scrollAdjust); + InflateLeft(&contentArea, suppressLeft, scrollAdjust); + InflateRight(&contentArea, suppressRight, scrollAdjust); nsRect lineRect = aLine->GetScrollableOverflowArea(); - const bool leftOverflow = lineRect.x < contentArea.x; - const bool rightOverflow = lineRect.XMost() > contentArea.XMost(); + const bool leftOverflow = + !suppressLeft && lineRect.x < contentArea.x; + const bool rightOverflow = + !suppressRight && lineRect.XMost() > contentArea.XMost(); if (!leftOverflow && !rightOverflow) { - // The line does not overflow - no need to traverse the frame tree. + // The line does not overflow on a side we should ellipsize. return; } PRUint32 pass = 0; - bool guessLeft = - mLeft.mStyle->mType != NS_STYLE_TEXT_OVERFLOW_CLIP && leftOverflow; - bool guessRight = - mRight.mStyle->mType != NS_STYLE_TEXT_OVERFLOW_CLIP && rightOverflow; + bool guessLeft = leftOverflow; + bool guessRight = rightOverflow; do { // Setup marker strings as needed. if (guessLeft) { mLeft.SetupString(mBlock); } if (guessRight) { mRight.SetupString(mBlock); }
--- a/layout/reftests/text-overflow/bidi-simple-scrolled.html +++ b/layout/reftests/text-overflow/bidi-simple-scrolled.html @@ -12,17 +12,17 @@ font-family: DejaVuSansMono; src: url(../fonts/DejaVuSansMono.woff); } html,body { color:black; background-color:white; font-size:16px; padding:0; margin:0; font-family:DejaVuSansMono; } .test { overflow:auto; - text-overflow:ellipsis; + text-overflow:ellipsis ellipsis; white-space:nowrap; width: 4.4em; margin-bottom:1em; position:relative; line-height:2em; } .hidden {
--- a/layout/reftests/text-overflow/ellipsis-font-fallback.html +++ b/layout/reftests/text-overflow/ellipsis-font-fallback.html @@ -26,17 +26,17 @@ html,body { .rlo { unicode-bidi: bidi-override; direction: rtl; } .lro { unicode-bidi: bidi-override; direction: ltr; } .o { - text-overflow: ellipsis; + text-overflow: ellipsis ellipsis; color:blue; } .o span { color:black; } .s { width:10em;
--- a/layout/reftests/text-overflow/false-marker-overlap.html +++ b/layout/reftests/text-overflow/false-marker-overlap.html @@ -14,17 +14,17 @@ } html,body { color:black; background-color:white; font-size:16px; padding:0; margin:0; font-family:DejaVuSansMono; } .test { overflow: hidden; white-space: nowrap; - text-overflow: ellipsis; + text-overflow: ellipsis ellipsis; color: black; height: 6em; width: 32.5em; margin-bottom: 1em; } i { display:inline-block;
--- a/layout/reftests/text-overflow/marker-basic-ref.html +++ b/layout/reftests/text-overflow/marker-basic-ref.html @@ -129,16 +129,18 @@ x1 m { position:absolute; right:0; font- #test8a { top:280px; left:0; position:absolute; } #test8b { top:280px; left:100px; position:absolute; } #test8c { top:280px; left:200px; position:absolute; } #test8d { top:280px; left:300px; position:absolute; } #test9a { top:320px; left:0; position:absolute; border:1px solid black; } #test9b { top:320px; left:100px; position:absolute; border:1px solid black; } #test9c { top:320px; left:200px; position:absolute; border:1px solid black; } #test9d { top:320px; left:300px; position:absolute; border:1px solid black; } +#test10a { top:360px; left:0; position:absolute; } +#test10b { top:360px; left:100px; position:absolute; } </style> </head> <body> <div style="position: absolute; top:20px; left:50px;"> <div id="test1a"> <div class="s a"><div class="p rel"> @@ -294,12 +296,15 @@ x1 m { position:absolute; right:0; font- <div id="test8a"><div class="s a"><div class="a p ltr"><span class="c5 a"></span><span class="e"></span><span style="margin-right:-0.5em">…</span><span>‌</span></div></div></div> <div id="test8d"><div class="s a"><div class="a p rtl"><span class="c5 a"></span><span class="e"></span><span style="margin-right:-0.5em">…</span><span>‌</span></div></div></div> <div id="test9a"><div class="s a"><div class="p ltr"><span class="e"></span><i> </i><m>…</m><span class="e a"></span></div></div></div> <div id="test9b"><div class="s a"><div class="p rtl"><span class="e"></span><i> </i><m>…</m><span class="e a"></span></div></div></div> <div id="test9c"><div class="s a"><div class="p ltr"><span class="e"></span><i> </i><m>…</m><span class="e a"></span></div></div></div> <div id="test9d"><div class="s a"><div class="p rtl"><span class="e"></span><i> </i><m>…</m><span class="e a"></span></div></div></div> +<!-- no marker for overflow:auto that doesn't trigger scrollbar --> +<div id="test10a"><div class="s a"><div class="p o ltr"><span style="margin-left:-5px" >||||||</span></div></div></div> +<div id="test10b"><div class="s a"><div class="p o rtl"><span style="margin-right:-5px">||||||</span></div></div></div> </div> </body> </html>
--- a/layout/reftests/text-overflow/marker-basic.html +++ b/layout/reftests/text-overflow/marker-basic.html @@ -25,17 +25,17 @@ html,body { .rlo { unicode-bidi: bidi-override; direction: rtl; } .lro { unicode-bidi: bidi-override; direction: ltr; } .o { - text-overflow: ellipsis; + text-overflow: ellipsis ellipsis; } .rel { position: relative; height:2em; } .abs0 { position: absolute; @@ -45,16 +45,19 @@ html,body { .s { width:4em; } .p { overflow: hidden; white-space:nowrap; font-size:16px; } +.auto { + overflow: auto; +} .r { text-align:right; } .a { font-size:20px; } .l { text-align:left; @@ -126,16 +129,18 @@ i { #test8a { top:280px; left:0; position:absolute; } #test8b { top:280px; left:100px; position:absolute; } #test8c { top:280px; left:200px; position:absolute; } #test8d { top:280px; left:300px; position:absolute; } #test9a { top:320px; left:0; position:absolute; border:1px solid black; } #test9b { top:320px; left:100px; position:absolute; border:1px solid black; } #test9c { top:320px; left:200px; position:absolute; border:1px solid black; } #test9d { top:320px; left:300px; position:absolute; border:1px solid black; } +#test10a { top:360px; left:0; position:absolute; } +#test10b { top:360px; left:100px; position:absolute; } </style> </head> <body> <div style="position: absolute; top:20px; left:50px;"> <!-- start + end marker, aligned to text --> @@ -186,12 +191,15 @@ i { <div id="test8d"><div class="s a"><div class="a p o rtl"><span class="c5 a">|</span><span class="e"></span><span>‌</span></div></div></div> <!-- end marker, marker aligns to inline block with overflow --> <div id="test9a"><div class="s a"><div class="p o ltr"><span class="e"></span><i> </i><span class="e"></span><span class="c5 a">|||</span></div></div></div> <div id="test9b"><div class="s a"><div class="p o rtl"><span class="e"></span><i> </i><span class="e"></span><span class="c5 a">|||</span></div></div></div> <div id="test9c"><div class="s a"><div class="p o ltr"><span class="e"></span><i> </i><span class="e"></span><span class="c5 a">|||</span></div></div></div> <div id="test9d"><div class="s a"><div class="p o rtl"><span class="e"></span><i> </i><span class="e"></span><span class="c5 a">|||</span></div></div></div> +<!-- no marker for overflow:auto that doesn't trigger scrollbar --> +<div id="test10a"><div class="s a"><div class="p o ltr auto"><span style="margin-left:-5px" >||||||</span></div></div></div> +<div id="test10b"><div class="s a"><div class="p o rtl auto"><span style="margin-right:-5px">||||||</span></div></div></div> + </div> - </body> </html>
--- a/layout/reftests/text-overflow/marker-string.html +++ b/layout/reftests/text-overflow/marker-string.html @@ -39,19 +39,19 @@ s { } .rtl { direction:rtl; } .ltr { direction:ltr; } -.t1 { text-overflow:""; } -.t2 { text-overflow:"Hello World"; } -.t3 { text-overflow:"X"; } +.t1 { text-overflow:"" ""; } +.t2 { text-overflow:"Hello World" "Hello World"; } +.t3 { text-overflow:"X" "X"; } </style> </head><body> <!-- Empty marker clips text --> <div class="test t1"><span>xx</span></div>
--- a/layout/reftests/text-overflow/reftest.list +++ b/layout/reftests/text-overflow/reftest.list @@ -14,8 +14,9 @@ HTTP(..) == standards-decorations.html s HTTP(..) == standards-line-height.html standards-line-height-ref.html HTTP(..) == selection.html selection-ref.html HTTP(..) == marker-shadow.html marker-shadow-ref.html == aligned-baseline.html aligned-baseline-ref.html skip-if(Android) == clipped-elements.html clipped-elements-ref.html == theme-overflow.html theme-overflow-ref.html HTTP(..) == table-cell.html table-cell-ref.html HTTP(..) == two-value-syntax.html two-value-syntax-ref.html +HTTP(..) == single-value.html single-value-ref.html
--- a/layout/reftests/text-overflow/selection.html +++ b/layout/reftests/text-overflow/selection.html @@ -18,17 +18,17 @@ src: url(TestEllipsisFallback.woff); } html,body { color:black; background-color:white; font-size:16px; padding:0; margin:0; font-family:DejaVuSansMono; } .test { overflow:auto; - text-overflow:ellipsis; + text-overflow:ellipsis ellipsis; white-space:nowrap; width: 5em; position:relative; margin-top:1em; padding-left: 0.9em; padding-right: 1.3em; }
new file mode 100644 --- /dev/null +++ b/layout/reftests/text-overflow/single-value-ref.html @@ -0,0 +1,105 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/licenses/publicdomain/ + + Test: text-overflow: <single value>, scrolled and non-scrolled tests, (bug 684266) +--> +<html class="reftest-wait"><head> +<title>text-overflow: <single value>, scrolled and non-scrolled tests, (bug 684266)</title> +<style type="text/css"> +@font-face { + font-family: DejaVuSansMono; + src: url(../fonts/DejaVuSansMono.woff),url(DejaVuSansMono.woff); +} +html,body { + color:black; background-color:white; font-size:16px; padding:0; margin:0; font-family:DejaVuSansMono; +} + +body {padding:10px 40px;} + +div { + width:100px; + white-space:nowrap; +} +.hidden {overflow:hidden} +.auto {overflow:auto} +.autolong {overflow:auto; width:100%;} +.scroll {overflow:scroll} + +.ltr { direction:ltr; unicode-bidi: bidi-override; } +.rtl { direction:rtl; unicode-bidi: bidi-override; } + +.ltr.p { text-indent: -5px; padding-left: 40px; } /* overflow into padding, but not outside the padding edge */ +.rtl.p { text-indent: -5px; padding-right: 40px; } /* overflow into padding, but not outside the padding edge */ + +.s { text-indent: -5px; } /* overflow start edge outside the padding edge */ + +div.ltr { + text-overflow: clip ellipsis; +} +div.rtl { + text-overflow: ellipsis clip; +} + +</style> + +<script> +function scrolldivs() { + var divs = document.getElementsByTagName('div'); + for (i = 0; i < divs.length; ++i) { + var elm = divs[i]; + if (elm.hasAttribute('scroll')) { + if (window.getComputedStyle(elm).direction == 'ltr') + elm.scrollLeft = 8; + else + elm.scrollLeft = -8; + } + } + document.documentElement.removeAttribute('class'); +} +</script> +</head> +<body onload="scrolldivs()"> + + <div class="ltr start p hidden">A long line that does not break (overflow:hidden)</div> + <div class="ltr start p auto">A long line that does not break (overflow:auto)</div> + <div class="ltr start p autolong">A long line that does not break (overflow:auto)</div> + <div class="ltr start p scroll">A long line that does not break (overflow:scroll)</div> + <div class="ltr start s hidden">A long line that does not break (overflow:hidden)</div> + <div class="ltr start s auto">A long line that does not break (overflow:auto)</div> + <div class="ltr start s autolong">A long line that does not break (overflow:auto)</div> + <div class="ltr start s scroll">A long line that does not break (overflow:scroll)</div> + + <div scroll class="ltr start p hidden">A long line that does not break (overflow:hidden)</div> + <div scroll class="ltr start p auto">A long line that does not break (overflow:auto)</div> + <div scroll class="ltr start p autolong">A long line that does not break (overflow:auto)</div> + <div scroll class="ltr start p scroll">A long line that does not break (overflow:scroll)</div> + <div scroll class="ltr start s hidden">A long line that does not break (overflow:hidden)</div> + <div scroll class="ltr start s auto">A long line that does not break (overflow:auto)</div> + <div scroll class="ltr start s autolong">A long line that does not break (overflow:auto)</div> + <div scroll class="ltr start s scroll">A long line that does not break (overflow:scroll)</div> + +<div class="rtl" style="float:right"> + <div class="rtl start p hidden">A long line that does not break (overflow:hidden)</div> + <div class="rtl start p auto">A long line that does not break (overflow:auto)</div> + <div class="rtl start p autolong">A long line that does not break (overflow:auto)</div> + <div class="rtl start p scroll">A long line that does not break (overflow:scroll)</div> + <div class="rtl start s hidden">A long line that does not break (overflow:hidden)</div> + <div class="rtl start s auto">A long line that does not break (overflow:auto)</div> + <div class="rtl start s autolong">A long line that does not break (overflow:auto)</div> + <div class="rtl start s scroll">A long line that does not break (overflow:scroll)</div> + + <div scroll class="rtl start p hidden">A long line that does not break (overflow:hidden)</div> + <div scroll class="rtl start p auto">A long line that does not break (overflow:auto)</div> + <div scroll class="rtl start p autolong">A long line that does not break (overflow:auto)</div> + <div scroll class="rtl start p scroll">A long line that does not break (overflow:scroll)</div> + <div scroll class="rtl start s hidden">A long line that does not break (overflow:hidden)</div> + <div scroll class="rtl start s auto">A long line that does not break (overflow:auto)</div> + <div scroll class="rtl start s autolong">A long line that does not break (overflow:auto)</div> + <div scroll class="rtl start s scroll">A long line that does not break (overflow:scroll)</div> +</div> + + +</body> +</hml>
new file mode 100644 --- /dev/null +++ b/layout/reftests/text-overflow/single-value.html @@ -0,0 +1,98 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/licenses/publicdomain/ + + Test: text-overflow: <single value>, scrolled and non-scrolled tests, (bug 684266) +--> +<html class="reftest-wait"><head> +<title>text-overflow: <single value>, scrolled and non-scrolled tests, (bug 684266)</title> +<style type="text/css"> +@font-face { + font-family: DejaVuSansMono; + src: url(../fonts/DejaVuSansMono.woff),url(DejaVuSansMono.woff); +} +html,body { + color:black; background-color:white; font-size:16px; padding:0; margin:0; font-family:DejaVuSansMono; +} + +body {padding:10px 40px;} + +div { + text-overflow: ellipsis; + width:100px; + white-space:nowrap; +} +.hidden {overflow:hidden} +.auto {overflow:auto} +.autolong {overflow:auto; width:100%;} +.scroll {overflow:scroll} + +.ltr { direction:ltr; unicode-bidi: bidi-override; } +.rtl { direction:rtl; unicode-bidi: bidi-override; } + +.ltr.p { text-indent: -5px; padding-left: 40px; } /* overflow into padding, but not outside the padding edge */ +.rtl.p { text-indent: -5px; padding-right: 40px; } /* overflow into padding, but not outside the padding edge */ + +.s { text-indent: -5px; } /* overflow start edge outside the padding edge */ +</style> + +<script> +function scrolldivs() { + var divs = document.getElementsByTagName('div'); + for (i = 0; i < divs.length; ++i) { + var elm = divs[i]; + if (elm.hasAttribute('scroll')) { + if (window.getComputedStyle(elm).direction == 'ltr') + elm.scrollLeft = 8; + else + elm.scrollLeft = -8; + } + } + document.documentElement.removeAttribute('class'); +} +</script> +</head> +<body onload="scrolldivs()"> + + <div class="ltr start p hidden">A long line that does not break (overflow:hidden)</div> + <div class="ltr start p auto">A long line that does not break (overflow:auto)</div> + <div class="ltr start p autolong">A long line that does not break (overflow:auto)</div> + <div class="ltr start p scroll">A long line that does not break (overflow:scroll)</div> + <div class="ltr start s hidden">A long line that does not break (overflow:hidden)</div> + <div class="ltr start s auto">A long line that does not break (overflow:auto)</div> + <div class="ltr start s autolong">A long line that does not break (overflow:auto)</div> + <div class="ltr start s scroll">A long line that does not break (overflow:scroll)</div> + + <div scroll class="ltr start p hidden">A long line that does not break (overflow:hidden)</div> + <div scroll class="ltr start p auto">A long line that does not break (overflow:auto)</div> + <div scroll class="ltr start p autolong">A long line that does not break (overflow:auto)</div> + <div scroll class="ltr start p scroll">A long line that does not break (overflow:scroll)</div> + <div scroll class="ltr start s hidden">A long line that does not break (overflow:hidden)</div> + <div scroll class="ltr start s auto">A long line that does not break (overflow:auto)</div> + <div scroll class="ltr start s autolong">A long line that does not break (overflow:auto)</div> + <div scroll class="ltr start s scroll">A long line that does not break (overflow:scroll)</div> + +<div class="rtl" style="float:right"> + <div class="rtl start p hidden">A long line that does not break (overflow:hidden)</div> + <div class="rtl start p auto">A long line that does not break (overflow:auto)</div> + <div class="rtl start p autolong">A long line that does not break (overflow:auto)</div> + <div class="rtl start p scroll">A long line that does not break (overflow:scroll)</div> + <div class="rtl start s hidden">A long line that does not break (overflow:hidden)</div> + <div class="rtl start s auto">A long line that does not break (overflow:auto)</div> + <div class="rtl start s autolong">A long line that does not break (overflow:auto)</div> + <div class="rtl start s scroll">A long line that does not break (overflow:scroll)</div> + + <div scroll class="rtl start p hidden">A long line that does not break (overflow:hidden)</div> + <div scroll class="rtl start p auto">A long line that does not break (overflow:auto)</div> + <div scroll class="rtl start p autolong">A long line that does not break (overflow:auto)</div> + <div scroll class="rtl start p scroll">A long line that does not break (overflow:scroll)</div> + <div scroll class="rtl start s hidden">A long line that does not break (overflow:hidden)</div> + <div scroll class="rtl start s auto">A long line that does not break (overflow:auto)</div> + <div scroll class="rtl start s autolong">A long line that does not break (overflow:auto)</div> + <div scroll class="rtl start s scroll">A long line that does not break (overflow:scroll)</div> +</div> + + +</body> +</hml>
--- a/layout/reftests/text-overflow/theme-overflow.html +++ b/layout/reftests/text-overflow/theme-overflow.html @@ -2,17 +2,17 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <title>Testcase for bug 669284</title> <style type="text/css"> p { overflow: hidden; - text-overflow: ellipsis; + text-overflow: ellipsis ellipsis; width: 200px; } .r { direction:rtl; } .x0 { margin:0px;} .x1 { margin:1px;}
--- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -8181,18 +8181,19 @@ CSSParserImpl::ParseTextOverflow(nsCSSVa if (!ParseVariant(left, VARIANT_KEYWORD | VARIANT_STRING, nsCSSProps::kTextOverflowKTable)) return PR_FALSE; nsCSSValue right; if (ParseVariant(right, VARIANT_KEYWORD | VARIANT_STRING, nsCSSProps::kTextOverflowKTable)) aValue.SetPairValue(left, right); - else - aValue.SetPairValue(left, left); + else { + aValue = left; + } return PR_TRUE; } bool CSSParserImpl::ParseTransitionProperty() { nsCSSValue value; if (ParseVariant(value, VARIANT_INHERIT | VARIANT_NONE | VARIANT_ALL,
--- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -2481,43 +2481,45 @@ nsComputedDOMStyle::DoGetTextIndent() &nsComputedDOMStyle::GetCBContentWidth); return val; } nsIDOMCSSValue* nsComputedDOMStyle::DoGetTextOverflow() { const nsStyleTextReset *style = GetStyleTextReset(); - nsROCSSPrimitiveValue *left = GetROCSSPrimitiveValue(); - if (style->mTextOverflow.mLeft.mType == NS_STYLE_TEXT_OVERFLOW_STRING) { + nsROCSSPrimitiveValue *first = GetROCSSPrimitiveValue(); + const nsStyleTextOverflowSide *side = style->mTextOverflow.GetFirstValue(); + if (side->mType == NS_STYLE_TEXT_OVERFLOW_STRING) { nsString str; - nsStyleUtil::AppendEscapedCSSString(style->mTextOverflow.mLeft.mString, str); - left->SetString(str); + nsStyleUtil::AppendEscapedCSSString(side->mString, str); + first->SetString(str); } else { - left->SetIdent( - nsCSSProps::ValueToKeywordEnum(style->mTextOverflow.mLeft.mType, + first->SetIdent( + nsCSSProps::ValueToKeywordEnum(side->mType, nsCSSProps::kTextOverflowKTable)); } - if (style->mTextOverflow.mLeft == style->mTextOverflow.mRight) { - return left; + side = style->mTextOverflow.GetSecondValue(); + if (!side) { + return first; } - nsROCSSPrimitiveValue *right = GetROCSSPrimitiveValue(); - if (style->mTextOverflow.mRight.mType == NS_STYLE_TEXT_OVERFLOW_STRING) { + nsROCSSPrimitiveValue *second = GetROCSSPrimitiveValue(); + if (side->mType == NS_STYLE_TEXT_OVERFLOW_STRING) { nsString str; - nsStyleUtil::AppendEscapedCSSString(style->mTextOverflow.mRight.mString, str); - right->SetString(str); + nsStyleUtil::AppendEscapedCSSString(side->mString, str); + second->SetString(str); } else { - right->SetIdent( - nsCSSProps::ValueToKeywordEnum(style->mTextOverflow.mRight.mType, + second->SetIdent( + nsCSSProps::ValueToKeywordEnum(side->mType, nsCSSProps::kTextOverflowKTable)); } nsDOMCSSValueList *valueList = GetROCSSValueList(PR_FALSE); - valueList->AppendCSSValue(left); - valueList->AppendCSSValue(right); + valueList->AppendCSSValue(first); + valueList->AppendCSSValue(second); return valueList; } nsIDOMCSSValue* nsComputedDOMStyle::DoGetTextShadow() { return GetCSSShadowArray(GetStyleText()->mTextShadow, GetStyleColor()->mColor,
--- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -3489,25 +3489,44 @@ nsRuleNode::ComputeTextResetData(void* a text->SetDecorationStyle(decorationStyleValue->GetIntValue()); } else if (eCSSUnit_Inherit == decorationStyleValue->GetUnit()) { text->SetDecorationStyle(parentText->GetDecorationStyle()); canStoreInRuleTree = PR_FALSE; } else if (eCSSUnit_Initial == decorationStyleValue->GetUnit()) { text->SetDecorationStyle(NS_STYLE_TEXT_DECORATION_STYLE_SOLID); } - // text-overflow: pair(enum|string), inherit, initial + // text-overflow: enum, string, pair(enum|string), inherit, initial const nsCSSValue* textOverflowValue = aRuleData->ValueForTextOverflow(); if (eCSSUnit_Initial == textOverflowValue->GetUnit()) { text->mTextOverflow = nsStyleTextOverflow(); } else if (eCSSUnit_Inherit == textOverflowValue->GetUnit()) { canStoreInRuleTree = PR_FALSE; text->mTextOverflow = parentText->mTextOverflow; + } else if (eCSSUnit_Enumerated == textOverflowValue->GetUnit()) { + // A single enumerated value. + SetDiscrete(*textOverflowValue, text->mTextOverflow.mRight.mType, + canStoreInRuleTree, + SETDSC_ENUMERATED, parentText->mTextOverflow.mRight.mType, + NS_STYLE_TEXT_OVERFLOW_CLIP, 0, 0, 0, 0); + text->mTextOverflow.mRight.mString.Truncate(); + text->mTextOverflow.mLeft.mType = NS_STYLE_TEXT_OVERFLOW_CLIP; + text->mTextOverflow.mLeft.mString.Truncate(); + text->mTextOverflow.mLogicalDirections = true; + } else if (eCSSUnit_String == textOverflowValue->GetUnit()) { + // A single string value. + text->mTextOverflow.mRight.mType = NS_STYLE_TEXT_OVERFLOW_STRING; + textOverflowValue->GetStringValue(text->mTextOverflow.mRight.mString); + text->mTextOverflow.mLeft.mType = NS_STYLE_TEXT_OVERFLOW_CLIP; + text->mTextOverflow.mLeft.mString.Truncate(); + text->mTextOverflow.mLogicalDirections = true; } else if (eCSSUnit_Pair == textOverflowValue->GetUnit()) { + // Two values were specified. + text->mTextOverflow.mLogicalDirections = false; const nsCSSValuePair& textOverflowValue = aRuleData->ValueForTextOverflow()->GetPairValue(); const nsCSSValue *textOverflowLeftValue = &textOverflowValue.mXValue; if (eCSSUnit_Enumerated == textOverflowLeftValue->GetUnit()) { SetDiscrete(*textOverflowLeftValue, text->mTextOverflow.mLeft.mType, canStoreInRuleTree, SETDSC_ENUMERATED, parentText->mTextOverflow.mLeft.mType,
--- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -1143,25 +1143,53 @@ struct nsStyleTextOverflowSide { return !(*this == aOther); } nsString mString; PRUint8 mType; }; struct nsStyleTextOverflow { + nsStyleTextOverflow() : mLogicalDirections(true) {} bool operator==(const nsStyleTextOverflow& aOther) const { return mLeft == aOther.mLeft && mRight == aOther.mRight; } bool operator!=(const nsStyleTextOverflow& aOther) const { return !(*this == aOther); } - nsStyleTextOverflowSide mLeft; - nsStyleTextOverflowSide mRight; + // Returns the value to apply on the left side. + const nsStyleTextOverflowSide& GetLeft(PRUint8 aDirection) const { + NS_ASSERTION(aDirection == NS_STYLE_DIRECTION_LTR || + aDirection == NS_STYLE_DIRECTION_RTL, "bad direction"); + return !mLogicalDirections || aDirection == NS_STYLE_DIRECTION_LTR ? + mLeft : mRight; + } + + // Returns the value to apply on the right side. + const nsStyleTextOverflowSide& GetRight(PRUint8 aDirection) const { + NS_ASSERTION(aDirection == NS_STYLE_DIRECTION_LTR || + aDirection == NS_STYLE_DIRECTION_RTL, "bad direction"); + return !mLogicalDirections || aDirection == NS_STYLE_DIRECTION_LTR ? + mRight : mLeft; + } + + // Returns the first value that was specified. + const nsStyleTextOverflowSide* GetFirstValue() const { + return mLogicalDirections ? &mRight : &mLeft; + } + + // Returns the second value, or null if there was only one value specified. + const nsStyleTextOverflowSide* GetSecondValue() const { + return mLogicalDirections ? nsnull : &mRight; + } + + nsStyleTextOverflowSide mLeft; // start side when mLogicalDirections is true + nsStyleTextOverflowSide mRight; // end side when mLogicalDirections is true + bool mLogicalDirections; // true when only one value was specified }; struct nsStyleTextReset { nsStyleTextReset(void); nsStyleTextReset(const nsStyleTextReset& aOther); ~nsStyleTextReset(void); void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
--- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -2563,18 +2563,18 @@ var gCSSProperties = { "-moz-calc(3*25px + 50%)", ], invalid_values: [] }, "text-overflow": { domProp: "textOverflow", inherited: false, type: CSS_TYPE_LONGHAND, - initial_values: [ "clip", "clip clip" ], - other_values: [ "ellipsis", '""', "''", '"hello"', 'clip ellipsis', 'clip ""', '"hello" ""', '"" ellipsis' ], + initial_values: [ "clip" ], + other_values: [ "ellipsis", '""', "''", '"hello"', 'clip clip', 'ellipsis ellipsis', 'clip ellipsis', 'clip ""', '"hello" ""', '"" ellipsis' ], invalid_values: [ "none", "auto", '"hello" inherit', 'inherit "hello"', 'clip initial', 'initial clip', 'initial inherit', 'inherit initial', 'inherit none'] }, "text-shadow": { domProp: "textShadow", inherited: true, type: CSS_TYPE_LONGHAND, prerequisites: { "color": "blue" }, initial_values: [ "none" ],