Implement the computed value of text-shadow in the style system. (Bug 10713) r+sr=dbaron

This commit is contained in:
Christian Biesinger ext:(%2C%20Michael%20Ventnor%20%3Cventnor.bugzilla%40yahoo.com.au%3E) 2008-06-05 16:06:34 -07:00
parent 381100987f
commit 36d201c8f8
8 changed files with 254 additions and 25 deletions

View File

@ -101,6 +101,7 @@ input {
-moz-binding: url("chrome://global/content/platformHTMLBindings.xml#inputFields");
text-indent: 0;
-moz-user-select: text;
text-shadow: none;
}
input > .anonymous-div {
@ -124,6 +125,7 @@ textarea {
-moz-appearance: textfield-multiline;
text-indent: 0;
-moz-user-select: text;
text-shadow: none;
}
textarea > scrollbar {
@ -165,6 +167,7 @@ select {
border-style: inset;
text-indent: 0;
overflow: -moz-hidden-unscrollable;
text-shadow: none;
}
/* Need the "select[size][multiple]" selector to override the settings on
@ -482,6 +485,7 @@ input[type="submit"] {
-moz-user-select: none;
-moz-binding: none;
text-align: center;
text-shadow: none;
}
button {

View File

@ -492,7 +492,7 @@ CSS_PROP_TABLE(table-layout, table_layout, TableLayout, Table, mLayout, eCSSType
CSS_PROP_TEXT(text-align, text_align, TextAlign, Text, mTextAlign, eCSSType_Value, kTextAlignKTable)
CSS_PROP_TEXTRESET(text-decoration, text_decoration, TextDecoration, Text, mDecoration, eCSSType_Value, kTextDecorationKTable)
CSS_PROP_TEXT(text-indent, text_indent, TextIndent, Text, mTextIndent, eCSSType_Value, nsnull)
CSS_PROP_BACKENDONLY(text-shadow, text_shadow, TextShadow, Text, mTextShadow, eCSSType_ValueList, nsnull)
CSS_PROP_TEXT(text-shadow, text_shadow, TextShadow, Text, mTextShadow, eCSSType_ValueList, nsnull)
CSS_PROP_TEXT(text-transform, text_transform, TextTransform, Text, mTextTransform, eCSSType_Value, kTextTransformKTable)
CSS_PROP_POSITION(top, top, Top, Position, mOffset.mTop, eCSSType_Value, nsnull)
CSS_PROP_TEXTRESET(unicode-bidi, unicode_bidi, UnicodeBidi, Text, mUnicodeBidi, eCSSType_Value, kUnicodeBidiKTable)

View File

@ -25,6 +25,7 @@
* Christopher A. Aillon <christopher@aillon.com>
* Mats Palmgren <mats.palmgren@bredband.net>
* Christian Biesinger <cbiesinger@web.de>
* Michael Ventnor <m.ventnor@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -1208,9 +1209,8 @@ nsComputedDOMStyle::GetBorderSpacing(nsIDOMCSSValue** aValue)
}
const nsStyleTableBorder *border = GetStyleTableBorder();
// border-spacing will always be a coord
xSpacing->SetAppUnits(border->mBorderSpacingX.GetCoordValue());
ySpacing->SetAppUnits(border->mBorderSpacingY.GetCoordValue());
SetValueToCoord(xSpacing, border->mBorderSpacingX);
SetValueToCoord(ySpacing, border->mBorderSpacingY);
return CallQueryInterface(valueList, aValue);
}
@ -1791,6 +1791,65 @@ nsComputedDOMStyle::GetTextIndent(nsIDOMCSSValue** aValue)
return CallQueryInterface(val, aValue);
}
nsresult
nsComputedDOMStyle::GetTextShadow(nsIDOMCSSValue** aValue)
{
const nsStyleText* text = GetStyleText();
if (!text->mShadowArray) {
nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
val->SetIdent(nsGkAtoms::none);
return CallQueryInterface(val, aValue);
}
static const nsStyleCoord nsTextShadowItem::*shadowValues[] = {
&nsTextShadowItem::mXOffset,
&nsTextShadowItem::mYOffset,
&nsTextShadowItem::mRadius
};
nsDOMCSSValueList *valueList = GetROCSSValueList(PR_TRUE);
NS_ENSURE_TRUE(valueList, NS_ERROR_OUT_OF_MEMORY);
for (nsTextShadowItem *item = text->mShadowArray->ShadowAt(0),
*item_end = item + text->mShadowArray->Length();
item < item_end; ++item) {
nsDOMCSSValueList *itemList = GetROCSSValueList(PR_FALSE);
if (!itemList || !valueList->AppendCSSValue(itemList)) {
delete itemList;
delete valueList;
return NS_ERROR_OUT_OF_MEMORY;
}
// Color is either the specified shadow color or the foreground color
nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
if (!val || !itemList->AppendCSSValue(val)) {
delete val;
delete valueList;
return NS_ERROR_OUT_OF_MEMORY;
}
nscolor shadowColor;
if (item->mHasColor) {
shadowColor = item->mColor;
} else {
shadowColor = GetStyleColor()->mColor;
}
SetToRGBAColor(val, shadowColor);
// Set the offsets and blur radius
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(shadowValues); ++i) {
val = GetROCSSPrimitiveValue();
if (!val || !itemList->AppendCSSValue(val)) {
delete val;
delete valueList;
return NS_ERROR_OUT_OF_MEMORY;
}
SetValueToCoord(val, item->*(shadowValues[i]));
}
}
return CallQueryInterface(valueList, aValue);
}
nsresult
nsComputedDOMStyle::GetTextTransform(nsIDOMCSSValue** aValue)
{
@ -3770,7 +3829,7 @@ nsComputedDOMStyle::GetQueryablePropertyMap(PRUint32* aLength)
COMPUTED_STYLE_MAP_ENTRY(text_align, TextAlign),
COMPUTED_STYLE_MAP_ENTRY(text_decoration, TextDecoration),
COMPUTED_STYLE_MAP_ENTRY(text_indent, TextIndent),
// COMPUTED_STYLE_MAP_ENTRY(text_shadow, TextShadow),
COMPUTED_STYLE_MAP_ENTRY(text_shadow, TextShadow),
COMPUTED_STYLE_MAP_ENTRY(text_transform, TextTransform),
COMPUTED_STYLE_MAP_ENTRY(top, Top),
COMPUTED_STYLE_MAP_ENTRY(unicode_bidi, UnicodeBidi),

View File

@ -236,6 +236,7 @@ private:
nsresult GetTextDecoration(nsIDOMCSSValue** aValue);
nsresult GetTextIndent(nsIDOMCSSValue** aValue);
nsresult GetTextTransform(nsIDOMCSSValue** aValue);
nsresult GetTextShadow(nsIDOMCSSValue** aValue);
nsresult GetLetterSpacing(nsIDOMCSSValue** aValue);
nsresult GetWordSpacing(nsIDOMCSSValue** aValue);
nsresult GetWhiteSpace(nsIDOMCSSValue** aValue);

View File

@ -25,6 +25,8 @@
* Roger B. Sidje <rbs@maths.uq.edu.au>
* Mats Palmgren <mats.palmgren@bredband.net>
* L. David Baron <dbaron@dbaron.org>
* Christian Biesinger <cbiesinger@web.de>
* Michael Ventnor <m.ventnor@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -1143,7 +1145,9 @@ nsRuleNode::GetTextData(nsStyleContext* aContext)
nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Text), mPresContext, aContext);
ruleData.mTextData = &textData;
return WalkRuleTree(eStyleStruct_Text, aContext, &ruleData, &textData);
const void* res = WalkRuleTree(eStyleStruct_Text, aContext, &ruleData, &textData);
textData.mTextShadow = nsnull; // We are sharing with some style rule. It really owns the data.
return res;
}
const void*
@ -1153,9 +1157,7 @@ nsRuleNode::GetTextResetData(nsStyleContext* aContext)
nsRuleData ruleData(NS_STYLE_INHERIT_BIT(TextReset), mPresContext, aContext);
ruleData.mTextData = &textData;
const void* res = WalkRuleTree(eStyleStruct_TextReset, aContext, &ruleData, &textData);
textData.mTextShadow = nsnull; // We are sharing with some style rule. It really owns the data.
return res;
return WalkRuleTree(eStyleStruct_TextReset, aContext, &ruleData, &textData);
}
const void*
@ -2628,6 +2630,55 @@ nsRuleNode::ComputeTextData(void* aStartStruct,
SETCOORD_LH | SETCOORD_NORMAL | SETCOORD_INITIAL_NORMAL,
aContext, mPresContext, inherited);
// text-shadow: none, list, inherit, initial
nsCSSValueList* list = textData.mTextShadow;
if (list) {
text->mShadowArray = nsnull;
// Don't need to handle none/initial explicitly: The above assignment
// takes care of that
if (eCSSUnit_Inherit == list->mValue.GetUnit()) {
inherited = PR_TRUE;
text->mShadowArray = parentText->mShadowArray;
} else if (eCSSUnit_Array == list->mValue.GetUnit()) {
// List of arrays
PRUint32 arrayLength = 0;
for (nsCSSValueList *list2 = list; list2; list2 = list2->mNext)
++arrayLength;
NS_ASSERTION(arrayLength > 0, "Non-null text-shadow list, yet we counted 0 items.");
text->mShadowArray = new(arrayLength) nsTextShadowArray(arrayLength);
if (text->mShadowArray) {
for (nsTextShadowItem* item = text->mShadowArray->ShadowAt(0);
list;
list = list->mNext, ++item) {
nsCSSValue::Array *arr = list->mValue.GetArrayValue();
// OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
SetCoord(arr->Item(0), item->mXOffset, nsStyleCoord(),
SETCOORD_LENGTH, aContext, mPresContext, inherited);
SetCoord(arr->Item(1), item->mYOffset, nsStyleCoord(),
SETCOORD_LENGTH, aContext, mPresContext, inherited);
// Blur radius is optional in the text-shadow rule. If not available,
// set it to 0.
if (arr->Item(2).GetUnit() != eCSSUnit_Null) {
SetCoord(arr->Item(2), item->mRadius, nsStyleCoord(),
SETCOORD_LENGTH, aContext, mPresContext, inherited);
} else {
item->mRadius.SetCoordValue(0);
}
if (arr->Item(3).GetUnit() != eCSSUnit_Null) {
item->mHasColor = PR_TRUE;
// 2nd argument can be bogus since inherit is not a valid color
SetColor(arr->Item(3), 0, mPresContext, aContext, item->mColor,
inherited);
}
}
}
}
}
// line-height: normal, number, length, percent, inherit
if (eCSSUnit_Percent == textData.mLineHeight.GetUnit()) {
inherited = PR_TRUE;

View File

@ -22,6 +22,7 @@
* Contributor(s):
* David Hyatt (hyatt@netscape.com)
* Mats Palmgren <mats.palmgren@bredband.net>
* Michael Ventnor <m.ventnor@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -1541,11 +1542,27 @@ nsChangeHint nsStyleTextReset::MaxDifference()
}
#endif
// --------------------
// nsTextShadowArray
// nsTextShadowItem
//
nsrefcnt
nsTextShadowArray::Release()
{
mRefCnt--;
if (mRefCnt == 0) {
delete this;
return 0;
}
return mRefCnt;
}
// --------------------
// nsStyleText
//
nsStyleText::nsStyleText(void)
nsStyleText::nsStyleText(void)
{
mTextAlign = NS_STYLE_TEXT_ALIGN_DEFAULT;
mTextTransform = NS_STYLE_TEXT_TRANSFORM_NONE;
@ -1555,26 +1572,47 @@ nsStyleText::nsStyleText(void)
mLineHeight.SetNormalValue();
mTextIndent.SetCoordValue(0);
mWordSpacing.SetNormalValue();
mShadowArray = nsnull;
}
nsStyleText::nsStyleText(const nsStyleText& aSource)
{
memcpy((nsStyleText*)this, &aSource, sizeof(nsStyleText));
}
nsStyleText::nsStyleText(const nsStyleText& aSource)
: mTextAlign(aSource.mTextAlign),
mTextTransform(aSource.mTextTransform),
mWhiteSpace(aSource.mWhiteSpace),
mLetterSpacing(aSource.mLetterSpacing),
mLineHeight(aSource.mLineHeight),
mTextIndent(aSource.mTextIndent),
mWordSpacing(aSource.mWordSpacing),
mShadowArray(aSource.mShadowArray)
{ }
nsStyleText::~nsStyleText(void) { }
nsChangeHint nsStyleText::CalcDifference(const nsStyleText& aOther) const
{
if ((mTextAlign == aOther.mTextAlign) &&
(mTextTransform == aOther.mTextTransform) &&
(mWhiteSpace == aOther.mWhiteSpace) &&
(mLetterSpacing == aOther.mLetterSpacing) &&
(mLineHeight == aOther.mLineHeight) &&
(mTextIndent == aOther.mTextIndent) &&
(mWordSpacing == aOther.mWordSpacing))
if ((mTextAlign != aOther.mTextAlign) ||
(mTextTransform != aOther.mTextTransform) ||
(mWhiteSpace != aOther.mWhiteSpace) ||
(mLetterSpacing != aOther.mLetterSpacing) ||
(mLineHeight != aOther.mLineHeight) ||
(mTextIndent != aOther.mTextIndent) ||
(mWordSpacing != aOther.mWordSpacing))
return NS_STYLE_HINT_REFLOW;
if ((!mShadowArray && !aOther.mShadowArray) ||
mShadowArray == aOther.mShadowArray)
return NS_STYLE_HINT_NONE;
return NS_STYLE_HINT_REFLOW;
if (!mShadowArray || !aOther.mShadowArray ||
(mShadowArray->Length() != aOther.mShadowArray->Length()))
return NS_STYLE_HINT_REFLOW;
for (PRUint32 i = 0; i < mShadowArray->Length(); ++i) {
if (*mShadowArray->ShadowAt(i) != *aOther.mShadowArray->ShadowAt(i))
return NS_STYLE_HINT_REFLOW;
}
return NS_STYLE_HINT_NONE;
}
#ifdef DEBUG

View File

@ -669,6 +669,80 @@ struct nsStyleTextReset {
nsStyleCoord mVerticalAlign; // [reset] see nsStyleConsts.h for enums
};
struct nsTextShadowItem {
nsStyleCoord mXOffset; // length (coord, chars)
nsStyleCoord mYOffset; // length (coord, chars)
nsStyleCoord mRadius; // length (coord, chars)
nscolor mColor;
PRPackedBool mHasColor; // Whether mColor should be used
nsTextShadowItem() : mHasColor(PR_FALSE) {
MOZ_COUNT_CTOR(nsTextShadowItem);
}
~nsTextShadowItem() {
MOZ_COUNT_DTOR(nsTextShadowItem);
}
PRBool operator==(const nsTextShadowItem& aOther) {
return (mXOffset == aOther.mXOffset &&
mYOffset == aOther.mYOffset &&
mRadius == aOther.mRadius &&
mHasColor == aOther.mHasColor &&
(!mHasColor || mColor == aOther.mColor));
}
PRBool operator!=(const nsTextShadowItem& aOther) {
return !(*this == aOther);
}
};
class nsTextShadowArray {
public:
void* operator new(size_t aBaseSize, PRUint32 aArrayLen) {
// We can allocate both this nsTextShadowArray and the
// actual array in one allocation. The amount of memory to
// allocate is equal to the class's size + the number of bytes for all
// but the first array item (because aBaseSize includes one
// item, see the private declarations)
return ::operator new(aBaseSize +
(aArrayLen - 1) * sizeof(nsTextShadowItem));
}
nsTextShadowArray(PRUint32 aArrayLen) :
mLength(aArrayLen), mRefCnt(0)
{
MOZ_COUNT_CTOR(nsTextShadowArray);
for (PRUint32 i = 1; i < mLength; ++i) {
// Make sure we call the constructors of each nsTextShadowItem
// (the first one is called for us because we declared it under private)
new (&mArray[i]) nsTextShadowItem();
}
}
~nsTextShadowArray() {
MOZ_COUNT_DTOR(nsTextShadowArray);
for (PRUint32 i = 1; i < mLength; ++i) {
mArray[i].~nsTextShadowItem();
}
}
nsrefcnt AddRef() { return ++mRefCnt; }
nsrefcnt Release();
PRUint32 Length() const { return mLength; }
nsTextShadowItem* ShadowAt(PRUint32 i) {
NS_ABORT_IF_FALSE(i < mLength, "Accessing too high an index in the text shadow array!");
return &mArray[i];
}
const nsTextShadowItem* ShadowAt(PRUint32 i) const {
NS_ABORT_IF_FALSE(i < mLength, "Accessing too high an index in the text shadow array!");
return &mArray[i];
}
private:
PRUint32 mLength;
PRUint32 mRefCnt;
nsTextShadowItem mArray[1]; // This MUST be the last item
};
struct nsStyleText {
nsStyleText(void);
nsStyleText(const nsStyleText& aOther);
@ -695,6 +769,8 @@ struct nsStyleText {
nsStyleCoord mLineHeight; // [inherited]
nsStyleCoord mTextIndent; // [inherited]
nsStyleCoord mWordSpacing; // [inherited]
nsRefPtr<nsTextShadowArray> mShadowArray; // [inherited] NULL in case of a zero-length
PRBool WhiteSpaceIsSignificant() const {
return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||

View File

@ -1499,12 +1499,12 @@ var gCSSProperties = {
},
"text-shadow": {
domProp: "textShadow",
inherited: false,
backend_only: true,
inherited: true,
type: CSS_TYPE_LONGHAND,
initial_values: [ "none" ],
prerequisites: { "color": "blue" },
other_values: [ "2px 2px", "2px 2px 1px", "2px 2px green", "2px 2px 1px green", "green 2px 2px", "green 2px 2px 1px", "green 2px 2px, blue 1px 3px 4px", "currentColor 3px 3px", "blue 2px 2px, currentColor 1px 2px" ],
invalid_values: [ "3% 3%", "2px 2px 2px 2px", "2px 2px, none" ]
invalid_values: [ "3% 3%", "2px 2px 2px 2px", "2px 2px, none", "none, 2px 2px", "inherit, 2px 2px", "2px 2px, inherit" ]
},
"text-transform": {
domProp: "textTransform",