Bug 542731, Patch B: Clean up nsSMILCSS* classes. r=roc

This commit is contained in:
Daniel Holbert 2010-02-01 18:46:13 -08:00
parent be6baee47b
commit cbd7942798
3 changed files with 110 additions and 86 deletions

View File

@ -46,13 +46,16 @@
#include "nsIContent.h"
#include "nsIDOMElement.h"
// Helper function
static PRBool
GetCSSComputedValue(nsIContent* aElem,
nsCSSProperty aPropID,
nsAString& aResult)
{
NS_ENSURE_TRUE(nsSMILCSSProperty::IsPropertyAnimatable(aPropID),
PR_FALSE);
NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(aPropID),
"Can't look up computed value of shorthand property");
NS_ABORT_IF_FALSE(nsSMILCSSProperty::IsPropertyAnimatable(aPropID),
"Shouldn't get here for non-animatable properties");
nsIDocument* doc = aElem->GetCurrentDoc();
if (!doc) {
@ -73,8 +76,7 @@ GetCSSComputedValue(nsIContent* aElem,
nsresult rv = NS_NewComputedDOMStyle(domElement, EmptyString(), shell,
getter_AddRefs(computedStyle));
if (NS_SUCCEEDED(rv) && computedStyle) {
// NOTE: This will produce an empty string for shorthand values
if (NS_SUCCEEDED(rv)) {
computedStyle->GetPropertyValue(aPropID, aResult);
return PR_TRUE;
}
@ -94,6 +96,20 @@ nsSMILCSSProperty::nsSMILCSSProperty(nsCSSProperty aPropID,
nsSMILValue
nsSMILCSSProperty::GetBaseValue() const
{
// SPECIAL CASE: Shorthands
if (nsCSSProps::IsShorthand(mPropID)) {
// We can't look up the base (computed-style) value of shorthand
// properties, because they aren't guaranteed to have a consistent computed
// value. However, that's not a problem, because it turns out the caller
// isn't going to end up using the value we return anyway. Base values only
// get used when there's interpolation or addition, and the shorthand
// properties we know about don't support those operations. So, we can just
// return a dummy value (initialized with the right type, so as not to
// indicate failure).
return nsSMILValue(&nsSMILCSSValueType::sSingleton);
}
// GENERAL CASE: Non-Shorthands
// (1) Put empty string in override style for property mPropID
// (saving old override style value, so we can set it again when we're done)
nsCOMPtr<nsIDOMCSSStyleDeclaration> overrideStyle;
@ -118,18 +134,11 @@ nsSMILCSSProperty::GetBaseValue() const
overrideDecl->SetPropertyValue(mPropID, cachedOverrideStyleVal);
}
// (4) Create a nsSMILValue from the computed style
nsSMILValue baseValue;
if (didGetComputedVal) {
// (4) Create the nsSMILValue from the computed style value
nsSMILCSSValueType::sSingleton.Init(baseValue);
if (!nsCSSProps::IsShorthand(mPropID) &&
!nsSMILCSSValueType::sSingleton.ValueFromString(mPropID, mElement,
computedStyleVal,
baseValue)) {
nsSMILCSSValueType::sSingleton.Destroy(baseValue);
NS_ABORT_IF_FALSE(baseValue.IsNull(),
"Destroy should leave us with null-typed value");
}
nsSMILCSSValueType::ValueFromString(mPropID, mElement,
computedStyleVal, baseValue);
}
return baseValue;
}
@ -140,14 +149,9 @@ nsSMILCSSProperty::ValueFromString(const nsAString& aStr,
nsSMILValue& aValue) const
{
NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE);
nsSMILCSSValueType::sSingleton.Init(aValue);
PRBool success =
nsSMILCSSValueType::sSingleton.ValueFromString(mPropID, mElement,
aStr, aValue);
if (!success) {
nsSMILCSSValueType::sSingleton.Destroy(aValue);
}
return success ? NS_OK : NS_ERROR_FAILURE;
nsSMILCSSValueType::ValueFromString(mPropID, mElement, aStr, aValue);
return aValue.IsNull() ? NS_ERROR_FAILURE : NS_OK;
}
nsresult
@ -155,32 +159,29 @@ nsSMILCSSProperty::SetAnimValue(const nsSMILValue& aValue)
{
NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE);
nsresult rv = NS_OK;
// Convert nsSMILValue to string
nsAutoString valStr;
if (nsSMILCSSValueType::sSingleton.ValueToString(aValue, valStr)) {
// Apply the style to the target element
nsCOMPtr<nsIDOMCSSStyleDeclaration> overrideStyle;
mElement->GetSMILOverrideStyle(getter_AddRefs(overrideStyle));
NS_ABORT_IF_FALSE(overrideStyle, "Need a non-null overrideStyle");
nsCOMPtr<nsICSSDeclaration> overrideDecl =
do_QueryInterface(overrideStyle);
if (overrideDecl) {
overrideDecl->SetPropertyValue(mPropID, valStr);
}
} else {
if (!nsSMILCSSValueType::ValueToString(aValue, valStr)) {
NS_WARNING("Failed to convert nsSMILValue for CSS property into a string");
rv = NS_ERROR_FAILURE;
return NS_ERROR_FAILURE;
}
return rv;
// Use string value to style the target element
nsCOMPtr<nsIDOMCSSStyleDeclaration> overrideStyle;
mElement->GetSMILOverrideStyle(getter_AddRefs(overrideStyle));
NS_ABORT_IF_FALSE(overrideStyle, "Need a non-null overrideStyle");
nsCOMPtr<nsICSSDeclaration> overrideDecl = do_QueryInterface(overrideStyle);
if (overrideDecl) {
overrideDecl->SetPropertyValue(mPropID, valStr);
}
return NS_OK;
}
void
nsSMILCSSProperty::ClearAnimValue()
{
// Put empty string in override style for property propID
// Put empty string in override style for our property
nsCOMPtr<nsIDOMCSSStyleDeclaration> overrideStyle;
mElement->GetSMILOverrideStyle(getter_AddRefs(overrideStyle));
nsCOMPtr<nsICSSDeclaration> overrideDecl = do_QueryInterface(overrideStyle);

View File

@ -303,59 +303,79 @@ GetPresContextForElement(nsIContent* aElem)
return shell ? shell->GetPresContext() : nsnull;
}
PRBool
nsSMILCSSValueType::ValueFromString(nsCSSProperty aPropID,
nsIContent* aTargetElement,
const nsAString& aString,
nsSMILValue& aValue) const
// Helper function to parse a string into a nsStyleAnimation::Value
static PRBool
ValueFromStringHelper(nsCSSProperty aPropID,
nsIContent* aTargetElement,
nsPresContext* aPresContext,
const nsAString& aString,
nsStyleAnimation::Value& aStyleAnimValue)
{
NS_ABORT_IF_FALSE(aValue.mType == &nsSMILCSSValueType::sSingleton,
"Passed-in value is wrong type");
NS_ABORT_IF_FALSE(!aValue.mU.mPtr, "expecting barely-initialized outparam");
nsPresContext* presContext = GetPresContextForElement(aTargetElement);
if (!presContext) {
NS_WARNING("Not parsing animation value; unable to get PresContext");
return PR_FALSE;
}
// If value is negative, we'll strip off the "-" so the CSS parser won't
// barf, and then manually make the parsed value negative. (This is a partial
// solution to let us accept some otherwise out-of-bounds CSS values -- bug
// 501188 will provide a more complete fix.)
// barf, and then manually make the parsed value negative.
// (This is a partial solution to let us accept some otherwise out-of-bounds
// CSS values. Bug 501188 will provide a more complete fix.)
PRBool isNegative = PR_FALSE;
PRUint32 subStringBegin = 0;
PRInt32 absValuePos = nsSMILParserUtils::CheckForNegativeNumber(aString);
if (absValuePos > 0) {
subStringBegin = (PRUint32)absValuePos;
isNegative = PR_TRUE;
subStringBegin = (PRUint32)absValuePos; // Start parsing after '-' sign
}
nsDependentSubstring subString(aString, subStringBegin);
nsStyleAnimation::Value parsedValue;
if (nsStyleAnimation::ComputeValue(aPropID, aTargetElement,
subString, parsedValue)) {
if (isNegative) {
InvertSign(parsedValue);
}
if (aPropID == eCSSProperty_font_size) {
// Divide out text-zoom, since SVG is supposed to ignore it
NS_ABORT_IF_FALSE(parsedValue.GetUnit() == nsStyleAnimation::eUnit_Coord,
"'font-size' value with unexpected style unit");
parsedValue.SetCoordValue(parsedValue.GetCoordValue() /
presContext->TextZoom());
}
aValue.mU.mPtr = new ValueWrapper(aPropID, parsedValue, presContext);
return aValue.mU.mPtr != nsnull;
if (!nsStyleAnimation::ComputeValue(aPropID, aTargetElement,
subString, aStyleAnimValue)) {
return PR_FALSE;
}
return PR_FALSE;
if (isNegative) {
InvertSign(aStyleAnimValue);
}
if (aPropID == eCSSProperty_font_size) {
// Divide out text-zoom, since SVG is supposed to ignore it
NS_ABORT_IF_FALSE(aStyleAnimValue.GetUnit() ==
nsStyleAnimation::eUnit_Coord,
"'font-size' value with unexpected style unit");
aStyleAnimValue.SetCoordValue(aStyleAnimValue.GetCoordValue() /
aPresContext->TextZoom());
}
return PR_TRUE;
}
// static
void
nsSMILCSSValueType::ValueFromString(nsCSSProperty aPropID,
nsIContent* aTargetElement,
const nsAString& aString,
nsSMILValue& aValue)
{
NS_ABORT_IF_FALSE(aValue.IsNull(), "Outparam should be null-typed");
nsPresContext* presContext = GetPresContextForElement(aTargetElement);
if (!presContext) {
NS_WARNING("Not parsing animation value; unable to get PresContext");
return;
}
nsStyleAnimation::Value parsedValue;
if (ValueFromStringHelper(aPropID, aTargetElement, presContext,
aString, parsedValue)) {
sSingleton.Init(aValue);
aValue.mU.mPtr = new ValueWrapper(aPropID, parsedValue, presContext);
if (!aValue.mU.mPtr) {
// Out of memory! Destroy outparam, to leave it as nsSMILNullType,
// which indicates to our caller that we failed.
sSingleton.Destroy(aValue);
}
}
}
// static
PRBool
nsSMILCSSValueType::ValueToString(const nsSMILValue& aValue,
nsAString& aString) const
nsAString& aString)
{
NS_ABORT_IF_FALSE(aValue.mType == &nsSMILCSSValueType::sSingleton,
"Passed-in value is wrong type");
"Unexpected SMIL value type");
const ValueWrapper* wrapper = ExtractValueWrapper(aValue);
return !wrapper ||
nsStyleAnimation::UncomputeValue(wrapper->mPropID, wrapper->mPresContext,

View File

@ -54,8 +54,8 @@ class nsAString;
class nsSMILCSSValueType : public nsISMILType
{
public:
// nsISMILValueType Methods
// ------------------------
// nsISMILType Methods
// -------------------
NS_OVERRIDE virtual nsresult Init(nsSMILValue& aValue) const;
NS_OVERRIDE virtual void Destroy(nsSMILValue&) const;
NS_OVERRIDE virtual nsresult Assign(nsSMILValue& aDest,
@ -71,24 +71,27 @@ public:
double aUnitDistance,
nsSMILValue& aResult) const;
/* ---------- Helper methods, not inherited from nsISMILType ---------- */
/**
* Sets up the given nsSMILValue to represent the given string value. The
* string is interpreted as a value for the given property on the given
* element.
*
* Note: aValue is expected to be freshly initialized (i.e. it should already
* have been passed into nsSMILCSSValueType::Init(), and it should not have
* been set up further via e.g. Assign() or another ValueFromString() call.)
* On failure, this method leaves aValue.mType == nsSMILNullType::sSingleton.
* Otherwise, this method leaves aValue.mType == this class's singleton.
*
* @param aPropID The property for which we're parsing a value.
* @param aTargetElement The target element to whom the property/value
* setting applies.
* @param aString The string to be parsed as a CSS value.
* @param [out] aValue The nsSMILValue to be populated.
* @return PR_TRUE on success, PR_FALSE on failure.
* @param [out] aValue The nsSMILValue to be populated. Should
* initially be null-typed.
* @pre aValue.IsNull()
* @post aValue.IsNull() || aValue.mType == nsSMILCSSValueType::sSingleton
*/
PRBool ValueFromString(nsCSSProperty aPropID, nsIContent* aTargetElement,
const nsAString& aString, nsSMILValue& aValue) const;
static void ValueFromString(nsCSSProperty aPropID,
nsIContent* aTargetElement,
const nsAString& aString, nsSMILValue& aValue);
/**
* Creates a string representation of the given nsSMILValue.
@ -102,7 +105,7 @@ public:
* @param [out] aString The string to be populated with the given value.
* @return PR_TRUE on success, PR_FALSE on failure.
*/
PRBool ValueToString(const nsSMILValue& aValue, nsAString& aString) const;
static PRBool ValueToString(const nsSMILValue& aValue, nsAString& aString);
// Singleton for nsSMILValue objects to hold onto.
static nsSMILCSSValueType sSingleton;