2001-09-25 05:32:19 +04:00
|
|
|
/* -*- 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
|
1998-04-14 00:24:54 +04:00
|
|
|
*
|
2001-09-25 05:32:19 +04:00
|
|
|
* 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/
|
1998-04-14 00:24:54 +04:00
|
|
|
*
|
2001-09-25 05:32:19 +04:00
|
|
|
* 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.
|
1998-04-14 00:24:54 +04:00
|
|
|
*
|
1999-11-06 06:40:37 +03:00
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
2001-09-25 05:32:19 +04:00
|
|
|
* 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.
|
1999-11-06 06:40:37 +03:00
|
|
|
*
|
2001-08-02 18:34:55 +04:00
|
|
|
* Contributor(s):
|
|
|
|
* Daniel Glazman <glazman@netscape.com>
|
2004-01-08 01:30:53 +03:00
|
|
|
* Brian Ryner <bryner@brianryner.com>
|
2001-09-25 05:32:19 +04:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* 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 ***** */
|
2004-01-08 01:30:53 +03:00
|
|
|
#include "nsStyleSet.h"
|
|
|
|
#include "nsNetUtil.h"
|
|
|
|
#include "nsICSSStyleSheet.h"
|
1999-01-23 10:01:57 +03:00
|
|
|
#include "nsIDocument.h"
|
2004-01-08 01:30:53 +03:00
|
|
|
#include "nsRuleWalker.h"
|
|
|
|
#include "nsStyleContext.h"
|
|
|
|
#include "nsICSSStyleRule.h"
|
2002-11-17 18:37:56 +03:00
|
|
|
#include "nsCSSAnonBoxes.h"
|
2003-02-23 20:28:25 +03:00
|
|
|
#include "nsCSSPseudoElements.h"
|
2004-01-08 01:30:53 +03:00
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "nsIFrame.h"
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
nsIURI *nsStyleSet::gQuirkURI = 0;
|
2000-11-08 06:13:53 +03:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
nsStyleSet::nsStyleSet()
|
|
|
|
: mRuleTree(nsnull),
|
2003-03-06 22:14:17 +03:00
|
|
|
mRuleWalker(nsnull),
|
2004-01-08 01:30:53 +03:00
|
|
|
mDestroyedCount(0),
|
2004-01-08 22:23:12 +03:00
|
|
|
mBatching(0),
|
2003-03-06 22:14:17 +03:00
|
|
|
mInShutdown(PR_FALSE),
|
2004-01-08 01:30:53 +03:00
|
|
|
mDirty(0)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
nsresult
|
|
|
|
nsStyleSet::Init(nsIPresContext *aPresContext)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2004-01-08 01:30:53 +03:00
|
|
|
if (!gQuirkURI) {
|
|
|
|
static const char kQuirk_href[] = "resource://gre/res/quirk.css";
|
|
|
|
NS_NewURI(&gQuirkURI, kQuirk_href);
|
|
|
|
NS_ENSURE_TRUE(gQuirkURI, NS_ERROR_OUT_OF_MEMORY);
|
2000-11-08 06:13:53 +03:00
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2004-01-08 22:23:12 +03:00
|
|
|
if (!BuildDefaultStyleData(aPresContext)) {
|
|
|
|
mDefaultStyleData.Destroy(0, aPresContext);
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
mRuleTree = nsRuleNode::CreateRootNode(aPresContext);
|
|
|
|
if (!mRuleTree) {
|
|
|
|
mDefaultStyleData.Destroy(0, aPresContext);
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
1999-10-08 07:09:31 +04:00
|
|
|
}
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
mRuleWalker = new nsRuleWalker(mRuleTree);
|
|
|
|
if (!mRuleWalker) {
|
|
|
|
mRuleTree->Destroy();
|
|
|
|
mDefaultStyleData.Destroy(0, aPresContext);
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
1999-10-08 07:09:31 +04:00
|
|
|
}
|
2001-11-06 13:04:05 +03:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
return NS_OK;
|
2000-08-12 10:28:02 +04:00
|
|
|
}
|
|
|
|
|
2001-11-11 02:51:45 +03:00
|
|
|
struct RuleProcessorEnumData {
|
2004-01-08 01:30:53 +03:00
|
|
|
RuleProcessorEnumData(nsCOMArray<nsIStyleRuleProcessor> *aRuleProcessors)
|
1999-10-08 07:09:31 +04:00
|
|
|
: mRuleProcessors(aRuleProcessors),
|
|
|
|
mPrevProcessor(nsnull)
|
|
|
|
{}
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
nsCOMArray<nsIStyleRuleProcessor>* mRuleProcessors;
|
1999-10-08 07:09:31 +04:00
|
|
|
nsIStyleRuleProcessor* mPrevProcessor;
|
|
|
|
};
|
|
|
|
|
|
|
|
static PRBool
|
2004-01-08 01:30:53 +03:00
|
|
|
EnumRuleProcessor(nsIStyleSheet *aSheet, void* aData)
|
1999-10-08 07:09:31 +04:00
|
|
|
{
|
2001-11-11 02:51:45 +03:00
|
|
|
RuleProcessorEnumData* data = (RuleProcessorEnumData*)aData;
|
1999-10-08 07:09:31 +04:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
nsCOMPtr<nsIStyleRuleProcessor> processor;
|
|
|
|
nsresult result = aSheet->GetStyleRuleProcessor(*getter_AddRefs(processor),
|
|
|
|
data->mPrevProcessor);
|
1999-10-08 07:09:31 +04:00
|
|
|
if (NS_SUCCEEDED(result) && processor) {
|
|
|
|
if (processor != data->mPrevProcessor) {
|
2004-01-08 01:30:53 +03:00
|
|
|
if (!data->mRuleProcessors->AppendObject(processor))
|
|
|
|
return PR_FALSE;
|
1999-10-08 07:09:31 +04:00
|
|
|
data->mPrevProcessor = processor; // ref is held by array
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
1999-10-08 07:09:31 +04:00
|
|
|
nsresult
|
2004-01-08 01:30:53 +03:00
|
|
|
nsStyleSet::GatherRuleProcessors(PRInt32 aType)
|
1999-10-08 07:09:31 +04:00
|
|
|
{
|
2004-01-08 01:30:53 +03:00
|
|
|
mRuleProcessors[aType].Clear();
|
|
|
|
if (mSheets[aType].Count()) {
|
|
|
|
RuleProcessorEnumData data(&mRuleProcessors[aType]);
|
|
|
|
if (!mSheets[aType].EnumerateBackwards(EnumRuleProcessor, &data))
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
1999-10-08 07:09:31 +04:00
|
|
|
}
|
2000-08-12 10:28:02 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
1999-10-08 07:09:31 +04:00
|
|
|
}
|
|
|
|
|
2002-12-03 08:48:14 +03:00
|
|
|
#ifdef DEBUG
|
2004-01-08 01:30:53 +03:00
|
|
|
#define CHECK_APPLICABLE \
|
|
|
|
PR_BEGIN_MACRO \
|
|
|
|
PRBool applicable = PR_TRUE; \
|
|
|
|
aSheet->GetApplicable(applicable); \
|
|
|
|
NS_ASSERTION(applicable, "Inapplicable sheet being placed in style set"); \
|
|
|
|
PR_END_MACRO
|
|
|
|
#else
|
|
|
|
#define CHECK_APPLICABLE
|
2002-12-03 08:48:14 +03:00
|
|
|
#endif
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
nsresult
|
|
|
|
nsStyleSet::AppendStyleSheet(sheetType aType, nsIStyleSheet *aSheet)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2004-01-08 01:30:53 +03:00
|
|
|
NS_PRECONDITION(aSheet, "null arg");
|
|
|
|
CHECK_APPLICABLE;
|
|
|
|
mSheets[aType].RemoveObject(aSheet);
|
|
|
|
if (!mSheets[aType].AppendObject(aSheet))
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
if (!mBatching)
|
|
|
|
return GatherRuleProcessors(aType);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
mDirty |= 1 << aType;
|
|
|
|
return NS_OK;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
nsresult
|
|
|
|
nsStyleSet::PrependStyleSheet(sheetType aType, nsIStyleSheet *aSheet)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2004-01-08 01:30:53 +03:00
|
|
|
NS_PRECONDITION(aSheet, "null arg");
|
|
|
|
CHECK_APPLICABLE;
|
|
|
|
mSheets[aType].RemoveObject(aSheet);
|
|
|
|
if (!mSheets[aType].InsertObjectAt(aSheet, 0))
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
if (!mBatching)
|
|
|
|
return GatherRuleProcessors(aType);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
mDirty |= 1 << aType;
|
|
|
|
return NS_OK;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
nsresult
|
|
|
|
nsStyleSet::RemoveStyleSheet(sheetType aType, nsIStyleSheet *aSheet)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2004-01-08 01:30:53 +03:00
|
|
|
NS_PRECONDITION(aSheet, "null arg");
|
2002-12-03 08:48:14 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
PRBool complete = PR_TRUE;
|
|
|
|
aSheet->GetComplete(complete);
|
|
|
|
NS_ASSERTION(complete, "Incomplete sheet being removed from style set");
|
|
|
|
#endif
|
2004-01-08 01:30:53 +03:00
|
|
|
mSheets[aType].RemoveObject(aSheet);
|
|
|
|
if (!mBatching)
|
|
|
|
return GatherRuleProcessors(aType);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
mDirty |= 1 << aType;
|
|
|
|
return NS_OK;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
nsresult
|
|
|
|
nsStyleSet::ReplaceSheets(sheetType aType,
|
|
|
|
const nsCOMArray<nsIStyleSheet> &aNewSheets)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2004-01-08 01:30:53 +03:00
|
|
|
mSheets[aType].Clear();
|
2004-01-08 22:23:12 +03:00
|
|
|
if (!mSheets[aType].AppendObjects(aNewSheets))
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
if (!mBatching)
|
|
|
|
return GatherRuleProcessors(aType);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
mDirty |= 1 << aType;
|
|
|
|
return NS_OK;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
// -------- Doc Sheets
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
nsresult
|
|
|
|
nsStyleSet::AddDocStyleSheet(nsIStyleSheet* aSheet, nsIDocument* aDocument)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2004-01-08 22:23:12 +03:00
|
|
|
NS_PRECONDITION(aSheet && aDocument, "null arg");
|
2004-01-08 01:30:53 +03:00
|
|
|
CHECK_APPLICABLE;
|
|
|
|
|
|
|
|
nsCOMArray<nsIStyleSheet>& docSheets = mSheets[eDocSheet];
|
|
|
|
|
|
|
|
docSheets.RemoveObject(aSheet);
|
|
|
|
// lowest index last
|
|
|
|
PRInt32 newDocIndex = aDocument->GetIndexOfStyleSheet(aSheet);
|
|
|
|
PRInt32 count = docSheets.Count();
|
|
|
|
for (PRInt32 index = 0; index < count; index++) {
|
|
|
|
nsIStyleSheet* sheet = docSheets.ObjectAt(index);
|
|
|
|
PRInt32 sheetDocIndex = aDocument->GetIndexOfStyleSheet(sheet);
|
|
|
|
if (sheetDocIndex < newDocIndex) {
|
|
|
|
if (!docSheets.InsertObjectAt(aSheet, index))
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
index = count; // break loop
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
2004-01-08 01:30:53 +03:00
|
|
|
if (docSheets.Count() == count) { // didn't insert it
|
|
|
|
if (!docSheets.AppendObject(aSheet))
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
2004-01-08 01:30:53 +03:00
|
|
|
if (!mBatching)
|
|
|
|
return GatherRuleProcessors(eDocSheet);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
mDirty |= 1 << eDocSheet;
|
|
|
|
return NS_OK;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
#undef CHECK_APPLICABLE
|
2001-11-06 13:04:05 +03:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
// Batching
|
2001-11-06 13:04:05 +03:00
|
|
|
void
|
2004-01-08 01:30:53 +03:00
|
|
|
nsStyleSet::BeginUpdate()
|
2001-11-06 13:04:05 +03:00
|
|
|
{
|
2004-01-08 22:23:12 +03:00
|
|
|
++mBatching;
|
2001-11-06 13:04:05 +03:00
|
|
|
}
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
nsresult
|
|
|
|
nsStyleSet::EndUpdate()
|
2001-11-06 13:04:05 +03:00
|
|
|
{
|
2004-01-08 22:23:12 +03:00
|
|
|
NS_ASSERTION(mBatching > 0, "Unbalanced EndUpdate");
|
|
|
|
if (--mBatching) {
|
|
|
|
// We're not completely done yet.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
for (int i = 0; i < eSheetTypeCount; ++i) {
|
2004-01-08 22:23:12 +03:00
|
|
|
if (mDirty & (1 << i)) {
|
2004-01-08 01:30:53 +03:00
|
|
|
nsresult rv = GatherRuleProcessors(i);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
2001-11-06 13:04:05 +03:00
|
|
|
}
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
mDirty = 0;
|
|
|
|
return NS_OK;
|
2001-11-06 13:04:05 +03:00
|
|
|
}
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
void
|
|
|
|
nsStyleSet::EnableQuirkStyleSheet(PRBool aEnable)
|
2000-06-03 01:45:06 +04:00
|
|
|
{
|
2004-01-08 01:30:53 +03:00
|
|
|
if (!mQuirkStyleSheet) {
|
2000-06-03 01:45:06 +04:00
|
|
|
// first find the quirk sheet:
|
2001-11-06 13:04:05 +03:00
|
|
|
// - run through all of the agent sheets and check for a CSSStyleSheet that
|
2000-06-03 01:45:06 +04:00
|
|
|
// has the URL we want
|
2004-01-08 01:30:53 +03:00
|
|
|
PRInt32 nSheets = mSheets[eAgentSheet].Count();
|
|
|
|
for (PRInt32 i = 0; i < nSheets; ++i) {
|
|
|
|
nsIStyleSheet *sheet = mSheets[eAgentSheet].ObjectAt(i);
|
|
|
|
NS_ASSERTION(sheet, "mAgentSheets should not contain null sheets");
|
|
|
|
|
|
|
|
nsICSSStyleSheet *cssSheet = NS_STATIC_CAST(nsICSSStyleSheet*, sheet);
|
|
|
|
NS_ASSERTION(nsCOMPtr<nsICSSStyleSheet>(do_QueryInterface(sheet)) == cssSheet,
|
|
|
|
"Agent sheet must be a CSSStyleSheet");
|
|
|
|
|
|
|
|
nsCOMPtr<nsIStyleSheet> quirkSheet;
|
|
|
|
PRBool bHasSheet = PR_FALSE;
|
|
|
|
if (NS_SUCCEEDED(cssSheet->ContainsStyleSheet(gQuirkURI, bHasSheet,
|
|
|
|
getter_AddRefs(quirkSheet)))
|
|
|
|
&& bHasSheet) {
|
|
|
|
NS_ASSERTION(quirkSheet, "QuirkSheet must be set: ContainsStyleSheet is hosed");
|
|
|
|
// cache the sheet for faster lookup next time
|
|
|
|
mQuirkStyleSheet = quirkSheet;
|
|
|
|
// only one quirk style sheet can exist, so stop looking
|
|
|
|
break;
|
2000-06-03 01:45:06 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-05-24 03:09:31 +04:00
|
|
|
NS_ASSERTION(mQuirkStyleSheet, "no quirk stylesheet");
|
2000-06-03 01:45:06 +04:00
|
|
|
if (mQuirkStyleSheet) {
|
2003-01-16 22:21:23 +03:00
|
|
|
#ifdef DEBUG_dbaron_off // XXX Make this |DEBUG| once it stops firing.
|
2004-01-08 01:30:53 +03:00
|
|
|
PRInt32 count = mRuleProcessors[eAgentSheet].Count()
|
2002-12-03 08:48:14 +03:00
|
|
|
PRBool applicableNow;
|
|
|
|
mQuirkStyleSheet->GetApplicable(applicableNow);
|
|
|
|
NS_ASSERTION(count == 0 || aEnable == applicableNow,
|
|
|
|
"enabling/disabling quirk stylesheet too late or incomplete quirk stylesheet");
|
2002-12-06 07:42:49 +03:00
|
|
|
if (count != 0 && aEnable == applicableNow)
|
2002-05-24 03:09:31 +04:00
|
|
|
printf("WARNING: We set the quirks mode too many times.\n"); // we do!
|
2000-10-29 02:17:53 +04:00
|
|
|
#endif
|
2000-06-03 01:45:06 +04:00
|
|
|
mQuirkStyleSheet->SetEnabled(aEnable);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-11-11 02:51:45 +03:00
|
|
|
struct RulesMatchingData : public ElementRuleProcessorData {
|
1999-06-15 10:15:51 +04:00
|
|
|
RulesMatchingData(nsIPresContext* aPresContext,
|
|
|
|
nsIAtom* aMedium,
|
|
|
|
nsIContent* aContent,
|
2001-10-24 04:01:09 +04:00
|
|
|
nsRuleWalker* aRuleWalker)
|
2001-11-11 02:51:45 +03:00
|
|
|
: ElementRuleProcessorData(aPresContext, aContent, aRuleWalker),
|
|
|
|
mMedium(aMedium)
|
1999-06-15 10:15:51 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
nsIAtom* mMedium;
|
|
|
|
};
|
|
|
|
|
|
|
|
static PRBool
|
2004-01-08 01:30:53 +03:00
|
|
|
EnumRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
1999-06-15 10:15:51 +04:00
|
|
|
RulesMatchingData* data = (RulesMatchingData*)aData;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
aProcessor->RulesMatching(data, data->mMedium);
|
1999-06-15 10:15:51 +04:00
|
|
|
return PR_TRUE;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2002-03-08 02:48:26 +03:00
|
|
|
/**
|
|
|
|
* |GetContext| implements sharing of style contexts (not just the data
|
|
|
|
* on the rule nodes) between siblings and cousins of the same
|
|
|
|
* generation. (It works for cousins of the same generation since
|
|
|
|
* |aParentContext| could itself be a shared context.)
|
|
|
|
*/
|
2003-02-22 03:32:13 +03:00
|
|
|
already_AddRefed<nsStyleContext>
|
2004-01-08 01:30:53 +03:00
|
|
|
nsStyleSet::GetContext(nsIPresContext* aPresContext,
|
|
|
|
nsStyleContext* aParentContext,
|
|
|
|
nsIAtom* aPseudoTag)
|
1998-05-19 01:05:52 +04:00
|
|
|
{
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext* result = nsnull;
|
2001-10-24 04:01:09 +04:00
|
|
|
nsRuleNode* ruleNode = mRuleWalker->GetCurrentNode();
|
2001-06-01 02:19:43 +04:00
|
|
|
|
2002-03-31 20:59:00 +04:00
|
|
|
if (aParentContext)
|
2003-02-22 03:32:13 +03:00
|
|
|
result = aParentContext->FindChildWithRules(aPseudoTag, ruleNode).get();
|
2000-03-31 11:08:36 +04:00
|
|
|
|
2000-06-22 00:44:59 +04:00
|
|
|
#ifdef NOISY_DEBUG
|
2002-03-31 20:59:00 +04:00
|
|
|
if (result)
|
2000-10-29 02:17:53 +04:00
|
|
|
fprintf(stdout, "--- SharedSC %d ---\n", ++gSharedCount);
|
2002-03-31 20:59:00 +04:00
|
|
|
else
|
|
|
|
fprintf(stdout, "+++ NewSC %d +++\n", ++gNewCount);
|
2000-03-31 11:08:36 +04:00
|
|
|
#endif
|
|
|
|
|
2003-03-06 22:14:17 +03:00
|
|
|
if (!result) {
|
2003-02-22 03:32:13 +03:00
|
|
|
result = NS_NewStyleContext(aParentContext, aPseudoTag, ruleNode,
|
|
|
|
aPresContext).get();
|
2003-03-06 22:14:17 +03:00
|
|
|
if (!aParentContext && result)
|
|
|
|
mRoots.AppendElement(result);
|
|
|
|
}
|
2002-03-31 20:59:00 +04:00
|
|
|
|
1998-05-19 01:05:52 +04:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2001-06-01 02:19:43 +04:00
|
|
|
void
|
2004-01-08 01:30:53 +03:00
|
|
|
nsStyleSet::AddImportantRules(nsRuleNode* aCurrLevelNode,
|
|
|
|
nsRuleNode* aLastPrevLevelNode)
|
2001-06-01 02:19:43 +04:00
|
|
|
{
|
2001-11-06 13:04:05 +03:00
|
|
|
if (!aCurrLevelNode || aCurrLevelNode == aLastPrevLevelNode)
|
|
|
|
return;
|
|
|
|
|
|
|
|
AddImportantRules(aCurrLevelNode->GetParent(), aLastPrevLevelNode);
|
2001-06-01 02:19:43 +04:00
|
|
|
|
2003-06-20 05:22:44 +04:00
|
|
|
nsIStyleRule *rule = aCurrLevelNode->GetRule();
|
2001-06-01 02:19:43 +04:00
|
|
|
nsCOMPtr<nsICSSStyleRule> cssRule(do_QueryInterface(rule));
|
|
|
|
if (cssRule) {
|
2002-10-09 05:59:43 +04:00
|
|
|
nsCOMPtr<nsIStyleRule> impRule = cssRule->GetImportantRule();
|
2001-06-01 02:19:43 +04:00
|
|
|
if (impRule)
|
|
|
|
mRuleWalker->Forward(impRule);
|
1998-09-11 06:05:30 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-11-11 02:51:45 +03:00
|
|
|
// Enumerate the rules in a way that cares about the order of the rules.
|
2001-11-06 13:04:05 +03:00
|
|
|
void
|
2004-01-08 01:30:53 +03:00
|
|
|
nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
|
|
|
RuleProcessorData* aData)
|
2001-11-06 13:04:05 +03:00
|
|
|
{
|
|
|
|
|
|
|
|
// Cascading order:
|
|
|
|
// [least important]
|
|
|
|
// 1. UA normal rules = Agent normal
|
|
|
|
// 2. User normal rules = User normal
|
|
|
|
// 3. Author normal rules = Document normal
|
|
|
|
// 4. Override normal rules = Override normal
|
|
|
|
// 5. Author !important rules = Document !important
|
|
|
|
// 6. Override !important rules = Override !important
|
|
|
|
// 7. User !important rules = User !important
|
|
|
|
// 8. UA !important rules = Agent !important
|
|
|
|
// [most important]
|
|
|
|
|
|
|
|
nsRuleNode* lastAgentRN = nsnull;
|
2004-01-08 01:30:53 +03:00
|
|
|
if (mRuleProcessors[eAgentSheet].Count()) {
|
|
|
|
mRuleProcessors[eAgentSheet].EnumerateForwards(aCollectorFunc, aData);
|
2001-11-06 13:04:05 +03:00
|
|
|
lastAgentRN = mRuleWalker->GetCurrentNode();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRuleNode* lastUserRN = lastAgentRN;
|
2004-01-08 01:30:53 +03:00
|
|
|
if (mRuleProcessors[eUserSheet].Count()) {
|
|
|
|
mRuleProcessors[eUserSheet].EnumerateForwards(aCollectorFunc, aData);
|
2001-11-06 13:04:05 +03:00
|
|
|
lastUserRN = mRuleWalker->GetCurrentNode();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRuleNode* lastDocRN = lastUserRN;
|
|
|
|
PRBool useRuleProcessors = PR_TRUE;
|
|
|
|
if (mStyleRuleSupplier) {
|
|
|
|
// We can supply additional document-level sheets that should be walked.
|
2001-11-11 02:51:45 +03:00
|
|
|
mStyleRuleSupplier->WalkRules(this, aCollectorFunc, aData);
|
|
|
|
mStyleRuleSupplier->UseDocumentRules(aData->mContent, &useRuleProcessors);
|
2001-11-06 13:04:05 +03:00
|
|
|
}
|
2004-01-12 01:03:41 +03:00
|
|
|
if (useRuleProcessors && mRuleProcessors[eDocSheet].Count()) {
|
2004-01-08 01:30:53 +03:00
|
|
|
mRuleProcessors[eDocSheet].EnumerateForwards(aCollectorFunc, aData);
|
2001-11-06 13:04:05 +03:00
|
|
|
}
|
|
|
|
lastDocRN = mRuleWalker->GetCurrentNode();
|
|
|
|
|
|
|
|
nsRuleNode* lastOvrRN = lastDocRN;
|
2004-01-08 01:30:53 +03:00
|
|
|
if (mRuleProcessors[eOverrideSheet].Count()) {
|
|
|
|
mRuleProcessors[eOverrideSheet].EnumerateForwards(aCollectorFunc, aData);
|
2001-11-06 13:04:05 +03:00
|
|
|
lastOvrRN = mRuleWalker->GetCurrentNode();
|
|
|
|
}
|
|
|
|
|
|
|
|
AddImportantRules(lastDocRN, lastUserRN); //doc
|
|
|
|
AddImportantRules(lastOvrRN, lastDocRN); //ovr
|
|
|
|
AddImportantRules(lastUserRN, lastAgentRN); //user
|
|
|
|
AddImportantRules(lastAgentRN, nsnull); //agent
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2001-11-11 02:51:45 +03:00
|
|
|
// Enumerate all the rules in a way that doesn't care about the order
|
|
|
|
// of the rules and break out if the enumeration is halted.
|
|
|
|
void
|
2004-01-08 01:30:53 +03:00
|
|
|
nsStyleSet::WalkRuleProcessors(nsIStyleRuleProcessor::EnumFunc aFunc,
|
|
|
|
RuleProcessorData* aData)
|
2001-11-11 02:51:45 +03:00
|
|
|
{
|
|
|
|
// Walk the agent rules first.
|
2004-01-08 01:30:53 +03:00
|
|
|
if (mRuleProcessors[eAgentSheet].Count() &&
|
|
|
|
!mRuleProcessors[eAgentSheet].EnumerateForwards(aFunc, aData))
|
|
|
|
return;
|
2001-11-11 02:51:45 +03:00
|
|
|
|
|
|
|
// Walk the user rules next.
|
2004-01-08 01:30:53 +03:00
|
|
|
if (mRuleProcessors[eUserSheet].Count() &&
|
|
|
|
!mRuleProcessors[eUserSheet].EnumerateForwards(aFunc, aData))
|
|
|
|
return;
|
2001-11-11 02:51:45 +03:00
|
|
|
|
|
|
|
PRBool useRuleProcessors = PR_TRUE;
|
|
|
|
if (mStyleRuleSupplier) {
|
|
|
|
// We can supply additional document-level sheets that should be walked.
|
|
|
|
// XXX We ignore whether the enumerator wants to halt here!
|
|
|
|
mStyleRuleSupplier->WalkRules(this, aFunc, aData);
|
|
|
|
mStyleRuleSupplier->UseDocumentRules(aData->mContent, &useRuleProcessors);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now walk the doc rules.
|
2004-01-08 01:30:53 +03:00
|
|
|
if (mRuleProcessors[eDocSheet].Count() && useRuleProcessors &&
|
|
|
|
!mRuleProcessors[eDocSheet].EnumerateForwards(aFunc, aData))
|
|
|
|
return;
|
2001-11-11 02:51:45 +03:00
|
|
|
|
|
|
|
// Walk the override rules last.
|
2004-01-08 01:30:53 +03:00
|
|
|
if (mRuleProcessors[eOverrideSheet].Count())
|
|
|
|
mRuleProcessors[eOverrideSheet].EnumerateForwards(aFunc, aData);
|
2001-06-01 02:19:43 +04:00
|
|
|
}
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
PRBool nsStyleSet::BuildDefaultStyleData(nsIPresContext* aPresContext)
|
2003-03-13 18:29:36 +03:00
|
|
|
{
|
|
|
|
NS_ASSERTION(!mDefaultStyleData.mResetData &&
|
|
|
|
!mDefaultStyleData.mInheritedData,
|
|
|
|
"leaking default style data");
|
|
|
|
mDefaultStyleData.mResetData = new (aPresContext) nsResetStyleData;
|
|
|
|
if (!mDefaultStyleData.mResetData)
|
|
|
|
return PR_FALSE;
|
|
|
|
mDefaultStyleData.mInheritedData = new (aPresContext) nsInheritedStyleData;
|
|
|
|
if (!mDefaultStyleData.mInheritedData)
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
#define SSARG_PRESCONTEXT aPresContext
|
|
|
|
|
|
|
|
#define CREATE_DATA(name, type, args) \
|
|
|
|
if (!(mDefaultStyleData.m##type##Data->m##name##Data = \
|
|
|
|
new (aPresContext) nsStyle##name args)) \
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
#define STYLE_STRUCT_INHERITED(name, checkdata_cb, ctor_args) \
|
|
|
|
CREATE_DATA(name, Inherited, ctor_args)
|
|
|
|
#define STYLE_STRUCT_RESET(name, checkdata_cb, ctor_args) \
|
|
|
|
CREATE_DATA(name, Reset, ctor_args)
|
|
|
|
|
|
|
|
#include "nsStyleStructList.h"
|
|
|
|
|
|
|
|
#undef STYLE_STRUCT_INHERITED
|
|
|
|
#undef STYLE_STRUCT_RESET
|
|
|
|
#undef SSARG_PRESCONTEXT
|
|
|
|
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2003-02-22 03:32:13 +03:00
|
|
|
already_AddRefed<nsStyleContext>
|
2004-01-08 01:30:53 +03:00
|
|
|
nsStyleSet::ResolveStyleFor(nsIPresContext* aPresContext,
|
|
|
|
nsIContent* aContent,
|
|
|
|
nsStyleContext* aParentContext)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext* result = nsnull;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1999-06-22 23:16:40 +04:00
|
|
|
NS_ASSERTION(aContent, "must have content");
|
|
|
|
NS_ASSERTION(aPresContext, "must have pres context");
|
2001-10-30 09:02:05 +03:00
|
|
|
NS_ASSERTION(aContent->IsContentOfType(nsIContent::eELEMENT),
|
|
|
|
"content must be element");
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1999-06-22 23:16:40 +04:00
|
|
|
if (aContent && aPresContext) {
|
2004-01-08 01:30:53 +03:00
|
|
|
if (mRuleProcessors[eAgentSheet].Count() ||
|
|
|
|
mRuleProcessors[eUserSheet].Count() ||
|
|
|
|
mRuleProcessors[eDocSheet].Count() ||
|
|
|
|
mRuleProcessors[eOverrideSheet].Count()) {
|
2001-06-01 02:19:43 +04:00
|
|
|
nsCOMPtr<nsIAtom> medium;
|
|
|
|
aPresContext->GetMedium(getter_AddRefs(medium));
|
2001-11-11 02:51:45 +03:00
|
|
|
RulesMatchingData data(aPresContext, medium, aContent, mRuleWalker);
|
|
|
|
FileRules(EnumRulesMatching, &data);
|
2003-02-22 03:32:13 +03:00
|
|
|
result = GetContext(aPresContext, aParentContext, nsnull).get();
|
2004-01-08 01:30:53 +03:00
|
|
|
|
2001-06-01 02:19:43 +04:00
|
|
|
// Now reset the walker back to the root of the tree.
|
|
|
|
mRuleWalker->Reset();
|
1998-07-17 09:43:31 +04:00
|
|
|
}
|
1998-05-19 01:05:52 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2003-02-22 03:32:13 +03:00
|
|
|
already_AddRefed<nsStyleContext>
|
2004-01-08 01:30:53 +03:00
|
|
|
nsStyleSet::ResolveStyleForNonElement(nsIPresContext* aPresContext,
|
|
|
|
nsStyleContext* aParentContext)
|
2001-10-30 09:02:05 +03:00
|
|
|
{
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext* result = nsnull;
|
2001-10-30 09:02:05 +03:00
|
|
|
|
|
|
|
NS_ASSERTION(aPresContext, "must have pres context");
|
|
|
|
|
|
|
|
if (aPresContext) {
|
2004-01-08 01:30:53 +03:00
|
|
|
if (mRuleProcessors[eAgentSheet].Count() ||
|
|
|
|
mRuleProcessors[eUserSheet].Count() ||
|
|
|
|
mRuleProcessors[eDocSheet].Count() ||
|
|
|
|
mRuleProcessors[eOverrideSheet].Count()) {
|
2002-03-27 05:38:13 +03:00
|
|
|
result = GetContext(aPresContext, aParentContext,
|
2003-02-22 03:32:13 +03:00
|
|
|
nsCSSAnonBoxes::mozNonElement).get();
|
2001-10-30 09:02:05 +03:00
|
|
|
NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-11-11 02:51:45 +03:00
|
|
|
struct PseudoRulesMatchingData : public PseudoRuleProcessorData {
|
1999-06-15 10:15:51 +04:00
|
|
|
PseudoRulesMatchingData(nsIPresContext* aPresContext,
|
|
|
|
nsIAtom* aMedium,
|
|
|
|
nsIContent* aParentContent,
|
|
|
|
nsIAtom* aPseudoTag,
|
2001-02-16 00:24:47 +03:00
|
|
|
nsICSSPseudoComparator* aComparator,
|
2001-11-11 02:51:45 +03:00
|
|
|
nsRuleWalker* aRuleWalker)
|
2004-01-08 01:30:53 +03:00
|
|
|
: PseudoRuleProcessorData(aPresContext, aParentContent, aPseudoTag,
|
|
|
|
aComparator, aRuleWalker),
|
2001-11-11 02:51:45 +03:00
|
|
|
mMedium(aMedium)
|
1999-06-15 10:15:51 +04:00
|
|
|
{
|
|
|
|
}
|
2001-02-16 00:24:47 +03:00
|
|
|
nsIAtom* mMedium;
|
1999-06-15 10:15:51 +04:00
|
|
|
};
|
1998-05-19 01:05:52 +04:00
|
|
|
|
1999-06-15 10:15:51 +04:00
|
|
|
static PRBool
|
2004-01-08 01:30:53 +03:00
|
|
|
EnumPseudoRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData)
|
1998-05-19 01:05:52 +04:00
|
|
|
{
|
1999-06-15 10:15:51 +04:00
|
|
|
PseudoRulesMatchingData* data = (PseudoRulesMatchingData*)aData;
|
1998-05-19 01:05:52 +04:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
aProcessor->RulesMatching(data, data->mMedium);
|
1999-06-15 10:15:51 +04:00
|
|
|
return PR_TRUE;
|
1998-05-19 01:05:52 +04:00
|
|
|
}
|
|
|
|
|
2003-02-22 03:32:13 +03:00
|
|
|
already_AddRefed<nsStyleContext>
|
2004-01-08 01:30:53 +03:00
|
|
|
nsStyleSet::ResolvePseudoStyleFor(nsIPresContext* aPresContext,
|
|
|
|
nsIContent* aParentContent,
|
|
|
|
nsIAtom* aPseudoTag,
|
|
|
|
nsStyleContext* aParentContext,
|
|
|
|
nsICSSPseudoComparator* aComparator)
|
1998-05-19 01:05:52 +04:00
|
|
|
{
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext* result = nsnull;
|
1998-05-19 01:05:52 +04:00
|
|
|
|
1999-06-22 23:16:40 +04:00
|
|
|
NS_ASSERTION(aPseudoTag, "must have pseudo tag");
|
|
|
|
NS_ASSERTION(aPresContext, "must have pres context");
|
2001-10-30 09:02:05 +03:00
|
|
|
NS_ASSERTION(!aParentContent ||
|
|
|
|
aParentContent->IsContentOfType(nsIContent::eELEMENT),
|
|
|
|
"content (if non-null) must be element");
|
1998-05-19 01:05:52 +04:00
|
|
|
|
1999-06-22 23:16:40 +04:00
|
|
|
if (aPseudoTag && aPresContext) {
|
2004-01-08 01:30:53 +03:00
|
|
|
if (mRuleProcessors[eAgentSheet].Count() ||
|
|
|
|
mRuleProcessors[eUserSheet].Count() ||
|
|
|
|
mRuleProcessors[eDocSheet].Count() ||
|
|
|
|
mRuleProcessors[eOverrideSheet].Count()) {
|
2001-06-01 02:19:43 +04:00
|
|
|
nsCOMPtr<nsIAtom> medium;
|
|
|
|
aPresContext->GetMedium(getter_AddRefs(medium));
|
|
|
|
PseudoRulesMatchingData data(aPresContext, medium, aParentContent,
|
2001-11-11 02:51:45 +03:00
|
|
|
aPseudoTag, aComparator, mRuleWalker);
|
|
|
|
FileRules(EnumPseudoRulesMatching, &data);
|
2001-11-06 13:04:05 +03:00
|
|
|
|
2003-02-22 03:32:13 +03:00
|
|
|
result = GetContext(aPresContext, aParentContext, aPseudoTag).get();
|
2004-01-08 01:30:53 +03:00
|
|
|
|
2001-06-01 02:19:43 +04:00
|
|
|
// Now reset the walker back to the root of the tree.
|
|
|
|
mRuleWalker->Reset();
|
1998-10-13 23:09:39 +04:00
|
|
|
}
|
1998-05-19 01:05:52 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2003-02-22 03:32:13 +03:00
|
|
|
already_AddRefed<nsStyleContext>
|
2004-01-08 01:30:53 +03:00
|
|
|
nsStyleSet::ProbePseudoStyleFor(nsIPresContext* aPresContext,
|
2003-02-22 03:32:13 +03:00
|
|
|
nsIContent* aParentContent,
|
|
|
|
nsIAtom* aPseudoTag,
|
|
|
|
nsStyleContext* aParentContext)
|
1998-05-19 01:05:52 +04:00
|
|
|
{
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext* result = nsnull;
|
1998-05-19 01:05:52 +04:00
|
|
|
|
1999-06-22 23:16:40 +04:00
|
|
|
NS_ASSERTION(aPseudoTag, "must have pseudo tag");
|
|
|
|
NS_ASSERTION(aPresContext, "must have pres context");
|
2001-10-30 09:02:05 +03:00
|
|
|
NS_ASSERTION(!aParentContent ||
|
|
|
|
aParentContent->IsContentOfType(nsIContent::eELEMENT),
|
|
|
|
"content (if non-null) must be element");
|
1998-05-19 01:05:52 +04:00
|
|
|
|
1999-06-22 23:16:40 +04:00
|
|
|
if (aPseudoTag && aPresContext) {
|
2004-01-08 01:30:53 +03:00
|
|
|
if (mRuleProcessors[eAgentSheet].Count() ||
|
|
|
|
mRuleProcessors[eUserSheet].Count() ||
|
|
|
|
mRuleProcessors[eDocSheet].Count() ||
|
|
|
|
mRuleProcessors[eOverrideSheet].Count()) {
|
2001-06-01 02:19:43 +04:00
|
|
|
nsCOMPtr<nsIAtom> medium;
|
|
|
|
aPresContext->GetMedium(getter_AddRefs(medium));
|
|
|
|
PseudoRulesMatchingData data(aPresContext, medium, aParentContent,
|
2001-11-11 02:51:45 +03:00
|
|
|
aPseudoTag, nsnull, mRuleWalker);
|
|
|
|
FileRules(EnumPseudoRulesMatching, &data);
|
2001-11-06 13:04:05 +03:00
|
|
|
|
2001-10-24 04:01:09 +04:00
|
|
|
if (!mRuleWalker->AtRoot())
|
2003-02-22 03:32:13 +03:00
|
|
|
result = GetContext(aPresContext, aParentContext, aPseudoTag).get();
|
2004-01-08 01:30:53 +03:00
|
|
|
|
2001-06-01 02:19:43 +04:00
|
|
|
// Now reset the walker back to the root of the tree.
|
|
|
|
mRuleWalker->Reset();
|
1998-10-13 23:09:39 +04:00
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
2003-02-23 20:28:25 +03:00
|
|
|
|
|
|
|
// For :before and :after pseudo-elements, having display: none or no
|
|
|
|
// 'content' property is equivalent to not having the pseudo-element
|
|
|
|
// at all.
|
|
|
|
if (result &&
|
|
|
|
(aPseudoTag == nsCSSPseudoElements::before ||
|
|
|
|
aPseudoTag == nsCSSPseudoElements::after)) {
|
2003-05-15 07:42:21 +04:00
|
|
|
const nsStyleDisplay *display = result->GetStyleDisplay();
|
|
|
|
const nsStyleContent *content = result->GetStyleContent();
|
2003-02-23 20:28:25 +03:00
|
|
|
// XXXldb What is contentCount for |content: ""|?
|
|
|
|
if (display->mDisplay == NS_STYLE_DISPLAY_NONE ||
|
|
|
|
content->ContentCount() == 0) {
|
|
|
|
result->Release();
|
|
|
|
result = nsnull;
|
|
|
|
}
|
|
|
|
}
|
1999-10-12 03:42:56 +04:00
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
void
|
|
|
|
nsStyleSet::BeginShutdown(nsIPresContext* aPresContext)
|
2003-03-06 22:14:17 +03:00
|
|
|
{
|
2004-01-08 01:30:53 +03:00
|
|
|
mInShutdown = 1;
|
2003-03-06 22:14:17 +03:00
|
|
|
mRoots.Clear(); // no longer valid, since we won't keep it up to date
|
|
|
|
}
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
void
|
|
|
|
nsStyleSet::Shutdown(nsIPresContext* aPresContext)
|
2001-06-01 02:19:43 +04:00
|
|
|
{
|
2001-10-24 04:01:09 +04:00
|
|
|
delete mRuleWalker;
|
2003-03-13 18:29:36 +03:00
|
|
|
mRuleWalker = nsnull;
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
mRuleTree->Destroy();
|
|
|
|
mRuleTree = nsnull;
|
2003-03-13 18:29:36 +03:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
mDefaultStyleData.Destroy(0, aPresContext);
|
2001-06-01 02:19:43 +04:00
|
|
|
}
|
|
|
|
|
2003-03-06 22:14:17 +03:00
|
|
|
static const PRInt32 kGCInterval = 1000;
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
void
|
|
|
|
nsStyleSet::NotifyStyleContextDestroyed(nsIPresContext* aPresContext,
|
|
|
|
nsStyleContext* aStyleContext)
|
2003-03-06 22:14:17 +03:00
|
|
|
{
|
|
|
|
if (mInShutdown)
|
2004-01-08 01:30:53 +03:00
|
|
|
return;
|
2003-03-06 22:14:17 +03:00
|
|
|
|
|
|
|
if (!aStyleContext->GetParent()) {
|
|
|
|
mRoots.RemoveElement(aStyleContext);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (++mDestroyedCount == kGCInterval) {
|
|
|
|
mDestroyedCount = 0;
|
|
|
|
|
|
|
|
// Mark the style context tree by marking all roots, which will mark
|
|
|
|
// all descendants. This will reach style contexts in the
|
|
|
|
// undisplayed map and "additional style contexts" since they are
|
|
|
|
// descendants of the root.
|
|
|
|
for (PRInt32 i = mRoots.Count() - 1; i >= 0; --i) {
|
|
|
|
NS_STATIC_CAST(nsStyleContext*,mRoots[i])->Mark();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sweep the rule tree.
|
2004-01-08 01:30:53 +03:00
|
|
|
NS_ASSERTION(mRuleWalker->AtRoot(), "Rule walker should be at root");
|
|
|
|
#ifdef DEBUG
|
|
|
|
PRBool deleted =
|
|
|
|
#endif
|
|
|
|
mRuleTree->Sweep();
|
2003-03-06 22:14:17 +03:00
|
|
|
|
2004-01-08 22:23:12 +03:00
|
|
|
NS_ASSERTION(!deleted, "Root node must not be gc'd");
|
2004-01-08 01:30:53 +03:00
|
|
|
}
|
2003-03-06 22:14:17 +03:00
|
|
|
}
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
void
|
|
|
|
nsStyleSet::ClearStyleData(nsIPresContext* aPresContext)
|
2001-06-01 02:19:43 +04:00
|
|
|
{
|
2004-01-08 01:30:53 +03:00
|
|
|
mRuleTree->ClearStyleData();
|
2001-10-24 04:01:09 +04:00
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
for (PRInt32 i = mRoots.Count() - 1; i >= 0; --i) {
|
|
|
|
NS_STATIC_CAST(nsStyleContext*,mRoots[i])->ClearStyleData(aPresContext);
|
|
|
|
}
|
2003-03-13 18:29:36 +03:00
|
|
|
}
|
|
|
|
|
2003-02-22 03:32:13 +03:00
|
|
|
already_AddRefed<nsStyleContext>
|
2004-01-08 01:30:53 +03:00
|
|
|
nsStyleSet::ReParentStyleContext(nsIPresContext* aPresContext,
|
|
|
|
nsStyleContext* aStyleContext,
|
|
|
|
nsStyleContext* aNewParentContext)
|
1999-09-04 03:35:41 +04:00
|
|
|
{
|
|
|
|
NS_ASSERTION(aPresContext, "must have pres context");
|
2000-03-31 11:08:36 +04:00
|
|
|
NS_ASSERTION(aStyleContext, "must have style context");
|
1999-09-04 03:35:41 +04:00
|
|
|
|
2003-02-22 03:32:13 +03:00
|
|
|
if (aPresContext && aStyleContext) {
|
2003-03-06 22:14:17 +03:00
|
|
|
if (aStyleContext->GetParent() == aNewParentContext) {
|
2003-02-22 03:32:13 +03:00
|
|
|
aStyleContext->AddRef();
|
|
|
|
return aStyleContext;
|
1999-09-04 03:35:41 +04:00
|
|
|
}
|
|
|
|
else { // really a new parent
|
2003-10-17 06:38:37 +04:00
|
|
|
nsIAtom* pseudoTag = aStyleContext->GetPseudoType();
|
2001-06-01 02:19:43 +04:00
|
|
|
|
2003-06-20 05:22:44 +04:00
|
|
|
nsRuleNode* ruleNode = aStyleContext->GetRuleNode();
|
2003-03-06 22:14:17 +03:00
|
|
|
mRuleWalker->SetCurrentNode(ruleNode);
|
|
|
|
|
|
|
|
already_AddRefed<nsStyleContext> result =
|
|
|
|
GetContext(aPresContext, aNewParentContext, pseudoTag);
|
|
|
|
mRuleWalker->Reset();
|
|
|
|
return result;
|
1999-09-04 03:35:41 +04:00
|
|
|
}
|
|
|
|
}
|
2003-02-22 03:32:13 +03:00
|
|
|
return nsnull;
|
1999-09-04 03:35:41 +04:00
|
|
|
}
|
|
|
|
|
2001-11-11 02:51:45 +03:00
|
|
|
struct StatefulData : public StateRuleProcessorData {
|
2002-04-11 07:49:30 +04:00
|
|
|
StatefulData(nsIPresContext* aPresContext, nsIAtom* aMedium,
|
|
|
|
nsIContent* aContent, PRInt32 aStateMask)
|
|
|
|
: StateRuleProcessorData(aPresContext, aContent, aStateMask),
|
1999-10-08 07:09:31 +04:00
|
|
|
mMedium(aMedium),
|
2003-02-22 19:10:53 +03:00
|
|
|
mHasStyle(PR_FALSE)
|
1999-04-20 04:02:22 +04:00
|
|
|
{}
|
1999-10-08 07:09:31 +04:00
|
|
|
nsIAtom* mMedium;
|
2003-02-22 19:10:53 +03:00
|
|
|
PRBool mHasStyle;
|
1999-04-20 04:02:22 +04:00
|
|
|
};
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
static PRBool SheetHasStatefulStyle(nsIStyleRuleProcessor* aProcessor,
|
|
|
|
void *aData)
|
1999-04-20 04:02:22 +04:00
|
|
|
{
|
|
|
|
StatefulData* data = (StatefulData*)aData;
|
2003-02-22 19:10:53 +03:00
|
|
|
PRBool hasStyle;
|
2004-01-08 01:30:53 +03:00
|
|
|
aProcessor->HasStateDependentStyle(data, data->mMedium, &hasStyle);
|
2003-02-22 19:10:53 +03:00
|
|
|
if (hasStyle) {
|
|
|
|
data->mHasStyle = PR_TRUE;
|
2004-01-08 01:30:53 +03:00
|
|
|
// Stop iteration. Note that nsStyleSet::WalkRuleProcessors uses
|
2002-04-16 02:28:54 +04:00
|
|
|
// this to stop its own iteration in some cases, but not all (the
|
|
|
|
// style rule supplier case). Since this optimization is only for
|
|
|
|
// the case where we have a lot more work to do, it's not worth the
|
|
|
|
// code needed to make the stopping perfect.
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
1999-04-20 04:02:22 +04:00
|
|
|
return PR_TRUE; // continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test if style is dependent on content state
|
2004-01-08 01:30:53 +03:00
|
|
|
PRBool
|
|
|
|
nsStyleSet::HasStateDependentStyle(nsIPresContext* aPresContext,
|
|
|
|
nsIContent* aContent,
|
|
|
|
PRInt32 aStateMask)
|
1999-04-20 04:02:22 +04:00
|
|
|
{
|
2004-01-08 01:30:53 +03:00
|
|
|
PRBool result = PR_FALSE;
|
2001-10-30 09:02:05 +03:00
|
|
|
|
|
|
|
if (aContent->IsContentOfType(nsIContent::eELEMENT) &&
|
2004-01-08 01:30:53 +03:00
|
|
|
(mRuleProcessors[eAgentSheet].Count() ||
|
|
|
|
mRuleProcessors[eUserSheet].Count() ||
|
|
|
|
mRuleProcessors[eDocSheet].Count() ||
|
|
|
|
mRuleProcessors[eOverrideSheet].Count())) {
|
2003-02-22 19:10:53 +03:00
|
|
|
nsCOMPtr<nsIAtom> medium;
|
|
|
|
aPresContext->GetMedium(getter_AddRefs(medium));
|
2002-04-11 07:49:30 +04:00
|
|
|
StatefulData data(aPresContext, medium, aContent, aStateMask);
|
2001-11-11 02:51:45 +03:00
|
|
|
WalkRuleProcessors(SheetHasStatefulStyle, &data);
|
2004-01-08 01:30:53 +03:00
|
|
|
result = data.mHasStyle;
|
2003-02-22 19:10:53 +03:00
|
|
|
}
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
return result;
|
2003-02-22 19:10:53 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
struct AttributeData : public AttributeRuleProcessorData {
|
|
|
|
AttributeData(nsIPresContext* aPresContext, nsIAtom* aMedium,
|
|
|
|
nsIContent* aContent, nsIAtom* aAttribute, PRInt32 aModType)
|
|
|
|
: AttributeRuleProcessorData(aPresContext, aContent, aAttribute, aModType),
|
|
|
|
mMedium(aMedium),
|
|
|
|
mHasStyle(PR_FALSE)
|
|
|
|
{}
|
|
|
|
nsIAtom* mMedium;
|
|
|
|
PRBool mHasStyle;
|
|
|
|
};
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
static PRBool
|
|
|
|
SheetHasAttributeStyle(nsIStyleRuleProcessor* aProcessor, void *aData)
|
2003-02-22 19:10:53 +03:00
|
|
|
{
|
|
|
|
AttributeData* data = (AttributeData*)aData;
|
|
|
|
PRBool hasStyle;
|
2004-01-08 01:30:53 +03:00
|
|
|
aProcessor->HasAttributeDependentStyle(data, data->mMedium, &hasStyle);
|
2003-02-22 19:10:53 +03:00
|
|
|
if (hasStyle) {
|
|
|
|
data->mHasStyle = PR_TRUE;
|
2004-01-08 01:30:53 +03:00
|
|
|
// Stop iteration. Note that nsStyleSet::WalkRuleProcessors uses
|
2003-02-22 19:10:53 +03:00
|
|
|
// this to stop its own iteration in some cases, but not all (the
|
|
|
|
// style rule supplier case). Since this optimization is only for
|
|
|
|
// the case where we have a lot more work to do, it's not worth the
|
|
|
|
// code needed to make the stopping perfect.
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
return PR_TRUE; // continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test if style is dependent on content state
|
2004-01-08 01:30:53 +03:00
|
|
|
PRBool
|
|
|
|
nsStyleSet::HasAttributeDependentStyle(nsIPresContext* aPresContext,
|
|
|
|
nsIContent* aContent,
|
|
|
|
nsIAtom* aAttribute,
|
|
|
|
PRInt32 aModType)
|
2003-02-22 19:10:53 +03:00
|
|
|
{
|
2004-01-08 01:30:53 +03:00
|
|
|
PRBool result = PR_FALSE;
|
2003-02-22 19:10:53 +03:00
|
|
|
|
|
|
|
if (aContent->IsContentOfType(nsIContent::eELEMENT) &&
|
2004-01-08 01:30:53 +03:00
|
|
|
(mRuleProcessors[eAgentSheet].Count() ||
|
|
|
|
mRuleProcessors[eUserSheet].Count() ||
|
|
|
|
mRuleProcessors[eDocSheet].Count() ||
|
|
|
|
mRuleProcessors[eOverrideSheet].Count())) {
|
2003-02-22 19:10:53 +03:00
|
|
|
nsCOMPtr<nsIAtom> medium;
|
|
|
|
aPresContext->GetMedium(getter_AddRefs(medium));
|
|
|
|
AttributeData data(aPresContext, medium, aContent, aAttribute, aModType);
|
|
|
|
WalkRuleProcessors(SheetHasAttributeStyle, &data);
|
2004-01-08 01:30:53 +03:00
|
|
|
result = data.mHasStyle;
|
1999-09-20 10:53:40 +04:00
|
|
|
}
|
|
|
|
|
2004-01-08 01:30:53 +03:00
|
|
|
return result;
|
2000-03-31 11:08:36 +04:00
|
|
|
}
|