/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: NPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Netscape Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Original Author: David W. Hyatt (hyatt@netscape.com) * Daniel Glazman * Roger B. Sidje * * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the NPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the NPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nscore.h" #include "nsRuleNode.h" #include "nsIDeviceContext.h" #include "nsILookAndFeel.h" #include "nsIPresShell.h" #include "nsIFontMetrics.h" #include "nsIDocShellTreeItem.h" #include "nsStyleUtil.h" #include "nsCSSAtoms.h" #include "nsThemeConstants.h" #include "nsITheme.h" // Temporary - Test of full time Standard mode for forms #include "nsIPref.h" #include "nsIServiceManager.h" struct nsRuleList { nsRuleNode* mRuleNode; nsRuleList* mNext; public: nsRuleList(nsRuleNode* aNode, nsRuleList* aNext= nsnull) { MOZ_COUNT_CTOR(nsRuleList); mRuleNode = aNode; mNext = aNext; } ~nsRuleList() { MOZ_COUNT_DTOR(nsRuleList); mRuleNode->Destroy(); if (mNext) mNext->Destroy(mNext->mRuleNode->mPresContext); } void* operator new(size_t sz, nsIPresContext* aContext) { void* result = nsnull; aContext->AllocateFromShell(sz, &result); return result; }; void operator delete(void* aPtr) {} // Does nothing. The arena will free us up when the rule tree // dies. void Destroy(nsIPresContext* aContext) { this->~nsRuleList(); aContext->FreeToShell(sizeof(nsRuleList), this); } }; class nsShellISupportsKey : public nsHashKey { public: nsISupports* mKey; public: nsShellISupportsKey(nsISupports* key) { #ifdef DEBUG mKeyType = SupportsKey; #endif mKey = key; } ~nsShellISupportsKey(void) { } void* operator new(size_t sz, nsIPresContext* aContext) { void* result = nsnull; aContext->AllocateFromShell(sz, &result); return result; }; void operator delete(void* aPtr) {} // Does nothing. The arena will free us up when the rule tree // dies. void Destroy(nsIPresContext* aContext) { this->~nsShellISupportsKey(); aContext->FreeToShell(sizeof(nsShellISupportsKey), this); } PRUint32 HashCode(void) const { return NS_PTR_TO_INT32(mKey); } PRBool Equals(const nsHashKey *aKey) const { NS_ASSERTION(aKey->GetKeyType() == SupportsKey, "mismatched key types"); return (mKey == ((nsShellISupportsKey *) aKey)->mKey); } nsHashKey* Clone() const { return (nsHashKey*)this; // Just return ourselves. } }; // EnsureBlockDisplay: // - if the display value (argument) is not a block-type // then we set it to a valid block display value // - For enforcing the floated/positioned element CSS2 rules static void EnsureBlockDisplay(PRUint8& display) { // see if the display value is already a block switch (display) { case NS_STYLE_DISPLAY_NONE : // never change display:none *ever* break; case NS_STYLE_DISPLAY_TABLE : case NS_STYLE_DISPLAY_BLOCK : // do not muck with these at all - already blocks break; case NS_STYLE_DISPLAY_LIST_ITEM : // do not change list items to blocks - retain the bullet/numbering break; case NS_STYLE_DISPLAY_TABLE_ROW_GROUP : case NS_STYLE_DISPLAY_TABLE_COLUMN : case NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP : case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP : case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP : case NS_STYLE_DISPLAY_TABLE_ROW : case NS_STYLE_DISPLAY_TABLE_CELL : case NS_STYLE_DISPLAY_TABLE_CAPTION : // special cases: don't do anything since these cannot really be floated anyway break; case NS_STYLE_DISPLAY_INLINE_TABLE : // make inline tables into tables display = NS_STYLE_DISPLAY_TABLE; break; default : // make it a block display = NS_STYLE_DISPLAY_BLOCK; } } nsString& Unquote(nsString& aString) { PRUnichar start = aString.First(); PRUnichar end = aString.Last(); if ((start == end) && ((start == PRUnichar('\"')) || (start == PRUnichar('\'')))) { PRInt32 length = aString.Length(); aString.Truncate(length - 1); aString.Cut(0, 1); } return aString; } nscoord CalcLength(const nsCSSValue& aValue, const nsFont* aFont, nsIStyleContext* aStyleContext, nsIPresContext* aPresContext, PRBool& aInherited) { NS_ASSERTION(aValue.IsLengthUnit(), "not a length unit"); if (aValue.IsFixedLengthUnit()) { return aValue.GetLengthTwips(); } nsCSSUnit unit = aValue.GetUnit(); switch (unit) { case eCSSUnit_EM: case eCSSUnit_Char: { aInherited = PR_TRUE; const nsFont* font = aStyleContext ? &(((nsStyleFont*)aStyleContext->GetStyleData(eStyleStruct_Font))->mFont) : aFont; return NSToCoordRound(aValue.GetFloatValue() * (float)font->size); // XXX scale against font metrics height instead? } case eCSSUnit_EN: { aInherited = PR_TRUE; const nsFont* font = aStyleContext ? &(((nsStyleFont*)aStyleContext->GetStyleData(eStyleStruct_Font))->mFont) : aFont; return NSToCoordRound((aValue.GetFloatValue() * (float)font->size) / 2.0f); } case eCSSUnit_XHeight: { aInherited = PR_TRUE; const nsFont* font = aStyleContext ? &(((nsStyleFont*)aStyleContext->GetStyleData(eStyleStruct_Font))->mFont) : aFont; nsIFontMetrics* fm; aPresContext->GetMetricsFor(*font, &fm); NS_ASSERTION(nsnull != fm, "can't get font metrics"); nscoord xHeight; if (nsnull != fm) { fm->GetXHeight(xHeight); NS_RELEASE(fm); } else { xHeight = ((font->size * 2) / 3); } return NSToCoordRound(aValue.GetFloatValue() * (float)xHeight); } case eCSSUnit_CapHeight: { NS_NOTYETIMPLEMENTED("cap height unit"); aInherited = PR_TRUE; const nsFont* font = aStyleContext ? &(((nsStyleFont*)aStyleContext->GetStyleData(eStyleStruct_Font))->mFont) : aFont; nscoord capHeight = ((font->size / 3) * 2); // XXX HACK! return NSToCoordRound(aValue.GetFloatValue() * (float)capHeight); } case eCSSUnit_Pixel: float p2t; aPresContext->GetScaledPixelsToTwips(&p2t); return NSFloatPixelsToTwips(aValue.GetFloatValue(), p2t); default: break; } return 0; } #define SETCOORD_NORMAL 0x01 // N #define SETCOORD_AUTO 0x02 // A #define SETCOORD_INHERIT 0x04 // H #define SETCOORD_PERCENT 0x08 // P #define SETCOORD_FACTOR 0x10 // F #define SETCOORD_LENGTH 0x20 // L #define SETCOORD_INTEGER 0x40 // I #define SETCOORD_ENUMERATED 0x80 // E #define SETCOORD_LP (SETCOORD_LENGTH | SETCOORD_PERCENT) #define SETCOORD_LH (SETCOORD_LENGTH | SETCOORD_INHERIT) #define SETCOORD_AH (SETCOORD_AUTO | SETCOORD_INHERIT) #define SETCOORD_LPH (SETCOORD_LP | SETCOORD_INHERIT) #define SETCOORD_LPAH (SETCOORD_LP | SETCOORD_AH) #define SETCOORD_LPEH (SETCOORD_LP | SETCOORD_ENUMERATED | SETCOORD_INHERIT) #define SETCOORD_LE (SETCOORD_LENGTH | SETCOORD_ENUMERATED) #define SETCOORD_LEH (SETCOORD_LE | SETCOORD_INHERIT) #define SETCOORD_IA (SETCOORD_INTEGER | SETCOORD_AUTO) #define SETCOORD_LAE (SETCOORD_LENGTH | SETCOORD_AUTO | SETCOORD_ENUMERATED) static PRBool SetCoord(const nsCSSValue& aValue, nsStyleCoord& aCoord, const nsStyleCoord& aParentCoord, PRInt32 aMask, nsIStyleContext* aStyleContext, nsIPresContext* aPresContext, PRBool& aInherited) { PRBool result = PR_TRUE; if (aValue.GetUnit() == eCSSUnit_Null) { result = PR_FALSE; } else if (((aMask & SETCOORD_LENGTH) != 0) && (aValue.GetUnit() == eCSSUnit_Char)) { aCoord.SetIntValue(NSToIntFloor(aValue.GetFloatValue()), eStyleUnit_Chars); } else if (((aMask & SETCOORD_LENGTH) != 0) && aValue.IsLengthUnit()) { aCoord.SetCoordValue(CalcLength(aValue, nsnull, aStyleContext, aPresContext, aInherited)); } else if (((aMask & SETCOORD_PERCENT) != 0) && (aValue.GetUnit() == eCSSUnit_Percent)) { aCoord.SetPercentValue(aValue.GetPercentValue()); } else if (((aMask & SETCOORD_INTEGER) != 0) && (aValue.GetUnit() == eCSSUnit_Integer)) { aCoord.SetIntValue(aValue.GetIntValue(), eStyleUnit_Integer); } else if (((aMask & SETCOORD_ENUMERATED) != 0) && (aValue.GetUnit() == eCSSUnit_Enumerated)) { aCoord.SetIntValue(aValue.GetIntValue(), eStyleUnit_Enumerated); } else if (((aMask & SETCOORD_AUTO) != 0) && (aValue.GetUnit() == eCSSUnit_Auto)) { aCoord.SetAutoValue(); } else if (((aMask & SETCOORD_INHERIT) != 0) && (aValue.GetUnit() == eCSSUnit_Inherit)) { nsStyleUnit unit = aParentCoord.GetUnit(); if ((eStyleUnit_Null == unit) || // parent has explicit computed value (eStyleUnit_Factor == unit) || (eStyleUnit_Coord == unit) || (eStyleUnit_Integer == unit) || (eStyleUnit_Enumerated == unit) || (eStyleUnit_Normal == unit) || (eStyleUnit_Chars == unit)) { aCoord = aParentCoord; // just inherit value from parent aInherited = PR_TRUE; } else { aCoord.SetInheritValue(); // needs to be computed by client // Since this works just like being // specified and not inherited, that's // how it's treated. } } else if (((aMask & SETCOORD_NORMAL) != 0) && (aValue.GetUnit() == eCSSUnit_Normal)) { aCoord.SetNormalValue(); } else if (((aMask & SETCOORD_FACTOR) != 0) && (aValue.GetUnit() == eCSSUnit_Number)) { aCoord.SetFactorValue(aValue.GetFloatValue()); } else { result = PR_FALSE; // didn't set anything } return result; } static PRBool SetColor(const nsCSSValue& aValue, const nscolor aParentColor, nsIPresContext* aPresContext, nscolor& aResult, PRBool& aInherited) { PRBool result = PR_FALSE; nsCSSUnit unit = aValue.GetUnit(); if (eCSSUnit_Color == unit) { aResult = aValue.GetColorValue(); result = PR_TRUE; } else if (eCSSUnit_String == unit) { nsAutoString value; aValue.GetStringValue(value); nscolor rgba; if (NS_ColorNameToRGB(value, &rgba)) { aResult = rgba; result = PR_TRUE; } } else if (eCSSUnit_Integer == unit) { nsILookAndFeel* look = nsnull; if (NS_SUCCEEDED(aPresContext->GetLookAndFeel(&look)) && look) { nsILookAndFeel::nsColorID colorID = (nsILookAndFeel::nsColorID)aValue.GetIntValue(); if (colorID == nsILookAndFeel::eColor_theme) return PR_FALSE; if (NS_SUCCEEDED(look->GetColor(colorID, aResult))) { result = PR_TRUE; } NS_RELEASE(look); } } else if (eCSSUnit_Inherit == unit) { aResult = aParentColor; result = PR_TRUE; aInherited = PR_TRUE; } return result; } // Overloaded new operator. Initializes the memory to 0 and relies on an arena // (which comes from the presShell) to perform the allocation. void* nsRuleNode::operator new(size_t sz, nsIPresContext* aPresContext) { // Check the recycle list first. void* result = nsnull; aPresContext->AllocateFromShell(sz, &result); return result; } // Overridden to prevent the global delete from being called, since the memory // came out of an nsIArena instead of the global delete operator's heap. void nsRuleNode::Destroy() { // Destroy ourselves. this->~nsRuleNode(); // Don't let the memory be freed, since it will be recycled // instead. Don't call the global operator delete. mPresContext->FreeToShell(sizeof(nsRuleNode), this); } void nsRuleNode::CreateRootNode(nsIPresContext* aPresContext, nsRuleNode** aResult) { *aResult = new (aPresContext) nsRuleNode(aPresContext); } nsILanguageAtomService* nsRuleNode::gLangService = nsnull; nsRuleNode::nsRuleNode(nsIPresContext* aContext, nsIStyleRule* aRule, nsRuleNode* aParent) :mPresContext(aContext), mParent(aParent), mInheritBits(0), mNoneBits(0) { MOZ_COUNT_CTOR(nsRuleNode); mRule = aRule; if (mParent) mChildren = nsnull; else mRootChildren = nsnull; } PR_STATIC_CALLBACK(PRBool) DeleteRuleNodeChildren(nsHashKey* aKey, void* aData, void* aClosure) { nsRuleNode* ruleNode = (nsRuleNode*)aData; ruleNode->Destroy(); return PR_TRUE; } nsRuleNode::~nsRuleNode() { MOZ_COUNT_DTOR(nsRuleNode); if (mStyleData.mResetData || mStyleData.mInheritedData) mStyleData.Destroy(0, mPresContext); if (mParent) { if (mChildren) mChildren->Destroy(mPresContext); } else { if (mRootChildren) { mRootChildren->Enumerate(DeleteRuleNodeChildren, nsnull); delete mRootChildren; } } } nsresult nsRuleNode::GetBits(PRInt32 aType, PRUint32* aResult) { switch (aType) { case eNoneBits : *aResult = mNoneBits; break; case eInheritBits : *aResult = mInheritBits; break; default: NS_ERROR("invalid arg"); return NS_ERROR_INVALID_ARG; } return NS_OK; } nsresult nsRuleNode::Transition(nsIStyleRule* aRule, nsRuleNode** aResult) { nsRuleNode* next = nsnull; if (!mParent) { nsShellISupportsKey key(aRule); if (mRootChildren) next = NS_STATIC_CAST(nsRuleNode*, mRootChildren->Get(&key)); if (!next) { // Create the new entry in our table. nsRuleNode* newNode = new (mPresContext) nsRuleNode(mPresContext, aRule, this); next = newNode; if (!mRootChildren) mRootChildren = new nsHashtable(4); // Clone the key ourselves by allocating it from the shell's arena. nsShellISupportsKey* clonedKey = new (mPresContext) nsShellISupportsKey(aRule); mRootChildren->Put(clonedKey, next); } } else { if (mChildren) { nsRuleList* curr = mChildren; for ( ; curr && curr->mRuleNode->mRule != aRule; curr = curr->mNext); if (curr) next = curr->mRuleNode; } if (!next) { // Create the new entry in our table. nsRuleNode* newNode = new (mPresContext) nsRuleNode(mPresContext, aRule, this); next = newNode; if (!mChildren) mChildren = new (mPresContext) nsRuleList(newNode); else mChildren = new (mPresContext) nsRuleList(newNode, mChildren); } } *aResult = next; return NS_OK; } nsresult nsRuleNode::PathContainsRule(nsIStyleRule* aRule, PRBool* aMatched) { *aMatched = PR_FALSE; nsRuleNode* ruleDest = this; while (ruleDest) { if (ruleDest->mRule == aRule) { *aMatched = PR_TRUE; break; } ruleDest = ruleDest->mParent; } return NS_OK; } nsresult nsRuleNode::ClearCachedData(nsIStyleRule* aRule) { nsRuleNode* ruleDest = this; while (ruleDest) { if (ruleDest->mRule == aRule) break; ruleDest = ruleDest->mParent; } if (ruleDest) { // The rule was contained along our branch. We need to blow away // all cached data along this path. Note that, because of the definition // of inline style, all nodes along this path must have exactly one child. This // is not a bushy subtree, and so we know that by clearing this path, we've // invalidated everything that we need to. nsRuleNode* curr = this; while (curr) { curr->mNoneBits &= ~NS_STYLE_INHERIT_MASK; curr->mInheritBits &= ~NS_STYLE_INHERIT_MASK; if (curr->mStyleData.mResetData || curr->mStyleData.mInheritedData) curr->mStyleData.Destroy(0, mPresContext); if (curr == ruleDest) break; curr = curr->mParent; } } return NS_OK; } PRBool PR_CALLBACK ClearCachedDataInSubtreeHelper(nsHashKey* aKey, void* aData, void* aClosure) { nsRuleNode* ruleNode = (nsRuleNode*)aData; nsIStyleRule* rule = (nsIStyleRule*)aClosure; ruleNode->ClearCachedDataInSubtree(rule); return PR_TRUE; } nsresult nsRuleNode::ClearCachedDataInSubtree(nsIStyleRule* aRule) { if (aRule == nsnull || mRule == aRule) { // We have a match. Blow away all data stored at this node. if (mStyleData.mResetData || mStyleData.mInheritedData) mStyleData.Destroy(0, mPresContext); mNoneBits &= ~NS_STYLE_INHERIT_MASK; mInheritBits &= ~NS_STYLE_INHERIT_MASK; aRule = nsnull; } if (!mParent) { if (mRootChildren) mRootChildren->Enumerate(ClearCachedDataInSubtreeHelper, (void*)aRule); } else for (nsRuleList* curr = mChildren; curr; curr = curr->mNext) curr->mRuleNode->ClearCachedDataInSubtree(curr->mRuleNode->mRule); return NS_OK; } nsresult nsRuleNode::GetPresContext(nsIPresContext** aResult) { *aResult = mPresContext; NS_IF_ADDREF(*aResult); return NS_OK; } inline void nsRuleNode::PropagateNoneBit(PRUint32 aBit, nsRuleNode* aHighestNode) { nsRuleNode* curr = this; while (curr != aHighestNode) { NS_ASSERTION(!(curr->mNoneBits & aBit), "propagating too far"); curr->mNoneBits |= aBit; curr = curr->mParent; } } inline void nsRuleNode::PropagateInheritBit(PRUint32 aBit, nsRuleNode* aHighestNode) { if (mInheritBits & aBit) return; // Already set. nsRuleNode* curr = this; while (curr != aHighestNode) { if (curr->mInheritBits & aBit) { #ifdef DEBUG while (curr != aHighestNode) { NS_ASSERTION(curr->mInheritBits & aBit, "bit not set"); curr = curr->mParent; } #endif break; } curr->mInheritBits |= aBit; curr = curr->mParent; } } inline PRBool nsRuleNode::InheritsFromParentRule(const nsStyleStructID aSID) { return mInheritBits & nsCachedStyleData::GetBitForSID(aSID); } /* * The following "Check" functions are used for determining what type of * sharing can be used for the data on this rule node. MORE HERE... */ /* the information for a property (or in some cases, a rect group of properties) */ // for PropertyCheckData::type // XXX Would bits be more efficient? #define CHECKDATA_VALUE 0 #define CHECKDATA_RECT 1 #define CHECKDATA_VALUELIST 2 #define CHECKDATA_COUNTERDATA 3 #define CHECKDATA_QUOTES 4 #define CHECKDATA_SHADOW 5 #define CHECKDATA_VALUELIST_ARRAY 6 struct PropertyCheckData { size_t offset; PRUint16 type; PRPackedBool mayHaveExplicitInherit; }; #define CHECKDATA_PROP(_datastruct, _member, _type, _iscoord) \ { offsetof(_datastruct, _member), _type, _iscoord } /* the information for all the properties in a style struct */ typedef nsRuleNode::RuleDetail (* PR_CALLBACK CheckCallbackFn)(const nsCSSStruct& aData); struct StructCheckData { const PropertyCheckData* props; PRInt32 nprops; CheckCallbackFn callback; }; #define CHECKDATA_STRUCT(_props) \ {_props, sizeof(_props)/sizeof(PropertyCheckData), nsnull} #define CHECKDATA_STRUCT_WITH_CALLBACK(_props, _cb) \ {_props, sizeof(_props)/sizeof(PropertyCheckData), _cb} static void ExamineRectProperties(const nsCSSRect* aRect, PRUint32& aSpecifiedCount, PRUint32& aInheritedCount) { if (!aRect) return; if (eCSSUnit_Null != aRect->mLeft.GetUnit()) { aSpecifiedCount++; if (eCSSUnit_Inherit == aRect->mLeft.GetUnit()) aInheritedCount++; } if (eCSSUnit_Null != aRect->mTop.GetUnit()) { aSpecifiedCount++; if (eCSSUnit_Inherit == aRect->mTop.GetUnit()) aInheritedCount++; } if (eCSSUnit_Null != aRect->mRight.GetUnit()) { aSpecifiedCount++; if (eCSSUnit_Inherit == aRect->mRight.GetUnit()) aInheritedCount++; } if (eCSSUnit_Null != aRect->mBottom.GetUnit()) { aSpecifiedCount++; if (eCSSUnit_Inherit == aRect->mBottom.GetUnit()) aInheritedCount++; } } static void ExamineRectCoordProperties(const nsCSSRect* aRect, PRUint32& aSpecifiedCount, PRUint32& aInheritedCount, PRBool& aCanHaveExplicitInherit) { if (!aRect) return; if (eCSSUnit_Null != aRect->mLeft.GetUnit()) { aSpecifiedCount++; if (eCSSUnit_Inherit == aRect->mLeft.GetUnit()) { aInheritedCount++; aCanHaveExplicitInherit = PR_TRUE; } } if (eCSSUnit_Null != aRect->mTop.GetUnit()) { aSpecifiedCount++; if (eCSSUnit_Inherit == aRect->mTop.GetUnit()) { aInheritedCount++; aCanHaveExplicitInherit = PR_TRUE; } } if (eCSSUnit_Null != aRect->mRight.GetUnit()) { aSpecifiedCount++; if (eCSSUnit_Inherit == aRect->mRight.GetUnit()) { aInheritedCount++; aCanHaveExplicitInherit = PR_TRUE; } } if (eCSSUnit_Null != aRect->mBottom.GetUnit()) { aSpecifiedCount++; if (eCSSUnit_Inherit == aRect->mBottom.GetUnit()) { aInheritedCount++; aCanHaveExplicitInherit = PR_TRUE; } } } PR_STATIC_CALLBACK(nsRuleNode::RuleDetail) CheckFontCallback(const nsCSSStruct& aData) { const nsCSSFont& fontData = NS_STATIC_CAST(const nsCSSFont&, aData); if (eCSSUnit_Enumerated == fontData.mFamily.GetUnit()) { // A special case. We treat this as a fully specified font, // since no other font props are legal with a system font. PRInt32 family = fontData.mFamily.GetIntValue(); if ((family == NS_STYLE_FONT_CAPTION) || (family == NS_STYLE_FONT_ICON) || (family == NS_STYLE_FONT_MENU) || (family == NS_STYLE_FONT_MESSAGE_BOX) || (family == NS_STYLE_FONT_SMALL_CAPTION) || (family == NS_STYLE_FONT_STATUS_BAR) || (family == NS_STYLE_FONT_WINDOW) || (family == NS_STYLE_FONT_DOCUMENT) || (family == NS_STYLE_FONT_WORKSPACE) || (family == NS_STYLE_FONT_DESKTOP) || (family == NS_STYLE_FONT_INFO) || (family == NS_STYLE_FONT_DIALOG) || (family == NS_STYLE_FONT_BUTTON) || (family == NS_STYLE_FONT_PULL_DOWN_MENU) || (family == NS_STYLE_FONT_LIST) || (family == NS_STYLE_FONT_FIELD) || (family == NS_STYLE_FONT_THEME)) return nsRuleNode::eRuleFullMixed; } return nsRuleNode::eRuleUnknown; } static const PropertyCheckData FontCheckProperties[] = { CHECKDATA_PROP(nsCSSFont, mFamily, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSFont, mStyle, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSFont, mVariant, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSFont, mWeight, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSFont, mSize, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSFont, mSizeAdjust, CHECKDATA_VALUE, PR_FALSE) }; static const PropertyCheckData DisplayCheckProperties[] = { CHECKDATA_PROP(nsCSSDisplay, mAppearance, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSDisplay, mClip, CHECKDATA_RECT, PR_FALSE), CHECKDATA_PROP(nsCSSDisplay, mDisplay, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSDisplay, mBinding, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSDisplay, mPosition, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSDisplay, mFloat, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSDisplay, mClear, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSDisplay, mOverflow, CHECKDATA_VALUE, PR_FALSE) }; static const PropertyCheckData VisibilityCheckProperties[] = { CHECKDATA_PROP(nsCSSDisplay, mVisibility, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSDisplay, mDirection, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSDisplay, mLang, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSDisplay, mOpacity, CHECKDATA_VALUE, PR_FALSE) }; static const PropertyCheckData MarginCheckProperties[] = { CHECKDATA_PROP(nsCSSMargin, mMargin, CHECKDATA_RECT, PR_TRUE) }; static const PropertyCheckData BorderCheckProperties[] = { CHECKDATA_PROP(nsCSSMargin, mBorderWidth, CHECKDATA_RECT, PR_FALSE), CHECKDATA_PROP(nsCSSMargin, mBorderStyle, CHECKDATA_RECT, PR_FALSE), CHECKDATA_PROP(nsCSSMargin, mBorderColor, CHECKDATA_RECT, PR_FALSE), CHECKDATA_PROP(nsCSSMargin, mBorderRadius, CHECKDATA_RECT, PR_TRUE), CHECKDATA_PROP(nsCSSMargin, mFloatEdge, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSMargin, mBorderColors, CHECKDATA_VALUELIST_ARRAY, PR_FALSE) }; static const PropertyCheckData PaddingCheckProperties[] = { CHECKDATA_PROP(nsCSSMargin, mPadding, CHECKDATA_RECT, PR_TRUE) }; static const PropertyCheckData OutlineCheckProperties[] = { CHECKDATA_PROP(nsCSSMargin, mOutlineColor, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSMargin, mOutlineWidth, CHECKDATA_VALUE, PR_TRUE), CHECKDATA_PROP(nsCSSMargin, mOutlineStyle, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSMargin, mOutlineRadius, CHECKDATA_RECT, PR_TRUE) }; static const PropertyCheckData ListCheckProperties[] = { CHECKDATA_PROP(nsCSSList, mType, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSList, mImage, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSList, mPosition, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSList, mImageRegion, CHECKDATA_RECT, PR_TRUE) }; static const PropertyCheckData ColorCheckProperties[] = { CHECKDATA_PROP(nsCSSColor, mColor, CHECKDATA_VALUE, PR_FALSE) }; static const PropertyCheckData BackgroundCheckProperties[] = { CHECKDATA_PROP(nsCSSColor, mBackAttachment, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSColor, mBackRepeat, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSColor, mBackColor, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSColor, mBackImage, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSColor, mBackPositionX, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSColor, mBackPositionY, CHECKDATA_VALUE, PR_FALSE) }; static const PropertyCheckData PositionCheckProperties[] = { CHECKDATA_PROP(nsCSSPosition, mOffset, CHECKDATA_RECT, PR_TRUE), CHECKDATA_PROP(nsCSSPosition, mWidth, CHECKDATA_VALUE, PR_TRUE), CHECKDATA_PROP(nsCSSPosition, mMinWidth, CHECKDATA_VALUE, PR_TRUE), CHECKDATA_PROP(nsCSSPosition, mMaxWidth, CHECKDATA_VALUE, PR_TRUE), CHECKDATA_PROP(nsCSSPosition, mHeight, CHECKDATA_VALUE, PR_TRUE), CHECKDATA_PROP(nsCSSPosition, mMinHeight, CHECKDATA_VALUE, PR_TRUE), CHECKDATA_PROP(nsCSSPosition, mMaxHeight, CHECKDATA_VALUE, PR_TRUE), CHECKDATA_PROP(nsCSSPosition, mBoxSizing, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSPosition, mZIndex, CHECKDATA_VALUE, PR_FALSE) }; static const PropertyCheckData TableCheckProperties[] = { CHECKDATA_PROP(nsCSSTable, mLayout, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSTable, mFrame, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSTable, mRules, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSTable, mCols, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSTable, mSpan, CHECKDATA_VALUE, PR_FALSE) }; static const PropertyCheckData TableBorderCheckProperties[] = { CHECKDATA_PROP(nsCSSTable, mBorderCollapse, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSTable, mBorderSpacingX, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSTable, mBorderSpacingY, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSTable, mCaptionSide, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSTable, mEmptyCells, CHECKDATA_VALUE, PR_FALSE) }; static const PropertyCheckData ContentCheckProperties[] = { CHECKDATA_PROP(nsCSSContent, mContent, CHECKDATA_VALUELIST, PR_FALSE), CHECKDATA_PROP(nsCSSContent, mMarkerOffset, CHECKDATA_VALUE, PR_TRUE), CHECKDATA_PROP(nsCSSContent, mCounterIncrement, CHECKDATA_COUNTERDATA, PR_FALSE), CHECKDATA_PROP(nsCSSContent, mCounterReset, CHECKDATA_COUNTERDATA, PR_FALSE) }; static const PropertyCheckData QuotesCheckProperties[] = { CHECKDATA_PROP(nsCSSContent, mQuotes, CHECKDATA_QUOTES, PR_FALSE) }; static const PropertyCheckData TextCheckProperties[] = { CHECKDATA_PROP(nsCSSText, mLineHeight, CHECKDATA_VALUE, PR_TRUE), CHECKDATA_PROP(nsCSSText, mTextIndent, CHECKDATA_VALUE, PR_TRUE), CHECKDATA_PROP(nsCSSText, mWordSpacing, CHECKDATA_VALUE, PR_TRUE), CHECKDATA_PROP(nsCSSText, mLetterSpacing, CHECKDATA_VALUE, PR_TRUE), CHECKDATA_PROP(nsCSSText, mTextAlign, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSText, mTextTransform, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSText, mWhiteSpace, CHECKDATA_VALUE, PR_FALSE) }; static const PropertyCheckData TextResetCheckProperties[] = { CHECKDATA_PROP(nsCSSText, mDecoration, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSText, mVerticalAlign, CHECKDATA_VALUE, PR_TRUE), CHECKDATA_PROP(nsCSSText, mUnicodeBidi, CHECKDATA_VALUE, PR_FALSE) }; static const PropertyCheckData UserInterfaceCheckProperties[] = { CHECKDATA_PROP(nsCSSUserInterface, mUserInput, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSUserInterface, mUserModify, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSUserInterface, mUserFocus, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSUserInterface, mCursor, CHECKDATA_VALUELIST, PR_FALSE) }; static const PropertyCheckData UIResetCheckProperties[] = { CHECKDATA_PROP(nsCSSUserInterface, mUserSelect, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSUserInterface, mResizer, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSUserInterface, mKeyEquivalent, CHECKDATA_VALUELIST, PR_FALSE) }; #ifdef INCLUDE_XUL static const PropertyCheckData XULCheckProperties[] = { CHECKDATA_PROP(nsCSSXUL, mBoxAlign, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSXUL, mBoxDirection, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSXUL, mBoxFlex, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSXUL, mBoxOrient, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSXUL, mBoxPack, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSXUL, mBoxOrdinal, CHECKDATA_VALUE, PR_FALSE) }; #endif #ifdef MOZ_SVG static const PropertyCheckData SVGCheckProperties[] = { CHECKDATA_PROP(nsCSSSVG, mFill, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSSVG, mFillOpacity, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSSVG, mFillRule, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSSVG, mStroke, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSSVG, mStrokeDasharray, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSSVG, mStrokeDashoffset, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSSVG, mStrokeLinecap, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSSVG, mStrokeLinejoin, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSSVG, mStrokeMiterlimit, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSSVG, mStrokeOpacity, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSSVG, mStrokeWidth, CHECKDATA_VALUE, PR_FALSE) }; #endif // These are indexed by style struct ID and must stay in order! static const StructCheckData gCheckProperties[] = { { nsnull, 0, nsnull}, /* empty, since no 0th SID */ CHECKDATA_STRUCT_WITH_CALLBACK(FontCheckProperties, CheckFontCallback), CHECKDATA_STRUCT(ColorCheckProperties), CHECKDATA_STRUCT(BackgroundCheckProperties), CHECKDATA_STRUCT(ListCheckProperties), CHECKDATA_STRUCT(PositionCheckProperties), CHECKDATA_STRUCT(TextCheckProperties), CHECKDATA_STRUCT(TextResetCheckProperties), CHECKDATA_STRUCT(DisplayCheckProperties), CHECKDATA_STRUCT(VisibilityCheckProperties), CHECKDATA_STRUCT(ContentCheckProperties), CHECKDATA_STRUCT(QuotesCheckProperties), CHECKDATA_STRUCT(UserInterfaceCheckProperties), CHECKDATA_STRUCT(UIResetCheckProperties), CHECKDATA_STRUCT(TableCheckProperties), CHECKDATA_STRUCT(TableBorderCheckProperties), CHECKDATA_STRUCT(MarginCheckProperties), CHECKDATA_STRUCT(PaddingCheckProperties), CHECKDATA_STRUCT(BorderCheckProperties), CHECKDATA_STRUCT(OutlineCheckProperties), #ifdef INCLUDE_XUL CHECKDATA_STRUCT(XULCheckProperties), #endif #ifdef MOZ_SVG CHECKDATA_STRUCT(SVGCheckProperties), #endif { nsnull, 0, nsnull} /* empty, so at least we crash reliably if someone passes in the BorderPaddingShortcut ID */ }; // XXXldb Taking the address of a reference is evil. inline const nsCSSValue& ValueAtOffset(const nsCSSStruct& aCSSStruct, size_t aOffset) { return * NS_REINTERPRET_CAST(const nsCSSValue*, NS_REINTERPRET_CAST(const char*, &aCSSStruct) + aOffset); } inline const nsCSSRect* RectAtOffset(const nsCSSStruct& aCSSStruct, size_t aOffset) { return * NS_REINTERPRET_CAST(const nsCSSRect*const*, NS_REINTERPRET_CAST(const char*, &aCSSStruct) + aOffset); } inline const nsCSSValueList* ValueListAtOffset(const nsCSSStruct& aCSSStruct, size_t aOffset) { return * NS_REINTERPRET_CAST(const nsCSSValueList*const*, NS_REINTERPRET_CAST(const char*, &aCSSStruct) + aOffset); } inline const nsCSSValueList** ValueListArrayAtOffset(const nsCSSStruct& aCSSStruct, size_t aOffset) { return * NS_REINTERPRET_CAST(const nsCSSValueList**const*, NS_REINTERPRET_CAST(const char*, &aCSSStruct) + aOffset); } inline const nsCSSCounterData* CounterDataAtOffset(const nsCSSStruct& aCSSStruct, size_t aOffset) { return * NS_REINTERPRET_CAST(const nsCSSCounterData*const*, NS_REINTERPRET_CAST(const char*, &aCSSStruct) + aOffset); } inline const nsCSSQuotes* QuotesAtOffset(const nsCSSStruct& aCSSStruct, size_t aOffset) { return * NS_REINTERPRET_CAST(const nsCSSQuotes*const*, NS_REINTERPRET_CAST(const char*, &aCSSStruct) + aOffset); } inline nsRuleNode::RuleDetail nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID, const nsCSSStruct& aCSSStruct) { const StructCheckData *structData = gCheckProperties + aSID; if (structData->callback) { nsRuleNode::RuleDetail res = (*structData->callback)(aCSSStruct); if (res != eRuleUnknown) return res; } // Build a count of the: PRUint32 total = 0, // total number of props in the struct specified = 0, // number that were specified for this node inherited = 0; // number that were 'inherit' (and not // eCSSUnit_Inherit) for this node PRBool canHaveExplicitInherit = PR_FALSE; for (const PropertyCheckData *prop = structData->props, *prop_end = prop + structData->nprops; prop != prop_end; ++prop) switch (prop->type) { case CHECKDATA_VALUE: { ++total; const nsCSSValue& value = ValueAtOffset(aCSSStruct, prop->offset); if (eCSSUnit_Null != value.GetUnit()) { ++specified; if (eCSSUnit_Inherit == value.GetUnit()) { ++inherited; if (prop->mayHaveExplicitInherit) canHaveExplicitInherit = PR_TRUE; } } } break; case CHECKDATA_RECT: total += 4; if (prop->mayHaveExplicitInherit) ExamineRectCoordProperties(RectAtOffset(aCSSStruct, prop->offset), specified, inherited, canHaveExplicitInherit); else ExamineRectProperties(RectAtOffset(aCSSStruct, prop->offset), specified, inherited); break; case CHECKDATA_VALUELIST: { ++total; const nsCSSValueList* valueList = ValueListAtOffset(aCSSStruct, prop->offset); if (valueList) { ++specified; if (eCSSUnit_Inherit == valueList->mValue.GetUnit()) { ++inherited; if (prop->mayHaveExplicitInherit) canHaveExplicitInherit = PR_TRUE; } } } break; case CHECKDATA_COUNTERDATA: { ++total; NS_ASSERTION(!prop->mayHaveExplicitInherit, "counters can't be coordinates"); const nsCSSCounterData* counterData = CounterDataAtOffset(aCSSStruct, prop->offset); if (counterData) { ++specified; if (eCSSUnit_Inherit == counterData->mCounter.GetUnit()) { ++inherited; } } } break; case CHECKDATA_QUOTES: { ++total; NS_ASSERTION(!prop->mayHaveExplicitInherit, "quotes can't be coordinates"); const nsCSSQuotes* quotes = QuotesAtOffset(aCSSStruct, prop->offset); if (quotes) { ++specified; if (eCSSUnit_Inherit == quotes->mOpen.GetUnit()) { ++inherited; } } } break; case CHECKDATA_VALUELIST_ARRAY: { total += 4; const nsCSSValueList** valueArray = ValueListArrayAtOffset(aCSSStruct, prop->offset); if (valueArray) { for (PRInt32 i = 0; i < 4; i++) { const nsCSSValueList* valList = valueArray[i]; if (valList) { ++specified; if (eCSSUnit_Inherit == valList->mValue.GetUnit()) { ++inherited; NS_ASSERTION(!prop->mayHaveExplicitInherit, "Value list arrays can't inherit!"); } } } } } break; case CHECKDATA_SHADOW: NS_NOTYETIMPLEMENTED("nsCSSShadow not yet transferred to structs"); break; default: NS_NOTREACHED("unknown type"); break; } #if 0 printf("CheckSpecifiedProperties: SID=%d total=%d spec=%d inh=%d chei=%s.\n", aSID, total, specified, inherited, canHaveExplicitInherit?"true":"false"); #endif if (canHaveExplicitInherit) { if (specified == total) return eRuleFullMixed; return eRulePartialMixed; } if (inherited == total) return eRuleFullInherited; if (specified == total) return eRuleFullMixed; if (specified == 0) return eRuleNone; if (specified == inherited) return eRulePartialInherited; return eRulePartialMixed; } const nsStyleStruct* nsRuleNode::GetDisplayData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSDisplay displayData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Display, mPresContext, aContext); ruleData.mDisplayData = &displayData; nsCSSRect clip; displayData.mClip = &clip; const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Display, aContext, &ruleData, &displayData, aComputeData); displayData.mClip = nsnull; return res; } const nsStyleStruct* nsRuleNode::GetVisibilityData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSDisplay displayData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Visibility, mPresContext, aContext); ruleData.mDisplayData = &displayData; return WalkRuleTree(eStyleStruct_Visibility, aContext, &ruleData, &displayData, aComputeData); } const nsStyleStruct* nsRuleNode::GetTextData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSText textData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Text, mPresContext, aContext); ruleData.mTextData = &textData; return WalkRuleTree(eStyleStruct_Text, aContext, &ruleData, &textData, aComputeData); } const nsStyleStruct* nsRuleNode::GetTextResetData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSText textData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_TextReset, mPresContext, aContext); ruleData.mTextData = &textData; return WalkRuleTree(eStyleStruct_TextReset, aContext, &ruleData, &textData, aComputeData); } const nsStyleStruct* nsRuleNode::GetUIData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSUserInterface uiData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_UserInterface, mPresContext, aContext); ruleData.mUIData = &uiData; const nsStyleStruct* res = WalkRuleTree(eStyleStruct_UserInterface, aContext, &ruleData, &uiData, aComputeData); uiData.mCursor = nsnull; return res; } const nsStyleStruct* nsRuleNode::GetUIResetData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSUserInterface uiData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_UIReset, mPresContext, aContext); ruleData.mUIData = &uiData; const nsStyleStruct* res = WalkRuleTree(eStyleStruct_UIReset, aContext, &ruleData, &uiData, aComputeData); uiData.mKeyEquivalent = nsnull; return res; } const nsStyleStruct* nsRuleNode::GetFontData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSFont fontData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Font, mPresContext, aContext); ruleData.mFontData = &fontData; return WalkRuleTree(eStyleStruct_Font, aContext, &ruleData, &fontData, aComputeData); } const nsStyleStruct* nsRuleNode::GetColorData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSColor colorData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Color, mPresContext, aContext); ruleData.mColorData = &colorData; return WalkRuleTree(eStyleStruct_Color, aContext, &ruleData, &colorData, aComputeData); } const nsStyleStruct* nsRuleNode::GetBackgroundData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSColor colorData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Background, mPresContext, aContext); ruleData.mColorData = &colorData; return WalkRuleTree(eStyleStruct_Background, aContext, &ruleData, &colorData, aComputeData); } const nsStyleStruct* nsRuleNode::GetMarginData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Margin, mPresContext, aContext); ruleData.mMarginData = &marginData; nsCSSRect margin; marginData.mMargin = &margin; const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Margin, aContext, &ruleData, &marginData, aComputeData); marginData.mMargin = nsnull; return res; } const nsStyleStruct* nsRuleNode::GetBorderData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Border, mPresContext, aContext); ruleData.mMarginData = &marginData; nsCSSRect borderWidth; nsCSSRect borderColor; nsCSSRect borderStyle; nsCSSRect borderRadius; nsCSSValueList* borderColors[4]; for (PRInt32 i = 0; i < 4; i++) borderColors[i] = nsnull; marginData.mBorderWidth = &borderWidth; marginData.mBorderColor = &borderColor; marginData.mBorderStyle = &borderStyle; marginData.mBorderRadius = &borderRadius; marginData.mBorderColors = borderColors; const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Border, aContext, &ruleData, &marginData, aComputeData); marginData.mBorderWidth = marginData.mBorderColor = marginData.mBorderStyle = marginData.mBorderRadius = nsnull; marginData.mBorderColors = nsnull; return res; } const nsStyleStruct* nsRuleNode::GetPaddingData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Padding, mPresContext, aContext); ruleData.mMarginData = &marginData; nsCSSRect padding; marginData.mPadding = &padding; const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Padding, aContext, &ruleData, &marginData, aComputeData); marginData.mPadding = nsnull; return res; } const nsStyleStruct* nsRuleNode::GetOutlineData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Outline, mPresContext, aContext); ruleData.mMarginData = &marginData; nsCSSRect outlineRadius; marginData.mOutlineRadius = &outlineRadius; const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Outline, aContext, &ruleData, &marginData, aComputeData); marginData.mOutlineRadius = nsnull; return res; } const nsStyleStruct* nsRuleNode::GetListData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSList listData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_List, mPresContext, aContext); ruleData.mListData = &listData; nsCSSRect imageRegion; listData.mImageRegion = &imageRegion; const nsStyleStruct* res = WalkRuleTree(eStyleStruct_List, aContext, &ruleData, &listData, aComputeData); listData.mImageRegion = nsnull; return res; } const nsStyleStruct* nsRuleNode::GetPositionData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSPosition posData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Position, mPresContext, aContext); ruleData.mPositionData = &posData; nsCSSRect offset; posData.mOffset = &offset; const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Position, aContext, &ruleData, &posData, aComputeData); posData.mOffset = nsnull; return res; } const nsStyleStruct* nsRuleNode::GetTableData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSTable tableData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Table, mPresContext, aContext); ruleData.mTableData = &tableData; return WalkRuleTree(eStyleStruct_Table, aContext, &ruleData, &tableData, aComputeData); } const nsStyleStruct* nsRuleNode::GetTableBorderData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSTable tableData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_TableBorder, mPresContext, aContext); ruleData.mTableData = &tableData; return WalkRuleTree(eStyleStruct_TableBorder, aContext, &ruleData, &tableData, aComputeData); } const nsStyleStruct* nsRuleNode::GetContentData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSContent contentData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Content, mPresContext, aContext); ruleData.mContentData = &contentData; const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Content, aContext, &ruleData, &contentData, aComputeData); contentData.mCounterIncrement = contentData.mCounterReset = nsnull; contentData.mContent = nsnull; // We are sharing with some style rule. It really owns the data. return res; } const nsStyleStruct* nsRuleNode::GetQuotesData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSContent contentData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Quotes, mPresContext, aContext); ruleData.mContentData = &contentData; const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Quotes, aContext, &ruleData, &contentData, aComputeData); contentData.mQuotes = nsnull; // We are sharing with some style rule. It really owns the data. return res; } #ifdef INCLUDE_XUL const nsStyleStruct* nsRuleNode::GetXULData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSXUL xulData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_XUL, mPresContext, aContext); ruleData.mXULData = &xulData; return WalkRuleTree(eStyleStruct_XUL, aContext, &ruleData, &xulData, aComputeData); } #endif #ifdef MOZ_SVG const nsStyleStruct* nsRuleNode::GetSVGData(nsIStyleContext* aContext, PRBool aComputeData) { nsCSSSVG svgData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_SVG, mPresContext, aContext); ruleData.mSVGData = &svgData; return WalkRuleTree(eStyleStruct_SVG, aContext, &ruleData, &svgData, aComputeData); } #endif const nsStyleStruct* nsRuleNode::WalkRuleTree(const nsStyleStructID aSID, nsIStyleContext* aContext, nsRuleData* aRuleData, nsCSSStruct* aSpecificData, PRBool aComputeData) { // We start at the most specific rule in the tree. nsStyleStruct* startStruct = nsnull; nsRuleNode* ruleNode = this; nsRuleNode* highestNode = nsnull; // The highest node in the rule tree // that has the same properties // specified for struct |aSID| as // |this| does. nsRuleNode* rootNode = this; // After the loop below, this will be the // highest node that we've walked without // finding cached data on the rule tree. // If we don't find any cached data, it // will be the root. (XXX misnamed) RuleDetail detail = eRuleNone; PRUint32 bit = nsCachedStyleData::GetBitForSID(aSID); while (ruleNode) { // See if this rule node has cached the fact that the remaining // nodes along this path specify no data whatsoever. if (ruleNode->mNoneBits & bit) break; // If the inherit bit is set on a rule node for this struct, that // means its rule won't have any information to add, so skip it. // XXXldb I don't understand why we need to check |detail| here, but // we do. if (detail == eRuleNone) while (ruleNode->mInheritBits & bit) { NS_ASSERTION(ruleNode->mStyleData.GetStyleData(aSID) == nsnull, "inherit bit with cached data makes no sense"); // Climb up to the next rule in the tree (a less specific rule). rootNode = ruleNode; ruleNode = ruleNode->mParent; NS_ASSERTION(!(ruleNode->mNoneBits & bit), "can't have both bits set"); } // Check for cached data after the inner loop above -- otherwise // we'll miss it. startStruct = ruleNode->mStyleData.GetStyleData(aSID); if (startStruct) break; // We found a rule with fully specified data. We don't // need to go up the tree any further, since the remainder // of this branch has already been computed. // Ask the rule to fill in the properties that it specifies. nsIStyleRule *rule = ruleNode->mRule; if (rule) rule->MapRuleInfoInto(aRuleData); // Now we check to see how many properties have been specified by // the rules we've examined so far. RuleDetail oldDetail = detail; detail = CheckSpecifiedProperties(aSID, *aSpecificData); if (oldDetail == eRuleNone && detail != eRuleNone) highestNode = ruleNode; if (detail == eRuleFullMixed || detail == eRuleFullInherited) break; // We don't need to examine any more rules. All properties // have been fully specified. // Climb up to the next rule in the tree (a less specific rule). rootNode = ruleNode; ruleNode = ruleNode->mParent; } PRBool isReset = nsCachedStyleData::IsReset(aSID); if (!highestNode) highestNode = rootNode; if (!aRuleData->mCanStoreInRuleTree) detail = eRulePartialMixed; // Treat as though some data is specified to avoid // the optimizations and force data computation. if (detail == eRuleNone && startStruct && !aRuleData->mPostResolveCallback) { // We specified absolutely no rule information, but a parent rule in the tree // specified all the rule information. We set a bit along the branch from our // node in the tree to the node that specified the data that tells nodes on that // branch that they never need to examine their rules for this particular struct type // ever again. PropagateInheritBit(bit, ruleNode); if (eStyleStruct_Background == aSID && aRuleData->mPostResolveCallback) (*aRuleData->mPostResolveCallback) ((nsStyleStruct *)startStruct, aRuleData); return startStruct; } else if (!startStruct && ((!isReset && (detail == eRuleNone || detail == eRulePartialInherited)) || detail == eRuleFullInherited)) { // We specified no non-inherited information and neither did any of // our parent rules. // We set a bit along the branch from the highest node (ruleNode) // down to our node (this) indicating that no non-inherited data was // specified. This bit is guaranteed to be set already on the path // from the highest node to the root node. (We can only set this // bit if detail == eRuleNone because an explicit inherit value // could override a non-inherited value higher in the rule tree.) // XXXldb But doesn't that mean we could propagate to |highestNode| // (and along with that, break the invariant that the none bit always // goes all the way to the top)? if (detail == eRuleNone) PropagateNoneBit(bit, ruleNode); // All information must necessarily be inherited from our parent style context. // In the absence of any computed data in the rule tree and with // no rules specified that didn't have values of 'inherit', we should check our parent. nsCOMPtr parentContext = dont_AddRef(aContext->GetParent()); if (parentContext) { // We have a parent, and so we should just inherit from the parent. // Set the inherit bits on our context. These bits tell the style context that // it never has to go back to the rule tree for data. Instead the style context tree // should be walked to find the data. const nsStyleStruct* parentStruct = parentContext->GetStyleData(aSID); aContext->AddStyleBit(bit); aContext->SetStyle(aSID, *parentStruct); return parentStruct; } else // We are the root. In the case of fonts, the default values just // come from the pres context. return SetDefaultOnRoot(aSID, aContext); } // We need to compute the data from the information that the rules specified. if (!aComputeData) return nsnull; ComputeStyleDataFn fn = gComputeStyleDataFn[aSID]; const nsStyleStruct* res = (this->*fn)(startStruct, *aSpecificData, aContext, highestNode, detail, !aRuleData->mCanStoreInRuleTree); // If we have a post-resolve callback, handle that now. if (aRuleData->mPostResolveCallback) (*aRuleData->mPostResolveCallback)((nsStyleStruct*)res, aRuleData); // Now return the result. return res; } const nsStyleStruct* nsRuleNode::SetDefaultOnRoot(const nsStyleStructID aSID, nsIStyleContext* aContext) { switch (aSID) { case eStyleStruct_Font: { const nsFont* defaultFont; mPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID, &defaultFont); nsStyleFont* fontData = new (mPresContext) nsStyleFont(*defaultFont); aContext->SetStyle(eStyleStruct_Font, *fontData); return fontData; } case eStyleStruct_Display: { nsStyleDisplay* disp = new (mPresContext) nsStyleDisplay(); aContext->SetStyle(eStyleStruct_Display, *disp); return disp; } case eStyleStruct_Visibility: { nsStyleVisibility* vis = new (mPresContext) nsStyleVisibility(mPresContext); aContext->SetStyle(eStyleStruct_Visibility, *vis); return vis; } case eStyleStruct_Text: { nsStyleText* text = new (mPresContext) nsStyleText(); aContext->SetStyle(eStyleStruct_Text, *text); return text; } case eStyleStruct_TextReset: { nsStyleTextReset* text = new (mPresContext) nsStyleTextReset(); aContext->SetStyle(eStyleStruct_TextReset, *text); return text; } case eStyleStruct_Color: { nsStyleColor* color = new (mPresContext) nsStyleColor(mPresContext); aContext->SetStyle(eStyleStruct_Color, *color); return color; } case eStyleStruct_Background: { nsStyleBackground* bg = new (mPresContext) nsStyleBackground(mPresContext); aContext->SetStyle(eStyleStruct_Background, *bg); return bg; } case eStyleStruct_Margin: { nsStyleMargin* margin = new (mPresContext) nsStyleMargin(); aContext->SetStyle(eStyleStruct_Margin, *margin); return margin; } case eStyleStruct_Border: { nsStyleBorder* border = new (mPresContext) nsStyleBorder(mPresContext); aContext->SetStyle(eStyleStruct_Border, *border); return border; } case eStyleStruct_Padding: { nsStylePadding* padding = new (mPresContext) nsStylePadding(); aContext->SetStyle(eStyleStruct_Padding, *padding); return padding; } case eStyleStruct_Outline: { nsStyleOutline* outline = new (mPresContext) nsStyleOutline(mPresContext); aContext->SetStyle(eStyleStruct_Outline, *outline); return outline; } case eStyleStruct_List: { nsStyleList* list = new (mPresContext) nsStyleList(); aContext->SetStyle(eStyleStruct_List, *list); return list; } case eStyleStruct_Position: { nsStylePosition* pos = new (mPresContext) nsStylePosition(); aContext->SetStyle(eStyleStruct_Position, *pos); return pos; } case eStyleStruct_Table: { nsStyleTable* table = new (mPresContext) nsStyleTable(); aContext->SetStyle(eStyleStruct_Table, *table); return table; } case eStyleStruct_TableBorder: { nsStyleTableBorder* table = new (mPresContext) nsStyleTableBorder(mPresContext); aContext->SetStyle(eStyleStruct_TableBorder, *table); return table; } case eStyleStruct_Content: { nsStyleContent* content = new (mPresContext) nsStyleContent(); aContext->SetStyle(eStyleStruct_Content, *content); return content; } case eStyleStruct_Quotes: { nsStyleQuotes* quotes = new (mPresContext) nsStyleQuotes(); aContext->SetStyle(eStyleStruct_Quotes, *quotes); return quotes; } case eStyleStruct_UserInterface: { nsStyleUserInterface* ui = new (mPresContext) nsStyleUserInterface(); aContext->SetStyle(eStyleStruct_UserInterface, *ui); return ui; } case eStyleStruct_UIReset: { nsStyleUIReset* ui = new (mPresContext) nsStyleUIReset(); aContext->SetStyle(eStyleStruct_UIReset, *ui); return ui; } #ifdef INCLUDE_XUL case eStyleStruct_XUL: { nsStyleXUL* xul = new (mPresContext) nsStyleXUL(); aContext->SetStyle(eStyleStruct_XUL, *xul); return xul; } #endif #ifdef MOZ_SVG case eStyleStruct_SVG: { nsStyleSVG* svg = new (mPresContext) nsStyleSVG(); aContext->SetStyle(eStyleStruct_SVG, *svg); return svg; } #endif case eStyleStruct_BorderPaddingShortcut: NS_ERROR("unexpected SID"); } return nsnull; } nsRuleNode::ComputeStyleDataFn nsRuleNode::gComputeStyleDataFn[] = { // Note that these must line up _exactly_ with the numeric values of // the nsStyleStructID enum. nsnull, &nsRuleNode::ComputeFontData, &nsRuleNode::ComputeColorData, &nsRuleNode::ComputeBackgroundData, &nsRuleNode::ComputeListData, &nsRuleNode::ComputePositionData, &nsRuleNode::ComputeTextData, &nsRuleNode::ComputeTextResetData, &nsRuleNode::ComputeDisplayData, &nsRuleNode::ComputeVisibilityData, &nsRuleNode::ComputeContentData, &nsRuleNode::ComputeQuotesData, &nsRuleNode::ComputeUIData, &nsRuleNode::ComputeUIResetData, &nsRuleNode::ComputeTableData, &nsRuleNode::ComputeTableBorderData, &nsRuleNode::ComputeMarginData, &nsRuleNode::ComputePaddingData, &nsRuleNode::ComputeBorderData, &nsRuleNode::ComputeOutlineData, #ifdef INCLUDE_XUL &nsRuleNode::ComputeXULData, #endif #ifdef MOZ_SVG &nsRuleNode::ComputeSVGData, #endif nsnull }; static void SetFont(nsIPresContext* aPresContext, nsIStyleContext* aContext, nscoord aMinFontSize, PRBool aUseDocumentFonts, PRBool aChromeOverride, PRBool aIsGeneric, const nsCSSFont& aFontData, const nsFont& aDefaultFont, const nsStyleFont* aParentFont, nsStyleFont* aFont, PRBool& aInherited) { const nsFont* defaultVariableFont; const nsFont* defaultFixedFont; aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID, &defaultVariableFont); aPresContext->GetDefaultFont(kPresContext_DefaultFixedFont_ID, &defaultFixedFont); // font-family: string list, enum, inherit if (eCSSUnit_String == aFontData.mFamily.GetUnit()) { // set the correct font if we are using DocumentFonts OR we are overriding for XUL // MJA: bug 31816 if (aChromeOverride || aUseDocumentFonts) { if (!aIsGeneric) { // only bother appending fallback fonts if this isn't a fallback generic font itself aFont->mFont.name.Append((PRUnichar)','); aFont->mFont.name.Append(aDefaultFont.name); } } else { // now set to defaults aFont->mFont.name = aDefaultFont.name; } } else if (eCSSUnit_Enumerated == aFontData.mFamily.GetUnit()) { nsSystemFontID sysID; switch (aFontData.mFamily.GetIntValue()) { // If you add fonts to this list, you need to also patch the list // in CheckFontCallback (also in this file). case NS_STYLE_FONT_CAPTION: sysID = eSystemFont_Caption; break; // css2 case NS_STYLE_FONT_ICON: sysID = eSystemFont_Icon; break; case NS_STYLE_FONT_MENU: sysID = eSystemFont_Menu; break; case NS_STYLE_FONT_MESSAGE_BOX: sysID = eSystemFont_MessageBox; break; case NS_STYLE_FONT_SMALL_CAPTION: sysID = eSystemFont_SmallCaption; break; case NS_STYLE_FONT_STATUS_BAR: sysID = eSystemFont_StatusBar; break; case NS_STYLE_FONT_WINDOW: sysID = eSystemFont_Window; break; // css3 case NS_STYLE_FONT_DOCUMENT: sysID = eSystemFont_Document; break; case NS_STYLE_FONT_WORKSPACE: sysID = eSystemFont_Workspace; break; case NS_STYLE_FONT_DESKTOP: sysID = eSystemFont_Desktop; break; case NS_STYLE_FONT_INFO: sysID = eSystemFont_Info; break; case NS_STYLE_FONT_DIALOG: sysID = eSystemFont_Dialog; break; case NS_STYLE_FONT_BUTTON: sysID = eSystemFont_Button; break; case NS_STYLE_FONT_PULL_DOWN_MENU:sysID = eSystemFont_PullDownMenu; break; case NS_STYLE_FONT_LIST: sysID = eSystemFont_List; break; case NS_STYLE_FONT_FIELD: sysID = eSystemFont_Field; break; case NS_STYLE_FONT_THEME: sysID = eSystemFont_Theme; break; } nsCompatibility mode = eCompatibility_Standard; if (sysID == eSystemFont_Field || sysID == eSystemFont_List || sysID == eSystemFont_Button) { nsCOMPtr prefService(do_GetService(NS_PREF_CONTRACTID)); if (prefService) { PRBool useEitherMode; if (NS_SUCCEEDED(prefService->GetBoolPref("layout.forms.use_standard_or_quirks", &useEitherMode))) { if (useEitherMode) { aPresContext->GetCompatibilityMode(&mode); } } } } nsCOMPtr dc; aPresContext->GetDeviceContext(getter_AddRefs(dc)); if (dc) { // GetSystemFont sets the font face but not necessarily the size aFont->mFont.size = defaultVariableFont->size; if (NS_FAILED(dc->GetSystemFont(sysID, &aFont->mFont))) { aFont->mFont.name = defaultVariableFont->name; } aFont->mSize = aFont->mFont.size; // this becomes our cascading size } // NavQuirks uses sans-serif instead of whatever the native font is #ifdef XP_MAC if (eCompatibility_NavQuirks == mode) { switch (sysID) { case eSystemFont_Field: case eSystemFont_List: aFont->mFont.name.Assign(NS_LITERAL_STRING("monospace")); aFont->mSize = defaultFixedFont->size; break; case eSystemFont_Button: aFont->mFont.name.Assign(NS_LITERAL_STRING("serif")); aFont->mSize = defaultVariableFont->size; break; } } #endif #ifdef XP_PC // // As far as I can tell the system default fonts and sizes for // on MS-Windows for Buttons, Listboxes/Comboxes and Text Fields are // all pre-determined and cannot be changed by either the control panel // or programmtically. // switch (sysID) { // Fields (text fields) // // For NavQuirks: // We always use the monospace font and whatever // the "fixed" font size this that is set by the browser // // For Standard/Strict Mode: // We use whatever font is defined by the system. Which it appears // (and the assumption is) it is always a proportional font. Then we // always use 2 points smaller than what the browser has defined as // the default proportional font. case eSystemFont_Field: if (eCompatibility_NavQuirks == mode) { aFont->mFont.name.Assign(NS_LITERAL_STRING("monospace")); aFont->mSize = defaultFixedFont->size; } else { // Assumption: system defined font is proportional aFont->mSize = PR_MAX(defaultVariableFont->size - NSIntPointsToTwips(2), 0); } break; // // Button and Selects (listboxes/comboboxes) // // For NavQuirks: // We always use the sans-serif font and 2 point point sizes smaller // that whatever the "proportional" font size this that is set by the browser // // For Standard/Strict Mode: // We use whatever font is defined by the system. Which it appears // (and the assumption is) it is always a proportional font. Then we // always use 2 points smaller than what the browser has defined as // the default proportional font. case eSystemFont_Button: case eSystemFont_List: if (eCompatibility_NavQuirks == mode) { aFont->mFont.name.Assign(NS_LITERAL_STRING("sans-serif")); } // Assumption: system defined font is proportional aFont->mSize = PR_MAX(defaultVariableFont->size - NSIntPointsToTwips(2), 0); break; } #endif #ifdef XP_UNIX if (eCompatibility_NavQuirks == mode) { switch (sysID) { case eSystemFont_Field: aFont->mFont.name.Assign(NS_LITERAL_STRING("monospace")); aFont->mSize = defaultFixedFont->size; break; case eSystemFont_Button: case eSystemFont_List: aFont->mFont.name.Assign(NS_LITERAL_STRING("serif")); aFont->mSize = defaultVariableFont->size; break; default: NS_ERROR("unexpected SID"); } } #endif } else if (eCSSUnit_Inherit == aFontData.mFamily.GetUnit()) { aInherited = PR_TRUE; aFont->mFont.name = aParentFont->mFont.name; } else if (eCSSUnit_Initial == aFontData.mFamily.GetUnit()) { aFont->mFont.name = aDefaultFont.name; } // font-style: enum, normal, inherit if (eCSSUnit_Enumerated == aFontData.mStyle.GetUnit()) { aFont->mFont.style = aFontData.mStyle.GetIntValue(); } else if (eCSSUnit_Normal == aFontData.mStyle.GetUnit()) { aFont->mFont.style = NS_STYLE_FONT_STYLE_NORMAL; } else if (eCSSUnit_Inherit == aFontData.mStyle.GetUnit()) { aInherited = PR_TRUE; aFont->mFont.style = aParentFont->mFont.style; } else if (eCSSUnit_Initial == aFontData.mStyle.GetUnit()) { aFont->mFont.style = aDefaultFont.style; } // font-variant: enum, normal, inherit if (eCSSUnit_Enumerated == aFontData.mVariant.GetUnit()) { aFont->mFont.variant = aFontData.mVariant.GetIntValue(); } else if (eCSSUnit_Normal == aFontData.mVariant.GetUnit()) { aFont->mFont.variant = NS_STYLE_FONT_VARIANT_NORMAL; } else if (eCSSUnit_Inherit == aFontData.mVariant.GetUnit()) { aInherited = PR_TRUE; aFont->mFont.variant = aParentFont->mFont.variant; } else if (eCSSUnit_Initial == aFontData.mVariant.GetUnit()) { aFont->mFont.variant = aDefaultFont.variant; } // font-weight: int, enum, normal, inherit if (eCSSUnit_Integer == aFontData.mWeight.GetUnit()) { aFont->mFont.weight = aFontData.mWeight.GetIntValue(); } else if (eCSSUnit_Enumerated == aFontData.mWeight.GetUnit()) { PRInt32 value = aFontData.mWeight.GetIntValue(); switch (value) { case NS_STYLE_FONT_WEIGHT_NORMAL: case NS_STYLE_FONT_WEIGHT_BOLD: aFont->mFont.weight = value; break; case NS_STYLE_FONT_WEIGHT_BOLDER: case NS_STYLE_FONT_WEIGHT_LIGHTER: aInherited = PR_TRUE; aFont->mFont.weight = nsStyleUtil::ConstrainFontWeight(aParentFont->mFont.weight + value); break; } } else if (eCSSUnit_Normal == aFontData.mWeight.GetUnit()) { aFont->mFont.weight = NS_STYLE_FONT_WEIGHT_NORMAL; } else if (eCSSUnit_Inherit == aFontData.mWeight.GetUnit()) { aInherited = PR_TRUE; aFont->mFont.weight = aParentFont->mFont.weight; } else if (eCSSUnit_Initial == aFontData.mWeight.GetUnit()) { aFont->mFont.weight = aDefaultFont.weight; } // font-size: enum, length, percent, inherit if (eCSSUnit_Enumerated == aFontData.mSize.GetUnit()) { PRInt32 value = aFontData.mSize.GetIntValue(); PRInt32 scaler; aPresContext->GetFontScaler(&scaler); float scaleFactor = nsStyleUtil::GetScalingFactor(scaler); aInherited = PR_TRUE; if ((NS_STYLE_FONT_SIZE_XXSMALL <= value) && (value <= NS_STYLE_FONT_SIZE_XXLARGE)) { aFont->mSize = nsStyleUtil::CalcFontPointSize(value, (PRInt32)aDefaultFont.size, scaleFactor, aPresContext, eFontSize_CSS); } else if (NS_STYLE_FONT_SIZE_XXXLARGE == value) { // is not specified in CSS, so we don't use eFontSize_CSS. aFont->mSize = nsStyleUtil::CalcFontPointSize(value, (PRInt32)aDefaultFont.size, scaleFactor, aPresContext); } else if (NS_STYLE_FONT_SIZE_LARGER == value) { PRInt32 index = nsStyleUtil::FindNextLargerFontSize(aParentFont->mSize, (PRInt32)aDefaultFont.size, scaleFactor, aPresContext, eFontSize_CSS); nscoord largerSize = nsStyleUtil::CalcFontPointSize(index, (PRInt32)aDefaultFont.size, scaleFactor, aPresContext, eFontSize_CSS); aFont->mSize = PR_MAX(largerSize, aParentFont->mSize); } else if (NS_STYLE_FONT_SIZE_SMALLER == value) { PRInt32 index = nsStyleUtil::FindNextSmallerFontSize(aParentFont->mSize, (PRInt32)aDefaultFont.size, scaleFactor, aPresContext, eFontSize_CSS); nscoord smallerSize = nsStyleUtil::CalcFontPointSize(index, (PRInt32)aDefaultFont.size, scaleFactor, aPresContext, eFontSize_CSS); aFont->mSize = PR_MIN(smallerSize, aParentFont->mSize); } } else if (aFontData.mSize.IsLengthUnit()) { aFont->mSize = CalcLength(aFontData.mSize, &aParentFont->mFont, nsnull, aPresContext, aInherited); } else if (eCSSUnit_Percent == aFontData.mSize.GetUnit()) { aInherited = PR_TRUE; aFont->mSize = (nscoord)((float)(aParentFont->mSize) * aFontData.mSize.GetPercentValue()); } else if (eCSSUnit_Inherit == aFontData.mSize.GetUnit()) { aInherited = PR_TRUE; aFont->mSize = aParentFont->mSize; } else if (eCSSUnit_Initial == aFontData.mSize.GetUnit()) { aFont->mSize = aDefaultFont.size; } // enforce the user' specified minimum font-size on the value that we expose if (aChromeOverride) { // the chrome is unconstrained, it always uses our cascading size aFont->mFont.size = aFont->mSize; } else { aFont->mFont.size = PR_MAX(aFont->mSize, aMinFontSize); } // font-size-adjust: number, none, inherit if (eCSSUnit_Number == aFontData.mSizeAdjust.GetUnit()) { aFont->mFont.sizeAdjust = aFontData.mSizeAdjust.GetFloatValue(); } else if (eCSSUnit_None == aFontData.mSizeAdjust.GetUnit()) { aFont->mFont.sizeAdjust = 0.0f; } else if (eCSSUnit_Inherit == aFontData.mSizeAdjust.GetUnit()) { aInherited = PR_TRUE; aFont->mFont.sizeAdjust = aParentFont->mFont.sizeAdjust; } else if (eCSSUnit_Initial == aFontData.mSizeAdjust.GetUnit()) { aFont->mFont.sizeAdjust = 0.0f; } } // SetGenericFont: // - backtrack to an ancestor with the same generic font name (possibly // up to the root where default values come from the presentation context) // - re-apply cascading rules from there without caching intermediate values static void SetGenericFont(nsIPresContext* aPresContext, nsIStyleContext* aContext, const nsCSSFont& aFontData, PRUint8 aGenericFontID, nscoord aMinFontSize, PRBool aUseDocumentFonts, PRBool aChromeOverride, nsStyleFont* aFont) { // walk up the contexts until a context with the desired generic font nsAutoVoidArray contextPath; nsCOMPtr higherContext = getter_AddRefs(aContext->GetParent()); while (higherContext) { contextPath.AppendElement(higherContext); const nsStyleFont* higherFont = (const nsStyleFont*)higherContext->GetStyleData(eStyleStruct_Font); if (higherFont && higherFont->mFlags & aGenericFontID) { // done walking up the higher contexts break; } higherContext = getter_AddRefs(higherContext->GetParent()); } // re-apply the cascading rules, starting from the higher context // If we stopped earlier because we reached the root of the style tree, // we will start with the default generic font from the presentation // context. Otherwise we start with the higher context. const nsFont* defaultFont; aPresContext->GetDefaultFont(aGenericFontID, &defaultFont); nsStyleFont parentFont(*defaultFont); PRInt32 i = contextPath.Count() - 1; if (higherContext) { nsIStyleContext* context = (nsIStyleContext*)contextPath[i]; nsStyleFont* tmpFont = (nsStyleFont*)context->GetStyleData(eStyleStruct_Font); parentFont.mFlags = tmpFont->mFlags; parentFont.mFont = tmpFont->mFont; parentFont.mSize = tmpFont->mSize; --i; } aFont->mFlags = parentFont.mFlags; aFont->mFont = parentFont.mFont; aFont->mSize = parentFont.mSize; PRBool dummy; PRUint32 noneBits; PRUint32 fontBit = nsCachedStyleData::GetBitForSID(eStyleStruct_Font); nsRuleNode* ruleNode = nsnull; nsCOMPtr rule; for (; i >= 0; --i) { nsIStyleContext* context = (nsIStyleContext*)contextPath[i]; nsCSSFont fontData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Font, aPresContext, context); ruleData.mFontData = &fontData; // Trimmed down version of ::WalkRuleTree() to re-apply the style rules context->GetRuleNode(&ruleNode); while (ruleNode) { ruleNode->GetBits(nsRuleNode::eNoneBits, &noneBits); if (noneBits & fontBit) // no more font rules on this branch, get out break; ruleNode->GetRule(getter_AddRefs(rule)); if (rule) rule->MapRuleInfoInto(&ruleData); ruleNode = ruleNode->GetParent(); } // Compute the delta from the information that the rules specified fontData.mFamily.Reset(); // avoid unnecessary operations in SetFont() SetFont(aPresContext, context, aMinFontSize, aUseDocumentFonts, aChromeOverride, PR_TRUE, fontData, *defaultFont, &parentFont, aFont, dummy); // XXX Not sure if we need to do this here // If we have a post-resolve callback, handle that now. if (ruleData.mPostResolveCallback) (ruleData.mPostResolveCallback)((nsStyleStruct*)aFont, &ruleData); parentFont.mFlags = aFont->mFlags; parentFont.mFont = aFont->mFont; parentFont.mSize = aFont->mSize; } // Finish off by applying our own rules. In this case, aFontData // already has the current cascading information that we want. We // can just compute the delta from the parent. SetFont(aPresContext, aContext, aMinFontSize, aUseDocumentFonts, aChromeOverride, PR_TRUE, aFontData, *defaultFont, &parentFont, aFont, dummy); } const nsStyleStruct* nsRuleNode::ComputeFontData(nsStyleStruct* aStartStruct, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW FONT CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSFont& fontData = NS_STATIC_CAST(const nsCSSFont&, aData); nsStyleFont* font = nsnull; const nsStyleFont* parentFont = nsnull; PRBool inherited = aInherited; if (parentContext) parentFont = NS_STATIC_CAST(const nsStyleFont*, parentContext->GetStyleData(eStyleStruct_Font)); if (aStartStruct) // We only need to compute the delta between this computed data and our // computed data. font = new (mPresContext) nsStyleFont(*NS_STATIC_CAST(nsStyleFont*, aStartStruct)); else { if (aRuleDetail != eRuleFullMixed) { // No question. We will have to inherit. Go ahead and init // with inherited vals from parent. inherited = PR_TRUE; if (parentFont) font = new (mPresContext) nsStyleFont(*parentFont); } } const nsFont* defaultFont; if (!font) { mPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID, &defaultFont); font = new (mPresContext) nsStyleFont(*defaultFont); } if (!parentFont) parentFont = font; // See if there is a minimum font-size constraint to honor nscoord minimumFontSize = 0; // unconstrained by default mPresContext->GetCachedIntPref(kPresContext_MinimumFontSize, minimumFontSize); PRBool chromeOverride = PR_FALSE; PRBool useDocumentFonts = PR_TRUE; // Figure out if we are a generic font PRUint8 generic = kGenericFont_NONE; if (eCSSUnit_String == fontData.mFamily.GetUnit()) { fontData.mFamily.GetStringValue(font->mFont.name); nsFont::GetGenericID(font->mFont.name, &generic); // MJA: bug 31816 // if we are not using document fonts, but this is a XUL document, // then we set the chromeOverride flag to use the document fonts anyway mPresContext->GetCachedBoolPref(kPresContext_UseDocumentFonts, useDocumentFonts); if (!useDocumentFonts) { // check if the prefs have been disabled for this shell // - if prefs are disabled then we use the document fonts anyway (yet another override) PRBool prefsEnabled = PR_TRUE; nsCOMPtr shell; mPresContext->GetShell(getter_AddRefs(shell)); if (shell) shell->ArePrefStyleRulesEnabled(prefsEnabled); if (!prefsEnabled) useDocumentFonts = PR_TRUE; } } // See if we are in the chrome // We only need to know this to determine if we have to use the // document fonts (overriding the useDocumentFonts flag), or to // determine if we have to override the minimum font-size constraint. if (!useDocumentFonts || minimumFontSize > 0) { nsCOMPtr container; nsresult result = mPresContext->GetContainer(getter_AddRefs(container)); if (NS_SUCCEEDED(result) && container) { nsCOMPtr docShell(do_QueryInterface(container, &result)); if (NS_SUCCEEDED(result) && docShell) { PRInt32 docShellType; result = docShell->GetItemType(&docShellType); if (NS_SUCCEEDED(result)) { chromeOverride = nsIDocShellTreeItem::typeChrome == docShellType; } } } } // If we don't have to use document fonts, then we are only entitled // to use the user's default variable-width font and fixed-width font if (!useDocumentFonts && !chromeOverride) { if (generic != kGenericFont_moz_fixed) generic = kGenericFont_NONE; } // Now compute our font struct if (generic == kGenericFont_NONE) { // continue the normal processing // our default font is the most recent generic font generic = parentFont->mFlags & NS_STYLE_FONT_FACE_MASK; mPresContext->GetDefaultFont(generic, &defaultFont); SetFont(mPresContext, aContext, minimumFontSize, useDocumentFonts, chromeOverride, PR_FALSE, fontData, *defaultFont, parentFont, font, inherited); } else { // re-calculate the font as a generic font inherited = PR_TRUE; SetGenericFont(mPresContext, aContext, fontData, generic, minimumFontSize, useDocumentFonts, chromeOverride, font); } // Set our generic font's bit to inform our descendants font->mFlags &= ~NS_STYLE_FONT_FACE_MASK; font->mFlags |= generic; if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_Font, *font); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mInheritedData) aHighestNode->mStyleData.mInheritedData = new (mPresContext) nsInheritedStyleData; aHighestNode->mStyleData.mInheritedData->mFontData = font; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_FONT, aHighestNode); } return font; } const nsStyleStruct* nsRuleNode::ComputeTextData(nsStyleStruct* aStartStruct, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW TEXT CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSText& textData = NS_STATIC_CAST(const nsCSSText&, aData); nsStyleText* text = nsnull; const nsStyleText* parentText = nsnull; PRBool inherited = aInherited; if (parentContext) parentText = NS_STATIC_CAST(const nsStyleText*, parentContext->GetStyleData(eStyleStruct_Text)); if (aStartStruct) // We only need to compute the delta between this computed data and our // computed data. text = new (mPresContext) nsStyleText(*NS_STATIC_CAST(nsStyleText*, aStartStruct)); else { if (aRuleDetail != eRuleFullMixed) { // No question. We will have to inherit. Go ahead and init // with inherited vals from parent. inherited = PR_TRUE; if (parentText) text = new (mPresContext) nsStyleText(*parentText); } } if (!text) text = new (mPresContext) nsStyleText(); if (!parentText) parentText = text; // letter-spacing: normal, length, inherit SetCoord(textData.mLetterSpacing, text->mLetterSpacing, parentText->mLetterSpacing, SETCOORD_LH | SETCOORD_NORMAL, aContext, mPresContext, inherited); // line-height: normal, number, length, percent, inherit if (eCSSUnit_Percent == textData.mLineHeight.GetUnit()) { aInherited = PR_TRUE; const nsStyleFont* font = NS_STATIC_CAST(const nsStyleFont*, aContext->GetStyleData(eStyleStruct_Font)); text->mLineHeight.SetCoordValue((nscoord)((float)(font->mSize) * textData.mLineHeight.GetPercentValue())); } else SetCoord(textData.mLineHeight, text->mLineHeight, parentText->mLineHeight, SETCOORD_LH | SETCOORD_FACTOR | SETCOORD_NORMAL, aContext, mPresContext, inherited); // text-align: enum, string, inherit if (eCSSUnit_Enumerated == textData.mTextAlign.GetUnit()) { text->mTextAlign = textData.mTextAlign.GetIntValue(); } else if (eCSSUnit_String == textData.mTextAlign.GetUnit()) { NS_NOTYETIMPLEMENTED("align string"); } else if (eCSSUnit_Inherit == textData.mTextAlign.GetUnit()) { inherited = PR_TRUE; text->mTextAlign = parentText->mTextAlign; } else if (eCSSUnit_Initial == textData.mTextAlign.GetUnit()) text->mTextAlign = NS_STYLE_TEXT_ALIGN_DEFAULT; // text-indent: length, percent, inherit SetCoord(textData.mTextIndent, text->mTextIndent, parentText->mTextIndent, SETCOORD_LPH, aContext, mPresContext, inherited); // text-transform: enum, none, inherit if (eCSSUnit_Enumerated == textData.mTextTransform.GetUnit()) { text->mTextTransform = textData.mTextTransform.GetIntValue(); } else if (eCSSUnit_None == textData.mTextTransform.GetUnit()) { text->mTextTransform = NS_STYLE_TEXT_TRANSFORM_NONE; } else if (eCSSUnit_Inherit == textData.mTextTransform.GetUnit()) { inherited = PR_TRUE; text->mTextTransform = parentText->mTextTransform; } // white-space: enum, normal, inherit if (eCSSUnit_Enumerated == textData.mWhiteSpace.GetUnit()) { text->mWhiteSpace = textData.mWhiteSpace.GetIntValue(); } else if (eCSSUnit_Normal == textData.mWhiteSpace.GetUnit()) { text->mWhiteSpace = NS_STYLE_WHITESPACE_NORMAL; } else if (eCSSUnit_Inherit == textData.mWhiteSpace.GetUnit()) { inherited = PR_TRUE; text->mWhiteSpace = parentText->mWhiteSpace; } // word-spacing: normal, length, inherit SetCoord(textData.mWordSpacing, text->mWordSpacing, parentText->mWordSpacing, SETCOORD_LH | SETCOORD_NORMAL, aContext, mPresContext, inherited); if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_Text, *text); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mInheritedData) aHighestNode->mStyleData.mInheritedData = new (mPresContext) nsInheritedStyleData; aHighestNode->mStyleData.mInheritedData->mTextData = text; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_TEXT, aHighestNode); } return text; } const nsStyleStruct* nsRuleNode::ComputeTextResetData(nsStyleStruct* aStartData, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW TEXTRESET CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSText& textData = NS_STATIC_CAST(const nsCSSText&, aData); nsStyleTextReset* text; if (aStartData) // We only need to compute the delta between this computed data and our // computed data. text = new (mPresContext) nsStyleTextReset(*NS_STATIC_CAST(nsStyleTextReset*, aStartData)); else text = new (mPresContext) nsStyleTextReset(); nsStyleTextReset* parentText = text; if (parentContext) parentText = (nsStyleTextReset*)parentContext->GetStyleData(eStyleStruct_TextReset); PRBool inherited = aInherited; // vertical-align: enum, length, percent, inherit SetCoord(textData.mVerticalAlign, text->mVerticalAlign, parentText->mVerticalAlign, SETCOORD_LPH | SETCOORD_ENUMERATED, aContext, mPresContext, inherited); // text-decoration: none, enum (bit field), inherit if (eCSSUnit_Enumerated == textData.mDecoration.GetUnit()) { PRInt32 td = textData.mDecoration.GetIntValue(); text->mTextDecoration = td; } else if (eCSSUnit_None == textData.mDecoration.GetUnit()) { text->mTextDecoration = NS_STYLE_TEXT_DECORATION_NONE; } else if (eCSSUnit_Inherit == textData.mDecoration.GetUnit()) { inherited = PR_TRUE; text->mTextDecoration = parentText->mTextDecoration; } #ifdef IBMBIDI // unicode-bidi: enum, normal, inherit if (eCSSUnit_Normal == textData.mUnicodeBidi.GetUnit() ) { text->mUnicodeBidi = NS_STYLE_UNICODE_BIDI_NORMAL; } else if (eCSSUnit_Enumerated == textData.mUnicodeBidi.GetUnit() ) { text->mUnicodeBidi = textData.mUnicodeBidi.GetIntValue(); } else if (eCSSUnit_Inherit == textData.mUnicodeBidi.GetUnit() ) { inherited = PR_TRUE; text->mUnicodeBidi = parentText->mUnicodeBidi; } #endif // IBMBIDI if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_TextReset, *text); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mResetData) aHighestNode->mStyleData.mResetData = new (mPresContext) nsResetStyleData; aHighestNode->mStyleData.mResetData->mTextData = text; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_TEXT_RESET, aHighestNode); } return text; } const nsStyleStruct* nsRuleNode::ComputeUIData(nsStyleStruct* aStartData, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW UI CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSUserInterface& uiData = NS_STATIC_CAST(const nsCSSUserInterface&, aData); nsStyleUserInterface* ui = nsnull; const nsStyleUserInterface* parentUI = nsnull; PRBool inherited = aInherited; if (parentContext) parentUI = NS_STATIC_CAST(const nsStyleUserInterface*, parentContext->GetStyleData(eStyleStruct_UserInterface)); if (aStartData) // We only need to compute the delta between this computed data and our // computed data. ui = new (mPresContext) nsStyleUserInterface(*NS_STATIC_CAST(nsStyleUserInterface*, aStartData)); else { if (aRuleDetail != eRuleFullMixed) { // No question. We will have to inherit. Go ahead and init // with inherited vals from parent. inherited = PR_TRUE; if (parentUI) ui = new (mPresContext) nsStyleUserInterface(*parentUI); } } if (!ui) ui = new (mPresContext) nsStyleUserInterface(); if (!parentUI) parentUI = ui; // cursor: enum, auto, url, inherit nsCSSValueList* list = uiData.mCursor; if (nsnull != list) { // XXX need to deal with multiple URL values if (eCSSUnit_Enumerated == list->mValue.GetUnit()) { ui->mCursor = list->mValue.GetIntValue(); } else if (eCSSUnit_Auto == list->mValue.GetUnit()) { ui->mCursor = NS_STYLE_CURSOR_AUTO; } else if (eCSSUnit_URL == list->mValue.GetUnit()) { list->mValue.GetStringValue(ui->mCursorImage); } else if (eCSSUnit_Inherit == list->mValue.GetUnit()) { inherited = PR_TRUE; ui->mCursor = parentUI->mCursor; } } // user-input: auto, none, enum, inherit if (eCSSUnit_Enumerated == uiData.mUserInput.GetUnit()) { ui->mUserInput = uiData.mUserInput.GetIntValue(); } else if (eCSSUnit_Auto == uiData.mUserInput.GetUnit()) { ui->mUserInput = NS_STYLE_USER_INPUT_AUTO; } else if (eCSSUnit_None == uiData.mUserInput.GetUnit()) { ui->mUserInput = NS_STYLE_USER_INPUT_NONE; } else if (eCSSUnit_Inherit == uiData.mUserInput.GetUnit()) { inherited = PR_TRUE; ui->mUserInput = parentUI->mUserInput; } // user-modify: enum, inherit if (eCSSUnit_Enumerated == uiData.mUserModify.GetUnit()) { ui->mUserModify = uiData.mUserModify.GetIntValue(); } else if (eCSSUnit_Inherit == uiData.mUserModify.GetUnit()) { inherited = PR_TRUE; ui->mUserModify = parentUI->mUserModify; } // user-focus: none, normal, enum, inherit if (eCSSUnit_Enumerated == uiData.mUserFocus.GetUnit()) { ui->mUserFocus = uiData.mUserFocus.GetIntValue(); } else if (eCSSUnit_None == uiData.mUserFocus.GetUnit()) { ui->mUserFocus = NS_STYLE_USER_FOCUS_NONE; } else if (eCSSUnit_Normal == uiData.mUserFocus.GetUnit()) { ui->mUserFocus = NS_STYLE_USER_FOCUS_NORMAL; } else if (eCSSUnit_Inherit == uiData.mUserFocus.GetUnit()) { inherited = PR_TRUE; ui->mUserFocus = parentUI->mUserFocus; } if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_UserInterface, *ui); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mInheritedData) aHighestNode->mStyleData.mInheritedData = new (mPresContext) nsInheritedStyleData; aHighestNode->mStyleData.mInheritedData->mUIData = ui; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_UI, aHighestNode); } return ui; } const nsStyleStruct* nsRuleNode::ComputeUIResetData(nsStyleStruct* aStartData, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW UIRESET CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSUserInterface& uiData = NS_STATIC_CAST(const nsCSSUserInterface&, aData); nsStyleUIReset* ui; if (aStartData) // We only need to compute the delta between this computed data and our // computed data. ui = new (mPresContext) nsStyleUIReset(*NS_STATIC_CAST(nsStyleUIReset*, aStartData)); else ui = new (mPresContext) nsStyleUIReset(); const nsStyleUIReset* parentUI = ui; if (parentContext) parentUI = NS_STATIC_CAST(const nsStyleUIReset*, parentContext->GetStyleData(eStyleStruct_UIReset)); PRBool inherited = aInherited; // user-select: none, enum, inherit if (eCSSUnit_Enumerated == uiData.mUserSelect.GetUnit()) { ui->mUserSelect = uiData.mUserSelect.GetIntValue(); } else if (eCSSUnit_None == uiData.mUserSelect.GetUnit()) { ui->mUserSelect = NS_STYLE_USER_SELECT_NONE; } else if (eCSSUnit_Inherit == uiData.mUserSelect.GetUnit()) { inherited = PR_TRUE; ui->mUserSelect = parentUI->mUserSelect; } // key-equivalent: none, enum XXX, inherit nsCSSValueList* keyEquiv = uiData.mKeyEquivalent; if (keyEquiv) { // XXX need to deal with multiple values if (eCSSUnit_Enumerated == keyEquiv->mValue.GetUnit()) { ui->mKeyEquivalent = PRUnichar(0); // XXX To be implemented } else if (eCSSUnit_None == keyEquiv->mValue.GetUnit()) { ui->mKeyEquivalent = PRUnichar(0); } else if (eCSSUnit_Inherit == keyEquiv->mValue.GetUnit()) { inherited = PR_TRUE; ui->mKeyEquivalent = parentUI->mKeyEquivalent; } } // resizer: auto, none, enum, inherit if (eCSSUnit_Enumerated == uiData.mResizer.GetUnit()) { ui->mResizer = uiData.mResizer.GetIntValue(); } else if (eCSSUnit_Auto == uiData.mResizer.GetUnit()) { ui->mResizer = NS_STYLE_RESIZER_AUTO; } else if (eCSSUnit_None == uiData.mResizer.GetUnit()) { ui->mResizer = NS_STYLE_RESIZER_NONE; } else if (eCSSUnit_Inherit == uiData.mResizer.GetUnit()) { inherited = PR_TRUE; ui->mResizer = parentUI->mResizer; } if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_UIReset, *ui); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mResetData) aHighestNode->mStyleData.mResetData = new (mPresContext) nsResetStyleData; aHighestNode->mStyleData.mResetData->mUIData = ui; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_UI_RESET, aHighestNode); } return ui; } const nsStyleStruct* nsRuleNode::ComputeDisplayData(nsStyleStruct* aStartStruct, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW DISPLAY CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSDisplay& displayData = NS_STATIC_CAST(const nsCSSDisplay&, aData); nsStyleDisplay* display; if (aStartStruct) // We only need to compute the delta between this computed data and our // computed data. display = new (mPresContext) nsStyleDisplay(*NS_STATIC_CAST(nsStyleDisplay*, aStartStruct)); else display = new (mPresContext) nsStyleDisplay(); const nsStyleDisplay* parentDisplay = display; if (parentContext) parentDisplay = NS_STATIC_CAST(const nsStyleDisplay*, parentContext->GetStyleData(eStyleStruct_Display)); PRBool inherited = aInherited; // display: enum, none, inherit if (eCSSUnit_Enumerated == displayData.mDisplay.GetUnit()) { display->mDisplay = displayData.mDisplay.GetIntValue(); } else if (eCSSUnit_None == displayData.mDisplay.GetUnit()) { display->mDisplay = NS_STYLE_DISPLAY_NONE; } else if (eCSSUnit_Inherit == displayData.mDisplay.GetUnit()) { inherited = PR_TRUE; display->mDisplay = parentDisplay->mDisplay; } // appearance: enum, none, inherit if (eCSSUnit_Enumerated == displayData.mAppearance.GetUnit()) { display->mAppearance = displayData.mAppearance.GetIntValue(); } else if (eCSSUnit_None == displayData.mAppearance.GetUnit()) { display->mAppearance = NS_THEME_NONE; } else if (eCSSUnit_Inherit == displayData.mAppearance.GetUnit()) { inherited = PR_TRUE; display->mAppearance = parentDisplay->mAppearance; } // binding: url, none, inherit if (eCSSUnit_URL == displayData.mBinding.GetUnit()) { displayData.mBinding.GetStringValue(display->mBinding); } else if (eCSSUnit_None == displayData.mBinding.GetUnit()) { display->mBinding.Truncate(); } else if (eCSSUnit_Inherit == displayData.mBinding.GetUnit()) { inherited = PR_TRUE; display->mBinding = parentDisplay->mBinding; } // position: enum, inherit if (eCSSUnit_Enumerated == displayData.mPosition.GetUnit()) { display->mPosition = displayData.mPosition.GetIntValue(); if (display->mPosition != NS_STYLE_POSITION_NORMAL) { // :before and :after elts cannot be positioned. We need to check for this // case. nsCOMPtr tag; aContext->GetPseudoType(*getter_AddRefs(tag)); if (tag && tag.get() == nsCSSAtoms::beforePseudo || tag.get() == nsCSSAtoms::afterPseudo) display->mPosition = NS_STYLE_POSITION_NORMAL; } } else if (eCSSUnit_Inherit == displayData.mPosition.GetUnit()) { inherited = PR_TRUE; display->mPosition = parentDisplay->mPosition; } // clear: enum, none, inherit if (eCSSUnit_Enumerated == displayData.mClear.GetUnit()) { display->mBreakType = displayData.mClear.GetIntValue(); } else if (eCSSUnit_None == displayData.mClear.GetUnit()) { display->mBreakType = NS_STYLE_CLEAR_NONE; } else if (eCSSUnit_Inherit == displayData.mClear.GetUnit()) { inherited = PR_TRUE; display->mBreakType = parentDisplay->mBreakType; } // float: enum, none, inherit if (eCSSUnit_Enumerated == displayData.mFloat.GetUnit()) { display->mFloats = displayData.mFloat.GetIntValue(); } else if (eCSSUnit_None == displayData.mFloat.GetUnit()) { display->mFloats = NS_STYLE_FLOAT_NONE; } else if (eCSSUnit_Inherit == displayData.mFloat.GetUnit()) { inherited = PR_TRUE; display->mFloats = parentDisplay->mFloats; } // overflow: enum, auto, inherit if (eCSSUnit_Enumerated == displayData.mOverflow.GetUnit()) { display->mOverflow = displayData.mOverflow.GetIntValue(); } else if (eCSSUnit_Auto == displayData.mOverflow.GetUnit()) { display->mOverflow = NS_STYLE_OVERFLOW_AUTO; } else if (eCSSUnit_Inherit == displayData.mOverflow.GetUnit()) { inherited = PR_TRUE; display->mOverflow = parentDisplay->mOverflow; } // clip property: length, auto, inherit if (nsnull != displayData.mClip) { if (eCSSUnit_Inherit == displayData.mClip->mTop.GetUnit()) { // if one is inherit, they all are inherited = PR_TRUE; display->mClipFlags = NS_STYLE_CLIP_INHERIT; } else { PRBool fullAuto = PR_TRUE; display->mClipFlags = 0; // clear it if (eCSSUnit_Auto == displayData.mClip->mTop.GetUnit()) { display->mClip.y = 0; display->mClipFlags |= NS_STYLE_CLIP_TOP_AUTO; } else if (displayData.mClip->mTop.IsLengthUnit()) { display->mClip.y = CalcLength(displayData.mClip->mTop, nsnull, aContext, mPresContext, inherited); fullAuto = PR_FALSE; } if (eCSSUnit_Auto == displayData.mClip->mBottom.GetUnit()) { display->mClip.height = 0; display->mClipFlags |= NS_STYLE_CLIP_BOTTOM_AUTO; } else if (displayData.mClip->mBottom.IsLengthUnit()) { display->mClip.height = CalcLength(displayData.mClip->mBottom, nsnull, aContext, mPresContext, inherited) - display->mClip.y; fullAuto = PR_FALSE; } if (eCSSUnit_Auto == displayData.mClip->mLeft.GetUnit()) { display->mClip.x = 0; display->mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO; } else if (displayData.mClip->mLeft.IsLengthUnit()) { display->mClip.x = CalcLength(displayData.mClip->mLeft, nsnull, aContext, mPresContext, inherited); fullAuto = PR_FALSE; } if (eCSSUnit_Auto == displayData.mClip->mRight.GetUnit()) { display->mClip.width = 0; display->mClipFlags |= NS_STYLE_CLIP_RIGHT_AUTO; } else if (displayData.mClip->mRight.IsLengthUnit()) { display->mClip.width = CalcLength(displayData.mClip->mRight, nsnull, aContext, mPresContext, inherited) - display->mClip.x; fullAuto = PR_FALSE; } display->mClipFlags &= ~NS_STYLE_CLIP_TYPE_MASK; if (fullAuto) { display->mClipFlags |= NS_STYLE_CLIP_AUTO; } else { display->mClipFlags |= NS_STYLE_CLIP_RECT; } } } if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_Display, *display); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mResetData) aHighestNode->mStyleData.mResetData = new (mPresContext) nsResetStyleData; aHighestNode->mStyleData.mResetData->mDisplayData = display; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_DISPLAY, aHighestNode); } // CSS2 specified fixups: // 1) if float is not none, and display is not none, then we must set display to block // XXX - there are problems with following the spec here: what we will do instead of // following the letter of the spec is to make sure that floated elements are // some kind of block, not strictly 'block' - see EnsureBlockDisplay method if (display->mDisplay != NS_STYLE_DISPLAY_NONE && display->mFloats != NS_STYLE_FLOAT_NONE ) EnsureBlockDisplay(display->mDisplay); // 2) if position is 'absolute' or 'fixed' then display must be 'block and float must be 'none' // XXX - see note for fixup 1) above... if (display->IsAbsolutelyPositioned() && display->mDisplay != NS_STYLE_DISPLAY_NONE) { EnsureBlockDisplay(display->mDisplay); display->mFloats = NS_STYLE_FLOAT_NONE; } nsCOMPtr tag; aContext->GetPseudoType(*getter_AddRefs(tag)); if (tag && tag.get() == nsCSSAtoms::beforePseudo || tag.get() == nsCSSAtoms::afterPseudo) { PRUint8 displayValue = display->mDisplay; if (parentDisplay->IsBlockLevel()) { // For block-level elements the only allowed 'display' values are: // 'none', 'inline', 'block', and 'marker' if ((NS_STYLE_DISPLAY_INLINE != displayValue) && (NS_STYLE_DISPLAY_BLOCK != displayValue) && (NS_STYLE_DISPLAY_MARKER != displayValue)) { // Pseudo-element behaves as if the value were 'block' displayValue = NS_STYLE_DISPLAY_BLOCK; } } else { // For inline-level elements the only allowed 'display' values are // 'none' and 'inline' displayValue = NS_STYLE_DISPLAY_INLINE; } if (display->mDisplay != displayValue) { // Reset the value display->mDisplay = displayValue; } } return display; } const nsStyleStruct* nsRuleNode::ComputeVisibilityData(nsStyleStruct* aStartStruct, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW VISIBILITY CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSDisplay& displayData = NS_STATIC_CAST(const nsCSSDisplay&, aData); nsStyleVisibility* visibility = nsnull; const nsStyleVisibility* parentVisibility = nsnull; PRBool inherited = aInherited; if (parentContext) parentVisibility = NS_STATIC_CAST(const nsStyleVisibility*, parentContext->GetStyleData(eStyleStruct_Visibility)); if (aStartStruct) // We only need to compute the delta between this computed data and our // computed data. visibility = new (mPresContext) nsStyleVisibility(*NS_STATIC_CAST(nsStyleVisibility*, aStartStruct)); else { if (aRuleDetail != eRuleFullMixed) { // No question. We will have to inherit. Go ahead and init // with inherited vals from parent. inherited = PR_TRUE; if (parentVisibility) visibility = new (mPresContext) nsStyleVisibility(*parentVisibility); } } if (!visibility) visibility = new (mPresContext) nsStyleVisibility(mPresContext); if (!parentVisibility) parentVisibility = visibility; // opacity: factor, percent, inherit if (eCSSUnit_Percent == displayData.mOpacity.GetUnit()) { inherited = PR_TRUE; float opacity = parentVisibility->mOpacity * displayData.mOpacity.GetPercentValue(); if (opacity < 0.0f) { visibility->mOpacity = 0.0f; } else if (1.0 < opacity) { visibility->mOpacity = 1.0f; } else { visibility->mOpacity = opacity; } } else if (eCSSUnit_Number == displayData.mOpacity.GetUnit()) { visibility->mOpacity = displayData.mOpacity.GetFloatValue(); } else if (eCSSUnit_Inherit == displayData.mOpacity.GetUnit()) { inherited = PR_TRUE; visibility->mOpacity = parentVisibility->mOpacity; } // direction: enum, inherit if (eCSSUnit_Enumerated == displayData.mDirection.GetUnit()) { visibility->mDirection = displayData.mDirection.GetIntValue(); #ifdef IBMBIDI if (NS_STYLE_DIRECTION_RTL == visibility->mDirection) mPresContext->SetBidiEnabled(PR_TRUE); #endif // IBMBIDI } else if (eCSSUnit_Inherit == displayData.mDirection.GetUnit()) { inherited = PR_TRUE; visibility->mDirection = parentVisibility->mDirection; } // visibility: enum, inherit if (eCSSUnit_Enumerated == displayData.mVisibility.GetUnit()) { visibility->mVisible = displayData.mVisibility.GetIntValue(); } else if (eCSSUnit_Inherit == displayData.mVisibility.GetUnit()) { inherited = PR_TRUE; visibility->mVisible = parentVisibility->mVisible; } // lang: string, inherit // this is not a real CSS property, it is a html attribute mapped to CSS struture if (eCSSUnit_String == displayData.mLang.GetUnit()) { if (!gLangService) { CallGetService(NS_LANGUAGEATOMSERVICE_CONTRACTID, &gLangService); } if (gLangService) { nsAutoString lang; displayData.mLang.GetStringValue(lang); gLangService->LookupLanguage(lang.get(), getter_AddRefs(visibility->mLanguage)); } } if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_Visibility, *visibility); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mInheritedData) aHighestNode->mStyleData.mInheritedData = new (mPresContext) nsInheritedStyleData; aHighestNode->mStyleData.mInheritedData->mVisibilityData = visibility; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_VISIBILITY, aHighestNode); } return visibility; } const nsStyleStruct* nsRuleNode::ComputeColorData(nsStyleStruct* aStartStruct, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW COLOR CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSColor& colorData = NS_STATIC_CAST(const nsCSSColor&, aData); nsStyleColor* color = nsnull; const nsStyleColor* parentColor = nsnull; PRBool inherited = aInherited; if (parentContext) parentColor = NS_STATIC_CAST(const nsStyleColor*, parentContext->GetStyleData(eStyleStruct_Color)); if (aStartStruct) // We only need to compute the delta between this computed data and our // computed data. color = new (mPresContext) nsStyleColor(*NS_STATIC_CAST(nsStyleColor*, aStartStruct)); else { if (aRuleDetail != eRuleFullMixed) { // No question. We will have to inherit. Go ahead and init // with inherited vals from parent. inherited = PR_TRUE; if (parentColor) color = new (mPresContext) nsStyleColor(*parentColor); } } if (!color) color = new (mPresContext) nsStyleColor(mPresContext); if (!parentColor) parentColor = color; // color: color, string, inherit if (!SetColor(colorData.mColor, parentColor->mColor, mPresContext, color->mColor, inherited) && colorData.mColor.GetUnit() == eCSSUnit_Integer) { // See if this is a special theme color. Theme colors must always be resolved // dynamically at paint time. nsCOMPtr look; mPresContext->GetLookAndFeel(getter_AddRefs(look)); if (look) { nsILookAndFeel::nsColorID colorID = (nsILookAndFeel::nsColorID)colorData.mColor.GetIntValue(); if (colorID == nsILookAndFeel::eColor_theme) color->mColorFlags = NS_COLORFLAGS_THEME; } } if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_Color, *color); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mInheritedData) aHighestNode->mStyleData.mInheritedData = new (mPresContext) nsInheritedStyleData; aHighestNode->mStyleData.mInheritedData->mColorData = color; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_COLOR, aHighestNode); } return color; } const nsStyleStruct* nsRuleNode::ComputeBackgroundData(nsStyleStruct* aStartStruct, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW BACKGROUND CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSColor& colorData = NS_STATIC_CAST(const nsCSSColor&, aData); nsStyleBackground* bg; if (aStartStruct) // We only need to compute the delta between this computed data and our // computed data. bg = new (mPresContext) nsStyleBackground(*NS_STATIC_CAST(nsStyleBackground*, aStartStruct)); else bg = new (mPresContext) nsStyleBackground(mPresContext); const nsStyleBackground* parentBG = bg; if (parentContext) parentBG = NS_STATIC_CAST(const nsStyleBackground*, parentContext->GetStyleData(eStyleStruct_Background)); PRBool inherited = aInherited; // background-color: color, string, enum (flags), inherit if (eCSSUnit_Inherit == colorData.mBackColor.GetUnit()) { // do inherit first, so SetColor doesn't do it bg->mBackgroundColor = parentBG->mBackgroundColor; bg->mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT; bg->mBackgroundFlags |= (parentBG->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT); inherited = PR_TRUE; } else if (SetColor(colorData.mBackColor, parentBG->mBackgroundColor, mPresContext, bg->mBackgroundColor, inherited)) { bg->mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT; } else if (eCSSUnit_Enumerated == colorData.mBackColor.GetUnit()) { //bg->mBackgroundColor = parentBG->mBackgroundColor; XXXwdh crap crap crap! bg->mBackgroundFlags |= NS_STYLE_BG_COLOR_TRANSPARENT; } // background-image: url, none, inherit if (eCSSUnit_URL == colorData.mBackImage.GetUnit()) { colorData.mBackImage.GetStringValue(bg->mBackgroundImage); bg->mBackgroundFlags &= ~NS_STYLE_BG_IMAGE_NONE; } else if (eCSSUnit_None == colorData.mBackImage.GetUnit()) { bg->mBackgroundImage.Truncate(); bg->mBackgroundFlags |= NS_STYLE_BG_IMAGE_NONE; } else if (eCSSUnit_Inherit == colorData.mBackImage.GetUnit()) { inherited = PR_TRUE; bg->mBackgroundImage = parentBG->mBackgroundImage; bg->mBackgroundFlags &= ~NS_STYLE_BG_IMAGE_NONE; bg->mBackgroundFlags |= (parentBG->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE); } // background-repeat: enum, inherit if (eCSSUnit_Enumerated == colorData.mBackRepeat.GetUnit()) { bg->mBackgroundRepeat = colorData.mBackRepeat.GetIntValue(); } else if (eCSSUnit_Inherit == colorData.mBackRepeat.GetUnit()) { inherited = PR_TRUE; bg->mBackgroundRepeat = parentBG->mBackgroundRepeat; } // background-attachment: enum, inherit if (eCSSUnit_Enumerated == colorData.mBackAttachment.GetUnit()) { bg->mBackgroundAttachment = colorData.mBackAttachment.GetIntValue(); } else if (eCSSUnit_Inherit == colorData.mBackAttachment.GetUnit()) { inherited = PR_TRUE; bg->mBackgroundAttachment = parentBG->mBackgroundAttachment; } // background-position: enum, length, percent (flags), inherit if (eCSSUnit_Percent == colorData.mBackPositionX.GetUnit()) { bg->mBackgroundXPosition = (nscoord)(100.0f * colorData.mBackPositionX.GetPercentValue()); bg->mBackgroundFlags |= NS_STYLE_BG_X_POSITION_PERCENT; bg->mBackgroundFlags &= ~NS_STYLE_BG_X_POSITION_LENGTH; } else if (colorData.mBackPositionX.IsLengthUnit()) { bg->mBackgroundXPosition = CalcLength(colorData.mBackPositionX, nsnull, aContext, mPresContext, inherited); bg->mBackgroundFlags |= NS_STYLE_BG_X_POSITION_LENGTH; bg->mBackgroundFlags &= ~NS_STYLE_BG_X_POSITION_PERCENT; } else if (eCSSUnit_Enumerated == colorData.mBackPositionX.GetUnit()) { bg->mBackgroundXPosition = (nscoord)colorData.mBackPositionX.GetIntValue(); bg->mBackgroundFlags |= NS_STYLE_BG_X_POSITION_PERCENT; bg->mBackgroundFlags &= ~NS_STYLE_BG_X_POSITION_LENGTH; } else if (eCSSUnit_Inherit == colorData.mBackPositionX.GetUnit()) { inherited = PR_TRUE; bg->mBackgroundXPosition = parentBG->mBackgroundXPosition; bg->mBackgroundFlags &= ~(NS_STYLE_BG_X_POSITION_LENGTH | NS_STYLE_BG_X_POSITION_PERCENT); bg->mBackgroundFlags |= (parentBG->mBackgroundFlags & (NS_STYLE_BG_X_POSITION_LENGTH | NS_STYLE_BG_X_POSITION_PERCENT)); } if (eCSSUnit_Percent == colorData.mBackPositionY.GetUnit()) { bg->mBackgroundYPosition = (nscoord)(100.0f * colorData.mBackPositionY.GetPercentValue()); bg->mBackgroundFlags |= NS_STYLE_BG_Y_POSITION_PERCENT; bg->mBackgroundFlags &= ~NS_STYLE_BG_Y_POSITION_LENGTH; } else if (colorData.mBackPositionY.IsLengthUnit()) { bg->mBackgroundYPosition = CalcLength(colorData.mBackPositionY, nsnull, aContext, mPresContext, inherited); bg->mBackgroundFlags |= NS_STYLE_BG_Y_POSITION_LENGTH; bg->mBackgroundFlags &= ~NS_STYLE_BG_Y_POSITION_PERCENT; } else if (eCSSUnit_Enumerated == colorData.mBackPositionY.GetUnit()) { bg->mBackgroundYPosition = (nscoord)colorData.mBackPositionY.GetIntValue(); bg->mBackgroundFlags |= NS_STYLE_BG_Y_POSITION_PERCENT; bg->mBackgroundFlags &= ~NS_STYLE_BG_Y_POSITION_LENGTH; } else if (eCSSUnit_Inherit == colorData.mBackPositionY.GetUnit()) { inherited = PR_TRUE; bg->mBackgroundYPosition = parentBG->mBackgroundYPosition; bg->mBackgroundFlags &= ~(NS_STYLE_BG_Y_POSITION_LENGTH | NS_STYLE_BG_Y_POSITION_PERCENT); bg->mBackgroundFlags |= (parentBG->mBackgroundFlags & (NS_STYLE_BG_Y_POSITION_LENGTH | NS_STYLE_BG_Y_POSITION_PERCENT)); } if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_Background, *bg); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mResetData) aHighestNode->mStyleData.mResetData = new (mPresContext) nsResetStyleData; aHighestNode->mStyleData.mResetData->mBackgroundData = bg; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_BACKGROUND, aHighestNode); } return bg; } const nsStyleStruct* nsRuleNode::ComputeMarginData(nsStyleStruct* aStartStruct, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW MARGIN CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSMargin& marginData = NS_STATIC_CAST(const nsCSSMargin&, aData); nsStyleMargin* margin; if (aStartStruct) // We only need to compute the delta between this computed data and our // computed data. margin = new (mPresContext) nsStyleMargin(*NS_STATIC_CAST(nsStyleMargin*, aStartStruct)); else margin = new (mPresContext) nsStyleMargin(); const nsStyleMargin* parentMargin = margin; if (parentContext) parentMargin = NS_STATIC_CAST(const nsStyleMargin*, parentContext->GetStyleData(eStyleStruct_Margin)); PRBool inherited = aInherited; // margin: length, percent, auto, inherit if (marginData.mMargin) { nsStyleCoord coord; nsStyleCoord parentCoord; parentMargin->mMargin.GetLeft(parentCoord); if (SetCoord(marginData.mMargin->mLeft, coord, parentCoord, SETCOORD_LPAH, aContext, mPresContext, inherited)) { margin->mMargin.SetLeft(coord); } parentMargin->mMargin.GetTop(parentCoord); if (SetCoord(marginData.mMargin->mTop, coord, parentCoord, SETCOORD_LPAH, aContext, mPresContext, inherited)) { margin->mMargin.SetTop(coord); } parentMargin->mMargin.GetRight(parentCoord); if (SetCoord(marginData.mMargin->mRight, coord, parentCoord, SETCOORD_LPAH, aContext, mPresContext, inherited)) { margin->mMargin.SetRight(coord); } parentMargin->mMargin.GetBottom(parentCoord); if (SetCoord(marginData.mMargin->mBottom, coord, parentCoord, SETCOORD_LPAH, aContext, mPresContext, inherited)) { margin->mMargin.SetBottom(coord); } } if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_Margin, *margin); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mResetData) aHighestNode->mStyleData.mResetData = new (mPresContext) nsResetStyleData; aHighestNode->mStyleData.mResetData->mMarginData = margin; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_MARGIN, aHighestNode); } margin->RecalcData(); return margin; } const nsStyleStruct* nsRuleNode::ComputeBorderData(nsStyleStruct* aStartStruct, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW BORDER CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSMargin& marginData = NS_STATIC_CAST(const nsCSSMargin&, aData); nsStyleBorder* border; if (aStartStruct) // We only need to compute the delta between this computed data and our // computed data. border = new (mPresContext) nsStyleBorder(*NS_STATIC_CAST(nsStyleBorder*, aStartStruct)); else border = new (mPresContext) nsStyleBorder(mPresContext); const nsStyleBorder* parentBorder = border; if (parentContext) parentBorder = NS_STATIC_CAST(const nsStyleBorder*, parentContext->GetStyleData(eStyleStruct_Border)); PRBool inherited = aInherited; // border-size: length, enum, inherit if (marginData.mBorderWidth) { nsStyleCoord coord; nsStyleCoord parentCoord; if (SetCoord(marginData.mBorderWidth->mLeft, coord, parentCoord, SETCOORD_LE, aContext, mPresContext, inherited)) border->mBorder.SetLeft(coord); else if (eCSSUnit_Inherit == marginData.mBorderWidth->mLeft.GetUnit()) { inherited = PR_TRUE; border->mBorder.SetLeft(parentBorder->mBorder.GetLeft(coord)); } if (SetCoord(marginData.mBorderWidth->mTop, coord, parentCoord, SETCOORD_LE, aContext, mPresContext, inherited)) border->mBorder.SetTop(coord); else if (eCSSUnit_Inherit == marginData.mBorderWidth->mTop.GetUnit()) { inherited = PR_TRUE; border->mBorder.SetTop(parentBorder->mBorder.GetTop(coord)); } if (SetCoord(marginData.mBorderWidth->mRight, coord, parentCoord, SETCOORD_LE, aContext, mPresContext, inherited)) border->mBorder.SetRight(coord); else if (eCSSUnit_Inherit == marginData.mBorderWidth->mRight.GetUnit()) { inherited = PR_TRUE; border->mBorder.SetRight(parentBorder->mBorder.GetRight(coord)); } if (SetCoord(marginData.mBorderWidth->mBottom, coord, parentCoord, SETCOORD_LE, aContext, mPresContext, inherited)) border->mBorder.SetBottom(coord); else if (eCSSUnit_Inherit == marginData.mBorderWidth->mBottom.GetUnit()) { inherited = PR_TRUE; border->mBorder.SetBottom(parentBorder->mBorder.GetBottom(coord)); } } // border-style: enum, none, inhert if (nsnull != marginData.mBorderStyle) { nsCSSRect* ourStyle = marginData.mBorderStyle; if (eCSSUnit_Enumerated == ourStyle->mTop.GetUnit()) { border->SetBorderStyle(NS_SIDE_TOP, ourStyle->mTop.GetIntValue()); } else if (eCSSUnit_None == ourStyle->mTop.GetUnit()) { border->SetBorderStyle(NS_SIDE_TOP, NS_STYLE_BORDER_STYLE_NONE); } else if (eCSSUnit_Inherit == ourStyle->mTop.GetUnit()) { inherited = PR_TRUE; border->SetBorderStyle(NS_SIDE_TOP, parentBorder->GetBorderStyle(NS_SIDE_TOP)); } if (eCSSUnit_Enumerated == ourStyle->mRight.GetUnit()) { border->SetBorderStyle(NS_SIDE_RIGHT, ourStyle->mRight.GetIntValue()); } else if (eCSSUnit_None == ourStyle->mRight.GetUnit()) { border->SetBorderStyle(NS_SIDE_RIGHT, NS_STYLE_BORDER_STYLE_NONE); } else if (eCSSUnit_Inherit == ourStyle->mRight.GetUnit()) { inherited = PR_TRUE; border->SetBorderStyle(NS_SIDE_RIGHT, parentBorder->GetBorderStyle(NS_SIDE_RIGHT)); } if (eCSSUnit_Enumerated == ourStyle->mBottom.GetUnit()) { border->SetBorderStyle(NS_SIDE_BOTTOM, ourStyle->mBottom.GetIntValue()); } else if (eCSSUnit_None == ourStyle->mBottom.GetUnit()) { border->SetBorderStyle(NS_SIDE_BOTTOM, NS_STYLE_BORDER_STYLE_NONE); } else if (eCSSUnit_Inherit == ourStyle->mBottom.GetUnit()) { inherited = PR_TRUE; border->SetBorderStyle(NS_SIDE_BOTTOM, parentBorder->GetBorderStyle(NS_SIDE_BOTTOM)); } if (eCSSUnit_Enumerated == ourStyle->mLeft.GetUnit()) { border->SetBorderStyle(NS_SIDE_LEFT, ourStyle->mLeft.GetIntValue()); } else if (eCSSUnit_None == ourStyle->mLeft.GetUnit()) { border->SetBorderStyle(NS_SIDE_LEFT, NS_STYLE_BORDER_STYLE_NONE); } else if (eCSSUnit_Inherit == ourStyle->mLeft.GetUnit()) { inherited = PR_TRUE; border->SetBorderStyle(NS_SIDE_LEFT, parentBorder->GetBorderStyle(NS_SIDE_LEFT)); } } // border-colors: color, string, enum if (marginData.mBorderColors) { nscolor borderColor; nscolor unused = NS_RGB(0,0,0); for (PRInt32 i = 0; i < 4; i++) { if (marginData.mBorderColors[i]) { // Some composite border color information has been specified for this // border side. border->EnsureBorderColors(); border->ClearBorderColors(i); nsCSSValueList* list = marginData.mBorderColors[i]; while (list) { if (SetColor(list->mValue, unused, mPresContext, borderColor, inherited)) border->AppendBorderColor(i, borderColor, PR_FALSE); else if (eCSSUnit_Enumerated == list->mValue.GetUnit() && NS_STYLE_COLOR_TRANSPARENT == list->mValue.GetIntValue()) border->AppendBorderColor(i, nsnull, PR_TRUE); list = list->mNext; } } } } // border-color: color, string, enum, inherit if (nsnull != marginData.mBorderColor) { nsCSSRect* ourBorderColor = marginData.mBorderColor; nscolor borderColor; nscolor unused = NS_RGB(0,0,0); PRBool transparent; PRBool foreground; // top if (eCSSUnit_Inherit == ourBorderColor->mTop.GetUnit()) { inherited = PR_TRUE; parentBorder->GetBorderColor(NS_SIDE_TOP, borderColor, transparent, foreground); if (transparent) border->SetBorderTransparent(NS_SIDE_TOP); else if (foreground) border->SetBorderToForeground(NS_SIDE_TOP); else border->SetBorderColor(NS_SIDE_TOP, borderColor); } else if (SetColor(ourBorderColor->mTop, unused, mPresContext, borderColor, inherited)) { border->SetBorderColor(NS_SIDE_TOP, borderColor); } else if (eCSSUnit_Enumerated == ourBorderColor->mTop.GetUnit()) { switch (ourBorderColor->mTop.GetIntValue()) { case NS_STYLE_COLOR_TRANSPARENT: border->SetBorderTransparent(NS_SIDE_TOP); break; case NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR: border->SetBorderToForeground(NS_SIDE_TOP); break; } } // right if (eCSSUnit_Inherit == ourBorderColor->mRight.GetUnit()) { inherited = PR_TRUE; parentBorder->GetBorderColor(NS_SIDE_RIGHT, borderColor, transparent, foreground); if (transparent) border->SetBorderTransparent(NS_SIDE_RIGHT); else if (foreground) border->SetBorderToForeground(NS_SIDE_RIGHT); else border->SetBorderColor(NS_SIDE_RIGHT, borderColor); } else if (SetColor(ourBorderColor->mRight, unused, mPresContext, borderColor, inherited)) { border->SetBorderColor(NS_SIDE_RIGHT, borderColor); } else if (eCSSUnit_Enumerated == ourBorderColor->mRight.GetUnit()) { switch (ourBorderColor->mRight.GetIntValue()) { case NS_STYLE_COLOR_TRANSPARENT: border->SetBorderTransparent(NS_SIDE_RIGHT); break; case NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR: border->SetBorderToForeground(NS_SIDE_RIGHT); break; } } // bottom if (eCSSUnit_Inherit == ourBorderColor->mBottom.GetUnit()) { inherited = PR_TRUE; parentBorder->GetBorderColor(NS_SIDE_BOTTOM, borderColor, transparent, foreground); if (transparent) border->SetBorderTransparent(NS_SIDE_BOTTOM); else if (foreground) border->SetBorderToForeground(NS_SIDE_BOTTOM); else border->SetBorderColor(NS_SIDE_BOTTOM, borderColor); } else if (SetColor(ourBorderColor->mBottom, unused, mPresContext, borderColor, inherited)) { border->SetBorderColor(NS_SIDE_BOTTOM, borderColor); } else if (eCSSUnit_Enumerated == ourBorderColor->mBottom.GetUnit()) { switch (ourBorderColor->mBottom.GetIntValue()) { case NS_STYLE_COLOR_TRANSPARENT: border->SetBorderTransparent(NS_SIDE_BOTTOM); break; case NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR: border->SetBorderToForeground(NS_SIDE_BOTTOM); break; } } // left if (eCSSUnit_Inherit == ourBorderColor->mLeft.GetUnit()) { inherited = PR_TRUE; parentBorder->GetBorderColor(NS_SIDE_LEFT, borderColor, transparent, foreground); if (transparent) border->SetBorderTransparent(NS_SIDE_LEFT); else if (foreground) border->SetBorderToForeground(NS_SIDE_LEFT); else border->SetBorderColor(NS_SIDE_LEFT, borderColor); } else if (SetColor(ourBorderColor->mLeft, unused, mPresContext, borderColor, inherited)) { border->SetBorderColor(NS_SIDE_LEFT, borderColor); } else if (eCSSUnit_Enumerated == ourBorderColor->mLeft.GetUnit()) { switch (ourBorderColor->mLeft.GetIntValue()) { case NS_STYLE_COLOR_TRANSPARENT: border->SetBorderTransparent(NS_SIDE_LEFT); break; case NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR: border->SetBorderToForeground(NS_SIDE_LEFT); break; } } } // -moz-border-radius: length, percent, inherit if (marginData.mBorderRadius) { nsStyleCoord coord; nsStyleCoord parentCoord; parentBorder->mBorderRadius.GetLeft(parentCoord); if (SetCoord(marginData.mBorderRadius->mLeft, coord, parentCoord, SETCOORD_LPH, aContext, mPresContext, inherited)) border->mBorderRadius.SetLeft(coord); parentBorder->mBorderRadius.GetTop(parentCoord); if (SetCoord(marginData.mBorderRadius->mTop, coord, parentCoord, SETCOORD_LPH, aContext, mPresContext, inherited)) border->mBorderRadius.SetTop(coord); parentBorder->mBorderRadius.GetRight(parentCoord); if (SetCoord(marginData.mBorderRadius->mRight, coord, parentCoord, SETCOORD_LPH, aContext, mPresContext, inherited)) border->mBorderRadius.SetRight(coord); parentBorder->mBorderRadius.GetBottom(parentCoord); if (SetCoord(marginData.mBorderRadius->mBottom, coord, parentCoord, SETCOORD_LPH, aContext, mPresContext, inherited)) border->mBorderRadius.SetBottom(coord); } // float-edge: enum, inherit if (eCSSUnit_Enumerated == marginData.mFloatEdge.GetUnit()) border->mFloatEdge = marginData.mFloatEdge.GetIntValue(); else if (eCSSUnit_Inherit == marginData.mFloatEdge.GetUnit()) { inherited = PR_TRUE; border->mFloatEdge = parentBorder->mFloatEdge; } if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_Border, *border); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mResetData) aHighestNode->mStyleData.mResetData = new (mPresContext) nsResetStyleData; aHighestNode->mStyleData.mResetData->mBorderData = border; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_BORDER, aHighestNode); } border->RecalcData(); return border; } const nsStyleStruct* nsRuleNode::ComputePaddingData(nsStyleStruct* aStartStruct, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW PADDING CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSMargin& marginData = NS_STATIC_CAST(const nsCSSMargin&, aData); nsStylePadding* padding; if (aStartStruct) // We only need to compute the delta between this computed data and our // computed data. padding = new (mPresContext) nsStylePadding(*NS_STATIC_CAST(nsStylePadding*, aStartStruct)); else padding = new (mPresContext) nsStylePadding(); const nsStylePadding* parentPadding = padding; if (parentContext) parentPadding = NS_STATIC_CAST(const nsStylePadding*, parentContext->GetStyleData(eStyleStruct_Padding)); PRBool inherited = aInherited; // padding: length, percent, inherit if (marginData.mPadding) { nsStyleCoord coord; nsStyleCoord parentCoord; parentPadding->mPadding.GetLeft(parentCoord); if (SetCoord(marginData.mPadding->mLeft, coord, parentCoord, SETCOORD_LPH, aContext, mPresContext, inherited)) { padding->mPadding.SetLeft(coord); } parentPadding->mPadding.GetTop(parentCoord); if (SetCoord(marginData.mPadding->mTop, coord, parentCoord, SETCOORD_LPH, aContext, mPresContext, inherited)) { padding->mPadding.SetTop(coord); } parentPadding->mPadding.GetRight(parentCoord); if (SetCoord(marginData.mPadding->mRight, coord, parentCoord, SETCOORD_LPH, aContext, mPresContext, inherited)) { padding->mPadding.SetRight(coord); } parentPadding->mPadding.GetBottom(parentCoord); if (SetCoord(marginData.mPadding->mBottom, coord, parentCoord, SETCOORD_LPH, aContext, mPresContext, inherited)) { padding->mPadding.SetBottom(coord); } } if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_Padding, *padding); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mResetData) aHighestNode->mStyleData.mResetData = new (mPresContext) nsResetStyleData; aHighestNode->mStyleData.mResetData->mPaddingData = padding; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_PADDING, aHighestNode); } padding->RecalcData(); return padding; } const nsStyleStruct* nsRuleNode::ComputeOutlineData(nsStyleStruct* aStartStruct, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW OUTLINE CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSMargin& marginData = NS_STATIC_CAST(const nsCSSMargin&, aData); nsStyleOutline* outline; if (aStartStruct) // We only need to compute the delta between this computed data and our // computed data. outline = new (mPresContext) nsStyleOutline(*NS_STATIC_CAST(nsStyleOutline*, aStartStruct)); else outline = new (mPresContext) nsStyleOutline(mPresContext); const nsStyleOutline* parentOutline = outline; if (parentContext) parentOutline = NS_STATIC_CAST(const nsStyleOutline*, parentContext->GetStyleData(eStyleStruct_Outline)); PRBool inherited = aInherited; // outline-width: length, enum, inherit SetCoord(marginData.mOutlineWidth, outline->mOutlineWidth, parentOutline->mOutlineWidth, SETCOORD_LEH, aContext, mPresContext, inherited); // outline-color: color, string, enum, inherit nscolor outlineColor; nscolor unused = NS_RGB(0,0,0); if (eCSSUnit_Inherit == marginData.mOutlineColor.GetUnit()) { inherited = PR_TRUE; if (parentOutline->GetOutlineColor(outlineColor)) outline->SetOutlineColor(outlineColor); else outline->SetOutlineInvert(); } else if (SetColor(marginData.mOutlineColor, unused, mPresContext, outlineColor, inherited)) outline->SetOutlineColor(outlineColor); else if (eCSSUnit_Enumerated == marginData.mOutlineColor.GetUnit()) outline->SetOutlineInvert(); // outline-style: enum, none, inherit if (eCSSUnit_Enumerated == marginData.mOutlineStyle.GetUnit()) outline->SetOutlineStyle(marginData.mOutlineStyle.GetIntValue()); else if (eCSSUnit_None == marginData.mOutlineStyle.GetUnit()) outline->SetOutlineStyle(NS_STYLE_BORDER_STYLE_NONE); else if (eCSSUnit_Inherit == marginData.mOutlineStyle.GetUnit()) { inherited = PR_TRUE; outline->SetOutlineStyle(parentOutline->GetOutlineStyle()); } if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_Outline, *outline); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mResetData) aHighestNode->mStyleData.mResetData = new (mPresContext) nsResetStyleData; aHighestNode->mStyleData.mResetData->mOutlineData = outline; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_OUTLINE, aHighestNode); } outline->RecalcData(); return outline; } const nsStyleStruct* nsRuleNode::ComputeListData(nsStyleStruct* aStartStruct, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW LIST CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSList& listData = NS_STATIC_CAST(const nsCSSList&, aData); nsStyleList* list = nsnull; const nsStyleList* parentList = nsnull; PRBool inherited = aInherited; if (parentContext) parentList = NS_STATIC_CAST(const nsStyleList*, parentContext->GetStyleData(eStyleStruct_List)); if (aStartStruct) // We only need to compute the delta between this computed data and our // computed data. list = new (mPresContext) nsStyleList(*NS_STATIC_CAST(nsStyleList*, aStartStruct)); else { if (aRuleDetail != eRuleFullMixed) { // No question. We will have to inherit. Go ahead and init // with inherited vals from parent. inherited = PR_TRUE; if (parentList) list = new (mPresContext) nsStyleList(*parentList); } } if (!list) list = new (mPresContext) nsStyleList(); if (!parentList) parentList = list; // list-style-type: enum, none, inherit if (eCSSUnit_Enumerated == listData.mType.GetUnit()) { list->mListStyleType = listData.mType.GetIntValue(); } else if (eCSSUnit_None == listData.mType.GetUnit()) { list->mListStyleType = NS_STYLE_LIST_STYLE_NONE; } else if (eCSSUnit_Inherit == listData.mType.GetUnit()) { inherited = PR_TRUE; list->mListStyleType = parentList->mListStyleType; } // list-style-image: url, none, inherit if (eCSSUnit_URL == listData.mImage.GetUnit()) { listData.mImage.GetStringValue(list->mListStyleImage); } else if (eCSSUnit_None == listData.mImage.GetUnit()) { list->mListStyleImage.Truncate(); } else if (eCSSUnit_Inherit == listData.mImage.GetUnit()) { inherited = PR_TRUE; list->mListStyleImage = parentList->mListStyleImage; } // list-style-position: enum, inherit if (eCSSUnit_Enumerated == listData.mPosition.GetUnit()) { list->mListStylePosition = listData.mPosition.GetIntValue(); } else if (eCSSUnit_Inherit == listData.mPosition.GetUnit()) { inherited = PR_TRUE; list->mListStylePosition = parentList->mListStylePosition; } // image region property: length, auto, inherit if (listData.mImageRegion) { if (eCSSUnit_Inherit == listData.mImageRegion->mTop.GetUnit()) { // if one is inherit, they all are inherited = PR_TRUE; list->mImageRegion = parentList->mImageRegion; } else { if (eCSSUnit_Auto == listData.mImageRegion->mTop.GetUnit()) list->mImageRegion.y = 0; else if (listData.mImageRegion->mTop.IsLengthUnit()) list->mImageRegion.y = CalcLength(listData.mImageRegion->mTop, nsnull, aContext, mPresContext, inherited); if (eCSSUnit_Auto == listData.mImageRegion->mBottom.GetUnit()) list->mImageRegion.height = 0; else if (listData.mImageRegion->mBottom.IsLengthUnit()) list->mImageRegion.height = CalcLength(listData.mImageRegion->mBottom, nsnull, aContext, mPresContext, inherited) - list->mImageRegion.y; if (eCSSUnit_Auto == listData.mImageRegion->mLeft.GetUnit()) list->mImageRegion.x = 0; else if (listData.mImageRegion->mLeft.IsLengthUnit()) list->mImageRegion.x = CalcLength(listData.mImageRegion->mLeft, nsnull, aContext, mPresContext, inherited); if (eCSSUnit_Auto == listData.mImageRegion->mRight.GetUnit()) list->mImageRegion.width = 0; else if (listData.mImageRegion->mRight.IsLengthUnit()) list->mImageRegion.width = CalcLength(listData.mImageRegion->mRight, nsnull, aContext, mPresContext, inherited) - list->mImageRegion.x; } } if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_List, *list); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mInheritedData) aHighestNode->mStyleData.mInheritedData = new (mPresContext) nsInheritedStyleData; aHighestNode->mStyleData.mInheritedData->mListData = list; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_LIST, aHighestNode); } return list; } const nsStyleStruct* nsRuleNode::ComputePositionData(nsStyleStruct* aStartStruct, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW POSITION CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSPosition& posData = NS_STATIC_CAST(const nsCSSPosition&, aData); nsStylePosition* pos; if (aStartStruct) // We only need to compute the delta between this computed data and our // computed data. pos = new (mPresContext) nsStylePosition(*NS_STATIC_CAST(nsStylePosition*, aStartStruct)); else pos = new (mPresContext) nsStylePosition(); const nsStylePosition* parentPos = pos; if (parentContext) parentPos = NS_STATIC_CAST(const nsStylePosition*, parentContext->GetStyleData(eStyleStruct_Position)); PRBool inherited = aInherited; // box offsets: length, percent, auto, inherit if (posData.mOffset) { nsStyleCoord coord; nsStyleCoord parentCoord; parentPos->mOffset.GetTop(parentCoord); if (SetCoord(posData.mOffset->mTop, coord, parentCoord, SETCOORD_LPAH, aContext, mPresContext, inherited)) { pos->mOffset.SetTop(coord); } parentPos->mOffset.GetRight(parentCoord); if (SetCoord(posData.mOffset->mRight, coord, parentCoord, SETCOORD_LPAH, aContext, mPresContext, inherited)) { pos->mOffset.SetRight(coord); } parentPos->mOffset.GetBottom(parentCoord); if (SetCoord(posData.mOffset->mBottom, coord, parentCoord, SETCOORD_LPAH, aContext, mPresContext, inherited)) { pos->mOffset.SetBottom(coord); } parentPos->mOffset.GetLeft(parentCoord); if (SetCoord(posData.mOffset->mLeft, coord, parentCoord, SETCOORD_LPAH, aContext, mPresContext, inherited)) { pos->mOffset.SetLeft(coord); } } if (posData.mWidth.GetUnit() == eCSSUnit_Proportional) pos->mWidth.SetIntValue((PRInt32)(posData.mWidth.GetFloatValue()), eStyleUnit_Proportional); else SetCoord(posData.mWidth, pos->mWidth, parentPos->mWidth, SETCOORD_LPAH, aContext, mPresContext, inherited); SetCoord(posData.mMinWidth, pos->mMinWidth, parentPos->mMinWidth, SETCOORD_LPH, aContext, mPresContext, inherited); if (! SetCoord(posData.mMaxWidth, pos->mMaxWidth, parentPos->mMaxWidth, SETCOORD_LPH, aContext, mPresContext, inherited)) { if (eCSSUnit_None == posData.mMaxWidth.GetUnit()) { pos->mMaxWidth.Reset(); } } SetCoord(posData.mHeight, pos->mHeight, parentPos->mHeight, SETCOORD_LPAH, aContext, mPresContext, inherited); SetCoord(posData.mMinHeight, pos->mMinHeight, parentPos->mMinHeight, SETCOORD_LPH, aContext, mPresContext, inherited); if (! SetCoord(posData.mMaxHeight, pos->mMaxHeight, parentPos->mMaxHeight, SETCOORD_LPH, aContext, mPresContext, inherited)) { if (eCSSUnit_None == posData.mMaxHeight.GetUnit()) { pos->mMaxHeight.Reset(); } } // box-sizing: enum, inherit if (eCSSUnit_Enumerated == posData.mBoxSizing.GetUnit()) { pos->mBoxSizing = posData.mBoxSizing.GetIntValue(); } else if (eCSSUnit_Inherit == posData.mBoxSizing.GetUnit()) { inherited = PR_TRUE; pos->mBoxSizing = parentPos->mBoxSizing; } // z-index if (! SetCoord(posData.mZIndex, pos->mZIndex, parentPos->mZIndex, SETCOORD_IA, aContext, nsnull, inherited)) { if (eCSSUnit_Inherit == posData.mZIndex.GetUnit()) { // handle inherit, because it's ok to inherit 'auto' here inherited = PR_TRUE; pos->mZIndex = parentPos->mZIndex; } } if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_Position, *pos); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mResetData) aHighestNode->mStyleData.mResetData = new (mPresContext) nsResetStyleData; aHighestNode->mStyleData.mResetData->mPositionData = pos; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_POSITION, aHighestNode); } return pos; } const nsStyleStruct* nsRuleNode::ComputeTableData(nsStyleStruct* aStartStruct, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW TABLE CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSTable& tableData = NS_STATIC_CAST(const nsCSSTable&, aData); nsStyleTable* table; if (aStartStruct) // We only need to compute the delta between this computed data and our // computed data. table = new (mPresContext) nsStyleTable(*NS_STATIC_CAST(nsStyleTable*, aStartStruct)); else table = new (mPresContext) nsStyleTable(); const nsStyleTable* parentTable = table; if (parentContext) parentTable = NS_STATIC_CAST(const nsStyleTable*, parentContext->GetStyleData(eStyleStruct_Table)); PRBool inherited = aInherited; // table-layout: auto, enum, inherit if (eCSSUnit_Enumerated == tableData.mLayout.GetUnit()) table->mLayoutStrategy = tableData.mLayout.GetIntValue(); else if (eCSSUnit_Auto == tableData.mLayout.GetUnit()) table->mLayoutStrategy = NS_STYLE_TABLE_LAYOUT_AUTO; else if (eCSSUnit_Inherit == tableData.mLayout.GetUnit()) { inherited = PR_TRUE; table->mLayoutStrategy = parentTable->mLayoutStrategy; } // rules: enum (not a real CSS prop) if (eCSSUnit_Enumerated == tableData.mRules.GetUnit()) table->mRules = tableData.mRules.GetIntValue(); // frame: enum (not a real CSS prop) if (eCSSUnit_Enumerated == tableData.mFrame.GetUnit()) table->mFrame = tableData.mFrame.GetIntValue(); // cols: enum, int (not a real CSS prop) if (eCSSUnit_Enumerated == tableData.mCols.GetUnit() || eCSSUnit_Integer == tableData.mCols.GetUnit()) table->mCols = tableData.mCols.GetIntValue(); // span: pixels (not a real CSS prop) if (eCSSUnit_Enumerated == tableData.mSpan.GetUnit() || eCSSUnit_Integer == tableData.mSpan.GetUnit()) table->mSpan = tableData.mSpan.GetIntValue(); if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_Table, *table); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mResetData) aHighestNode->mStyleData.mResetData = new (mPresContext) nsResetStyleData; aHighestNode->mStyleData.mResetData->mTableData = table; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_TABLE, aHighestNode); } return table; } const nsStyleStruct* nsRuleNode::ComputeTableBorderData(nsStyleStruct* aStartStruct, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW TABLE BORDER CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSTable& tableData = NS_STATIC_CAST(const nsCSSTable&, aData); nsStyleTableBorder* table = nsnull; const nsStyleTableBorder* parentTable = nsnull; PRBool inherited = aInherited; if (parentContext) parentTable = NS_STATIC_CAST(const nsStyleTableBorder*, parentContext->GetStyleData(eStyleStruct_TableBorder)); if (aStartStruct) // We only need to compute the delta between this computed data and our // computed data. table = new (mPresContext) nsStyleTableBorder(*NS_STATIC_CAST(nsStyleTableBorder*, aStartStruct)); else { if (aRuleDetail != eRuleFullMixed) { // No question. We will have to inherit. Go ahead and init // with inherited vals from parent. inherited = PR_TRUE; if (parentTable) table = new (mPresContext) nsStyleTableBorder(*parentTable); } } if (!table) table = new (mPresContext) nsStyleTableBorder(mPresContext); if (!parentTable) parentTable = table; // border-collapse: enum, inherit if (eCSSUnit_Enumerated == tableData.mBorderCollapse.GetUnit()) { table->mBorderCollapse = tableData.mBorderCollapse.GetIntValue(); } else if (eCSSUnit_Inherit == tableData.mBorderCollapse.GetUnit()) { inherited = PR_TRUE; table->mBorderCollapse = parentTable->mBorderCollapse; } nsStyleCoord coord; // border-spacing-x: length, inherit if (SetCoord(tableData.mBorderSpacingX, coord, coord, SETCOORD_LENGTH, aContext, mPresContext, inherited)) { table->mBorderSpacingX = coord.GetCoordValue(); } else if (eCSSUnit_Inherit == tableData.mBorderSpacingX.GetUnit()) { inherited = PR_TRUE; table->mBorderSpacingX = parentTable->mBorderSpacingX; } // border-spacing-y: length, inherit if (SetCoord(tableData.mBorderSpacingY, coord, coord, SETCOORD_LENGTH, aContext, mPresContext, inherited)) { table->mBorderSpacingY = coord.GetCoordValue(); } else if (eCSSUnit_Inherit == tableData.mBorderSpacingY.GetUnit()) { inherited = PR_TRUE; table->mBorderSpacingY = parentTable->mBorderSpacingY; } // caption-side: enum, inherit if (eCSSUnit_Enumerated == tableData.mCaptionSide.GetUnit()) { table->mCaptionSide = tableData.mCaptionSide.GetIntValue(); } else if (eCSSUnit_Inherit == tableData.mCaptionSide.GetUnit()) { inherited = PR_TRUE; table->mCaptionSide = parentTable->mCaptionSide; } // empty-cells: enum, inherit if (eCSSUnit_Enumerated == tableData.mEmptyCells.GetUnit()) { table->mEmptyCells = tableData.mEmptyCells.GetIntValue(); } else if (eCSSUnit_Inherit == tableData.mEmptyCells.GetUnit()) { inherited = PR_TRUE; table->mEmptyCells = parentTable->mEmptyCells; } if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_TableBorder, *table); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mInheritedData) aHighestNode->mStyleData.mInheritedData = new (mPresContext) nsInheritedStyleData; aHighestNode->mStyleData.mInheritedData->mTableData = table; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_TABLE_BORDER, aHighestNode); } return table; } const nsStyleStruct* nsRuleNode::ComputeContentData(nsStyleStruct* aStartStruct, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW CONTENT CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSContent& contentData = NS_STATIC_CAST(const nsCSSContent&, aData); nsStyleContent* content; if (aStartStruct) // We only need to compute the delta between this computed data and our // computed data. content = new (mPresContext) nsStyleContent(*NS_STATIC_CAST(nsStyleContent*, aStartStruct)); else content = new (mPresContext) nsStyleContent(); const nsStyleContent* parentContent = content; if (parentContext) parentContent = NS_STATIC_CAST(const nsStyleContent*, parentContext->GetStyleData(eStyleStruct_Content)); PRBool inherited = aInherited; // content: [string, url, counter, attr, enum]+, inherit PRUint32 count; nsAutoString buffer; nsCSSValueList* contentValue = contentData.mContent; if (contentValue) { if (eCSSUnit_Inherit == contentValue->mValue.GetUnit()) { inherited = PR_TRUE; count = parentContent->ContentCount(); if (NS_SUCCEEDED(content->AllocateContents(count))) { nsStyleContentType type; while (0 < count--) { parentContent->GetContentAt(count, type, buffer); content->SetContentAt(count, type, buffer); } } } else { count = 0; while (contentValue) { count++; contentValue = contentValue->mNext; } if (NS_SUCCEEDED(content->AllocateContents(count))) { const nsAutoString nullStr; count = 0; contentValue = contentData.mContent; while (contentValue) { const nsCSSValue& value = contentValue->mValue; nsCSSUnit unit = value.GetUnit(); nsStyleContentType type; switch (unit) { case eCSSUnit_String: type = eStyleContentType_String; break; case eCSSUnit_URL: type = eStyleContentType_URL; break; case eCSSUnit_Attr: type = eStyleContentType_Attr; break; case eCSSUnit_Counter: type = eStyleContentType_Counter; break; case eCSSUnit_Counters: type = eStyleContentType_Counters; break; case eCSSUnit_Enumerated: switch (value.GetIntValue()) { case NS_STYLE_CONTENT_OPEN_QUOTE: type = eStyleContentType_OpenQuote; break; case NS_STYLE_CONTENT_CLOSE_QUOTE: type = eStyleContentType_CloseQuote; break; case NS_STYLE_CONTENT_NO_OPEN_QUOTE: type = eStyleContentType_NoOpenQuote; break; case NS_STYLE_CONTENT_NO_CLOSE_QUOTE: type = eStyleContentType_NoCloseQuote; break; default: NS_ERROR("bad content value"); } break; default: NS_ERROR("bad content type"); } if (type < eStyleContentType_OpenQuote) { value.GetStringValue(buffer); Unquote(buffer); content->SetContentAt(count++, type, buffer); } else { content->SetContentAt(count++, type, nullStr); } contentValue = contentValue->mNext; } } } } // counter-increment: [string [int]]+, none, inherit nsCSSCounterData* ourIncrement = contentData.mCounterIncrement; if (ourIncrement) { PRInt32 increment; if (eCSSUnit_Inherit == ourIncrement->mCounter.GetUnit()) { inherited = PR_TRUE; count = parentContent->CounterIncrementCount(); if (NS_SUCCEEDED(content->AllocateCounterIncrements(count))) { while (0 < count--) { parentContent->GetCounterIncrementAt(count, buffer, increment); content->SetCounterIncrementAt(count, buffer, increment); } } } else if (eCSSUnit_None == ourIncrement->mCounter.GetUnit()) { content->AllocateCounterIncrements(0); } else if (eCSSUnit_String == ourIncrement->mCounter.GetUnit()) { count = 0; while (ourIncrement) { count++; ourIncrement = ourIncrement->mNext; } if (NS_SUCCEEDED(content->AllocateCounterIncrements(count))) { count = 0; ourIncrement = contentData.mCounterIncrement; while (ourIncrement) { if (eCSSUnit_Integer == ourIncrement->mValue.GetUnit()) { increment = ourIncrement->mValue.GetIntValue(); } else { increment = 1; } ourIncrement->mCounter.GetStringValue(buffer); content->SetCounterIncrementAt(count++, buffer, increment); ourIncrement = ourIncrement->mNext; } } } } // counter-reset: [string [int]]+, none, inherit nsCSSCounterData* ourReset = contentData.mCounterReset; if (ourReset) { PRInt32 reset; if (eCSSUnit_Inherit == ourReset->mCounter.GetUnit()) { inherited = PR_TRUE; count = parentContent->CounterResetCount(); if (NS_SUCCEEDED(content->AllocateCounterResets(count))) { while (0 < count--) { parentContent->GetCounterResetAt(count, buffer, reset); content->SetCounterResetAt(count, buffer, reset); } } } else if (eCSSUnit_None == ourReset->mCounter.GetUnit()) { content->AllocateCounterResets(0); } else if (eCSSUnit_String == ourReset->mCounter.GetUnit()) { count = 0; while (ourReset) { count++; ourReset = ourReset->mNext; } if (NS_SUCCEEDED(content->AllocateCounterResets(count))) { count = 0; ourReset = contentData.mCounterReset; while (ourReset) { if (eCSSUnit_Integer == ourReset->mValue.GetUnit()) { reset = ourReset->mValue.GetIntValue(); } else { reset = 0; } ourReset->mCounter.GetStringValue(buffer); content->SetCounterResetAt(count++, buffer, reset); ourReset = ourReset->mNext; } } } } // marker-offset: length, auto, inherit SetCoord(contentData.mMarkerOffset, content->mMarkerOffset, parentContent->mMarkerOffset, SETCOORD_LH | SETCOORD_AUTO, aContext, mPresContext, inherited); if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_Content, *content); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mResetData) aHighestNode->mStyleData.mResetData = new (mPresContext) nsResetStyleData; aHighestNode->mStyleData.mResetData->mContentData = content; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_CONTENT, aHighestNode); } return content; } const nsStyleStruct* nsRuleNode::ComputeQuotesData(nsStyleStruct* aStartStruct, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW QUOTES CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSContent& contentData = NS_STATIC_CAST(const nsCSSContent&, aData); nsStyleQuotes* quotes = nsnull; const nsStyleQuotes* parentQuotes = nsnull; PRBool inherited = aInherited; if (parentContext) parentQuotes = NS_STATIC_CAST(const nsStyleQuotes*, parentContext->GetStyleData(eStyleStruct_Quotes)); if (aStartStruct) // We only need to compute the delta between this computed data and our // computed data. quotes = new (mPresContext) nsStyleQuotes(*NS_STATIC_CAST(nsStyleQuotes*, aStartStruct)); else { if (aRuleDetail != eRuleFullMixed) { // No question. We will have to inherit. Go ahead and init // with inherited vals from parent. inherited = PR_TRUE; if (parentQuotes) quotes = new (mPresContext) nsStyleQuotes(*parentQuotes); } } if (!quotes) quotes = new (mPresContext) nsStyleQuotes(); if (!parentQuotes) parentQuotes = quotes; // quotes: [string string]+, none, inherit PRUint32 count; nsAutoString buffer; nsCSSQuotes* ourQuotes = contentData.mQuotes; if (ourQuotes) { nsAutoString closeBuffer; if (eCSSUnit_Inherit == ourQuotes->mOpen.GetUnit()) { inherited = PR_TRUE; count = parentQuotes->QuotesCount(); if (NS_SUCCEEDED(quotes->AllocateQuotes(count))) { while (0 < count--) { parentQuotes->GetQuotesAt(count, buffer, closeBuffer); quotes->SetQuotesAt(count, buffer, closeBuffer); } } } else if (eCSSUnit_None == ourQuotes->mOpen.GetUnit()) { quotes->AllocateQuotes(0); } else if (eCSSUnit_String == ourQuotes->mOpen.GetUnit()) { count = 0; while (ourQuotes) { count++; ourQuotes = ourQuotes->mNext; } if (NS_SUCCEEDED(quotes->AllocateQuotes(count))) { count = 0; ourQuotes = contentData.mQuotes; while (ourQuotes) { ourQuotes->mOpen.GetStringValue(buffer); ourQuotes->mClose.GetStringValue(closeBuffer); Unquote(buffer); Unquote(closeBuffer); quotes->SetQuotesAt(count++, buffer, closeBuffer); ourQuotes = ourQuotes->mNext; } } } } if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_Quotes, *quotes); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mInheritedData) aHighestNode->mStyleData.mInheritedData = new (mPresContext) nsInheritedStyleData; aHighestNode->mStyleData.mInheritedData->mQuotesData = quotes; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_QUOTES, aHighestNode); } return quotes; } #ifdef INCLUDE_XUL const nsStyleStruct* nsRuleNode::ComputeXULData(nsStyleStruct* aStartStruct, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { #ifdef DEBUG_hyatt printf("NEW XUL CREATED!\n"); #endif nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); const nsCSSXUL& xulData = NS_STATIC_CAST(const nsCSSXUL&, aData); nsStyleXUL* xul = nsnull; if (aStartStruct) // We only need to compute the delta between this computed data and our // computed data. xul = new (mPresContext) nsStyleXUL(*NS_STATIC_CAST(nsStyleXUL*, aStartStruct)); else xul = new (mPresContext) nsStyleXUL(); const nsStyleXUL* parentXUL = xul; if (parentContext) parentXUL = NS_STATIC_CAST(const nsStyleXUL*, parentContext->GetStyleData(eStyleStruct_XUL)); PRBool inherited = aInherited; // box-align: enum, inherit if (eCSSUnit_Enumerated == xulData.mBoxAlign.GetUnit()) { xul->mBoxAlign = xulData.mBoxAlign.GetIntValue(); } else if (eCSSUnit_Inherit == xulData.mBoxAlign.GetUnit()) { inherited = PR_TRUE; xul->mBoxAlign = parentXUL->mBoxAlign; } // box-direction: enum, inherit if (eCSSUnit_Enumerated == xulData.mBoxDirection.GetUnit()) { xul->mBoxDirection = xulData.mBoxDirection.GetIntValue(); } else if (eCSSUnit_Inherit == xulData.mBoxDirection.GetUnit()) { inherited = PR_TRUE; xul->mBoxDirection = parentXUL->mBoxDirection; } // box-flex: factor, inherit if (eCSSUnit_Number == xulData.mBoxFlex.GetUnit()) { xul->mBoxFlex = xulData.mBoxFlex.GetFloatValue(); } else if (eCSSUnit_Inherit == xulData.mBoxOrient.GetUnit()) { inherited = PR_TRUE; xul->mBoxFlex = parentXUL->mBoxFlex; } // box-orient: enum, inherit if (eCSSUnit_Enumerated == xulData.mBoxOrient.GetUnit()) { xul->mBoxOrient = xulData.mBoxOrient.GetIntValue(); } else if (eCSSUnit_Inherit == xulData.mBoxOrient.GetUnit()) { inherited = PR_TRUE; xul->mBoxOrient = parentXUL->mBoxOrient; } // box-pack: enum, inherit if (eCSSUnit_Enumerated == xulData.mBoxPack.GetUnit()) { xul->mBoxPack = xulData.mBoxPack.GetIntValue(); } else if (eCSSUnit_Inherit == xulData.mBoxPack.GetUnit()) { inherited = PR_TRUE; xul->mBoxPack = parentXUL->mBoxPack; } // box-ordinal-group: integer if (eCSSUnit_Integer == xulData.mBoxOrdinal.GetUnit()) { xul->mBoxOrdinal = xulData.mBoxOrdinal.GetIntValue(); } if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_XUL, *xul); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mResetData) aHighestNode->mStyleData.mResetData = new (mPresContext) nsResetStyleData; aHighestNode->mStyleData.mResetData->mXULData = xul; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_XUL, aHighestNode); } return xul; } #endif #ifdef MOZ_SVG static void SetSVGPaint(const nsCSSValue& aValue, const nsStyleSVGPaint& parentPaint, nsIPresContext* aPresContext, nsStyleSVGPaint& aResult, PRBool& aInherited) { if (aValue.GetUnit() == eCSSUnit_Inherit) { aResult = parentPaint; aInherited = PR_TRUE; } else if (aValue.GetUnit() == eCSSUnit_None) { aResult.mType = eStyleSVGPaintType_None; } else if (SetColor(aValue, parentPaint.mColor, aPresContext, aResult.mColor, aInherited)) { aResult.mType = eStyleSVGPaintType_Color; } } static void SetSVGOpacity(const nsCSSValue& aValue, float parentOpacity, float& opacity, PRBool& aInherited) { if (aValue.GetUnit() == eCSSUnit_Inherit) { opacity = parentOpacity; aInherited = PR_TRUE; } else if (aValue.GetUnit() == eCSSUnit_Number) { opacity = aValue.GetFloatValue(); } } static void SetSVGLength(const nsCSSValue& aValue, float parentLength, float& length, nsIStyleContext* aContext, nsIPresContext* aPresContext, PRBool& aInherited) { nsStyleCoord coord; PRBool dummy; if (SetCoord(aValue, coord, coord, SETCOORD_LP | SETCOORD_FACTOR, aContext, aPresContext, dummy)) { if (coord.GetUnit() == eStyleUnit_Factor) { // user units length = (float) coord.GetFactorValue(); } else { length = (float) coord.GetCoordValue(); float twipsPerPix; aPresContext->GetScaledPixelsToTwips(&twipsPerPix); if (twipsPerPix == 0.0f) twipsPerPix = 1e-20f; length /= twipsPerPix; } } else if (aValue.GetUnit() == eCSSUnit_Inherit) { length = parentLength; aInherited = PR_TRUE; } } const nsStyleStruct* nsRuleNode::ComputeSVGData(nsStyleStruct* aStartStruct, const nsCSSStruct& aData, nsIStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail& aRuleDetail, PRBool aInherited) { nsCOMPtr parentContext = getter_AddRefs(aContext->GetParent()); nsStyleSVG* svg = nsnull; nsStyleSVG* parentSVG = svg; PRBool inherited = aInherited; const nsCSSSVG& SVGData = NS_STATIC_CAST(const nsCSSSVG&, aData); if (aStartStruct) // We only need to compute the delta between this computed data and our // computed data. svg = new (mPresContext) nsStyleSVG(*NS_STATIC_CAST(nsStyleSVG*,aStartStruct)); else { if (aRuleDetail != eRuleFullMixed) { // No question. We will have to inherit. Go ahead and init // with inherited vals from parent. inherited = PR_TRUE; if (parentContext) parentSVG = (nsStyleSVG*)parentContext->GetStyleData(eStyleStruct_SVG); if (parentSVG) svg = new (mPresContext) nsStyleSVG(*parentSVG); } } if (!svg) svg = parentSVG = new (mPresContext) nsStyleSVG(); // fill: SetSVGPaint(SVGData.mFill, parentSVG->mFill, mPresContext, svg->mFill, inherited); // fill-opacity: SetSVGOpacity(SVGData.mFillOpacity, parentSVG->mFillOpacity, svg->mFillOpacity, inherited); // fill-rule: enum, inherit if (eCSSUnit_Enumerated == SVGData.mFillRule.GetUnit()) { svg->mFillRule = SVGData.mFillRule.GetIntValue(); } else if (eCSSUnit_Inherit == SVGData.mFillRule.GetUnit()) { inherited = PR_TRUE; svg->mFillRule = parentSVG->mFillRule; } // stroke: SetSVGPaint(SVGData.mStroke, parentSVG->mStroke, mPresContext, svg->mStroke, inherited); // stroke-dasharray: , none, inherit if (eCSSUnit_String == SVGData.mStrokeDasharray.GetUnit()) { SVGData.mStrokeDasharray.GetStringValue(svg->mStrokeDasharray); } else if (eCSSUnit_None == SVGData.mStrokeDasharray.GetUnit()) { svg->mStrokeDasharray.Truncate(); } else if (eCSSUnit_Inherit == SVGData.mStrokeDasharray.GetUnit()) { inherited = PR_TRUE; svg->mStrokeDasharray = parentSVG->mStrokeDasharray; } // stroke-dashoffset: , inherit SetSVGLength(SVGData.mStrokeDashoffset, parentSVG->mStrokeDashoffset, svg->mStrokeDashoffset, aContext, mPresContext, inherited); // stroke-linecap: enum, inherit if (eCSSUnit_Enumerated == SVGData.mStrokeLinecap.GetUnit()) { svg->mStrokeLinecap = SVGData.mStrokeLinecap.GetIntValue(); } else if (eCSSUnit_Inherit == SVGData.mStrokeLinecap.GetUnit()) { inherited = PR_TRUE; svg->mStrokeLinecap = parentSVG->mStrokeLinecap; } // stroke-linejoin: enum, inherit if (eCSSUnit_Enumerated == SVGData.mStrokeLinejoin.GetUnit()) { svg->mStrokeLinejoin = SVGData.mStrokeLinejoin.GetIntValue(); } else if (eCSSUnit_Inherit == SVGData.mStrokeLinejoin.GetUnit()) { inherited = PR_TRUE; svg->mStrokeLinejoin = parentSVG->mStrokeLinejoin; } // stroke-miterlimit: , inherit if (eCSSUnit_Number == SVGData.mStrokeMiterlimit.GetUnit()) { float value = SVGData.mStrokeMiterlimit.GetFloatValue(); if (value > 1) { // XXX this check should probably be in nsCSSParser svg->mStrokeMiterlimit = value; } } else if (eCSSUnit_Inherit == SVGData.mStrokeMiterlimit.GetUnit()) { svg->mStrokeMiterlimit = parentSVG->mStrokeMiterlimit; inherited = PR_TRUE; } // stroke-opacity: SetSVGOpacity(SVGData.mStrokeOpacity, parentSVG->mStrokeOpacity, svg->mStrokeOpacity, inherited); // stroke-width: SetSVGLength(SVGData.mStrokeWidth, parentSVG->mStrokeWidth, svg->mStrokeWidth, aContext, mPresContext, inherited); if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. aContext->SetStyle(eStyleStruct_SVG, *svg); else { // We were fully specified and can therefore be cached right on the rule node. if (!aHighestNode->mStyleData.mInheritedData) aHighestNode->mStyleData.mInheritedData = new (mPresContext) nsInheritedStyleData; aHighestNode->mStyleData.mInheritedData->mSVGData = svg; // Propagate the bit down. PropagateInheritBit(NS_STYLE_INHERIT_SVG, aHighestNode); } return svg; } #endif inline const nsStyleStruct* nsRuleNode::GetParentData(const nsStyleStructID aSID) { nsRuleNode* ruleNode = mParent; nsStyleStruct* currStruct = nsnull; while (ruleNode) { currStruct = ruleNode->mStyleData.GetStyleData(aSID); if (currStruct) break; // We found a rule with fully specified data. We don't need to go up // the tree any further, since the remainder of this branch has already // been computed. ruleNode = ruleNode->mParent; // Climb up to the next rule in the tree (a less specific rule). } return currStruct; // Just return whatever we found. } nsRuleNode::GetStyleDataFn nsRuleNode::gGetStyleDataFn[] = { // Note that these must line up _exactly_ with the numeric values of // the nsStyleStructID enum. nsnull, &nsRuleNode::GetFontData, &nsRuleNode::GetColorData, &nsRuleNode::GetBackgroundData, &nsRuleNode::GetListData, &nsRuleNode::GetPositionData, &nsRuleNode::GetTextData, &nsRuleNode::GetTextResetData, &nsRuleNode::GetDisplayData, &nsRuleNode::GetVisibilityData, &nsRuleNode::GetContentData, &nsRuleNode::GetQuotesData, &nsRuleNode::GetUIData, &nsRuleNode::GetUIResetData, &nsRuleNode::GetTableData, &nsRuleNode::GetTableBorderData, &nsRuleNode::GetMarginData, &nsRuleNode::GetPaddingData, &nsRuleNode::GetBorderData, &nsRuleNode::GetOutlineData, #ifdef INCLUDE_XUL &nsRuleNode::GetXULData, #endif #ifdef MOZ_SVG &nsRuleNode::GetSVGData, #endif nsnull }; const nsStyleStruct* nsRuleNode::GetStyleData(nsStyleStructID aSID, nsIStyleContext* aContext, PRBool aComputeData) { const nsStyleStruct* cachedData = mStyleData.GetStyleData(aSID); if (cachedData) return cachedData; // We have a fully specified struct. Just return it. if (InheritsFromParentRule(aSID)) return GetParentData(aSID); // We inherit. Just go up the rule tree and return the first // cached struct we find. // Nothing is cached. We'll have to delve further and examine our rules. GetStyleDataFn fn = gGetStyleDataFn[aSID]; return fn ? (this->*fn)(aContext, aComputeData) : nsnull; }