Bug 684266 - Do ellipsing on the end-edge only when a single value was specified for text-overflow. r=bzbarsky r=roc

This commit is contained in:
Mats Palmgren 2011-10-12 18:20:46 +02:00
Родитель 231ed58a1b
Коммит a52395739b
17 изменённых файлов: 317 добавлений и 50 удалений

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

@ -277,11 +277,11 @@ TextOverflow::WillProcessLines(nsDisplayListBuilder* aBuilder,
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.
@ -402,31 +402,31 @@ 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) {

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

@ -17,7 +17,7 @@ html,body {
}
.test {
overflow:auto;
text-overflow:ellipsis;
text-overflow:ellipsis ellipsis;
white-space:nowrap;
width: 4.4em;
margin-bottom:1em;

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

@ -31,7 +31,7 @@ html,body {
}
.o {
text-overflow: ellipsis;
text-overflow: ellipsis ellipsis;
color:blue;
}
.o span {

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

@ -19,7 +19,7 @@ html,body {
.test {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
text-overflow: ellipsis ellipsis;
color: black;
height: 6em;
width: 32.5em;

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

@ -134,6 +134,8 @@ x1 m { position:absolute; right:0; font-size:16px; }
#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>
@ -299,6 +301,9 @@ x1 m { position:absolute; right:0; font-size:16px; }
<div id="test9c"><div class="s a"><div class="p ltr"><span class="e"></span><i>&nbsp;&nbsp;&nbsp;&nbsp;</i><m>&#x2026;</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>&nbsp;&nbsp;&nbsp;&nbsp;</i><m>&#x2026;</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>

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

@ -30,7 +30,7 @@ html,body {
}
.o {
text-overflow: ellipsis;
text-overflow: ellipsis ellipsis;
}
.rel {
@ -50,6 +50,9 @@ html,body {
white-space:nowrap;
font-size:16px;
}
.auto {
overflow: auto;
}
.r {
text-align:right;
}
@ -131,6 +134,8 @@ i {
#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>
@ -191,7 +196,10 @@ i {
<div id="test9c"><div class="s a"><div class="p o ltr"><span class="e"></span><i>&nbsp;&nbsp;&nbsp;&nbsp;</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>&nbsp;&nbsp;&nbsp;&nbsp;</i><span class="e"></span><span class="c5 a">|||</span></div></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>

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

@ -44,9 +44,9 @@ s {
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>

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

@ -19,3 +19,4 @@ 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

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

@ -23,7 +23,7 @@ html,body {
.test {
overflow:auto;
text-overflow:ellipsis;
text-overflow:ellipsis ellipsis;
white-space:nowrap;
width: 5em;
position:relative;

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

@ -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: &lt;single value&gt;, 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>

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

@ -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: &lt;single value&gt;, 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>

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

@ -7,7 +7,7 @@
<style type="text/css">
p {
overflow: hidden;
text-overflow: ellipsis;
text-overflow: ellipsis ellipsis;
width: 200px;
}
.r {

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

@ -8186,8 +8186,9 @@ CSSParserImpl::ParseTextOverflow(nsCSSValue& aValue)
if (ParseVariant(right, VARIANT_KEYWORD | VARIANT_STRING,
nsCSSProps::kTextOverflowKTable))
aValue.SetPairValue(left, right);
else
aValue.SetPairValue(left, left);
else {
aValue = left;
}
return PR_TRUE;
}

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

@ -2486,33 +2486,35 @@ 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;
}

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

@ -3494,7 +3494,7 @@ nsRuleNode::ComputeTextResetData(void* aStartStruct,
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()) {
@ -3502,7 +3502,26 @@ nsRuleNode::ComputeTextResetData(void* aStartStruct,
} 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();

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

@ -1148,6 +1148,7 @@ struct nsStyleTextOverflowSide {
};
struct nsStyleTextOverflow {
nsStyleTextOverflow() : mLogicalDirections(true) {}
bool operator==(const nsStyleTextOverflow& aOther) const {
return mLeft == aOther.mLeft && mRight == aOther.mRight;
}
@ -1155,8 +1156,35 @@ struct nsStyleTextOverflow {
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 {

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

@ -2568,8 +2568,8 @@ var gCSSProperties = {
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": {