mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-08 12:37:37 +00:00
772 lines
24 KiB
C++
772 lines
24 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
#include "nsICSSStyleRule.h"
|
|
#include "nsICSSDeclaration.h"
|
|
#include "nsIStyleContext.h"
|
|
#include "nsIPresContext.h"
|
|
#include "nsIArena.h"
|
|
#include "nsIAtom.h"
|
|
#include "nsCRT.h"
|
|
#include "nsString.h"
|
|
#include "nsStyleConsts.h"
|
|
#include "nsUnitConversion.h"
|
|
|
|
//#define DEBUG_REFS
|
|
|
|
static NS_DEFINE_IID(kIStyleRuleIID, NS_ISTYLE_RULE_IID);
|
|
static NS_DEFINE_IID(kICSSDeclarationIID, NS_ICSS_DECLARATION_IID);
|
|
static NS_DEFINE_IID(kICSSStyleRuleIID, NS_ICSS_STYLE_RULE_IID);
|
|
|
|
static NS_DEFINE_IID(kStyleFontSID, NS_STYLEFONT_SID);
|
|
static NS_DEFINE_IID(kStyleColorSID, NS_STYLECOLOR_SID);
|
|
static NS_DEFINE_IID(kStyleListSID, NS_STYLELIST_SID);
|
|
static NS_DEFINE_IID(kStyleSpacingSID, NS_STYLESPACING_SID);
|
|
static NS_DEFINE_IID(kStyleMoleculeSID, NS_STYLEMOLECULE_SID);
|
|
|
|
static NS_DEFINE_IID(kCSSFontSID, NS_CSS_FONT_SID);
|
|
static NS_DEFINE_IID(kCSSColorSID, NS_CSS_COLOR_SID);
|
|
static NS_DEFINE_IID(kCSSTextSID, NS_CSS_TEXT_SID);
|
|
static NS_DEFINE_IID(kCSSMarginSID, NS_CSS_MARGIN_SID);
|
|
static NS_DEFINE_IID(kCSSPositionSID, NS_CSS_POSITION_SID);
|
|
static NS_DEFINE_IID(kCSSListSID, NS_CSS_LIST_SID);
|
|
|
|
|
|
// -- nsCSSSelector -------------------------------
|
|
|
|
nsCSSSelector::nsCSSSelector()
|
|
: mTag(nsnull), mID(nsnull), mClass(nsnull), mPseudoClass(nsnull),
|
|
mNext(nsnull)
|
|
{
|
|
}
|
|
|
|
nsCSSSelector::nsCSSSelector(nsIAtom* aTag, nsIAtom* aID, nsIAtom* aClass, nsIAtom* aPseudoClass)
|
|
: mTag(aTag), mID(aID), mClass(aClass), mPseudoClass(aPseudoClass),
|
|
mNext(nsnull)
|
|
{
|
|
NS_IF_ADDREF(mTag);
|
|
NS_IF_ADDREF(mID);
|
|
NS_IF_ADDREF(mClass);
|
|
NS_IF_ADDREF(mPseudoClass);
|
|
}
|
|
|
|
nsCSSSelector::nsCSSSelector(const nsCSSSelector& aCopy)
|
|
: mTag(aCopy.mTag), mID(aCopy.mID), mClass(aCopy.mClass), mPseudoClass(aCopy.mPseudoClass),
|
|
mNext(nsnull)
|
|
{ // implmented to support extension to CSS2 (when we have to copy the array)
|
|
NS_IF_ADDREF(mTag);
|
|
NS_IF_ADDREF(mID);
|
|
NS_IF_ADDREF(mClass);
|
|
NS_IF_ADDREF(mPseudoClass);
|
|
}
|
|
|
|
nsCSSSelector::~nsCSSSelector()
|
|
{
|
|
NS_IF_RELEASE(mTag);
|
|
NS_IF_RELEASE(mID);
|
|
NS_IF_RELEASE(mClass);
|
|
NS_IF_RELEASE(mPseudoClass);
|
|
}
|
|
|
|
nsCSSSelector& nsCSSSelector::operator=(const nsCSSSelector& aCopy)
|
|
{
|
|
NS_IF_RELEASE(mTag);
|
|
NS_IF_RELEASE(mID);
|
|
NS_IF_RELEASE(mClass);
|
|
NS_IF_RELEASE(mPseudoClass);
|
|
mTag = aCopy.mTag;
|
|
mID = aCopy.mID;
|
|
mClass = aCopy.mClass;
|
|
mPseudoClass = aCopy.mPseudoClass;
|
|
NS_IF_ADDREF(mTag);
|
|
NS_IF_ADDREF(mID);
|
|
NS_IF_ADDREF(mClass);
|
|
NS_IF_ADDREF(mPseudoClass);
|
|
return *this;
|
|
}
|
|
|
|
PRBool nsCSSSelector::Equals(const nsCSSSelector* aOther) const
|
|
{
|
|
if (nsnull != aOther) {
|
|
return (PRBool)((aOther->mTag == mTag) && (aOther->mID == mID) &&
|
|
(aOther->mClass == mClass) && (aOther->mPseudoClass == mPseudoClass));
|
|
}
|
|
return PR_FALSE;
|
|
}
|
|
|
|
|
|
void nsCSSSelector::Set(const nsString& aTag, const nsString& aID,
|
|
const nsString& aClass, const nsString& aPseudoClass)
|
|
{
|
|
NS_IF_RELEASE(mTag);
|
|
NS_IF_RELEASE(mID);
|
|
NS_IF_RELEASE(mClass);
|
|
NS_IF_RELEASE(mPseudoClass);
|
|
if (0 < aTag.Length()) {
|
|
mTag = NS_NewAtom(aTag);
|
|
}
|
|
if (0 < aID.Length()) {
|
|
mID = NS_NewAtom(aID);
|
|
}
|
|
if (0 < aClass.Length()) {
|
|
mClass = NS_NewAtom(aClass);
|
|
}
|
|
if (0 < aPseudoClass.Length()) {
|
|
mPseudoClass = NS_NewAtom(aPseudoClass);
|
|
}
|
|
}
|
|
|
|
// -- nsCSSStyleRule -------------------------------
|
|
|
|
class CSSStyleRuleImpl : public nsICSSStyleRule {
|
|
public:
|
|
void* operator new(size_t size);
|
|
void* operator new(size_t size, nsIArena* aArena);
|
|
void operator delete(void* ptr);
|
|
|
|
CSSStyleRuleImpl(const nsCSSSelector& aSelector);
|
|
|
|
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
|
|
NS_IMETHOD_(nsrefcnt) AddRef();
|
|
NS_IMETHOD_(nsrefcnt) Release();
|
|
|
|
virtual PRBool Equals(const nsIStyleRule* aRule) const;
|
|
virtual PRUint32 HashValue(void) const;
|
|
|
|
virtual nsCSSSelector* FirstSelector(void);
|
|
virtual void AddSelector(const nsCSSSelector& aSelector);
|
|
virtual void DeleteSelector(nsCSSSelector* aSelector);
|
|
|
|
virtual nsICSSDeclaration* GetDeclaration(void) const;
|
|
virtual void SetDeclaration(nsICSSDeclaration* aDeclaration);
|
|
|
|
virtual PRInt32 GetWeight(void) const;
|
|
virtual void SetWeight(PRInt32 aWeight);
|
|
|
|
virtual nscoord CalcLength(const nsCSSValue& aValue, nsStyleFont* aFont,
|
|
nsIPresContext* aPresContext);
|
|
virtual void MapStyleInto(nsIStyleContext* aContext, nsIPresContext* aPresContext);
|
|
|
|
virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
|
|
|
|
private:
|
|
// These are not supported and are not implemented!
|
|
CSSStyleRuleImpl(const CSSStyleRuleImpl& aCopy);
|
|
CSSStyleRuleImpl& operator=(const CSSStyleRuleImpl& aCopy);
|
|
|
|
protected:
|
|
virtual ~CSSStyleRuleImpl();
|
|
|
|
protected:
|
|
PRUint32 mInHeap : 1;
|
|
PRUint32 mRefCnt : 31;
|
|
|
|
nsCSSSelector mSelector;
|
|
nsICSSDeclaration* mDeclaration;
|
|
PRInt32 mWeight;
|
|
#ifdef DEBUG_REFS
|
|
PRInt32 mInstance;
|
|
#endif
|
|
};
|
|
|
|
|
|
void* CSSStyleRuleImpl::operator new(size_t size)
|
|
{
|
|
CSSStyleRuleImpl* rv = (CSSStyleRuleImpl*) ::operator new(size);
|
|
#ifdef NS_DEBUG
|
|
if (nsnull != rv) {
|
|
nsCRT::memset(rv, 0xEE, size);
|
|
}
|
|
#endif
|
|
rv->mInHeap = 1;
|
|
return (void*) rv;
|
|
}
|
|
|
|
void* CSSStyleRuleImpl::operator new(size_t size, nsIArena* aArena)
|
|
{
|
|
CSSStyleRuleImpl* rv = (CSSStyleRuleImpl*) aArena->Alloc(PRInt32(size));
|
|
#ifdef NS_DEBUG
|
|
if (nsnull != rv) {
|
|
nsCRT::memset(rv, 0xEE, size);
|
|
}
|
|
#endif
|
|
rv->mInHeap = 0;
|
|
return (void*) rv;
|
|
}
|
|
|
|
void CSSStyleRuleImpl::operator delete(void* ptr)
|
|
{
|
|
CSSStyleRuleImpl* rule = (CSSStyleRuleImpl*) ptr;
|
|
if (nsnull != rule) {
|
|
if (rule->mInHeap) {
|
|
::delete ptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef DEBUG_REFS
|
|
static PRInt32 gInstanceCount;
|
|
static const PRInt32 kInstrument = 1075;
|
|
#endif
|
|
|
|
CSSStyleRuleImpl::CSSStyleRuleImpl(const nsCSSSelector& aSelector)
|
|
: mSelector(aSelector), mDeclaration(nsnull), mWeight(0)
|
|
{
|
|
NS_INIT_REFCNT();
|
|
#ifdef DEBUG_REFS
|
|
mInstance = gInstanceCount++;
|
|
fprintf(stdout, "%d of %d + CSSStyleRule\n", mInstance, gInstanceCount);
|
|
#endif
|
|
}
|
|
|
|
CSSStyleRuleImpl::~CSSStyleRuleImpl()
|
|
{
|
|
nsCSSSelector* next = mSelector.mNext;
|
|
|
|
while (nsnull != next) {
|
|
nsCSSSelector* selector = next;
|
|
next = selector->mNext;
|
|
delete selector;
|
|
}
|
|
NS_IF_RELEASE(mDeclaration);
|
|
#ifdef DEBUG_REFS
|
|
--gInstanceCount;
|
|
fprintf(stdout, "%d of %d - CSSStyleRule\n", mInstance, gInstanceCount);
|
|
#endif
|
|
}
|
|
|
|
#ifdef DEBUG_REFS
|
|
nsrefcnt CSSStyleRuleImpl::AddRef(void)
|
|
{
|
|
if (mInstance == kInstrument) {
|
|
fprintf(stdout, "%d AddRef CSSStyleRule\n", mRefCnt + 1);
|
|
}
|
|
return ++mRefCnt;
|
|
}
|
|
|
|
nsrefcnt CSSStyleRuleImpl::Release(void)
|
|
{
|
|
if (mInstance == kInstrument) {
|
|
fprintf(stdout, "%d Release CSSStyleRule\n", mRefCnt - 1);
|
|
}
|
|
if (--mRefCnt == 0) {
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return mRefCnt;
|
|
}
|
|
#else
|
|
NS_IMPL_ADDREF(CSSStyleRuleImpl)
|
|
NS_IMPL_RELEASE(CSSStyleRuleImpl)
|
|
#endif
|
|
|
|
nsresult CSSStyleRuleImpl::QueryInterface(const nsIID& aIID,
|
|
void** aInstancePtrResult)
|
|
{
|
|
NS_PRECONDITION(nsnull != aInstancePtrResult, "null pointer");
|
|
if (nsnull == aInstancePtrResult) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
|
if (aIID.Equals(kICSSStyleRuleIID)) {
|
|
*aInstancePtrResult = (void*) ((nsICSSStyleRule*)this);
|
|
AddRef();
|
|
return NS_OK;
|
|
}
|
|
if (aIID.Equals(kIStyleRuleIID)) {
|
|
*aInstancePtrResult = (void*) ((nsIStyleRule*)this);
|
|
AddRef();
|
|
return NS_OK;
|
|
}
|
|
if (aIID.Equals(kISupportsIID)) {
|
|
*aInstancePtrResult = (void*) ((nsISupports*)this);
|
|
AddRef();
|
|
return NS_OK;
|
|
}
|
|
return NS_NOINTERFACE;
|
|
}
|
|
|
|
|
|
PRBool CSSStyleRuleImpl::Equals(const nsIStyleRule* aRule) const
|
|
{
|
|
nsICSSStyleRule* iCSSRule;
|
|
|
|
if (this == aRule) {
|
|
return PR_TRUE;
|
|
}
|
|
|
|
if ((nsnull != aRule) &&
|
|
(NS_OK == ((nsIStyleRule*)aRule)->QueryInterface(kICSSStyleRuleIID, (void**) &iCSSRule))) {
|
|
|
|
CSSStyleRuleImpl* rule = (CSSStyleRuleImpl*)iCSSRule;
|
|
const nsCSSSelector* local = &mSelector;
|
|
const nsCSSSelector* other = &(rule->mSelector);
|
|
PRBool result = PR_TRUE;
|
|
|
|
while ((PR_TRUE == result) && (nsnull != local) && (nsnull != other)) {
|
|
if (! local->Equals(other)) {
|
|
result = PR_FALSE;
|
|
}
|
|
local = local->mNext;
|
|
other = other->mNext;
|
|
}
|
|
if ((nsnull != local) || (nsnull != other)) { // more were left
|
|
result = PR_FALSE;
|
|
}
|
|
if ((rule->mDeclaration != mDeclaration) ||
|
|
(rule->mWeight != mWeight)) {
|
|
result = PR_FALSE;
|
|
}
|
|
NS_RELEASE(iCSSRule);
|
|
return result;
|
|
}
|
|
return PR_FALSE;
|
|
}
|
|
|
|
PRUint32 CSSStyleRuleImpl::HashValue(void) const
|
|
{
|
|
return (PRUint32)this;
|
|
}
|
|
|
|
nsCSSSelector* CSSStyleRuleImpl::FirstSelector(void)
|
|
{
|
|
return &mSelector;
|
|
}
|
|
|
|
void CSSStyleRuleImpl::AddSelector(const nsCSSSelector& aSelector)
|
|
{
|
|
nsCSSSelector* selector = new nsCSSSelector(aSelector);
|
|
nsCSSSelector* last = &mSelector;
|
|
|
|
while (nsnull != last->mNext) {
|
|
last = last->mNext;
|
|
}
|
|
last->mNext = selector;
|
|
}
|
|
|
|
|
|
void CSSStyleRuleImpl::DeleteSelector(nsCSSSelector* aSelector)
|
|
{
|
|
if (nsnull != aSelector) {
|
|
if (&mSelector == aSelector) { // handle first selector
|
|
mSelector = *aSelector; // assign value
|
|
mSelector.mNext = aSelector->mNext;
|
|
delete aSelector;
|
|
}
|
|
else {
|
|
nsCSSSelector* selector = &mSelector;
|
|
|
|
while (nsnull != selector->mNext) {
|
|
if (aSelector == selector->mNext) {
|
|
selector->mNext = aSelector->mNext;
|
|
delete aSelector;
|
|
return;
|
|
}
|
|
selector = selector->mNext;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
nsICSSDeclaration* CSSStyleRuleImpl::GetDeclaration(void) const
|
|
{
|
|
NS_IF_ADDREF(mDeclaration);
|
|
return mDeclaration;
|
|
}
|
|
|
|
void CSSStyleRuleImpl::SetDeclaration(nsICSSDeclaration* aDeclaration)
|
|
{
|
|
NS_IF_RELEASE(mDeclaration);
|
|
mDeclaration = aDeclaration;
|
|
NS_IF_ADDREF(mDeclaration);
|
|
}
|
|
|
|
PRInt32 CSSStyleRuleImpl::GetWeight(void) const
|
|
{
|
|
return mWeight;
|
|
}
|
|
|
|
void CSSStyleRuleImpl::SetWeight(PRInt32 aWeight)
|
|
{
|
|
mWeight = aWeight;
|
|
}
|
|
|
|
nscoord CSSStyleRuleImpl::CalcLength(const nsCSSValue& aValue, nsStyleFont* aFont,
|
|
nsIPresContext* aPresContext)
|
|
{
|
|
NS_ASSERTION(aValue.IsLengthUnit(), "not a length unit");
|
|
if (aValue.IsFixedLengthUnit()) {
|
|
return aValue.GetLengthTwips();
|
|
}
|
|
nsCSSUnit unit = aValue.GetUnit();
|
|
switch (unit) {
|
|
case eCSSUnit_EM:
|
|
return aFont->mFont.size;
|
|
case eCSSUnit_EN:
|
|
return (aFont->mFont.size / 2);
|
|
case eCSSUnit_XHeight:
|
|
NS_NOTYETIMPLEMENTED("x height unit");
|
|
return ((aFont->mFont.size / 3) * 2); // XXX HACK!
|
|
case eCSSUnit_CapHeight:
|
|
NS_NOTYETIMPLEMENTED("cap height unit");
|
|
return ((aFont->mFont.size / 3) * 2); // XXX HACK!
|
|
|
|
case eCSSUnit_Pixel:
|
|
return (nscoord)(aPresContext->GetPixelsToTwips() * aValue.GetFloatValue());
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void CSSStyleRuleImpl::MapStyleInto(nsIStyleContext* aContext, nsIPresContext* aPresContext)
|
|
{
|
|
if (nsnull != mDeclaration) {
|
|
nsStyleFont* font = (nsStyleFont*)aContext->GetData(kStyleFontSID);
|
|
|
|
nsCSSFont* ourFont;
|
|
if (NS_OK == mDeclaration->GetData(kCSSFontSID, (nsCSSStruct**)&ourFont)) {
|
|
if (nsnull != ourFont) {
|
|
nsStyleFont* parentFont = font;
|
|
nsIStyleContext* parentContext = aContext->GetParent();
|
|
if (nsnull != parentContext) {
|
|
parentFont = (nsStyleFont*)parentContext->GetData(kStyleFontSID);
|
|
}
|
|
|
|
// font-family: string list
|
|
if (ourFont->mFamily.GetUnit() == eCSSUnit_String) {
|
|
nsAutoString familyList;
|
|
ourFont->mFamily.GetStringValue(familyList);
|
|
// XXX meeds font support to determine usable fonts
|
|
// parse up the CSS string & remove the quotes
|
|
// XXX only does first until we can tell what are installed fonts
|
|
nsAutoString family;
|
|
PRInt32 index = familyList.Find(PRUnichar(','));
|
|
if (-1 < index) {
|
|
familyList.Left(family, index);
|
|
}
|
|
else {
|
|
family.Append(familyList);
|
|
}
|
|
family.StripChars("\"");
|
|
family.StripWhitespace();
|
|
|
|
font->mFont.name = family;
|
|
}
|
|
|
|
// font-style: enum
|
|
if (ourFont->mStyle.GetUnit() == eCSSUnit_Enumerated) {
|
|
font->mFont.style = ourFont->mStyle.GetIntValue();
|
|
}
|
|
|
|
// font-variant: enum
|
|
if (ourFont->mVariant.GetUnit() == eCSSUnit_Enumerated) {
|
|
font->mFont.variant = ourFont->mVariant.GetIntValue();
|
|
}
|
|
|
|
// font-weight: abs, enum
|
|
if (ourFont->mWeight.GetUnit() == eCSSUnit_Absolute) {
|
|
font->mFont.style = ourFont->mWeight.GetIntValue();
|
|
}
|
|
else if (ourFont->mWeight.GetUnit() == eCSSUnit_Enumerated) {
|
|
PRInt32 value = ourFont->mWeight.GetIntValue();
|
|
switch (value) {
|
|
case NS_STYLE_FONT_WEIGHT_NORMAL:
|
|
case NS_STYLE_FONT_WEIGHT_BOLD:
|
|
font->mFont.weight = value;
|
|
break;
|
|
case NS_STYLE_FONT_WEIGHT_BOLDER:
|
|
case NS_STYLE_FONT_WEIGHT_LIGHTER:
|
|
font->mFont.weight = (parentFont->mFont.weight + value);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// font-size: enum, length, percent
|
|
if (ourFont->mSize.GetUnit() == eCSSUnit_Enumerated) {
|
|
static float kFontScale[7] = {
|
|
0.5f, // xx-small
|
|
0.666667f, // x-small
|
|
0.833333f, // small
|
|
1.0f, // medium
|
|
1.5f, // large
|
|
1.5f * 1.5f, // x-large
|
|
1.5f * 1.5f * 1.5f, // xx-large
|
|
};
|
|
PRInt32 value = ourFont->mSize.GetIntValue();
|
|
|
|
const nsFont& normal = aPresContext->GetDefaultFont(); // use normal font or body font??
|
|
if ((NS_STYLE_FONT_SIZE_XXSMALL <= value) &&
|
|
(value <= NS_STYLE_FONT_SIZE_XXLARGE)) {
|
|
font->mFont.size = (nscoord)((float)normal.size * kFontScale[value]);
|
|
}
|
|
else if (NS_STYLE_FONT_SIZE_LARGER == value) {
|
|
PRInt32 index;
|
|
for (index = NS_STYLE_FONT_SIZE_XXSMALL;
|
|
index < NS_STYLE_FONT_SIZE_XXLARGE; index++)
|
|
if (parentFont->mFont.size < (nscoord)((float)normal.size * kFontScale[index]))
|
|
break;
|
|
font->mFont.size = (nscoord)((float)normal.size * kFontScale[index]);
|
|
}
|
|
else if (NS_STYLE_FONT_SIZE_SMALLER == value) {
|
|
PRInt32 index;
|
|
for (index = NS_STYLE_FONT_SIZE_XXLARGE;
|
|
index > NS_STYLE_FONT_SIZE_XXSMALL; index--)
|
|
if (parentFont->mFont.size > (nscoord)((float)normal.size * kFontScale[index]))
|
|
break;
|
|
font->mFont.size = (nscoord)((float)normal.size * kFontScale[index]);
|
|
}
|
|
}
|
|
else if (ourFont->mSize.IsLengthUnit()) {
|
|
font->mFont.size = CalcLength(ourFont->mSize, parentFont, aPresContext);
|
|
}
|
|
else if (ourFont->mSize.GetUnit() == eCSSUnit_Percent) {
|
|
font->mFont.size = (nscoord)((float)(parentFont->mFont.size) * ourFont->mSize.GetFloatValue());
|
|
}
|
|
|
|
NS_IF_RELEASE(parentContext);
|
|
}
|
|
}
|
|
|
|
nsCSSText* ourText;
|
|
if (NS_OK == mDeclaration->GetData(kCSSTextSID, (nsCSSStruct**)&ourText)) {
|
|
if (nsnull != ourText) {
|
|
|
|
// text-decoration: enum, absolute (bit field)
|
|
if (ourText->mDecoration.GetUnit() == eCSSUnit_Enumerated) {
|
|
font->mFont.decorations = ourText->mDecoration.GetIntValue();
|
|
}
|
|
else if (ourText->mDecoration.GetUnit() == eCSSUnit_Absolute) {
|
|
font->mFont.decorations = ourText->mDecoration.GetIntValue();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
nsCSSColor* ourColor;
|
|
if (NS_OK == mDeclaration->GetData(kCSSColorSID, (nsCSSStruct**)&ourColor)) {
|
|
if (nsnull != ourColor) {
|
|
nsStyleColor* color = (nsStyleColor*)aContext->GetData(kStyleColorSID);
|
|
|
|
// color: color
|
|
if (ourColor->mColor.GetUnit() == eCSSUnit_Color) {
|
|
color->mColor = ourColor->mColor.GetColorValue();
|
|
}
|
|
|
|
// background-color: color, enum (flags)
|
|
if (ourColor->mBackColor.GetUnit() == eCSSUnit_Color) {
|
|
color->mBackgroundColor = ourColor->mBackColor.GetColorValue();
|
|
color->mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT;
|
|
}
|
|
else if (ourColor->mBackColor.GetUnit() == eCSSUnit_Enumerated) {
|
|
color->mBackgroundFlags |= NS_STYLE_BG_COLOR_TRANSPARENT;
|
|
}
|
|
|
|
// background-image: string, enum (flags)
|
|
if (ourColor->mBackImage.GetUnit() == eCSSUnit_String) {
|
|
ourColor->mBackImage.GetStringValue(color->mBackgroundImage);
|
|
color->mBackgroundFlags &= ~NS_STYLE_BG_IMAGE_NONE;
|
|
}
|
|
else if (ourColor->mBackImage.GetUnit() == eCSSUnit_Enumerated) {
|
|
color->mBackgroundFlags |= NS_STYLE_BG_IMAGE_NONE;
|
|
}
|
|
|
|
// background-repeat: enum
|
|
if (ourColor->mBackRepeat.GetUnit() == eCSSUnit_Enumerated) {
|
|
color->mBackgroundRepeat = ourColor->mBackRepeat.GetIntValue();
|
|
}
|
|
|
|
// background-attachment: enum
|
|
if (ourColor->mBackAttachment.GetUnit() == eCSSUnit_Enumerated) {
|
|
color->mBackgroundAttachment = ourColor->mBackAttachment.GetIntValue();
|
|
}
|
|
|
|
// background-position: length, percent (flags)
|
|
if (ourColor->mBackPositionX.GetUnit() == eCSSUnit_Percent) {
|
|
color->mBackgroundXPosition = (nscoord)(TWIPS_CONST_FLOAT * ourColor->mBackPositionX.GetFloatValue());
|
|
color->mBackgroundFlags |= NS_STYLE_BG_X_POSITION_PCT;
|
|
color->mBackgroundFlags &= ~NS_STYLE_BG_X_POSITION_LENGTH;
|
|
}
|
|
else if (ourColor->mBackPositionX.IsLengthUnit()) {
|
|
color->mBackgroundXPosition = CalcLength(ourColor->mBackPositionX,
|
|
font, aPresContext);
|
|
color->mBackgroundFlags |= NS_STYLE_BG_X_POSITION_LENGTH;
|
|
color->mBackgroundFlags &= ~NS_STYLE_BG_X_POSITION_PCT;
|
|
}
|
|
if (ourColor->mBackPositionY.GetUnit() == eCSSUnit_Percent) {
|
|
color->mBackgroundYPosition = (nscoord)(TWIPS_CONST_FLOAT * ourColor->mBackPositionY.GetFloatValue());
|
|
color->mBackgroundFlags |= NS_STYLE_BG_Y_POSITION_PCT;
|
|
color->mBackgroundFlags &= ~NS_STYLE_BG_Y_POSITION_LENGTH;
|
|
}
|
|
else if (ourColor->mBackPositionY.IsLengthUnit()) {
|
|
color->mBackgroundYPosition = CalcLength(ourColor->mBackPositionY,
|
|
font, aPresContext);
|
|
color->mBackgroundFlags |= NS_STYLE_BG_Y_POSITION_LENGTH;
|
|
color->mBackgroundFlags &= ~NS_STYLE_BG_Y_POSITION_PCT;
|
|
}
|
|
|
|
// XXX: NYI nsCSSValue mBackFilter;
|
|
}
|
|
}
|
|
|
|
nsCSSMargin* ourMargin;
|
|
if (NS_OK == mDeclaration->GetData(kCSSMarginSID, (nsCSSStruct**)&ourMargin)) {
|
|
if (nsnull != ourMargin) {
|
|
nsStyleSpacing* spacing = (nsStyleSpacing*)aContext->GetData(kStyleSpacingSID);
|
|
|
|
// margin
|
|
if (nsnull != ourMargin->mMargin) {
|
|
if (ourMargin->mMargin->mLeft.IsLengthUnit()) {
|
|
spacing->mMargin.left = CalcLength(ourMargin->mMargin->mLeft, font, aPresContext);
|
|
} else if (ourMargin->mMargin->mLeft.GetUnit() != eCSSUnit_Null) {
|
|
// XXX handle percent properly, this isn't it
|
|
spacing->mMargin.left = (nscoord)ourMargin->mMargin->mLeft.GetFloatValue();
|
|
}
|
|
if (ourMargin->mMargin->mTop.IsLengthUnit()) {
|
|
spacing->mMargin.top = CalcLength(ourMargin->mMargin->mTop, font, aPresContext);
|
|
} else if (ourMargin->mMargin->mTop.GetUnit() != eCSSUnit_Null) {
|
|
// XXX handle percent properly, this isn't it
|
|
spacing->mMargin.top = (nscoord)ourMargin->mMargin->mTop.GetFloatValue();
|
|
}
|
|
if (ourMargin->mMargin->mRight.IsLengthUnit()) {
|
|
spacing->mMargin.right = CalcLength(ourMargin->mMargin->mRight, font, aPresContext);
|
|
} else if (ourMargin->mMargin->mRight.GetUnit() != eCSSUnit_Null) {
|
|
// XXX handle percent properly, this isn't it
|
|
spacing->mMargin.right = (nscoord)ourMargin->mMargin->mRight.GetFloatValue();
|
|
}
|
|
if (ourMargin->mMargin->mBottom.IsLengthUnit()) {
|
|
spacing->mMargin.bottom = CalcLength(ourMargin->mMargin->mBottom, font, aPresContext);
|
|
} else if (ourMargin->mMargin->mBottom.GetUnit() != eCSSUnit_Null) {
|
|
// XXX handle percent properly, this isn't it
|
|
spacing->mMargin.bottom = (nscoord)ourMargin->mMargin->mBottom.GetFloatValue();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
nsCSSPosition* ourPosition;
|
|
if (NS_OK == mDeclaration->GetData(kCSSPositionSID, (nsCSSStruct**)&ourPosition)) {
|
|
if (nsnull != ourPosition) {
|
|
nsStyleMolecule* hack = (nsStyleMolecule*)aContext->GetData(kStyleMoleculeSID);
|
|
|
|
if (ourPosition->mPosition.GetUnit() == eCSSUnit_Enumerated) {
|
|
hack->positionFlags = ourPosition->mPosition.GetIntValue();
|
|
} else {
|
|
hack->positionFlags = NS_STYLE_POSITION_STATIC;
|
|
}
|
|
}
|
|
}
|
|
|
|
nsCSSList* ourList;
|
|
if (NS_OK == mDeclaration->GetData(kCSSListSID, (nsCSSStruct**)&ourList)) {
|
|
if (nsnull != ourList) {
|
|
nsStyleList* list = (nsStyleList*)aContext->GetData(kStyleListSID);
|
|
|
|
// list-style-type: enum
|
|
if (ourList->mType.GetUnit() == eCSSUnit_Enumerated) {
|
|
list->mListStyleType = ourList->mType.GetIntValue();
|
|
}
|
|
|
|
// list-style-image: string
|
|
if (ourList->mImage.GetUnit() == eCSSUnit_String) {
|
|
ourList->mImage.GetStringValue(list->mListStyleImage);
|
|
}
|
|
else if (ourList->mImage.GetUnit() == eCSSUnit_Enumerated) { // handle "none"
|
|
list->mListStyleImage = "";
|
|
}
|
|
|
|
// list-style-position: enum
|
|
if (ourList->mPosition.GetUnit() == eCSSUnit_Enumerated) {
|
|
list->mListStyleType = ourList->mPosition.GetIntValue();
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ListSelector(FILE* out, const nsCSSSelector* aSelector)
|
|
{
|
|
nsAutoString buffer;
|
|
|
|
if (nsnull != aSelector->mTag) {
|
|
aSelector->mTag->ToString(buffer);
|
|
fputs(buffer, out);
|
|
}
|
|
if (nsnull != aSelector->mID) {
|
|
aSelector->mID->ToString(buffer);
|
|
fputs("#", out);
|
|
fputs(buffer, out);
|
|
}
|
|
if (nsnull != aSelector->mClass) {
|
|
aSelector->mClass->ToString(buffer);
|
|
fputs(".", out);
|
|
fputs(buffer, out);
|
|
}
|
|
if (nsnull != aSelector->mPseudoClass) {
|
|
aSelector->mPseudoClass->ToString(buffer);
|
|
fputs(":", out);
|
|
fputs(buffer, out);
|
|
}
|
|
}
|
|
|
|
void CSSStyleRuleImpl::List(FILE* out, PRInt32 aIndent) const
|
|
{
|
|
// Indent
|
|
for (PRInt32 index = aIndent; --index >= 0; ) fputs(" ", out);
|
|
|
|
const nsCSSSelector* selector = &mSelector;
|
|
|
|
while (nsnull != selector) {
|
|
ListSelector(out, selector);
|
|
fputs(" ", out);
|
|
selector = selector->mNext;
|
|
}
|
|
|
|
nsAutoString buffer;
|
|
|
|
buffer.Append("weight: ");
|
|
buffer.Append(mWeight, 10);
|
|
buffer.Append(" ");
|
|
fputs(buffer, out);
|
|
if (nsnull != mDeclaration) {
|
|
mDeclaration->List(out);
|
|
}
|
|
else {
|
|
fputs("{ null declaration }", out);
|
|
}
|
|
fputs("\n", out);
|
|
}
|
|
|
|
NS_HTML nsresult
|
|
NS_NewCSSStyleRule(nsICSSStyleRule** aInstancePtrResult, const nsCSSSelector& aSelector)
|
|
{
|
|
if (aInstancePtrResult == nsnull) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
|
|
CSSStyleRuleImpl *it = new CSSStyleRuleImpl(aSelector);
|
|
|
|
if (nsnull == it) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
return it->QueryInterface(kICSSStyleRuleIID, (void **) aInstancePtrResult);
|
|
}
|