Take advantage of fix for bug 60683 (thanks bz) in ChangeCSSInlineStyleTxn and then reduce a lot the size of the transaction, keeping only property values instead of a whole style attribute ; major memory impact in CSS mode; b=162473, r=brade, sr=kin

This commit is contained in:
glazman%netscape.com 2002-08-20 11:28:57 +00:00
Родитель ed3bf522d6
Коммит 6d9ec3b18b
2 изменённых файлов: 111 добавлений и 126 удалений

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

@ -165,10 +165,10 @@ NS_IMETHODIMP ChangeCSSInlineStyleTxn::Init(nsIEditor *aEditor,
NS_ADDREF(mProperty); NS_ADDREF(mProperty);
mValue.Assign(aValue); mValue.Assign(aValue);
mRemoveProperty = aRemoveProperty; mRemoveProperty = aRemoveProperty;
mPropertyWasSet = PR_FALSE;
mUndoAttributeWasSet = PR_FALSE; mUndoAttributeWasSet = PR_FALSE;
mRedoAttributeWasSet = PR_FALSE; mRedoAttributeWasSet = PR_FALSE;
mUndoValue.SetLength(0); mUndoValue.SetLength(0);
mRedoValue.SetLength(0);
return NS_OK; return NS_OK;
} }
@ -177,160 +177,139 @@ NS_IMETHODIMP ChangeCSSInlineStyleTxn::DoTransaction(void)
NS_ASSERTION(mEditor && mElement, "bad state"); NS_ASSERTION(mEditor && mElement, "bad state");
if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; } if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
nsresult result=NS_OK; nsresult result = NS_OK;
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl; nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
PRUint32 length = 0;
nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyles = do_QueryInterface(mElement); nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyles = do_QueryInterface(mElement);
if (!inlineStyles) return NS_ERROR_NULL_POINTER; if (!inlineStyles) return NS_ERROR_NULL_POINTER;
result = inlineStyles->GetStyle(getter_AddRefs(cssDecl)); result = inlineStyles->GetStyle(getter_AddRefs(cssDecl));
if (NS_FAILED(result)) return result; if (NS_FAILED(result)) return result;
if (!cssDecl) return NS_ERROR_NULL_POINTER; if (!cssDecl) return NS_ERROR_NULL_POINTER;
result = cssDecl->GetLength(&length);
if (NS_FAILED(result)) return result;
nsAutoString newDeclString, propertyNameString, undoString, redoString; nsAutoString propertyNameString;
mProperty->ToString(propertyNameString); mProperty->ToString(propertyNameString);
mPropertyWasSet = PR_FALSE;
// does this property accept more than 1 value ? // does this property accept more than 1 value ?
// we need to know that because of bug 62682
PRBool multiple = AcceptsMoreThanOneValue(mProperty); PRBool multiple = AcceptsMoreThanOneValue(mProperty);
nsAutoString styleAttr(NS_LITERAL_STRING("style")); nsAutoString styleAttr(NS_LITERAL_STRING("style"));
result = mEditor->GetAttributeValue(mElement, styleAttr, mUndoValue, &mUndoAttributeWasSet); result = mElement->HasAttribute(styleAttr, &mUndoAttributeWasSet);
if (NS_FAILED(result)) return result; if (NS_FAILED(result)) return result;
if (0 == length && !mRemoveProperty && mUndoAttributeWasSet) { nsAutoString values;
// dirty case, the style engine did not have the time to parse the style attribute result = cssDecl->GetPropertyValue(propertyNameString, values);
newDeclString.Append(mUndoValue + NS_LITERAL_STRING(" ")); if (NS_FAILED(result)) return result;
AppendDeclaration(newDeclString, propertyNameString, mValue); mUndoValue.Assign(values);
result = mElement->SetAttribute(styleAttr, newDeclString);
} if (mRemoveProperty) {
else if (0 == length) { nsAutoString returnString;
if (mRemoveProperty) { if (multiple) {
// there is no style attribute or it is empty and we want to remove something // the property can have more than one value, let's remove only
// so it is an early way out // the value we have to remove and not the others
result = mElement->RemoveAttribute(styleAttr);
} // the 2 lines below are a workaround because nsDOMCSSDeclaration::GetPropertyCSSValue
else { // is not yet implemented (bug 62682)
// the style attribute is empty or absent and we want to add a property RemoveValueFromListOfValues(values, NS_LITERAL_STRING("none"));
// let's do it... RemoveValueFromListOfValues(values, mValue);
AppendDeclaration(newDeclString, propertyNameString, mValue); if (values.IsEmpty()) {
result = mElement->SetAttribute(styleAttr, newDeclString); result = cssDecl->RemoveProperty(propertyNameString, returnString);
} if (NS_FAILED(result)) return result;
}
else if (mRemoveProperty && (1 == length)) {
// let's deal with a special case : we want to remove a property from the
// style attribute and it contains only one declaration...
// if it is the one we look for, let's remove the attribute ! Otherwise,
// do nothing.
nsAutoString itemPropertyNameString;
cssDecl->Item(0, itemPropertyNameString);
PRBool thisOne = propertyNameString.Equals(itemPropertyNameString, nsCaseInsensitiveStringComparator());
if (thisOne) {
mPropertyWasSet = PR_TRUE;
if (multiple) {
// the property accepts more than one value...
// cssDecl->GetPropertyValue(propertyNameString, mUndoValue);
nsAutoString values;
cssDecl->GetPropertyValue(propertyNameString, values);
RemoveValueFromListOfValues(values, NS_LITERAL_STRING("none"));
RemoveValueFromListOfValues(values, mValue);
if (0 != values.Length()) {
AppendDeclaration(newDeclString, propertyNameString, values);
}
result = mElement->SetAttribute(styleAttr, newDeclString);
} }
else { else {
result = mElement->RemoveAttribute(styleAttr); nsAutoString priority;
result = cssDecl->GetPropertyPriority(propertyNameString, priority);
if (NS_FAILED(result)) return result;
result = cssDecl->SetProperty(propertyNameString, values,
priority);
if (NS_FAILED(result)) return result;
} }
} }
else {
result = cssDecl->RemoveProperty(propertyNameString, returnString);
if (NS_FAILED(result)) return result;
}
} }
else { else {
// general case, we are going to browse all the CSS declarations in the nsAutoString priority;
// style attribute, and, if needed, remove or rewrite the one we want result = cssDecl->GetPropertyPriority(propertyNameString, priority);
PRUint32 index; if (NS_FAILED(result)) return result;
nsAutoString itemPropertyNameString; if (multiple) {
for (index = 0 ; index < length; index++) { // the property can have more than one value, let's add
cssDecl->Item(index, itemPropertyNameString); // the value we have to add to the others
PRBool thisOne = propertyNameString.Equals(itemPropertyNameString, nsCaseInsensitiveStringComparator());
if (thisOne) { // the line below is a workaround because nsDOMCSSDeclaration::GetPropertyCSSValue
// we have found the property we are looking for... // is not yet implemented (bug 62682)
// if we have to remove it, do nothing or remove only the corresponding value AddValueToMultivalueProperty(values, mValue);
// if we have to change it, do it below
if (mRemoveProperty) {
if (multiple) {
nsAutoString values;
cssDecl->GetPropertyValue(propertyNameString, values);
RemoveValueFromListOfValues(values, NS_LITERAL_STRING("none"));
RemoveValueFromListOfValues(values, mValue);
if (0 != values.Length()) {
AppendDeclaration(newDeclString, propertyNameString, values);
}
}
}
else {
newDeclString.Append(propertyNameString + NS_LITERAL_STRING(": "));
if (multiple) {
nsAutoString values;
cssDecl->GetPropertyValue(propertyNameString, values);
AddValueToMultivalueProperty(values, mValue);
newDeclString.Append(values);
}
else {
newDeclString.Append(mValue);
}
newDeclString.Append(NS_LITERAL_STRING("; "));
}
mPropertyWasSet = PR_TRUE;
}
else {
// this is not the property we are looking for, let's recreate the declaration
nsAutoString stringValue;
cssDecl->GetPropertyValue(itemPropertyNameString, stringValue);
AppendDeclaration(newDeclString, itemPropertyNameString, stringValue);
}
} }
// if we DON'T have to remove the property, ie if we have to change or set it, else
// did we find it earlier ? If not, let's set it now... values.Assign(mValue);
if (!mRemoveProperty && !mPropertyWasSet) { result = cssDecl->SetProperty(propertyNameString, values,
AppendDeclaration(newDeclString, propertyNameString, mValue); priority);
} if (NS_FAILED(result)) return result;
result = mElement->SetAttribute(styleAttr, newDeclString);
} }
result = mEditor->GetAttributeValue(mElement, styleAttr, mRedoValue, &mRedoAttributeWasSet);
// let's be sure we don't keep an empty style attribute
PRUint32 length;
result = cssDecl->GetLength(&length);
if (NS_FAILED(result)) return result;
if (!length) {
result = mElement->RemoveAttribute(styleAttr);
if (NS_FAILED(result)) return result;
}
else
mRedoAttributeWasSet = PR_TRUE;
return cssDecl->GetPropertyValue(propertyNameString, mRedoValue);
}
nsresult ChangeCSSInlineStyleTxn::SetStyle(PRBool aAttributeWasSet,
nsAString & aValue)
{
NS_ASSERTION(mEditor && mElement, "bad state");
if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
nsresult result = NS_OK;
if (aAttributeWasSet) {
// the style attribute was set and not empty, let's recreate the declaration
nsAutoString propertyNameString;
mProperty->ToString(propertyNameString);
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyles = do_QueryInterface(mElement);
if (!inlineStyles) return NS_ERROR_NULL_POINTER;
result = inlineStyles->GetStyle(getter_AddRefs(cssDecl));
if (NS_FAILED(result)) return result;
if (!cssDecl) return NS_ERROR_NULL_POINTER;
if (aValue.IsEmpty()) {
// an empty value means we have to remove the property
nsAutoString returnString;
result = cssDecl->RemoveProperty(propertyNameString, returnString);
}
else {
// let's recreate the declaration as it was
nsAutoString priority;
result = cssDecl->GetPropertyPriority(propertyNameString, priority);
if (NS_FAILED(result)) return result;
result = cssDecl->SetProperty(propertyNameString, aValue, priority);
}
}
else
result = mElement->RemoveAttribute(NS_LITERAL_STRING("style"));
return result; return result;
} }
// to undo a transaction, just reset the style attribute to its former value...
NS_IMETHODIMP ChangeCSSInlineStyleTxn::UndoTransaction(void) NS_IMETHODIMP ChangeCSSInlineStyleTxn::UndoTransaction(void)
{ {
NS_ASSERTION(mEditor && mElement, "bad state"); return SetStyle(mUndoAttributeWasSet, mUndoValue);
if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
nsresult result=NS_OK;
if (PR_TRUE == mUndoAttributeWasSet)
result = mElement->SetAttribute(NS_LITERAL_STRING("style"), mUndoValue);
else
result = mElement->RemoveAttribute(NS_LITERAL_STRING("style"));
return result;
} }
// to redo a transaction, just set again the style attribute
NS_IMETHODIMP ChangeCSSInlineStyleTxn::RedoTransaction(void) NS_IMETHODIMP ChangeCSSInlineStyleTxn::RedoTransaction(void)
{ {
NS_ASSERTION(mEditor && mElement, "bad state"); return SetStyle(mRedoAttributeWasSet, mRedoValue);
if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
nsresult result=NS_OK;
if (PR_TRUE == mRedoAttributeWasSet)
result = mElement->SetAttribute(NS_LITERAL_STRING("style"), mRedoValue);
else
result = mElement->RemoveAttribute(NS_LITERAL_STRING("style"));
return result;
} }
NS_IMETHODIMP ChangeCSSInlineStyleTxn::Merge(nsITransaction *aTransaction, PRBool *aDidMerge) NS_IMETHODIMP ChangeCSSInlineStyleTxn::Merge(nsITransaction *aTransaction, PRBool *aDidMerge)

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

@ -117,6 +117,13 @@ private:
const nsAString & aProperty, const nsAString & aProperty,
const nsAString & aValues); const nsAString & aValues);
/** If the boolean is true and if the value is not the empty string,
* set the property in the transaction to that value; if the value
* is empty, remove the property from element's styles. If the boolean
* is false, just remove the style attribute.
*/
nsresult SetStyle(PRBool aAttributeWasSet, nsAString & aValue);
public: public:
NS_IMETHOD DoTransaction(void); NS_IMETHOD DoTransaction(void);
@ -143,16 +150,15 @@ protected:
/** the value to set the property to (ignored if mRemoveProperty==PR_TRUE) */ /** the value to set the property to (ignored if mRemoveProperty==PR_TRUE) */
nsString mValue; nsString mValue;
/** the value to set the attribute to for undo */ /** the value to set the property to for undo */
nsString mUndoValue; nsString mUndoValue;
/** true if the style attribute was present and not empty before DoTransaction */
PRBool mUndoAttributeWasSet; PRBool mUndoAttributeWasSet;
/** the value to set the attribute to for redo */ /** the value to set the property to for redo */
nsString mRedoValue; nsString mRedoValue;
/** true if the style attribute is present and not empty after DoTransaction */
PRBool mRedoAttributeWasSet; PRBool mRedoAttributeWasSet;
/** PR_TRUE if the mProperty was explicitely set on mElement at the time of execution */
PRBool mPropertyWasSet;
/** PR_TRUE if the operation is to remove mProperty from mElement */ /** PR_TRUE if the operation is to remove mProperty from mElement */
PRBool mRemoveProperty; PRBool mRemoveProperty;