mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
Bug 212633 - "Add support for CSS3 box-shadow" (parsing support) [p=ventnor.bugzilla@gmail.com (Michael Ventnor) r+sr=dbaron]
This commit is contained in:
parent
0b959cc689
commit
b3e218a0a8
@ -406,7 +406,7 @@ interface nsIDOMCSS2Properties : nsISupports
|
||||
// raises(DOMException) on setting
|
||||
};
|
||||
|
||||
[scriptable, uuid(8a5b178d-c805-4f8e-8992-fa7c5c11d08e)]
|
||||
[scriptable, uuid(816581b0-3d89-11dd-ae16-0800200c9a66)]
|
||||
interface nsIDOMNSCSS2Properties : nsIDOMCSS2Properties
|
||||
{
|
||||
/* Non-DOM 2 extensions */
|
||||
@ -593,4 +593,7 @@ interface nsIDOMNSCSS2Properties : nsIDOMCSS2Properties
|
||||
|
||||
attribute DOMString MozStackSizing;
|
||||
// raises(DOMException) on setting
|
||||
|
||||
attribute DOMString MozBoxShadow;
|
||||
// raises(DOMException) on setting
|
||||
};
|
||||
|
@ -1291,13 +1291,13 @@ nsLayoutUtils::GetTextShadowRectsUnion(const nsRect& aTextAndDecorationsRect,
|
||||
nsIFrame* aFrame)
|
||||
{
|
||||
const nsStyleText* textStyle = aFrame->GetStyleText();
|
||||
if (!textStyle->mShadowArray)
|
||||
if (!textStyle->mTextShadow)
|
||||
return aTextAndDecorationsRect;
|
||||
|
||||
nsRect resultRect = aTextAndDecorationsRect;
|
||||
for (PRUint32 i = 0; i < textStyle->mShadowArray->Length(); ++i) {
|
||||
for (PRUint32 i = 0; i < textStyle->mTextShadow->Length(); ++i) {
|
||||
nsRect tmpRect(aTextAndDecorationsRect);
|
||||
nsTextShadowItem* shadow = textStyle->mShadowArray->ShadowAt(i);
|
||||
nsCSSShadowItem* shadow = textStyle->mTextShadow->ShadowAt(i);
|
||||
nscoord xOffset = shadow->mXOffset.GetCoordValue();
|
||||
nscoord yOffset = shadow->mYOffset.GetCoordValue();
|
||||
nscoord blurRadius = shadow->mRadius.GetCoordValue();
|
||||
|
@ -267,9 +267,9 @@ nsHTMLContainerFrame::DisplayTextDecorations(nsDisplayListBuilder* aBuilder,
|
||||
// it. So draw the shadows as part of the display list.
|
||||
const nsStyleText* textStyle = GetStyleText();
|
||||
|
||||
if (textStyle->mShadowArray) {
|
||||
for (PRUint32 i = textStyle->mShadowArray->Length(); i > 0; --i) {
|
||||
nsTextShadowItem* shadow = textStyle->mShadowArray->ShadowAt(i - 1);
|
||||
if (textStyle->mTextShadow) {
|
||||
for (PRUint32 i = textStyle->mTextShadow->Length(); i > 0; --i) {
|
||||
nsCSSShadowItem* shadow = textStyle->mTextShadow->ShadowAt(i - 1);
|
||||
nscoord blurRadius = shadow->mRadius.GetCoordValue();
|
||||
nscolor shadowColor;
|
||||
|
||||
|
@ -396,7 +396,7 @@ protected:
|
||||
|
||||
void PaintOneShadow(PRUint32 aOffset,
|
||||
PRUint32 aLength,
|
||||
nsTextShadowItem* aShadowDetails,
|
||||
nsCSSShadowItem* aShadowDetails,
|
||||
PropertyProvider* aProvider,
|
||||
const gfxRect& aDirtyRect,
|
||||
const gfxPoint& aFramePt,
|
||||
|
@ -3961,7 +3961,7 @@ PRBool SelectionIterator::GetNextSegment(gfxFloat* aXOffset,
|
||||
|
||||
void
|
||||
nsTextFrame::PaintOneShadow(PRUint32 aOffset, PRUint32 aLength,
|
||||
nsTextShadowItem* aShadowDetails,
|
||||
nsCSSShadowItem* aShadowDetails,
|
||||
PropertyProvider* aProvider, const gfxRect& aDirtyRect,
|
||||
const gfxPoint& aFramePt, const gfxPoint& aTextBaselinePt,
|
||||
gfxContext* aCtx, const nscolor& aForegroundColor)
|
||||
@ -4268,13 +4268,13 @@ nsTextFrame::PaintText(nsIRenderingContext* aRenderingContext, nsPoint aPt,
|
||||
|
||||
// Paint the text shadow before doing any foreground stuff
|
||||
const nsStyleText* textStyle = GetStyleText();
|
||||
if (textStyle->mShadowArray) {
|
||||
if (textStyle->mTextShadow) {
|
||||
// Text shadow happens with the last value being painted at the back,
|
||||
// ie. it is painted first.
|
||||
for (PRUint32 i = textStyle->mShadowArray->Length(); i > 0; --i) {
|
||||
for (PRUint32 i = textStyle->mTextShadow->Length(); i > 0; --i) {
|
||||
PaintOneShadow(provider.GetStart().GetSkippedOffset(),
|
||||
ComputeTransformedLength(provider),
|
||||
textStyle->mShadowArray->ShadowAt(i - 1), &provider,
|
||||
textStyle->mTextShadow->ShadowAt(i - 1), &provider,
|
||||
dirtyRect, framePt, textBaselinePt, ctx,
|
||||
textPaintStyle.GetTextColor());
|
||||
}
|
||||
|
@ -245,6 +245,7 @@ PRBool nsCSSDeclaration::AppendValueToString(nsCSSProperty aProperty, nsAString&
|
||||
if (val) {
|
||||
if (aProperty == eCSSProperty_cursor
|
||||
|| aProperty == eCSSProperty_text_shadow
|
||||
|| aProperty == eCSSProperty_box_shadow
|
||||
#ifdef MOZ_SVG
|
||||
|| aProperty == eCSSProperty_stroke_dasharray
|
||||
#endif
|
||||
|
@ -358,7 +358,11 @@ protected:
|
||||
PRBool ParseQuotes(nsresult& aErrorCode);
|
||||
PRBool ParseSize(nsresult& aErrorCode);
|
||||
PRBool ParseTextDecoration(nsresult& aErrorCode, nsCSSValue& aValue);
|
||||
|
||||
nsCSSValueList* ParseCSSShadowList(nsresult& aErrorCode,
|
||||
PRBool aUsesSpread);
|
||||
PRBool ParseTextShadow(nsresult& aErrorCode);
|
||||
PRBool ParseBoxShadow(nsresult& aErrorCode);
|
||||
|
||||
#ifdef MOZ_SVG
|
||||
PRBool ParsePaint(nsresult& aErrorCode,
|
||||
@ -4549,6 +4553,8 @@ PRBool CSSParserImpl::ParseProperty(nsresult& aErrorCode,
|
||||
return ParseSize(aErrorCode);
|
||||
case eCSSProperty_text_shadow:
|
||||
return ParseTextShadow(aErrorCode);
|
||||
case eCSSProperty_box_shadow:
|
||||
return ParseBoxShadow(aErrorCode);
|
||||
|
||||
#ifdef MOZ_SVG
|
||||
case eCSSProperty_fill:
|
||||
@ -4695,6 +4701,7 @@ PRBool CSSParserImpl::ParseSingleValueProperty(nsresult& aErrorCode,
|
||||
case eCSSProperty_quotes:
|
||||
case eCSSProperty_size:
|
||||
case eCSSProperty_text_shadow:
|
||||
case eCSSProperty_box_shadow:
|
||||
case eCSSProperty_COUNT:
|
||||
#ifdef MOZ_SVG
|
||||
case eCSSProperty_fill:
|
||||
@ -6436,7 +6443,8 @@ PRBool CSSParserImpl::ParseTextDecoration(nsresult& aErrorCode, nsCSSValue& aVal
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool CSSParserImpl::ParseTextShadow(nsresult& aErrorCode)
|
||||
nsCSSValueList* CSSParserImpl::ParseCSSShadowList(nsresult& aErrorCode,
|
||||
PRBool aUsesSpread)
|
||||
{
|
||||
nsAutoParseCompoundProperty compound(this);
|
||||
|
||||
@ -6449,14 +6457,10 @@ PRBool CSSParserImpl::ParseTextShadow(nsresult& aErrorCode)
|
||||
IndexX,
|
||||
IndexY,
|
||||
IndexRadius,
|
||||
IndexSpread,
|
||||
IndexColor
|
||||
};
|
||||
|
||||
// This variable is set to true if we already parsed an "end of property"
|
||||
// token. We can't unget it, as ExpectEndProperty already ungets the token in
|
||||
// some cases, and we can't detect that.
|
||||
PRBool atEOP = PR_FALSE;
|
||||
|
||||
nsCSSValueList *list = nsnull;
|
||||
for (nsCSSValueList **curp = &list, *cur; ; curp = &cur->mNext) {
|
||||
cur = *curp = new nsCSSValueList();
|
||||
@ -6474,7 +6478,7 @@ PRBool CSSParserImpl::ParseTextShadow(nsresult& aErrorCode)
|
||||
nsCSSUnit unit = cur->mValue.GetUnit();
|
||||
if (unit != eCSSUnit_None && unit != eCSSUnit_Inherit &&
|
||||
unit != eCSSUnit_Initial) {
|
||||
nsRefPtr<nsCSSValue::Array> val = nsCSSValue::Array::Create(4);
|
||||
nsRefPtr<nsCSSValue::Array> val = nsCSSValue::Array::Create(5);
|
||||
if (!val) {
|
||||
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
|
||||
break;
|
||||
@ -6491,7 +6495,7 @@ PRBool CSSParserImpl::ParseTextShadow(nsresult& aErrorCode)
|
||||
haveColor = PR_TRUE;
|
||||
val->Item(IndexColor) = cur->mValue;
|
||||
|
||||
// Parse the x coordinate
|
||||
// Parse the X coordinate
|
||||
if (!ParseVariant(aErrorCode, val->Item(IndexX), VARIANT_LENGTH,
|
||||
nsnull)) {
|
||||
break;
|
||||
@ -6504,22 +6508,25 @@ PRBool CSSParserImpl::ParseTextShadow(nsresult& aErrorCode)
|
||||
break;
|
||||
}
|
||||
|
||||
// Peek the next token to determine whether it's the radius or the color
|
||||
// EOF is fine too (properties can end in EOF)
|
||||
PRBool haveRadius = PR_FALSE;
|
||||
if (GetToken(aErrorCode, PR_TRUE)) {
|
||||
// The radius is a length, and all lengths are dimensions
|
||||
haveRadius = mToken.IsDimension();
|
||||
// Now unget the token, we didn't consume it
|
||||
UngetToken();
|
||||
// Optional radius. Ignore errors except if they pass a negative
|
||||
// value which we must reject. If we use ParsePositiveVariant we can't
|
||||
// tell the difference between an unspecified radius and a negative
|
||||
// radius, so that's why we don't use it.
|
||||
if (ParseVariant(aErrorCode, val->Item(IndexRadius), VARIANT_LENGTH, nsnull) &&
|
||||
val->Item(IndexRadius).GetFloatValue() < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (haveRadius) {
|
||||
// Optional radius
|
||||
if (!ParseVariant(aErrorCode, val->Item(IndexRadius), VARIANT_LENGTH,
|
||||
nsnull)) {
|
||||
break;
|
||||
}
|
||||
if (aUsesSpread) {
|
||||
// Optional spread (ignore errors)
|
||||
ParseVariant(aErrorCode, val->Item(IndexSpread), VARIANT_LENGTH,
|
||||
nsnull);
|
||||
}
|
||||
|
||||
if (!haveColor) {
|
||||
// Optional color (ignore errors)
|
||||
ParseVariant(aErrorCode, val->Item(IndexColor), VARIANT_COLOR,
|
||||
nsnull);
|
||||
}
|
||||
|
||||
// Might be at a comma now
|
||||
@ -6527,48 +6534,45 @@ PRBool CSSParserImpl::ParseTextShadow(nsresult& aErrorCode)
|
||||
// Go to next value
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!haveColor) {
|
||||
// Now, we are either at the end of the property, or have a color (or
|
||||
// have an error)
|
||||
|
||||
if (ExpectEndProperty(aErrorCode)) {
|
||||
atEOP = PR_TRUE;
|
||||
} else {
|
||||
// Clear the error from ExpectEndProperty - not a real error (if we
|
||||
// have a color here)
|
||||
CLEAR_ERROR();
|
||||
|
||||
// Since we're not at the end of the property, we must have a color,
|
||||
// or report an error.
|
||||
if (!ParseVariant(aErrorCode, val->Item(IndexColor), VARIANT_COLOR,
|
||||
nsnull)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ExpectSymbol(aErrorCode, ',', PR_TRUE)) {
|
||||
// Parse next value
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!atEOP && !ExpectEndProperty(aErrorCode)) {
|
||||
// Error
|
||||
if (!ExpectEndProperty(aErrorCode)) {
|
||||
// If we don't have a comma to delimit the next value, we
|
||||
// must be at the end of the property. Otherwise we've hit
|
||||
// something else, which is an error.
|
||||
break;
|
||||
}
|
||||
|
||||
// Only success case here, since having the failure case at the
|
||||
// end allows more sharing of code.
|
||||
mTempData.SetPropertyBit(eCSSProperty_text_shadow);
|
||||
mTempData.mText.mTextShadow = list;
|
||||
aErrorCode = NS_OK;
|
||||
return PR_TRUE;
|
||||
return list;
|
||||
}
|
||||
// Have failure case at the end so we can |break| to get to it.
|
||||
delete list;
|
||||
return PR_FALSE;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PRBool CSSParserImpl::ParseTextShadow(nsresult& aErrorCode)
|
||||
{
|
||||
nsCSSValueList* list = ParseCSSShadowList(aErrorCode, PR_FALSE);
|
||||
if (!list)
|
||||
return PR_FALSE;
|
||||
|
||||
mTempData.SetPropertyBit(eCSSProperty_text_shadow);
|
||||
mTempData.mText.mTextShadow = list;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool CSSParserImpl::ParseBoxShadow(nsresult& aErrorCode)
|
||||
{
|
||||
nsCSSValueList* list = ParseCSSShadowList(aErrorCode, PR_TRUE);
|
||||
if (!list)
|
||||
return PR_FALSE;
|
||||
|
||||
mTempData.SetPropertyBit(eCSSProperty_box_shadow);
|
||||
mTempData.mMargin.mBoxShadow = list;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
#ifdef MOZ_SVG
|
||||
|
@ -366,6 +366,7 @@ CSS_PROP_BORDER(border-top-style, border_top_style, BorderTopStyle, Margin, mBor
|
||||
CSS_PROP_BORDER(border-top-width, border_top_width, BorderTopWidth, Margin, mBorderWidth.mTop, eCSSType_Value, kBorderWidthKTable)
|
||||
CSS_PROP_SHORTHAND(border-width, border_width, BorderWidth)
|
||||
CSS_PROP_POSITION(bottom, bottom, Bottom, Position, mOffset.mBottom, eCSSType_Value, nsnull)
|
||||
CSS_PROP_BORDER(-moz-box-shadow, box_shadow, MozBoxShadow, Margin, mBoxShadow, eCSSType_ValueList, nsnull)
|
||||
CSS_PROP_POSITION(-moz-box-sizing, box_sizing, MozBoxSizing, Position, mBoxSizing, eCSSType_Value, kBoxSizingKTable) // XXX bug 3935
|
||||
CSS_PROP_TABLEBORDER(caption-side, caption_side, CaptionSide, Table, mCaptionSide, eCSSType_Value, kCaptionSideKTable)
|
||||
CSS_PROP_DISPLAY(clear, clear, Clear, Display, mClear, eCSSType_Value, kClearKTable)
|
||||
|
@ -226,6 +226,7 @@ nsCSSDisplay::~nsCSSDisplay(void)
|
||||
// --- nsCSSMargin -----------------
|
||||
|
||||
nsCSSMargin::nsCSSMargin(void)
|
||||
: mBoxShadow(nsnull)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsCSSMargin);
|
||||
}
|
||||
@ -233,6 +234,7 @@ nsCSSMargin::nsCSSMargin(void)
|
||||
nsCSSMargin::~nsCSSMargin(void)
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsCSSMargin);
|
||||
CSS_IF_DELETE(mBoxShadow);
|
||||
}
|
||||
|
||||
// --- nsCSSPosition -----------------
|
||||
|
@ -354,6 +354,7 @@ struct nsCSSMargin : public nsCSSStruct {
|
||||
nsCSSValue mOutlineOffset;
|
||||
nsCSSRect mOutlineRadius; // (extension)
|
||||
nsCSSValue mFloatEdge; // NEW
|
||||
nsCSSValueList* mBoxShadow;
|
||||
private:
|
||||
nsCSSMargin(const nsCSSMargin& aOther); // NOT IMPLEMENTED
|
||||
};
|
||||
|
@ -1569,6 +1569,92 @@ nsComputedDOMStyle::GetOutlineRadiusFor(PRUint8 aSide, nsIDOMCSSValue** aValue)
|
||||
return CallQueryInterface(val, aValue);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsComputedDOMStyle::GetCSSShadowArray(nsCSSShadowArray* aArray,
|
||||
const nscolor& aDefaultColor,
|
||||
PRBool aUsesSpread,
|
||||
nsIDOMCSSValue** aValue)
|
||||
{
|
||||
if (!aArray) {
|
||||
nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
|
||||
val->SetIdent(nsGkAtoms::none);
|
||||
return CallQueryInterface(val, aValue);
|
||||
}
|
||||
|
||||
static nsStyleCoord nsCSSShadowItem::* const shadowValuesNoSpread[] = {
|
||||
&nsCSSShadowItem::mXOffset,
|
||||
&nsCSSShadowItem::mYOffset,
|
||||
&nsCSSShadowItem::mRadius
|
||||
};
|
||||
|
||||
static nsStyleCoord nsCSSShadowItem::* const shadowValuesWithSpread[] = {
|
||||
&nsCSSShadowItem::mXOffset,
|
||||
&nsCSSShadowItem::mYOffset,
|
||||
&nsCSSShadowItem::mRadius,
|
||||
&nsCSSShadowItem::mSpread
|
||||
};
|
||||
|
||||
nsStyleCoord nsCSSShadowItem::* const * shadowValues;
|
||||
PRUint32 shadowValuesLength;
|
||||
if (aUsesSpread) {
|
||||
shadowValues = shadowValuesWithSpread;
|
||||
shadowValuesLength = NS_ARRAY_LENGTH(shadowValuesWithSpread);
|
||||
} else {
|
||||
shadowValues = shadowValuesNoSpread;
|
||||
shadowValuesLength = NS_ARRAY_LENGTH(shadowValuesNoSpread);
|
||||
}
|
||||
|
||||
nsDOMCSSValueList *valueList = GetROCSSValueList(PR_TRUE);
|
||||
NS_ENSURE_TRUE(valueList, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
for (nsCSSShadowItem *item = aArray->ShadowAt(0),
|
||||
*item_end = item + aArray->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 = aDefaultColor;
|
||||
}
|
||||
SetToRGBAColor(val, shadowColor);
|
||||
|
||||
// Set the offsets, blur radius, and spread if available
|
||||
for (PRUint32 i = 0; i < shadowValuesLength; ++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::GetBoxShadow(nsIDOMCSSValue** aValue)
|
||||
{
|
||||
return GetCSSShadowArray(GetStyleBorder()->mBoxShadow,
|
||||
GetStyleColor()->mColor,
|
||||
PR_TRUE, aValue);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsComputedDOMStyle::GetZIndex(nsIDOMCSSValue** aValue)
|
||||
{
|
||||
@ -1794,60 +1880,9 @@ nsComputedDOMStyle::GetTextIndent(nsIDOMCSSValue** 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);
|
||||
return GetCSSShadowArray(GetStyleText()->mTextShadow,
|
||||
GetStyleColor()->mColor,
|
||||
PR_FALSE, aValue);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -3866,6 +3901,7 @@ nsComputedDOMStyle::GetQueryablePropertyMap(PRUint32* aLength)
|
||||
COMPUTED_STYLE_MAP_ENTRY(box_ordinal_group, BoxOrdinalGroup),
|
||||
COMPUTED_STYLE_MAP_ENTRY(box_orient, BoxOrient),
|
||||
COMPUTED_STYLE_MAP_ENTRY(box_pack, BoxPack),
|
||||
COMPUTED_STYLE_MAP_ENTRY(box_shadow, BoxShadow),
|
||||
COMPUTED_STYLE_MAP_ENTRY(box_sizing, BoxSizing),
|
||||
COMPUTED_STYLE_MAP_ENTRY(_moz_column_count, ColumnCount),
|
||||
COMPUTED_STYLE_MAP_ENTRY(_moz_column_width, ColumnWidth),
|
||||
|
@ -110,6 +110,11 @@ private:
|
||||
|
||||
PRBool GetLineHeightCoord(nscoord& aCoord);
|
||||
|
||||
nsresult GetCSSShadowArray(nsCSSShadowArray* aArray,
|
||||
const nscolor& aDefaultColor,
|
||||
PRBool aUsesSpread,
|
||||
nsIDOMCSSValue** aValue);
|
||||
|
||||
/* Properties Queryable as CSSValues */
|
||||
|
||||
nsresult GetAppearance(nsIDOMCSSValue** aValue);
|
||||
@ -194,6 +199,9 @@ private:
|
||||
nsresult GetBorderRadiusTopRight(nsIDOMCSSValue** aValue);
|
||||
nsresult GetFloatEdge(nsIDOMCSSValue** aValue);
|
||||
|
||||
/* Box Shadow */
|
||||
nsresult GetBoxShadow(nsIDOMCSSValue** aValue);
|
||||
|
||||
/* Margin Properties */
|
||||
nsresult GetMarginWidth(nsIDOMCSSValue** aValue);
|
||||
nsresult GetMarginTopWidth(nsIDOMCSSValue** aValue);
|
||||
|
@ -1230,7 +1230,9 @@ nsRuleNode::GetBorderData(nsStyleContext* aContext)
|
||||
nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Border), mPresContext, aContext);
|
||||
ruleData.mMarginData = &marginData;
|
||||
|
||||
return WalkRuleTree(eStyleStruct_Border, aContext, &ruleData, &marginData);
|
||||
const void* res = WalkRuleTree(eStyleStruct_Border, aContext, &ruleData, &marginData);
|
||||
marginData.mBoxShadow = nsnull; // We are sharing with some style rule. It really owns the data.
|
||||
return res;
|
||||
}
|
||||
|
||||
const void*
|
||||
@ -2616,6 +2618,60 @@ nsRuleNode::ComputeFontData(void* aStartStruct,
|
||||
COMPUTE_END_INHERITED(Font, font)
|
||||
}
|
||||
|
||||
already_AddRefed<nsCSSShadowArray>
|
||||
nsRuleNode::GetShadowData(nsCSSValueList* aList,
|
||||
nsStyleContext* aContext,
|
||||
PRBool aUsesSpread,
|
||||
PRBool& inherited)
|
||||
{
|
||||
PRUint32 arrayLength = 0;
|
||||
for (nsCSSValueList *list2 = aList; list2; list2 = list2->mNext)
|
||||
++arrayLength;
|
||||
|
||||
NS_ASSERTION(arrayLength > 0, "Non-null text-shadow list, yet we counted 0 items.");
|
||||
nsCSSShadowArray* shadowList = new(arrayLength) nsCSSShadowArray(arrayLength);
|
||||
|
||||
if (!shadowList)
|
||||
return nsnull;
|
||||
|
||||
for (nsCSSShadowItem* item = shadowList->ShadowAt(0);
|
||||
aList;
|
||||
aList = aList->mNext, ++item) {
|
||||
nsCSSValue::Array *arr = aList->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 current box-shadow spec
|
||||
if (arr->Item(2).GetUnit() != eCSSUnit_Null) {
|
||||
SetCoord(arr->Item(2), item->mRadius, nsStyleCoord(),
|
||||
SETCOORD_LENGTH, aContext, mPresContext, inherited);
|
||||
} else {
|
||||
item->mRadius.SetCoordValue(0);
|
||||
}
|
||||
|
||||
// Find the spread radius
|
||||
if (aUsesSpread && arr->Item(3).GetUnit() != eCSSUnit_Null) {
|
||||
SetCoord(arr->Item(3), item->mSpread, nsStyleCoord(),
|
||||
SETCOORD_LENGTH, aContext, mPresContext, inherited);
|
||||
} else {
|
||||
item->mSpread.SetCoordValue(0);
|
||||
}
|
||||
|
||||
if (arr->Item(4).GetUnit() != eCSSUnit_Null) {
|
||||
item->mHasColor = PR_TRUE;
|
||||
// 2nd argument can be bogus since inherit is not a valid color
|
||||
SetColor(arr->Item(4), 0, mPresContext, aContext, item->mColor,
|
||||
inherited);
|
||||
}
|
||||
}
|
||||
|
||||
NS_ADDREF(shadowList);
|
||||
return shadowList;
|
||||
}
|
||||
|
||||
const void*
|
||||
nsRuleNode::ComputeTextData(void* aStartStruct,
|
||||
const nsRuleDataStruct& aData,
|
||||
@ -2633,49 +2689,16 @@ nsRuleNode::ComputeTextData(void* aStartStruct,
|
||||
// text-shadow: none, list, inherit, initial
|
||||
nsCSSValueList* list = textData.mTextShadow;
|
||||
if (list) {
|
||||
text->mShadowArray = nsnull;
|
||||
text->mTextShadow = 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;
|
||||
text->mTextShadow = parentText->mTextShadow;
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
text->mTextShadow = GetShadowData(list, aContext, PR_FALSE, inherited);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3684,6 +3707,21 @@ nsRuleNode::ComputeBorderData(void* aStartStruct,
|
||||
COMPUTE_START_RESET(Border, (mPresContext), border, parentBorder,
|
||||
Margin, marginData)
|
||||
|
||||
// -moz-box-shadow: none, list, inherit, initial
|
||||
nsCSSValueList* list = marginData.mBoxShadow;
|
||||
if (list) {
|
||||
// This handles 'none' and 'initial'
|
||||
border->mBoxShadow = nsnull;
|
||||
|
||||
if (eCSSUnit_Inherit == list->mValue.GetUnit()) {
|
||||
inherited = PR_TRUE;
|
||||
border->mBoxShadow = parentBorder->mBoxShadow;
|
||||
} else if (eCSSUnit_Array == list->mValue.GetUnit()) {
|
||||
// List of arrays
|
||||
border->mBoxShadow = GetShadowData(list, aContext, PR_TRUE, inherited);
|
||||
}
|
||||
}
|
||||
|
||||
// border-width, border-*-width: length, enum, inherit
|
||||
nsStyleCoord coord;
|
||||
nsCSSRect ourBorderWidth(marginData.mBorderWidth);
|
||||
|
@ -55,6 +55,7 @@ class nsILanguageAtomService;
|
||||
struct nsRuleData;
|
||||
class nsIStyleRule;
|
||||
struct nsCSSStruct;
|
||||
struct nsCSSValueList;
|
||||
// Copy of typedef that's in nsCSSStruct.h, for compilation speed.
|
||||
typedef nsCSSStruct nsRuleDataStruct;
|
||||
|
||||
@ -671,6 +672,12 @@ protected:
|
||||
NS_HIDDEN_(const void*) GetSVGResetData(nsStyleContext* aContext);
|
||||
#endif
|
||||
|
||||
NS_HIDDEN_(already_AddRefed<nsCSSShadowArray>)
|
||||
GetShadowData(nsCSSValueList* aList,
|
||||
nsStyleContext* aContext,
|
||||
PRBool aUsesSpread,
|
||||
PRBool& inherited);
|
||||
|
||||
private:
|
||||
nsRuleNode(nsPresContext* aPresContext, nsRuleNode* aParent,
|
||||
nsIStyleRule* aRule, PRUint8 aLevel, PRBool aIsImportant)
|
||||
|
@ -104,6 +104,9 @@ static PRBool EqualImages(imgIRequest *aImage1, imgIRequest* aImage2)
|
||||
return EqualURIs(uri1, uri2);
|
||||
}
|
||||
|
||||
static nsChangeHint CalcShadowDifference(nsCSSShadowArray* lhs,
|
||||
nsCSSShadowArray* rhs);
|
||||
|
||||
// --------------------
|
||||
// nsStyleFont
|
||||
//
|
||||
@ -366,6 +369,7 @@ nsStyleBorder::nsStyleBorder(nsPresContext* aPresContext)
|
||||
}
|
||||
|
||||
mBorderColors = nsnull;
|
||||
mBoxShadow = nsnull;
|
||||
|
||||
mFloatEdge = NS_STYLE_FLOAT_EDGE_CONTENT;
|
||||
|
||||
@ -373,8 +377,13 @@ nsStyleBorder::nsStyleBorder(nsPresContext* aPresContext)
|
||||
}
|
||||
|
||||
nsStyleBorder::nsStyleBorder(const nsStyleBorder& aSrc)
|
||||
: mActualBorder(aSrc.mActualBorder),
|
||||
mTwipsPerPixel(aSrc.mTwipsPerPixel),
|
||||
mBorder(aSrc.mBorder),
|
||||
mBorderRadius(aSrc.mBorderRadius),
|
||||
mFloatEdge(aSrc.mFloatEdge),
|
||||
mBoxShadow(aSrc.mBoxShadow)
|
||||
{
|
||||
memcpy((nsStyleBorder*)this, &aSrc, sizeof(nsStyleBorder));
|
||||
mBorderColors = nsnull;
|
||||
if (aSrc.mBorderColors) {
|
||||
EnsureBorderColors();
|
||||
@ -384,6 +393,11 @@ nsStyleBorder::nsStyleBorder(const nsStyleBorder& aSrc)
|
||||
else
|
||||
mBorderColors[i] = nsnull;
|
||||
}
|
||||
|
||||
NS_FOR_CSS_SIDES(side) {
|
||||
mBorderStyle[side] = aSrc.mBorderStyle[side];
|
||||
mBorderColor[side] = aSrc.mBorderColor[side];
|
||||
}
|
||||
}
|
||||
|
||||
void*
|
||||
@ -438,8 +452,8 @@ nsChangeHint nsStyleBorder::CalcDifference(const nsStyleBorder& aOther) const
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return NS_STYLE_HINT_NONE;
|
||||
// Decide what to do with regards to box-shadow
|
||||
return CalcShadowDifference(mBoxShadow, aOther.mBoxShadow);
|
||||
}
|
||||
return NS_STYLE_HINT_REFLOW;
|
||||
}
|
||||
@ -1543,12 +1557,12 @@ nsChangeHint nsStyleTextReset::MaxDifference()
|
||||
#endif
|
||||
|
||||
// --------------------
|
||||
// nsTextShadowArray
|
||||
// nsTextShadowItem
|
||||
// nsCSSShadowArray
|
||||
// nsCSSShadowItem
|
||||
//
|
||||
|
||||
nsrefcnt
|
||||
nsTextShadowArray::Release()
|
||||
nsCSSShadowArray::Release()
|
||||
{
|
||||
mRefCnt--;
|
||||
if (mRefCnt == 0) {
|
||||
@ -1558,6 +1572,23 @@ nsTextShadowArray::Release()
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
static nsChangeHint
|
||||
CalcShadowDifference(nsCSSShadowArray* lhs,
|
||||
nsCSSShadowArray* rhs)
|
||||
{
|
||||
if (lhs == rhs)
|
||||
return NS_STYLE_HINT_NONE;
|
||||
|
||||
if (!lhs || !rhs || lhs->Length() != rhs->Length())
|
||||
return NS_STYLE_HINT_REFLOW;
|
||||
|
||||
for (PRUint32 i = 0; i < lhs->Length(); ++i) {
|
||||
if (*lhs->ShadowAt(i) != *rhs->ShadowAt(i))
|
||||
return NS_STYLE_HINT_REFLOW;
|
||||
}
|
||||
return NS_STYLE_HINT_NONE;
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// nsStyleText
|
||||
//
|
||||
@ -1573,7 +1604,7 @@ nsStyleText::nsStyleText(void)
|
||||
mTextIndent.SetCoordValue(0);
|
||||
mWordSpacing.SetNormalValue();
|
||||
|
||||
mShadowArray = nsnull;
|
||||
mTextShadow = nsnull;
|
||||
}
|
||||
|
||||
nsStyleText::nsStyleText(const nsStyleText& aSource)
|
||||
@ -1584,7 +1615,7 @@ nsStyleText::nsStyleText(const nsStyleText& aSource)
|
||||
mLineHeight(aSource.mLineHeight),
|
||||
mTextIndent(aSource.mTextIndent),
|
||||
mWordSpacing(aSource.mWordSpacing),
|
||||
mShadowArray(aSource.mShadowArray)
|
||||
mTextShadow(aSource.mTextShadow)
|
||||
{ }
|
||||
|
||||
nsStyleText::~nsStyleText(void) { }
|
||||
@ -1600,19 +1631,7 @@ nsChangeHint nsStyleText::CalcDifference(const nsStyleText& aOther) const
|
||||
(mWordSpacing != aOther.mWordSpacing))
|
||||
return NS_STYLE_HINT_REFLOW;
|
||||
|
||||
if ((!mShadowArray && !aOther.mShadowArray) ||
|
||||
mShadowArray == aOther.mShadowArray)
|
||||
return NS_STYLE_HINT_NONE;
|
||||
|
||||
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;
|
||||
return CalcShadowDifference(mTextShadow, aOther.mTextShadow);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -306,6 +306,83 @@ struct nsBorderColors {
|
||||
}
|
||||
};
|
||||
|
||||
struct nsCSSShadowItem {
|
||||
nsStyleCoord mXOffset; // length (coord, chars)
|
||||
nsStyleCoord mYOffset; // length (coord, chars)
|
||||
nsStyleCoord mRadius; // length (coord, chars)
|
||||
nsStyleCoord mSpread; // length (coord, chars)
|
||||
|
||||
nscolor mColor;
|
||||
PRPackedBool mHasColor; // Whether mColor should be used
|
||||
|
||||
nsCSSShadowItem() : mHasColor(PR_FALSE) {
|
||||
MOZ_COUNT_CTOR(nsCSSShadowItem);
|
||||
}
|
||||
~nsCSSShadowItem() {
|
||||
MOZ_COUNT_DTOR(nsCSSShadowItem);
|
||||
}
|
||||
|
||||
PRBool operator==(const nsCSSShadowItem& aOther) {
|
||||
return (mXOffset == aOther.mXOffset &&
|
||||
mYOffset == aOther.mYOffset &&
|
||||
mRadius == aOther.mRadius &&
|
||||
mHasColor == aOther.mHasColor &&
|
||||
mSpread == aOther.mSpread &&
|
||||
(!mHasColor || mColor == aOther.mColor));
|
||||
}
|
||||
PRBool operator!=(const nsCSSShadowItem& aOther) {
|
||||
return !(*this == aOther);
|
||||
}
|
||||
};
|
||||
|
||||
class nsCSSShadowArray {
|
||||
public:
|
||||
void* operator new(size_t aBaseSize, PRUint32 aArrayLen) {
|
||||
// We can allocate both this nsCSSShadowArray 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(nsCSSShadowItem));
|
||||
}
|
||||
|
||||
nsCSSShadowArray(PRUint32 aArrayLen) :
|
||||
mLength(aArrayLen), mRefCnt(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsCSSShadowArray);
|
||||
for (PRUint32 i = 1; i < mLength; ++i) {
|
||||
// Make sure we call the constructors of each nsCSSShadowItem
|
||||
// (the first one is called for us because we declared it under private)
|
||||
new (&mArray[i]) nsCSSShadowItem();
|
||||
}
|
||||
}
|
||||
~nsCSSShadowArray() {
|
||||
MOZ_COUNT_DTOR(nsCSSShadowArray);
|
||||
for (PRUint32 i = 1; i < mLength; ++i) {
|
||||
mArray[i].~nsCSSShadowItem();
|
||||
}
|
||||
}
|
||||
|
||||
nsrefcnt AddRef() { return ++mRefCnt; }
|
||||
nsrefcnt Release();
|
||||
|
||||
PRUint32 Length() const { return mLength; }
|
||||
nsCSSShadowItem* ShadowAt(PRUint32 i) {
|
||||
NS_ABORT_IF_FALSE(i < mLength, "Accessing too high an index in the text shadow array!");
|
||||
return &mArray[i];
|
||||
}
|
||||
const nsCSSShadowItem* 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;
|
||||
nsCSSShadowItem mArray[1]; // This MUST be the last item
|
||||
};
|
||||
|
||||
// Border widths are rounded to the nearest-below integer number of pixels,
|
||||
// but values between zero and one device pixels are always rounded up to
|
||||
// one device pixel.
|
||||
@ -341,6 +418,7 @@ struct nsStyleBorder {
|
||||
nsStyleSides mBorderRadius; // [reset] length, percent
|
||||
PRUint8 mFloatEdge; // [reset] see nsStyleConsts.h
|
||||
nsBorderColors** mBorderColors; // [reset] multiple levels of color for a border.
|
||||
nsRefPtr<nsCSSShadowArray> mBoxShadow; // [reset] NULL for 'none'
|
||||
|
||||
void EnsureBorderColors() {
|
||||
if (!mBorderColors) {
|
||||
@ -669,80 +747,6 @@ 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);
|
||||
@ -770,7 +774,7 @@ struct nsStyleText {
|
||||
nsStyleCoord mTextIndent; // [inherited]
|
||||
nsStyleCoord mWordSpacing; // [inherited]
|
||||
|
||||
nsRefPtr<nsTextShadowArray> mShadowArray; // [inherited] NULL in case of a zero-length
|
||||
nsRefPtr<nsCSSShadowArray> mTextShadow; // [inherited] NULL in case of a zero-length
|
||||
|
||||
PRBool WhiteSpaceIsSignificant() const {
|
||||
return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
|
||||
|
@ -300,6 +300,15 @@ var gCSSProperties = {
|
||||
other_values: [ "center", "end", "justify" ],
|
||||
invalid_values: []
|
||||
},
|
||||
"-moz-box-shadow": {
|
||||
domProp: "MozBoxShadow",
|
||||
inherited: false,
|
||||
type: CSS_TYPE_LONGHAND,
|
||||
initial_values: [ "none" ],
|
||||
prerequisites: { "color": "blue" },
|
||||
other_values: [ "2px 2px", "2px 2px 1px", "2px 2px 2px 2px", "blue 3px 2px", "2px 2px 1px 5px green", "2px 2px red", "green 2px 2px 1px", "green 2px 2px, blue 1px 3px 4px", "currentColor 3px 3px", "blue 2px 2px, currentColor 1px 2px, 1px 2px 3px 2px orange", "3px 0 0 0" ],
|
||||
invalid_values: [ "3% 3%", "1px 1px 1px 1px 1px", "2px 2px, none", "red 2px 2px blue", "inherit, 2px 2px", "2px 2px, inherit", "2px 2px -5px" ]
|
||||
},
|
||||
"-moz-box-sizing": {
|
||||
domProp: "MozBoxSizing",
|
||||
inherited: false,
|
||||
|
Loading…
Reference in New Issue
Block a user