mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Bug 562815 part 6 - Check if property is cached in rule tree; r=dbaron
--HG-- extra : rebase_source : 9a7d2388bd00e2c8177cebc9d2a1339626cdd3ab
This commit is contained in:
parent
74603ec212
commit
3e8804de84
@ -387,13 +387,10 @@ ValueFromStringHelper(nsCSSProperty aPropID,
|
||||
}
|
||||
nsDependentSubstring subString(aString, subStringBegin);
|
||||
if (!nsStyleAnimation::ComputeValue(aPropID, aTargetElement, subString,
|
||||
PR_TRUE, aStyleAnimValue)) {
|
||||
PR_TRUE, aStyleAnimValue,
|
||||
aIsContextSensitive)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (aIsContextSensitive) {
|
||||
// XXX
|
||||
*aIsContextSensitive = PR_TRUE;
|
||||
}
|
||||
if (isNegative) {
|
||||
InvertSign(aStyleAnimValue);
|
||||
}
|
||||
|
@ -744,6 +744,10 @@ public:
|
||||
NS_ASSERTION(IsRoot(), "should only be called on root of rule tree");
|
||||
return HaveChildren() || mStyleData.mInheritedData || mStyleData.mResetData;
|
||||
}
|
||||
|
||||
PRBool NodeHasCachedData(const nsStyleStructID aSID) {
|
||||
return !!mStyleData.GetStyleData(aSID);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1926,48 +1926,13 @@ LookupStyleContext(dom::Element* aElement)
|
||||
return nsComputedDOMStyle::GetStyleContextForElement(aElement, nsnull, shell);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper function: StyleWithRuleAdded
|
||||
* Creates a custom style context as a sibling of the given element's
|
||||
* nsStyleContext with the given css::StyleRule added.
|
||||
*
|
||||
* @param aTargetElement The element whose style context we'll use as a
|
||||
* sibling for our custom style context.
|
||||
* @param aStyleRule The style rule to add to the style context.
|
||||
* @return The generated custom nsStyleContext, or nsnull on failure.
|
||||
*/
|
||||
already_AddRefed<nsStyleContext>
|
||||
StyleWithRuleAdded(dom::Element* aTargetElement,
|
||||
css::StyleRule* aStyleRule)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aTargetElement, "null target element");
|
||||
NS_ABORT_IF_FALSE(aTargetElement->GetCurrentDoc(),
|
||||
"element needs to be in a document "
|
||||
"if we're going to look up its style context");
|
||||
NS_ABORT_IF_FALSE(aStyleRule, "null style rule");
|
||||
|
||||
// Look up style context for our target element
|
||||
nsRefPtr<nsStyleContext> styleContext = LookupStyleContext(aTargetElement);
|
||||
if (!styleContext) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
aStyleRule->RuleMatched();
|
||||
|
||||
// Create a temporary nsStyleContext for the style rule
|
||||
nsCOMArray<nsIStyleRule> ruleArray;
|
||||
ruleArray.AppendObject(aStyleRule);
|
||||
nsStyleSet* styleSet = styleContext->PresContext()->StyleSet();
|
||||
return styleSet->ResolveStyleByAddingRules(styleContext, ruleArray);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsStyleAnimation::ComputeValue(nsCSSProperty aProperty,
|
||||
dom::Element* aTargetElement,
|
||||
const nsAString& aSpecifiedValue,
|
||||
PRBool aUseSVGMode,
|
||||
Value& aComputedValue)
|
||||
Value& aComputedValue,
|
||||
PRBool* aIsContextSensitive)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aTargetElement, "null target element");
|
||||
NS_ABORT_IF_FALSE(aTargetElement->GetCurrentDoc(),
|
||||
@ -1984,18 +1949,66 @@ nsStyleAnimation::ComputeValue(nsCSSProperty aProperty,
|
||||
if (!styleRule) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
nsRefPtr<nsStyleContext> tmpStyleContext =
|
||||
StyleWithRuleAdded(aTargetElement, styleRule);
|
||||
if (!tmpStyleContext) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (nsCSSProps::IsShorthand(aProperty) ||
|
||||
nsCSSProps::kAnimTypeTable[aProperty] == eStyleAnimType_None) {
|
||||
if (nsCSSProps::IsShorthand(aProperty) ||
|
||||
nsCSSProps::kAnimTypeTable[aProperty] == eStyleAnimType_None) {
|
||||
// Just capture the specified value
|
||||
aComputedValue.SetUnparsedStringValue(nsString(aSpecifiedValue));
|
||||
if (aIsContextSensitive) {
|
||||
// Since we're just returning the string as-is, aComputedValue isn't going
|
||||
// to change depending on the context
|
||||
*aIsContextSensitive = PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// Look up style context for our target element
|
||||
nsRefPtr<nsStyleContext> styleContext = LookupStyleContext(aTargetElement);
|
||||
if (!styleContext) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
nsStyleSet* styleSet = styleContext->PresContext()->StyleSet();
|
||||
|
||||
nsRefPtr<nsStyleContext> tmpStyleContext;
|
||||
if (aIsContextSensitive) {
|
||||
nsCOMArray<nsIStyleRule> ruleArray;
|
||||
ruleArray.AppendObject(styleSet->InitialStyleRule());
|
||||
ruleArray.AppendObject(styleRule);
|
||||
styleRule->RuleMatched();
|
||||
tmpStyleContext =
|
||||
styleSet->ResolveStyleByAddingRules(styleContext, ruleArray);
|
||||
if (!tmpStyleContext) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Force walk of rule tree
|
||||
nsStyleStructID sid = nsCSSProps::kSIDTable[aProperty];
|
||||
tmpStyleContext->GetStyleData(sid);
|
||||
|
||||
// If the rule node will have cached style data if the value is not
|
||||
// context-sensitive. So if there's nothing cached, it's not context
|
||||
// sensitive.
|
||||
*aIsContextSensitive =
|
||||
!tmpStyleContext->GetRuleNode()->NodeHasCachedData(sid);
|
||||
}
|
||||
|
||||
// If we're not concerned whether the property is context sensitive then just
|
||||
// add the rule to a new temporary style context alongside the target
|
||||
// element's style context.
|
||||
// Also, if we previously discovered that this property IS context-sensitive
|
||||
// then we need to throw the temporary style context out since the property's
|
||||
// value may have been biased by the 'initial' values supplied.
|
||||
if (!aIsContextSensitive || *aIsContextSensitive) {
|
||||
nsCOMArray<nsIStyleRule> ruleArray;
|
||||
ruleArray.AppendObject(styleRule);
|
||||
styleRule->RuleMatched();
|
||||
tmpStyleContext =
|
||||
styleSet->ResolveStyleByAddingRules(styleContext, ruleArray);
|
||||
if (!tmpStyleContext) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract computed value of our property from the temporary style rule
|
||||
return ExtractComputedValue(aProperty, tmpStyleContext, aComputedValue);
|
||||
}
|
||||
|
@ -175,13 +175,22 @@ public:
|
||||
* @param aUseSVGMode A flag to indicate whether we should parse
|
||||
* |aSpecifiedValue| in SVG mode.
|
||||
* @param [out] aComputedValue The resulting computed value.
|
||||
* @param [out] aIsContextSensitive
|
||||
* Set to PR_TRUE if |aSpecifiedValue| may produce
|
||||
* a different |aComputedValue| depending on other CSS
|
||||
* properties on |aTargetElement| or its ancestors.
|
||||
* PR_FALSE otherwise.
|
||||
* Note that the operation of this method is
|
||||
* significantly faster when |aIsContextSensitive| is
|
||||
* nsnull.
|
||||
* @return PR_TRUE on success, PR_FALSE on failure.
|
||||
*/
|
||||
static PRBool ComputeValue(nsCSSProperty aProperty,
|
||||
mozilla::dom::Element* aElement,
|
||||
mozilla::dom::Element* aTargetElement,
|
||||
const nsAString& aSpecifiedValue,
|
||||
PRBool aUseSVGMode,
|
||||
Value& aComputedValue);
|
||||
Value& aComputedValue,
|
||||
PRBool* aIsContextSensitive = nsnull);
|
||||
|
||||
/**
|
||||
* Creates a specified value for the given computed value.
|
||||
|
@ -57,6 +57,7 @@
|
||||
#include "nsIContent.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsRuleData.h"
|
||||
#include "nsRuleProcessorData.h"
|
||||
#include "nsTransitionManager.h"
|
||||
#include "nsAnimationManager.h"
|
||||
@ -80,6 +81,50 @@ nsEmptyStyleRule::List(FILE* out, PRInt32 aIndent) const
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsInitialStyleRule, nsIStyleRule)
|
||||
|
||||
/* virtual */ void
|
||||
nsInitialStyleRule::MapRuleInfoInto(nsRuleData* aRuleData)
|
||||
{
|
||||
// Iterate over the property groups
|
||||
for (nsStyleStructID sid = nsStyleStructID(0);
|
||||
sid < nsStyleStructID_Length; sid = nsStyleStructID(sid + 1)) {
|
||||
if (aRuleData->mSIDs & (1 << sid)) {
|
||||
// Iterate over nsCSSValues within the property group
|
||||
nsCSSValue * const value_start =
|
||||
aRuleData->mValueStorage + aRuleData->mValueOffsets[sid];
|
||||
for (nsCSSValue *value = value_start,
|
||||
*value_end = value + nsCSSProps::PropertyCountInStruct(sid);
|
||||
value != value_end; ++value) {
|
||||
// If MathML is disabled take care not to set MathML properties (or we
|
||||
// will trigger assertions in nsRuleNode)
|
||||
if (sid == eStyleStruct_Font &&
|
||||
!aRuleData->mPresContext->Document()->GetMathMLEnabled()) {
|
||||
size_t index = value - value_start;
|
||||
if (index == nsCSSProps::PropertyIndexInStruct(
|
||||
eCSSProperty_script_level) ||
|
||||
index == nsCSSProps::PropertyIndexInStruct(
|
||||
eCSSProperty_script_size_multiplier) ||
|
||||
index == nsCSSProps::PropertyIndexInStruct(
|
||||
eCSSProperty_script_min_size)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (value->GetUnit() == eCSSUnit_Null) {
|
||||
value->SetInitialValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* virtual */ void
|
||||
nsInitialStyleRule::List(FILE* out, PRInt32 aIndent) const
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static const nsStyleSet::sheetType gCSSSheetTypes[] = {
|
||||
nsStyleSet::eAgentSheet,
|
||||
nsStyleSet::eUserSheet,
|
||||
@ -1565,3 +1610,12 @@ nsStyleSet::EnsureUniqueInnerOnCSSSheets()
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
nsIStyleRule*
|
||||
nsStyleSet::InitialStyleRule()
|
||||
{
|
||||
if (!mInitialStyleRule) {
|
||||
mInitialStyleRule = new nsInitialStyleRule;
|
||||
}
|
||||
return mInitialStyleRule;
|
||||
}
|
||||
|
@ -74,6 +74,15 @@ class nsEmptyStyleRule : public nsIStyleRule
|
||||
#endif
|
||||
};
|
||||
|
||||
class nsInitialStyleRule : public nsIStyleRule
|
||||
{
|
||||
NS_DECL_ISUPPORTS
|
||||
virtual void MapRuleInfoInto(nsRuleData* aRuleData);
|
||||
#ifdef DEBUG
|
||||
virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
// The style set object is created by the document viewer and ownership is
|
||||
// then handed off to the PresShell. Only the PresShell should delete a
|
||||
// style set.
|
||||
@ -309,6 +318,8 @@ class nsStyleSet
|
||||
|
||||
nsCSSStyleSheet::EnsureUniqueInnerResult EnsureUniqueInnerOnCSSSheets();
|
||||
|
||||
nsIStyleRule* InitialStyleRule();
|
||||
|
||||
private:
|
||||
// Not to be implemented
|
||||
nsStyleSet(const nsStyleSet& aCopy);
|
||||
@ -400,6 +411,10 @@ class nsStyleSet
|
||||
// apply into different branches of the rule tree.
|
||||
nsRefPtr<nsEmptyStyleRule> mFirstLineRule, mFirstLetterRule;
|
||||
|
||||
// Style rule which sets all properties to their initial values for
|
||||
// determining when context-sensitive values are in use.
|
||||
nsRefPtr<nsInitialStyleRule> mInitialStyleRule;
|
||||
|
||||
PRUint16 mBatching;
|
||||
|
||||
// Old rule trees, which should only be non-empty between
|
||||
|
Loading…
Reference in New Issue
Block a user