The merge from inbound to central conflicted with the merge from autoland to central, it appears. Per tree rules, the commit from the autoland repo wins and the inbound commit gets backed out. CLOSED TREE
3284 lines
81 KiB
C++
3284 lines
81 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
/* rules in a CSS stylesheet other than style rules (e.g., @import rules) */
|
|
|
|
#include "mozilla/Attributes.h"
|
|
|
|
#include "nsCSSRules.h"
|
|
#include "nsCSSValue.h"
|
|
#include "mozilla/CSSStyleSheet.h"
|
|
#include "mozilla/MemoryReporting.h"
|
|
#include "mozilla/css/ImportRule.h"
|
|
#include "mozilla/css/NameSpaceRule.h"
|
|
|
|
#include "nsString.h"
|
|
#include "nsIAtom.h"
|
|
|
|
#include "nsCSSProps.h"
|
|
|
|
#include "nsCOMPtr.h"
|
|
#include "nsIDOMCSSStyleSheet.h"
|
|
#include "nsIMediaList.h"
|
|
#include "mozilla/dom/CSSRuleList.h"
|
|
#include "nsIDocument.h"
|
|
#include "nsPresContext.h"
|
|
|
|
#include "nsContentUtils.h"
|
|
#include "nsError.h"
|
|
#include "nsStyleUtil.h"
|
|
#include "mozilla/css/Declaration.h"
|
|
#include "nsCSSParser.h"
|
|
#include "nsDOMClassInfoID.h"
|
|
#include "mozilla/dom/CSSStyleDeclarationBinding.h"
|
|
#include "StyleRule.h"
|
|
#include "nsFont.h"
|
|
#include "nsIURI.h"
|
|
#include "mozAutoDocUpdate.h"
|
|
|
|
using namespace mozilla;
|
|
using namespace mozilla::dom;
|
|
|
|
#define IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(class_, super_) \
|
|
/* virtual */ nsIDOMCSSRule* class_::GetDOMRule() \
|
|
{ return this; } \
|
|
/* virtual */ nsIDOMCSSRule* class_::GetExistingDOMRule() \
|
|
{ return this; }
|
|
|
|
#define IMPL_STYLE_RULE_INHERIT(class_, super_) \
|
|
IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(class_, super_)
|
|
|
|
// base class for all rule types in a CSS style sheet
|
|
|
|
namespace mozilla {
|
|
namespace css {
|
|
|
|
/* virtual */ void
|
|
Rule::SetStyleSheet(CSSStyleSheet* aSheet)
|
|
{
|
|
// We don't reference count this up reference. The style sheet
|
|
// will tell us when it's going away or when we're detached from
|
|
// it.
|
|
mSheet = aSheet;
|
|
}
|
|
|
|
nsresult
|
|
Rule::GetParentRule(nsIDOMCSSRule** aParentRule)
|
|
{
|
|
if (mParentRule) {
|
|
NS_IF_ADDREF(*aParentRule = mParentRule->GetDOMRule());
|
|
} else {
|
|
*aParentRule = nullptr;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
Rule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aSheet);
|
|
|
|
NS_IF_ADDREF(*aSheet = GetStyleSheet());
|
|
return NS_OK;
|
|
}
|
|
|
|
css::Rule*
|
|
Rule::GetCSSRule()
|
|
{
|
|
return this;
|
|
}
|
|
|
|
// -------------------------------
|
|
// Style Rule List for group rules
|
|
//
|
|
|
|
class GroupRuleRuleList final : public dom::CSSRuleList
|
|
{
|
|
public:
|
|
explicit GroupRuleRuleList(GroupRule *aGroupRule);
|
|
|
|
virtual CSSStyleSheet* GetParentObject() override;
|
|
|
|
virtual nsIDOMCSSRule*
|
|
IndexedGetter(uint32_t aIndex, bool& aFound) override;
|
|
virtual uint32_t
|
|
Length() override;
|
|
|
|
void DropReference() { mGroupRule = nullptr; }
|
|
|
|
private:
|
|
~GroupRuleRuleList();
|
|
|
|
private:
|
|
GroupRule* mGroupRule;
|
|
};
|
|
|
|
GroupRuleRuleList::GroupRuleRuleList(GroupRule *aGroupRule)
|
|
{
|
|
// Not reference counted to avoid circular references.
|
|
// The rule will tell us when its going away.
|
|
mGroupRule = aGroupRule;
|
|
}
|
|
|
|
GroupRuleRuleList::~GroupRuleRuleList()
|
|
{
|
|
}
|
|
|
|
CSSStyleSheet*
|
|
GroupRuleRuleList::GetParentObject()
|
|
{
|
|
if (!mGroupRule) {
|
|
return nullptr;
|
|
}
|
|
|
|
return mGroupRule->GetStyleSheet();
|
|
}
|
|
|
|
uint32_t
|
|
GroupRuleRuleList::Length()
|
|
{
|
|
if (!mGroupRule) {
|
|
return 0;
|
|
}
|
|
|
|
return AssertedCast<uint32_t>(mGroupRule->StyleRuleCount());
|
|
}
|
|
|
|
nsIDOMCSSRule*
|
|
GroupRuleRuleList::IndexedGetter(uint32_t aIndex, bool& aFound)
|
|
{
|
|
aFound = false;
|
|
|
|
if (mGroupRule) {
|
|
RefPtr<Rule> rule = mGroupRule->GetStyleRuleAt(aIndex);
|
|
if (rule) {
|
|
aFound = true;
|
|
return rule->GetDOMRule();
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
// -------------------------------------------
|
|
// ImportRule
|
|
//
|
|
|
|
ImportRule::ImportRule(nsMediaList* aMedia, const nsString& aURLSpec,
|
|
uint32_t aLineNumber, uint32_t aColumnNumber)
|
|
: Rule(aLineNumber, aColumnNumber)
|
|
, mURLSpec(aURLSpec)
|
|
, mMedia(aMedia)
|
|
{
|
|
// XXXbz This is really silly.... the mMedia here will be replaced
|
|
// with itself if we manage to load a sheet. Which should really
|
|
// never fail nowadays, in sane cases.
|
|
}
|
|
|
|
ImportRule::ImportRule(const ImportRule& aCopy)
|
|
: Rule(aCopy),
|
|
mURLSpec(aCopy.mURLSpec)
|
|
{
|
|
// Whether or not an @import rule has a null sheet is a permanent
|
|
// property of that @import rule, since it is null only if the target
|
|
// sheet failed security checks.
|
|
if (aCopy.mChildSheet) {
|
|
RefPtr<CSSStyleSheet> sheet =
|
|
aCopy.mChildSheet->Clone(nullptr, this, nullptr, nullptr);
|
|
SetSheet(sheet);
|
|
// SetSheet sets mMedia appropriately
|
|
}
|
|
}
|
|
|
|
ImportRule::~ImportRule()
|
|
{
|
|
if (mChildSheet) {
|
|
mChildSheet->SetOwnerRule(nullptr);
|
|
}
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(ImportRule)
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(ImportRule)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION(ImportRule, mMedia, mChildSheet)
|
|
|
|
// QueryInterface implementation for ImportRule
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ImportRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSImportRule)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozilla::css::Rule)
|
|
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSImportRule)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
IMPL_STYLE_RULE_INHERIT(ImportRule, Rule)
|
|
|
|
#ifdef DEBUG
|
|
/* virtual */ void
|
|
ImportRule::List(FILE* out, int32_t aIndent) const
|
|
{
|
|
nsAutoCString str;
|
|
// Indent
|
|
for (int32_t indent = aIndent; --indent >= 0; ) {
|
|
str.AppendLiteral(" ");
|
|
}
|
|
|
|
str.AppendLiteral("@import \"");
|
|
AppendUTF16toUTF8(mURLSpec, str);
|
|
str.AppendLiteral("\" ");
|
|
|
|
nsAutoString mediaText;
|
|
mMedia->GetText(mediaText);
|
|
AppendUTF16toUTF8(mediaText, str);
|
|
str.AppendLiteral("\n");
|
|
fprintf_stderr(out, "%s", str.get());
|
|
}
|
|
#endif
|
|
|
|
/* virtual */ int32_t
|
|
ImportRule::GetType() const
|
|
{
|
|
return Rule::IMPORT_RULE;
|
|
}
|
|
|
|
/* virtual */ already_AddRefed<Rule>
|
|
ImportRule::Clone() const
|
|
{
|
|
RefPtr<Rule> clone = new ImportRule(*this);
|
|
return clone.forget();
|
|
}
|
|
|
|
void
|
|
ImportRule::SetSheet(CSSStyleSheet* aSheet)
|
|
{
|
|
NS_PRECONDITION(aSheet, "null arg");
|
|
|
|
// set the new sheet
|
|
mChildSheet = aSheet;
|
|
aSheet->SetOwnerRule(this);
|
|
|
|
// set our medialist to be the same as the sheet's medialist
|
|
mMedia = mChildSheet->Media();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ImportRule::GetType(uint16_t* aType)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aType);
|
|
*aType = nsIDOMCSSRule::IMPORT_RULE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ImportRule::GetCssText(nsAString& aCssText)
|
|
{
|
|
aCssText.AssignLiteral("@import url(");
|
|
nsStyleUtil::AppendEscapedCSSString(mURLSpec, aCssText);
|
|
aCssText.Append(')');
|
|
if (mMedia) {
|
|
nsAutoString mediaText;
|
|
mMedia->GetText(mediaText);
|
|
if (!mediaText.IsEmpty()) {
|
|
aCssText.Append(' ');
|
|
aCssText.Append(mediaText);
|
|
}
|
|
}
|
|
aCssText.Append(';');
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ImportRule::SetCssText(const nsAString& aCssText)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ImportRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
|
|
{
|
|
return Rule::GetParentStyleSheet(aSheet);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ImportRule::GetParentRule(nsIDOMCSSRule** aParentRule)
|
|
{
|
|
return Rule::GetParentRule(aParentRule);
|
|
}
|
|
|
|
css::Rule*
|
|
ImportRule::GetCSSRule()
|
|
{
|
|
return Rule::GetCSSRule();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ImportRule::GetHref(nsAString & aHref)
|
|
{
|
|
aHref = mURLSpec;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ImportRule::GetMedia(nsIDOMMediaList * *aMedia)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aMedia);
|
|
|
|
NS_IF_ADDREF(*aMedia = mMedia);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ImportRule::GetStyleSheet(nsIDOMCSSStyleSheet * *aStyleSheet)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aStyleSheet);
|
|
|
|
NS_IF_ADDREF(*aStyleSheet = mChildSheet);
|
|
return NS_OK;
|
|
}
|
|
|
|
/* virtual */ size_t
|
|
ImportRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
|
{
|
|
return aMallocSizeOf(this);
|
|
|
|
// Measurement of the following members may be added later if DMD finds it is
|
|
// worthwhile:
|
|
// - mURLSpec
|
|
//
|
|
// The following members are not measured:
|
|
// - mMedia, because it is measured via CSSStyleSheet::mMedia
|
|
// - mChildSheet, because it is measured via CSSStyleSheetInner::mSheets
|
|
}
|
|
|
|
GroupRule::GroupRule(uint32_t aLineNumber, uint32_t aColumnNumber)
|
|
: Rule(aLineNumber, aColumnNumber)
|
|
{
|
|
}
|
|
|
|
static bool
|
|
SetParentRuleReference(Rule* aRule, void* aParentRule)
|
|
{
|
|
GroupRule* parentRule = static_cast<GroupRule*>(aParentRule);
|
|
aRule->SetParentRule(parentRule);
|
|
return true;
|
|
}
|
|
|
|
GroupRule::GroupRule(const GroupRule& aCopy)
|
|
: Rule(aCopy)
|
|
{
|
|
const_cast<GroupRule&>(aCopy).mRules.EnumerateForwards(GroupRule::CloneRuleInto, &mRules);
|
|
mRules.EnumerateForwards(SetParentRuleReference, this);
|
|
}
|
|
|
|
GroupRule::~GroupRule()
|
|
{
|
|
MOZ_ASSERT(!mSheet, "SetStyleSheet should have been called");
|
|
mRules.EnumerateForwards(SetParentRuleReference, nullptr);
|
|
if (mRuleCollection) {
|
|
mRuleCollection->DropReference();
|
|
}
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(GroupRule)
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(GroupRule)
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GroupRule)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
static bool
|
|
SetStyleSheetReference(Rule* aRule, void* aSheet)
|
|
{
|
|
CSSStyleSheet* sheet = (CSSStyleSheet*)aSheet;
|
|
aRule->SetStyleSheet(sheet);
|
|
return true;
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(GroupRule)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(GroupRule)
|
|
tmp->mRules.EnumerateForwards(SetParentRuleReference, nullptr);
|
|
// If tmp does not have a stylesheet, neither do its descendants. In that
|
|
// case, don't try to null out their stylesheet, to avoid O(N^2) behavior in
|
|
// depth of group rule nesting. But if tmp _does_ have a stylesheet (which
|
|
// can happen if it gets unlinked earlier than its owning stylesheet), then we
|
|
// need to null out the stylesheet pointer on descendants now, before we clear
|
|
// tmp->mRules.
|
|
if (tmp->GetStyleSheet()) {
|
|
tmp->mRules.EnumerateForwards(SetStyleSheetReference, nullptr);
|
|
}
|
|
tmp->mRules.Clear();
|
|
if (tmp->mRuleCollection) {
|
|
tmp->mRuleCollection->DropReference();
|
|
tmp->mRuleCollection = nullptr;
|
|
}
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(GroupRule)
|
|
const nsCOMArray<Rule>& rules = tmp->mRules;
|
|
for (int32_t i = 0, count = rules.Count(); i < count; ++i) {
|
|
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mRules[i]");
|
|
cb.NoteXPCOMChild(rules[i]->GetExistingDOMRule());
|
|
}
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRuleCollection)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
/* virtual */ void
|
|
GroupRule::SetStyleSheet(CSSStyleSheet* aSheet)
|
|
{
|
|
// Don't set the sheet on the kids if it's already the same as the sheet we
|
|
// already have. This is needed to avoid O(N^2) behavior in group nesting
|
|
// depth when seting the sheet to null during unlink, if we happen to unlin in
|
|
// order from most nested rule up to least nested rule.
|
|
if (aSheet != GetStyleSheet()) {
|
|
mRules.EnumerateForwards(SetStyleSheetReference, aSheet);
|
|
Rule::SetStyleSheet(aSheet);
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
/* virtual */ void
|
|
GroupRule::List(FILE* out, int32_t aIndent) const
|
|
{
|
|
for (int32_t index = 0, count = mRules.Count(); index < count; ++index) {
|
|
mRules.ObjectAt(index)->List(out, aIndent + 1);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void
|
|
GroupRule::AppendStyleRule(Rule* aRule)
|
|
{
|
|
mRules.AppendObject(aRule);
|
|
CSSStyleSheet* sheet = GetStyleSheet();
|
|
aRule->SetStyleSheet(sheet);
|
|
aRule->SetParentRule(this);
|
|
if (sheet) {
|
|
sheet->SetModifiedByChildRule();
|
|
}
|
|
}
|
|
|
|
Rule*
|
|
GroupRule::GetStyleRuleAt(int32_t aIndex) const
|
|
{
|
|
return mRules.SafeObjectAt(aIndex);
|
|
}
|
|
|
|
bool
|
|
GroupRule::EnumerateRulesForwards(RuleEnumFunc aFunc, void * aData) const
|
|
{
|
|
return
|
|
const_cast<GroupRule*>(this)->mRules.EnumerateForwards(aFunc, aData);
|
|
}
|
|
|
|
/*
|
|
* The next two methods (DeleteStyleRuleAt and InsertStyleRuleAt)
|
|
* should never be called unless you have first called WillDirty() on
|
|
* the parents stylesheet. After they are called, DidDirty() needs to
|
|
* be called on the sheet
|
|
*/
|
|
nsresult
|
|
GroupRule::DeleteStyleRuleAt(uint32_t aIndex)
|
|
{
|
|
Rule* rule = mRules.SafeObjectAt(aIndex);
|
|
if (rule) {
|
|
rule->SetStyleSheet(nullptr);
|
|
rule->SetParentRule(nullptr);
|
|
}
|
|
return mRules.RemoveObjectAt(aIndex) ? NS_OK : NS_ERROR_ILLEGAL_VALUE;
|
|
}
|
|
|
|
nsresult
|
|
GroupRule::InsertStyleRuleAt(uint32_t aIndex, Rule* aRule)
|
|
{
|
|
aRule->SetStyleSheet(GetStyleSheet());
|
|
aRule->SetParentRule(this);
|
|
if (! mRules.InsertObjectAt(aRule, aIndex)) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
GroupRule::AppendRulesToCssText(nsAString& aCssText)
|
|
{
|
|
aCssText.AppendLiteral(" {\n");
|
|
|
|
// get all the rules
|
|
for (int32_t index = 0, count = mRules.Count(); index < count; ++index) {
|
|
Rule* rule = mRules.ObjectAt(index);
|
|
nsIDOMCSSRule* domRule = rule->GetDOMRule();
|
|
if (domRule) {
|
|
nsAutoString cssText;
|
|
domRule->GetCssText(cssText);
|
|
aCssText.AppendLiteral(" ");
|
|
aCssText.Append(cssText);
|
|
aCssText.Append('\n');
|
|
}
|
|
}
|
|
|
|
aCssText.Append('}');
|
|
}
|
|
|
|
// nsIDOMCSSMediaRule or nsIDOMCSSMozDocumentRule methods
|
|
nsresult
|
|
GroupRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
|
|
{
|
|
if (!mRuleCollection) {
|
|
mRuleCollection = new css::GroupRuleRuleList(this);
|
|
}
|
|
|
|
NS_ADDREF(*aRuleList = mRuleCollection);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
GroupRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
|
|
{
|
|
CSSStyleSheet* sheet = GetStyleSheet();
|
|
NS_ENSURE_TRUE(sheet, NS_ERROR_FAILURE);
|
|
|
|
if (aIndex > uint32_t(mRules.Count()))
|
|
return NS_ERROR_DOM_INDEX_SIZE_ERR;
|
|
|
|
NS_ASSERTION(uint32_t(mRules.Count()) <= INT32_MAX,
|
|
"Too many style rules!");
|
|
|
|
return sheet->InsertRuleIntoGroup(aRule, this, aIndex, _retval);
|
|
}
|
|
|
|
nsresult
|
|
GroupRule::DeleteRule(uint32_t aIndex)
|
|
{
|
|
CSSStyleSheet* sheet = GetStyleSheet();
|
|
NS_ENSURE_TRUE(sheet, NS_ERROR_FAILURE);
|
|
|
|
if (aIndex >= uint32_t(mRules.Count()))
|
|
return NS_ERROR_DOM_INDEX_SIZE_ERR;
|
|
|
|
NS_ASSERTION(uint32_t(mRules.Count()) <= INT32_MAX,
|
|
"Too many style rules!");
|
|
|
|
return sheet->DeleteRuleFromGroup(this, aIndex);
|
|
}
|
|
|
|
/* virtual */ size_t
|
|
GroupRule::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
|
{
|
|
size_t n = mRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
|
for (size_t i = 0; i < mRules.Length(); i++) {
|
|
n += mRules[i]->SizeOfIncludingThis(aMallocSizeOf);
|
|
}
|
|
|
|
// Measurement of the following members may be added later if DMD finds it is
|
|
// worthwhile:
|
|
// - mRuleCollection
|
|
return n;
|
|
}
|
|
|
|
|
|
// -------------------------------------------
|
|
// nsICSSMediaRule
|
|
//
|
|
MediaRule::MediaRule(uint32_t aLineNumber, uint32_t aColumnNumber)
|
|
: GroupRule(aLineNumber, aColumnNumber)
|
|
{
|
|
}
|
|
|
|
MediaRule::MediaRule(const MediaRule& aCopy)
|
|
: GroupRule(aCopy)
|
|
{
|
|
if (aCopy.mMedia) {
|
|
mMedia = aCopy.mMedia->Clone();
|
|
// XXXldb This doesn't really make sense.
|
|
mMedia->SetStyleSheet(aCopy.GetStyleSheet());
|
|
}
|
|
}
|
|
|
|
MediaRule::~MediaRule()
|
|
{
|
|
if (mMedia) {
|
|
mMedia->SetStyleSheet(nullptr);
|
|
}
|
|
}
|
|
|
|
NS_IMPL_ADDREF_INHERITED(MediaRule, GroupRule)
|
|
NS_IMPL_RELEASE_INHERITED(MediaRule, GroupRule)
|
|
|
|
// QueryInterface implementation for MediaRule
|
|
NS_INTERFACE_MAP_BEGIN(MediaRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMediaRule)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozilla::css::Rule)
|
|
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSMediaRule)
|
|
NS_INTERFACE_MAP_END_INHERITING(GroupRule)
|
|
|
|
/* virtual */ void
|
|
MediaRule::SetStyleSheet(CSSStyleSheet* aSheet)
|
|
{
|
|
if (mMedia) {
|
|
// Set to null so it knows it's leaving one sheet and joining another.
|
|
mMedia->SetStyleSheet(nullptr);
|
|
mMedia->SetStyleSheet(aSheet);
|
|
}
|
|
|
|
GroupRule::SetStyleSheet(aSheet);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
/* virtual */ void
|
|
MediaRule::List(FILE* out, int32_t aIndent) const
|
|
{
|
|
nsAutoCString indentStr;
|
|
for (int32_t indent = aIndent; --indent >= 0; ) {
|
|
indentStr.AppendLiteral(" ");
|
|
}
|
|
|
|
nsAutoCString str(indentStr);
|
|
str.AppendLiteral("@media ");
|
|
|
|
if (mMedia) {
|
|
nsAutoString mediaText;
|
|
mMedia->GetText(mediaText);
|
|
AppendUTF16toUTF8(mediaText, str);
|
|
}
|
|
|
|
str.AppendLiteral(" {\n");
|
|
fprintf_stderr(out, "%s", str.get());
|
|
|
|
GroupRule::List(out, aIndent);
|
|
|
|
fprintf_stderr(out, "%s}\n", indentStr.get());
|
|
}
|
|
#endif
|
|
|
|
/* virtual */ int32_t
|
|
MediaRule::GetType() const
|
|
{
|
|
return Rule::MEDIA_RULE;
|
|
}
|
|
|
|
/* virtual */ already_AddRefed<Rule>
|
|
MediaRule::Clone() const
|
|
{
|
|
RefPtr<Rule> clone = new MediaRule(*this);
|
|
return clone.forget();
|
|
}
|
|
|
|
nsresult
|
|
MediaRule::SetMedia(nsMediaList* aMedia)
|
|
{
|
|
mMedia = aMedia;
|
|
if (aMedia)
|
|
mMedia->SetStyleSheet(GetStyleSheet());
|
|
return NS_OK;
|
|
}
|
|
|
|
// nsIDOMCSSRule methods
|
|
NS_IMETHODIMP
|
|
MediaRule::GetType(uint16_t* aType)
|
|
{
|
|
*aType = nsIDOMCSSRule::MEDIA_RULE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
MediaRule::GetCssText(nsAString& aCssText)
|
|
{
|
|
aCssText.AssignLiteral("@media ");
|
|
AppendConditionText(aCssText);
|
|
GroupRule::AppendRulesToCssText(aCssText);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
MediaRule::SetCssText(const nsAString& aCssText)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
MediaRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
|
|
{
|
|
return GroupRule::GetParentStyleSheet(aSheet);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
MediaRule::GetParentRule(nsIDOMCSSRule** aParentRule)
|
|
{
|
|
return GroupRule::GetParentRule(aParentRule);
|
|
}
|
|
|
|
css::Rule*
|
|
MediaRule::GetCSSRule()
|
|
{
|
|
return Rule::GetCSSRule();
|
|
}
|
|
|
|
// nsIDOMCSSGroupingRule methods
|
|
NS_IMETHODIMP
|
|
MediaRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
|
|
{
|
|
return GroupRule::GetCssRules(aRuleList);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
MediaRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
|
|
{
|
|
return GroupRule::InsertRule(aRule, aIndex, _retval);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
MediaRule::DeleteRule(uint32_t aIndex)
|
|
{
|
|
return GroupRule::DeleteRule(aIndex);
|
|
}
|
|
|
|
// nsIDOMCSSConditionRule methods
|
|
NS_IMETHODIMP
|
|
MediaRule::GetConditionText(nsAString& aConditionText)
|
|
{
|
|
aConditionText.Truncate(0);
|
|
AppendConditionText(aConditionText);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
MediaRule::SetConditionText(const nsAString& aConditionText)
|
|
{
|
|
if (!mMedia) {
|
|
RefPtr<nsMediaList> media = new nsMediaList();
|
|
media->SetStyleSheet(GetStyleSheet());
|
|
nsresult rv = media->SetMediaText(aConditionText);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
mMedia = media;
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
return mMedia->SetMediaText(aConditionText);
|
|
}
|
|
|
|
// nsIDOMCSSMediaRule methods
|
|
NS_IMETHODIMP
|
|
MediaRule::GetMedia(nsIDOMMediaList* *aMedia)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aMedia);
|
|
NS_IF_ADDREF(*aMedia = mMedia);
|
|
return NS_OK;
|
|
}
|
|
|
|
// GroupRule interface
|
|
/* virtual */ bool
|
|
MediaRule::UseForPresentation(nsPresContext* aPresContext,
|
|
nsMediaQueryResultCacheKey& aKey)
|
|
{
|
|
if (mMedia) {
|
|
return mMedia->Matches(aPresContext, &aKey);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/* virtual */ size_t
|
|
MediaRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
|
{
|
|
size_t n = aMallocSizeOf(this);
|
|
n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
|
|
|
|
// Measurement of the following members may be added later if DMD finds it is
|
|
// worthwhile:
|
|
// - mMedia
|
|
|
|
return n;
|
|
}
|
|
|
|
void
|
|
MediaRule::AppendConditionText(nsAString& aOutput)
|
|
{
|
|
if (mMedia) {
|
|
nsAutoString mediaText;
|
|
mMedia->GetText(mediaText);
|
|
aOutput.Append(mediaText);
|
|
}
|
|
}
|
|
|
|
DocumentRule::DocumentRule(uint32_t aLineNumber, uint32_t aColumnNumber)
|
|
: GroupRule(aLineNumber, aColumnNumber)
|
|
{
|
|
}
|
|
|
|
DocumentRule::DocumentRule(const DocumentRule& aCopy)
|
|
: GroupRule(aCopy)
|
|
, mURLs(new URL(*aCopy.mURLs))
|
|
{
|
|
}
|
|
|
|
DocumentRule::~DocumentRule()
|
|
{
|
|
}
|
|
|
|
NS_IMPL_ADDREF_INHERITED(DocumentRule, GroupRule)
|
|
NS_IMPL_RELEASE_INHERITED(DocumentRule, GroupRule)
|
|
|
|
// QueryInterface implementation for DocumentRule
|
|
NS_INTERFACE_MAP_BEGIN(DocumentRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMozDocumentRule)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozilla::css::Rule)
|
|
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSMozDocumentRule)
|
|
NS_INTERFACE_MAP_END_INHERITING(GroupRule)
|
|
|
|
#ifdef DEBUG
|
|
/* virtual */ void
|
|
DocumentRule::List(FILE* out, int32_t aIndent) const
|
|
{
|
|
nsAutoCString indentStr;
|
|
for (int32_t indent = aIndent; --indent >= 0; ) {
|
|
indentStr.AppendLiteral(" ");
|
|
}
|
|
|
|
nsAutoCString str;
|
|
str.AppendLiteral("@-moz-document ");
|
|
for (URL *url = mURLs; url; url = url->next) {
|
|
switch (url->func) {
|
|
case eURL:
|
|
str.AppendLiteral("url(\"");
|
|
break;
|
|
case eURLPrefix:
|
|
str.AppendLiteral("url-prefix(\"");
|
|
break;
|
|
case eDomain:
|
|
str.AppendLiteral("domain(\"");
|
|
break;
|
|
case eRegExp:
|
|
str.AppendLiteral("regexp(\"");
|
|
break;
|
|
}
|
|
nsAutoCString escapedURL(url->url);
|
|
escapedURL.ReplaceSubstring("\"", "\\\""); // escape quotes
|
|
str.Append(escapedURL);
|
|
str.AppendLiteral("\"), ");
|
|
}
|
|
str.Cut(str.Length() - 2, 1); // remove last ,
|
|
fprintf_stderr(out, "%s%s {\n", indentStr.get(), str.get());
|
|
|
|
GroupRule::List(out, aIndent);
|
|
|
|
fprintf_stderr(out, "%s}\n", indentStr.get());
|
|
}
|
|
#endif
|
|
|
|
/* virtual */ int32_t
|
|
DocumentRule::GetType() const
|
|
{
|
|
return Rule::DOCUMENT_RULE;
|
|
}
|
|
|
|
/* virtual */ already_AddRefed<Rule>
|
|
DocumentRule::Clone() const
|
|
{
|
|
RefPtr<Rule> clone = new DocumentRule(*this);
|
|
return clone.forget();
|
|
}
|
|
|
|
// nsIDOMCSSRule methods
|
|
NS_IMETHODIMP
|
|
DocumentRule::GetType(uint16_t* aType)
|
|
{
|
|
// XXX What should really happen here?
|
|
*aType = nsIDOMCSSRule::UNKNOWN_RULE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DocumentRule::GetCssText(nsAString& aCssText)
|
|
{
|
|
aCssText.AssignLiteral("@-moz-document ");
|
|
AppendConditionText(aCssText);
|
|
GroupRule::AppendRulesToCssText(aCssText);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DocumentRule::SetCssText(const nsAString& aCssText)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DocumentRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
|
|
{
|
|
return GroupRule::GetParentStyleSheet(aSheet);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DocumentRule::GetParentRule(nsIDOMCSSRule** aParentRule)
|
|
{
|
|
return GroupRule::GetParentRule(aParentRule);
|
|
}
|
|
|
|
css::Rule*
|
|
DocumentRule::GetCSSRule()
|
|
{
|
|
return Rule::GetCSSRule();
|
|
}
|
|
|
|
// nsIDOMCSSGroupingRule methods
|
|
NS_IMETHODIMP
|
|
DocumentRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
|
|
{
|
|
return GroupRule::GetCssRules(aRuleList);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DocumentRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
|
|
{
|
|
return GroupRule::InsertRule(aRule, aIndex, _retval);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DocumentRule::DeleteRule(uint32_t aIndex)
|
|
{
|
|
return GroupRule::DeleteRule(aIndex);
|
|
}
|
|
|
|
// nsIDOMCSSConditionRule methods
|
|
NS_IMETHODIMP
|
|
DocumentRule::GetConditionText(nsAString& aConditionText)
|
|
{
|
|
aConditionText.Truncate(0);
|
|
AppendConditionText(aConditionText);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
DocumentRule::SetConditionText(const nsAString& aConditionText)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
// GroupRule interface
|
|
/* virtual */ bool
|
|
DocumentRule::UseForPresentation(nsPresContext* aPresContext,
|
|
nsMediaQueryResultCacheKey& aKey)
|
|
{
|
|
return UseForPresentation(aPresContext);
|
|
}
|
|
|
|
bool
|
|
DocumentRule::UseForPresentation(nsPresContext* aPresContext)
|
|
{
|
|
nsIDocument *doc = aPresContext->Document();
|
|
nsIURI *docURI = doc->GetDocumentURI();
|
|
nsAutoCString docURISpec;
|
|
if (docURI)
|
|
docURI->GetSpec(docURISpec);
|
|
|
|
for (URL *url = mURLs; url; url = url->next) {
|
|
switch (url->func) {
|
|
case eURL: {
|
|
if (docURISpec == url->url)
|
|
return true;
|
|
} break;
|
|
case eURLPrefix: {
|
|
if (StringBeginsWith(docURISpec, url->url))
|
|
return true;
|
|
} break;
|
|
case eDomain: {
|
|
nsAutoCString host;
|
|
if (docURI)
|
|
docURI->GetHost(host);
|
|
int32_t lenDiff = host.Length() - url->url.Length();
|
|
if (lenDiff == 0) {
|
|
if (host == url->url)
|
|
return true;
|
|
} else {
|
|
if (StringEndsWith(host, url->url) &&
|
|
host.CharAt(lenDiff - 1) == '.')
|
|
return true;
|
|
}
|
|
} break;
|
|
case eRegExp: {
|
|
NS_ConvertUTF8toUTF16 spec(docURISpec);
|
|
NS_ConvertUTF8toUTF16 regex(url->url);
|
|
if (nsContentUtils::IsPatternMatching(spec, regex, doc)) {
|
|
return true;
|
|
}
|
|
} break;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
DocumentRule::URL::~URL()
|
|
{
|
|
NS_CSS_DELETE_LIST_MEMBER(DocumentRule::URL, this, next);
|
|
}
|
|
|
|
/* virtual */ size_t
|
|
DocumentRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
|
{
|
|
size_t n = aMallocSizeOf(this);
|
|
n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
|
|
|
|
// Measurement of the following members may be added later if DMD finds it is
|
|
// worthwhile:
|
|
// - mURLs
|
|
|
|
return n;
|
|
}
|
|
|
|
void
|
|
DocumentRule::AppendConditionText(nsAString& aCssText)
|
|
{
|
|
for (URL *url = mURLs; url; url = url->next) {
|
|
switch (url->func) {
|
|
case eURL:
|
|
aCssText.AppendLiteral("url(");
|
|
break;
|
|
case eURLPrefix:
|
|
aCssText.AppendLiteral("url-prefix(");
|
|
break;
|
|
case eDomain:
|
|
aCssText.AppendLiteral("domain(");
|
|
break;
|
|
case eRegExp:
|
|
aCssText.AppendLiteral("regexp(");
|
|
break;
|
|
}
|
|
nsStyleUtil::AppendEscapedCSSString(NS_ConvertUTF8toUTF16(url->url),
|
|
aCssText);
|
|
aCssText.AppendLiteral("), ");
|
|
}
|
|
aCssText.Truncate(aCssText.Length() - 2); // remove last ", "
|
|
}
|
|
|
|
// -------------------------------------------
|
|
// NameSpaceRule
|
|
//
|
|
|
|
NameSpaceRule::NameSpaceRule(nsIAtom* aPrefix, const nsString& aURLSpec,
|
|
uint32_t aLineNumber, uint32_t aColumnNumber)
|
|
: Rule(aLineNumber, aColumnNumber),
|
|
mPrefix(aPrefix),
|
|
mURLSpec(aURLSpec)
|
|
{
|
|
}
|
|
|
|
NameSpaceRule::NameSpaceRule(const NameSpaceRule& aCopy)
|
|
: Rule(aCopy),
|
|
mPrefix(aCopy.mPrefix),
|
|
mURLSpec(aCopy.mURLSpec)
|
|
{
|
|
}
|
|
|
|
NameSpaceRule::~NameSpaceRule()
|
|
{
|
|
}
|
|
|
|
NS_IMPL_ADDREF(NameSpaceRule)
|
|
NS_IMPL_RELEASE(NameSpaceRule)
|
|
|
|
// QueryInterface implementation for NameSpaceRule
|
|
NS_INTERFACE_MAP_BEGIN(NameSpaceRule)
|
|
if (aIID.Equals(NS_GET_IID(css::NameSpaceRule))) {
|
|
*aInstancePtr = this;
|
|
NS_ADDREF_THIS();
|
|
return NS_OK;
|
|
}
|
|
else
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozilla::css::Rule)
|
|
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSNameSpaceRule)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
IMPL_STYLE_RULE_INHERIT(NameSpaceRule, Rule)
|
|
|
|
#ifdef DEBUG
|
|
/* virtual */ void
|
|
NameSpaceRule::List(FILE* out, int32_t aIndent) const
|
|
{
|
|
nsAutoCString str;
|
|
for (int32_t indent = aIndent; --indent >= 0; ) {
|
|
str.AppendLiteral(" ");
|
|
}
|
|
|
|
nsAutoString buffer;
|
|
|
|
str.AppendLiteral("@namespace ");
|
|
|
|
if (mPrefix) {
|
|
mPrefix->ToString(buffer);
|
|
AppendUTF16toUTF8(buffer, str);
|
|
str.Append(' ');
|
|
}
|
|
|
|
str.AppendLiteral("url(\"");
|
|
AppendUTF16toUTF8(mURLSpec, str);
|
|
str.AppendLiteral("\")\n");
|
|
fprintf_stderr(out, "%s", str.get());
|
|
}
|
|
#endif
|
|
|
|
/* virtual */ int32_t
|
|
NameSpaceRule::GetType() const
|
|
{
|
|
return Rule::NAMESPACE_RULE;
|
|
}
|
|
|
|
/* virtual */ already_AddRefed<Rule>
|
|
NameSpaceRule::Clone() const
|
|
{
|
|
RefPtr<Rule> clone = new NameSpaceRule(*this);
|
|
return clone.forget();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
NameSpaceRule::GetType(uint16_t* aType)
|
|
{
|
|
*aType = nsIDOMCSSRule::NAMESPACE_RULE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
NameSpaceRule::GetCssText(nsAString& aCssText)
|
|
{
|
|
aCssText.AssignLiteral("@namespace ");
|
|
if (mPrefix) {
|
|
aCssText.Append(nsDependentAtomString(mPrefix) + NS_LITERAL_STRING(" "));
|
|
}
|
|
aCssText.AppendLiteral("url(");
|
|
nsStyleUtil::AppendEscapedCSSString(mURLSpec, aCssText);
|
|
aCssText.AppendLiteral(");");
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
NameSpaceRule::SetCssText(const nsAString& aCssText)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
NameSpaceRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
|
|
{
|
|
return Rule::GetParentStyleSheet(aSheet);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
NameSpaceRule::GetParentRule(nsIDOMCSSRule** aParentRule)
|
|
{
|
|
return Rule::GetParentRule(aParentRule);
|
|
}
|
|
|
|
css::Rule*
|
|
NameSpaceRule::GetCSSRule()
|
|
{
|
|
return Rule::GetCSSRule();
|
|
}
|
|
|
|
/* virtual */ size_t
|
|
NameSpaceRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
|
{
|
|
return aMallocSizeOf(this);
|
|
|
|
// Measurement of the following members may be added later if DMD finds it is
|
|
// worthwhile:
|
|
// - mPrefix
|
|
// - mURLSpec
|
|
}
|
|
|
|
|
|
} // namespace css
|
|
} // namespace mozilla
|
|
|
|
// -------------------------------------------
|
|
// nsCSSFontFaceStyleDecl and related routines
|
|
//
|
|
|
|
// Mapping from nsCSSFontDesc codes to CSSFontFaceDescriptors fields.
|
|
nsCSSValue CSSFontFaceDescriptors::* const
|
|
CSSFontFaceDescriptors::Fields[] = {
|
|
#define CSS_FONT_DESC(name_, method_) &CSSFontFaceDescriptors::m##method_,
|
|
#include "nsCSSFontDescList.h"
|
|
#undef CSS_FONT_DESC
|
|
};
|
|
|
|
const nsCSSValue&
|
|
CSSFontFaceDescriptors::Get(nsCSSFontDesc aFontDescID) const
|
|
{
|
|
MOZ_ASSERT(aFontDescID > eCSSFontDesc_UNKNOWN &&
|
|
aFontDescID < eCSSFontDesc_COUNT);
|
|
return this->*CSSFontFaceDescriptors::Fields[aFontDescID];
|
|
}
|
|
|
|
nsCSSValue&
|
|
CSSFontFaceDescriptors::Get(nsCSSFontDesc aFontDescID)
|
|
{
|
|
MOZ_ASSERT(aFontDescID > eCSSFontDesc_UNKNOWN &&
|
|
aFontDescID < eCSSFontDesc_COUNT);
|
|
return this->*CSSFontFaceDescriptors::Fields[aFontDescID];
|
|
}
|
|
|
|
// QueryInterface implementation for nsCSSFontFaceStyleDecl
|
|
NS_INTERFACE_MAP_BEGIN(nsCSSFontFaceStyleDecl)
|
|
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleDeclaration)
|
|
NS_INTERFACE_MAP_ENTRY(nsICSSDeclaration)
|
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
// We forward the cycle collection interfaces to ContainingRule(), which is
|
|
// never null (in fact, we're part of that object!)
|
|
if (aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) ||
|
|
aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) {
|
|
return ContainingRule()->QueryInterface(aIID, aInstancePtr);
|
|
}
|
|
else
|
|
NS_INTERFACE_MAP_END
|
|
|
|
NS_IMPL_ADDREF_USING_AGGREGATOR(nsCSSFontFaceStyleDecl, ContainingRule())
|
|
NS_IMPL_RELEASE_USING_AGGREGATOR(nsCSSFontFaceStyleDecl, ContainingRule())
|
|
|
|
// helper for string GetPropertyValue and RemovePropertyValue
|
|
nsresult
|
|
nsCSSFontFaceStyleDecl::GetPropertyValue(nsCSSFontDesc aFontDescID,
|
|
nsAString & aResult) const
|
|
{
|
|
NS_ENSURE_ARG_RANGE(aFontDescID, eCSSFontDesc_UNKNOWN,
|
|
eCSSFontDesc_COUNT - 1);
|
|
|
|
aResult.Truncate();
|
|
if (aFontDescID == eCSSFontDesc_UNKNOWN)
|
|
return NS_OK;
|
|
|
|
const nsCSSValue& val = mDescriptors.Get(aFontDescID);
|
|
|
|
if (val.GetUnit() == eCSSUnit_Null) {
|
|
// Avoid having to check no-value in the Family and Src cases below.
|
|
return NS_OK;
|
|
}
|
|
|
|
switch (aFontDescID) {
|
|
case eCSSFontDesc_Family: {
|
|
// we don't use nsCSSValue::AppendToString here because it doesn't
|
|
// canonicalize the way we want, and anyway it's overkill when
|
|
// we know we have eCSSUnit_String
|
|
NS_ASSERTION(val.GetUnit() == eCSSUnit_String, "unexpected unit");
|
|
nsDependentString family(val.GetStringBufferValue());
|
|
nsStyleUtil::AppendEscapedCSSString(family, aResult);
|
|
return NS_OK;
|
|
}
|
|
|
|
case eCSSFontDesc_Style:
|
|
val.AppendToString(eCSSProperty_font_style, aResult,
|
|
nsCSSValue::eNormalized);
|
|
return NS_OK;
|
|
|
|
case eCSSFontDesc_Weight:
|
|
val.AppendToString(eCSSProperty_font_weight, aResult,
|
|
nsCSSValue::eNormalized);
|
|
return NS_OK;
|
|
|
|
case eCSSFontDesc_Stretch:
|
|
val.AppendToString(eCSSProperty_font_stretch, aResult,
|
|
nsCSSValue::eNormalized);
|
|
return NS_OK;
|
|
|
|
case eCSSFontDesc_FontFeatureSettings:
|
|
nsStyleUtil::AppendFontFeatureSettings(val, aResult);
|
|
return NS_OK;
|
|
|
|
case eCSSFontDesc_FontLanguageOverride:
|
|
val.AppendToString(eCSSProperty_font_language_override, aResult,
|
|
nsCSSValue::eNormalized);
|
|
return NS_OK;
|
|
|
|
case eCSSFontDesc_Display:
|
|
NS_ASSERTION(val.GetUnit() == eCSSUnit_Enumerated,
|
|
"unknown unit for font-display descriptor");
|
|
AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(val.GetIntValue(),
|
|
nsCSSProps::kFontDisplayKTable), aResult);
|
|
return NS_OK;
|
|
|
|
case eCSSFontDesc_Src:
|
|
nsStyleUtil::AppendSerializedFontSrc(val, aResult);
|
|
return NS_OK;
|
|
|
|
case eCSSFontDesc_UnicodeRange:
|
|
nsStyleUtil::AppendUnicodeRange(val, aResult);
|
|
return NS_OK;
|
|
|
|
case eCSSFontDesc_UNKNOWN:
|
|
case eCSSFontDesc_COUNT:
|
|
;
|
|
}
|
|
NS_NOTREACHED("nsCSSFontFaceStyleDecl::GetPropertyValue: "
|
|
"out-of-range value got to the switch");
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFaceStyleDecl::GetCssText(nsAString & aCssText)
|
|
{
|
|
nsAutoString descStr;
|
|
|
|
aCssText.Truncate();
|
|
for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
|
|
id < eCSSFontDesc_COUNT;
|
|
id = nsCSSFontDesc(id + 1)) {
|
|
if (mDescriptors.Get(id).GetUnit() != eCSSUnit_Null &&
|
|
NS_SUCCEEDED(GetPropertyValue(id, descStr))) {
|
|
NS_ASSERTION(descStr.Length() > 0,
|
|
"GetCssText: non-null unit, empty property value");
|
|
aCssText.AppendLiteral(" ");
|
|
aCssText.AppendASCII(nsCSSProps::GetStringValue(id).get());
|
|
aCssText.AppendLiteral(": ");
|
|
aCssText.Append(descStr);
|
|
aCssText.AppendLiteral(";\n");
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFaceStyleDecl::SetCssText(const nsAString & aCssText)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFaceStyleDecl::GetPropertyValue(const nsAString & propertyName,
|
|
nsAString & aResult)
|
|
{
|
|
return GetPropertyValue(nsCSSProps::LookupFontDesc(propertyName), aResult);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFaceStyleDecl::GetAuthoredPropertyValue(const nsAString& propertyName,
|
|
nsAString& aResult)
|
|
{
|
|
// We don't return any authored property values different from
|
|
// GetPropertyValue, currently.
|
|
return GetPropertyValue(nsCSSProps::LookupFontDesc(propertyName), aResult);
|
|
}
|
|
|
|
already_AddRefed<dom::CSSValue>
|
|
nsCSSFontFaceStyleDecl::GetPropertyCSSValue(const nsAString & propertyName,
|
|
ErrorResult& aRv)
|
|
{
|
|
// ??? nsDOMCSSDeclaration returns null/NS_OK, but that seems wrong.
|
|
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
|
return nullptr;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFaceStyleDecl::RemoveProperty(const nsAString & propertyName,
|
|
nsAString & aResult)
|
|
{
|
|
nsCSSFontDesc descID = nsCSSProps::LookupFontDesc(propertyName);
|
|
NS_ASSERTION(descID >= eCSSFontDesc_UNKNOWN &&
|
|
descID < eCSSFontDesc_COUNT,
|
|
"LookupFontDesc returned value out of range");
|
|
|
|
if (descID == eCSSFontDesc_UNKNOWN) {
|
|
aResult.Truncate();
|
|
} else {
|
|
nsresult rv = GetPropertyValue(descID, aResult);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
mDescriptors.Get(descID).Reset();
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFaceStyleDecl::GetPropertyPriority(const nsAString & propertyName,
|
|
nsAString & aResult)
|
|
{
|
|
// font descriptors do not have priorities at present
|
|
aResult.Truncate();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFaceStyleDecl::SetProperty(const nsAString & propertyName,
|
|
const nsAString & value,
|
|
const nsAString & priority)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFaceStyleDecl::GetLength(uint32_t *aLength)
|
|
{
|
|
uint32_t len = 0;
|
|
for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
|
|
id < eCSSFontDesc_COUNT;
|
|
id = nsCSSFontDesc(id + 1))
|
|
if (mDescriptors.Get(id).GetUnit() != eCSSUnit_Null)
|
|
len++;
|
|
|
|
*aLength = len;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFaceStyleDecl::Item(uint32_t aIndex, nsAString& aReturn)
|
|
{
|
|
bool found;
|
|
IndexedGetter(aIndex, found, aReturn);
|
|
if (!found) {
|
|
aReturn.Truncate();
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
nsCSSFontFaceStyleDecl::IndexedGetter(uint32_t index, bool& aFound, nsAString & aResult)
|
|
{
|
|
int32_t nset = -1;
|
|
for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
|
|
id < eCSSFontDesc_COUNT;
|
|
id = nsCSSFontDesc(id + 1)) {
|
|
if (mDescriptors.Get(id).GetUnit() != eCSSUnit_Null) {
|
|
nset++;
|
|
if (nset == int32_t(index)) {
|
|
aFound = true;
|
|
aResult.AssignASCII(nsCSSProps::GetStringValue(id).get());
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
aFound = false;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFaceStyleDecl::GetParentRule(nsIDOMCSSRule** aParentRule)
|
|
{
|
|
NS_IF_ADDREF(*aParentRule = ContainingRule()->GetDOMRule());
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFaceStyleDecl::GetPropertyValue(const nsCSSProperty aPropID,
|
|
nsAString& aValue)
|
|
{
|
|
return
|
|
GetPropertyValue(NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(aPropID)),
|
|
aValue);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFaceStyleDecl::SetPropertyValue(const nsCSSProperty aPropID,
|
|
const nsAString& aValue)
|
|
{
|
|
return SetProperty(NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(aPropID)),
|
|
aValue, EmptyString());
|
|
}
|
|
|
|
nsINode*
|
|
nsCSSFontFaceStyleDecl::GetParentObject()
|
|
{
|
|
return ContainingRule()->GetDocument();
|
|
}
|
|
|
|
JSObject*
|
|
nsCSSFontFaceStyleDecl::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
|
|
{
|
|
return mozilla::dom::CSSStyleDeclarationBinding::Wrap(cx, this, aGivenProto);
|
|
}
|
|
|
|
// -------------------------------------------
|
|
// nsCSSFontFaceRule
|
|
//
|
|
|
|
/* virtual */ already_AddRefed<css::Rule>
|
|
nsCSSFontFaceRule::Clone() const
|
|
{
|
|
RefPtr<css::Rule> clone = new nsCSSFontFaceRule(*this);
|
|
return clone.forget();
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSFontFaceRule)
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSFontFaceRule)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsCSSFontFaceRule)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsCSSFontFaceRule)
|
|
// Trace the wrapper for our declaration. This just expands out
|
|
// NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER which we can't use
|
|
// directly because the wrapper is on the declaration, not on us.
|
|
tmp->mDecl.TraceWrapper(aCallbacks, aClosure);
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCSSFontFaceRule)
|
|
// Unlink the wrapper for our declaraton. This just expands out
|
|
// NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER which we can't use
|
|
// directly because the wrapper is on the declaration, not on us.
|
|
tmp->mDecl.ReleaseWrapper(static_cast<nsISupports*>(p));
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCSSFontFaceRule)
|
|
// NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS will call into our
|
|
// Trace hook, where we do the right thing with declarations already.
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
// QueryInterface implementation for nsCSSFontFaceRule
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSFontFaceRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSFontFaceRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozilla::css::Rule)
|
|
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSFontFaceRule)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
IMPL_STYLE_RULE_INHERIT(nsCSSFontFaceRule, Rule)
|
|
|
|
#ifdef DEBUG
|
|
void
|
|
nsCSSFontFaceRule::List(FILE* out, int32_t aIndent) const
|
|
{
|
|
nsCString baseInd, descInd;
|
|
for (int32_t indent = aIndent; --indent >= 0; ) {
|
|
baseInd.AppendLiteral(" ");
|
|
descInd.AppendLiteral(" ");
|
|
}
|
|
descInd.AppendLiteral(" ");
|
|
|
|
nsString descStr;
|
|
|
|
fprintf_stderr(out, "%s@font-face {\n", baseInd.get());
|
|
for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
|
|
id < eCSSFontDesc_COUNT;
|
|
id = nsCSSFontDesc(id + 1))
|
|
if (mDecl.mDescriptors.Get(id).GetUnit() != eCSSUnit_Null) {
|
|
if (NS_FAILED(mDecl.GetPropertyValue(id, descStr)))
|
|
descStr.AssignLiteral("#<serialization error>");
|
|
else if (descStr.Length() == 0)
|
|
descStr.AssignLiteral("#<serialization missing>");
|
|
fprintf_stderr(out, "%s%s: %s\n",
|
|
descInd.get(), nsCSSProps::GetStringValue(id).get(),
|
|
NS_ConvertUTF16toUTF8(descStr).get());
|
|
}
|
|
fprintf_stderr(out, "%s}\n", baseInd.get());
|
|
}
|
|
#endif
|
|
|
|
/* virtual */ int32_t
|
|
nsCSSFontFaceRule::GetType() const
|
|
{
|
|
return Rule::FONT_FACE_RULE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFaceRule::GetType(uint16_t* aType)
|
|
{
|
|
*aType = nsIDOMCSSRule::FONT_FACE_RULE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFaceRule::GetCssText(nsAString& aCssText)
|
|
{
|
|
nsAutoString propText;
|
|
mDecl.GetCssText(propText);
|
|
|
|
aCssText.AssignLiteral("@font-face {\n");
|
|
aCssText.Append(propText);
|
|
aCssText.Append('}');
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFaceRule::SetCssText(const nsAString& aCssText)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFaceRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
|
|
{
|
|
return Rule::GetParentStyleSheet(aSheet);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFaceRule::GetParentRule(nsIDOMCSSRule** aParentRule)
|
|
{
|
|
return Rule::GetParentRule(aParentRule);
|
|
}
|
|
|
|
css::Rule*
|
|
nsCSSFontFaceRule::GetCSSRule()
|
|
{
|
|
return Rule::GetCSSRule();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFaceRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
|
|
{
|
|
NS_IF_ADDREF(*aStyle = &mDecl);
|
|
return NS_OK;
|
|
}
|
|
|
|
// Arguably these should forward to nsCSSFontFaceStyleDecl methods.
|
|
void
|
|
nsCSSFontFaceRule::SetDesc(nsCSSFontDesc aDescID, nsCSSValue const & aValue)
|
|
{
|
|
NS_PRECONDITION(aDescID > eCSSFontDesc_UNKNOWN &&
|
|
aDescID < eCSSFontDesc_COUNT,
|
|
"aDescID out of range in nsCSSFontFaceRule::SetDesc");
|
|
|
|
// FIXME: handle dynamic changes
|
|
|
|
mDecl.mDescriptors.Get(aDescID) = aValue;
|
|
}
|
|
|
|
void
|
|
nsCSSFontFaceRule::GetDesc(nsCSSFontDesc aDescID, nsCSSValue & aValue)
|
|
{
|
|
NS_PRECONDITION(aDescID > eCSSFontDesc_UNKNOWN &&
|
|
aDescID < eCSSFontDesc_COUNT,
|
|
"aDescID out of range in nsCSSFontFaceRule::GetDesc");
|
|
|
|
aValue = mDecl.mDescriptors.Get(aDescID);
|
|
}
|
|
|
|
/* virtual */ size_t
|
|
nsCSSFontFaceRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
|
{
|
|
return aMallocSizeOf(this);
|
|
|
|
// Measurement of the following members may be added later if DMD finds it is
|
|
// worthwhile:
|
|
// - mDecl
|
|
}
|
|
|
|
|
|
// -----------------------------------
|
|
// nsCSSFontFeatureValuesRule
|
|
//
|
|
|
|
/* virtual */ already_AddRefed<css::Rule>
|
|
nsCSSFontFeatureValuesRule::Clone() const
|
|
{
|
|
RefPtr<css::Rule> clone = new nsCSSFontFeatureValuesRule(*this);
|
|
return clone.forget();
|
|
}
|
|
|
|
NS_IMPL_ADDREF(nsCSSFontFeatureValuesRule)
|
|
NS_IMPL_RELEASE(nsCSSFontFeatureValuesRule)
|
|
|
|
// QueryInterface implementation for nsCSSFontFeatureValuesRule
|
|
NS_INTERFACE_MAP_BEGIN(nsCSSFontFeatureValuesRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSFontFeatureValuesRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozilla::css::Rule)
|
|
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSFontFeatureValuesRule)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
IMPL_STYLE_RULE_INHERIT(nsCSSFontFeatureValuesRule, Rule)
|
|
|
|
static void
|
|
FeatureValuesToString(
|
|
const nsTArray<gfxFontFeatureValueSet::FeatureValues>& aFeatureValues,
|
|
nsAString& aOutStr)
|
|
{
|
|
uint32_t i, n;
|
|
|
|
// append values
|
|
n = aFeatureValues.Length();
|
|
for (i = 0; i < n; i++) {
|
|
const gfxFontFeatureValueSet::FeatureValues& fv = aFeatureValues[i];
|
|
|
|
// @alternate
|
|
aOutStr.AppendLiteral(" @");
|
|
nsAutoString functAlt;
|
|
nsStyleUtil::GetFunctionalAlternatesName(fv.alternate, functAlt);
|
|
aOutStr.Append(functAlt);
|
|
aOutStr.AppendLiteral(" {");
|
|
|
|
// for each ident-values tuple
|
|
uint32_t j, numValues = fv.valuelist.Length();
|
|
for (j = 0; j < numValues; j++) {
|
|
aOutStr.Append(' ');
|
|
const gfxFontFeatureValueSet::ValueList& vlist = fv.valuelist[j];
|
|
nsStyleUtil::AppendEscapedCSSIdent(vlist.name, aOutStr);
|
|
aOutStr.Append(':');
|
|
|
|
uint32_t k, numSelectors = vlist.featureSelectors.Length();
|
|
for (k = 0; k < numSelectors; k++) {
|
|
aOutStr.Append(' ');
|
|
aOutStr.AppendInt(vlist.featureSelectors[k]);
|
|
}
|
|
|
|
aOutStr.Append(';');
|
|
}
|
|
aOutStr.AppendLiteral(" }\n");
|
|
}
|
|
}
|
|
|
|
static void
|
|
FontFeatureValuesRuleToString(
|
|
const mozilla::FontFamilyList& aFamilyList,
|
|
const nsTArray<gfxFontFeatureValueSet::FeatureValues>& aFeatureValues,
|
|
nsAString& aOutStr)
|
|
{
|
|
aOutStr.AssignLiteral("@font-feature-values ");
|
|
nsAutoString familyListStr, valueTextStr;
|
|
nsStyleUtil::AppendEscapedCSSFontFamilyList(aFamilyList, familyListStr);
|
|
aOutStr.Append(familyListStr);
|
|
aOutStr.AppendLiteral(" {\n");
|
|
FeatureValuesToString(aFeatureValues, valueTextStr);
|
|
aOutStr.Append(valueTextStr);
|
|
aOutStr.Append('}');
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
void
|
|
nsCSSFontFeatureValuesRule::List(FILE* out, int32_t aIndent) const
|
|
{
|
|
nsAutoString text;
|
|
FontFeatureValuesRuleToString(mFamilyList, mFeatureValues, text);
|
|
NS_ConvertUTF16toUTF8 utf8(text);
|
|
|
|
// replace newlines with newlines plus indent spaces
|
|
char* indent = new char[(aIndent + 1) * 2];
|
|
int32_t i;
|
|
for (i = 1; i < (aIndent + 1) * 2 - 1; i++) {
|
|
indent[i] = 0x20;
|
|
}
|
|
indent[0] = 0xa;
|
|
indent[aIndent * 2 + 1] = 0;
|
|
utf8.ReplaceSubstring("\n", indent);
|
|
delete [] indent;
|
|
|
|
nsAutoCString indentStr;
|
|
for (i = aIndent; --i >= 0; ) {
|
|
indentStr.AppendLiteral(" ");
|
|
}
|
|
fprintf_stderr(out, "%s%s\n", indentStr.get(), utf8.get());
|
|
}
|
|
#endif
|
|
|
|
/* virtual */ int32_t
|
|
nsCSSFontFeatureValuesRule::GetType() const
|
|
{
|
|
return Rule::FONT_FEATURE_VALUES_RULE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFeatureValuesRule::GetType(uint16_t* aType)
|
|
{
|
|
*aType = nsIDOMCSSRule::FONT_FEATURE_VALUES_RULE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFeatureValuesRule::GetCssText(nsAString& aCssText)
|
|
{
|
|
FontFeatureValuesRuleToString(mFamilyList, mFeatureValues, aCssText);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFeatureValuesRule::SetCssText(const nsAString& aCssText)
|
|
{
|
|
// FIXME: implement???
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFeatureValuesRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
|
|
{
|
|
return Rule::GetParentStyleSheet(aSheet);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFeatureValuesRule::GetParentRule(nsIDOMCSSRule** aParentRule)
|
|
{
|
|
return Rule::GetParentRule(aParentRule);
|
|
}
|
|
|
|
css::Rule*
|
|
nsCSSFontFeatureValuesRule::GetCSSRule()
|
|
{
|
|
return Rule::GetCSSRule();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFeatureValuesRule::GetFontFamily(nsAString& aFamilyListStr)
|
|
{
|
|
nsStyleUtil::AppendEscapedCSSFontFamilyList(mFamilyList, aFamilyListStr);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFeatureValuesRule::SetFontFamily(const nsAString& aFontFamily)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFeatureValuesRule::GetValueText(nsAString& aValueText)
|
|
{
|
|
FeatureValuesToString(mFeatureValues, aValueText);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSFontFeatureValuesRule::SetValueText(const nsAString& aValueText)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
struct MakeFamilyArray {
|
|
explicit MakeFamilyArray(nsTArray<nsString>& aFamilyArray)
|
|
: familyArray(aFamilyArray), hasGeneric(false)
|
|
{}
|
|
|
|
static bool
|
|
AddFamily(const nsString& aFamily, bool aGeneric, void* aData)
|
|
{
|
|
MakeFamilyArray *familyArr = reinterpret_cast<MakeFamilyArray*> (aData);
|
|
if (!aGeneric && !aFamily.IsEmpty()) {
|
|
familyArr->familyArray.AppendElement(aFamily);
|
|
}
|
|
if (aGeneric) {
|
|
familyArr->hasGeneric = true;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
nsTArray<nsString>& familyArray;
|
|
bool hasGeneric;
|
|
};
|
|
|
|
void
|
|
nsCSSFontFeatureValuesRule::SetFamilyList(
|
|
const mozilla::FontFamilyList& aFamilyList)
|
|
{
|
|
mFamilyList = aFamilyList;
|
|
}
|
|
|
|
void
|
|
nsCSSFontFeatureValuesRule::AddValueList(int32_t aVariantAlternate,
|
|
nsTArray<gfxFontFeatureValueSet::ValueList>& aValueList)
|
|
{
|
|
uint32_t i, len = mFeatureValues.Length();
|
|
bool foundAlternate = false;
|
|
|
|
// add to an existing list for a given property value
|
|
for (i = 0; i < len; i++) {
|
|
gfxFontFeatureValueSet::FeatureValues& f = mFeatureValues.ElementAt(i);
|
|
|
|
if (f.alternate == uint32_t(aVariantAlternate)) {
|
|
f.valuelist.AppendElements(aValueList);
|
|
foundAlternate = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// create a new list for a given property value
|
|
if (!foundAlternate) {
|
|
gfxFontFeatureValueSet::FeatureValues &f = *mFeatureValues.AppendElement();
|
|
f.alternate = aVariantAlternate;
|
|
f.valuelist.AppendElements(aValueList);
|
|
}
|
|
}
|
|
|
|
size_t
|
|
nsCSSFontFeatureValuesRule::SizeOfIncludingThis(
|
|
MallocSizeOf aMallocSizeOf) const
|
|
{
|
|
return aMallocSizeOf(this);
|
|
}
|
|
|
|
// -------------------------------------------
|
|
// nsCSSKeyframeStyleDeclaration
|
|
//
|
|
|
|
nsCSSKeyframeStyleDeclaration::nsCSSKeyframeStyleDeclaration(nsCSSKeyframeRule *aRule)
|
|
: mRule(aRule)
|
|
{
|
|
}
|
|
|
|
nsCSSKeyframeStyleDeclaration::~nsCSSKeyframeStyleDeclaration()
|
|
{
|
|
NS_ASSERTION(!mRule, "DropReference not called.");
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSKeyframeStyleDeclaration)
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSKeyframeStyleDeclaration)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsCSSKeyframeStyleDeclaration)
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSKeyframeStyleDeclaration)
|
|
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
|
NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration)
|
|
|
|
css::Declaration*
|
|
nsCSSKeyframeStyleDeclaration::GetCSSDeclaration(Operation aOperation)
|
|
{
|
|
if (mRule) {
|
|
return mRule->Declaration();
|
|
} else {
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
void
|
|
nsCSSKeyframeStyleDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
|
|
{
|
|
GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframeStyleDeclaration::GetParentRule(nsIDOMCSSRule **aParent)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aParent);
|
|
|
|
NS_IF_ADDREF(*aParent = mRule);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsCSSKeyframeStyleDeclaration::SetCSSDeclaration(css::Declaration* aDecl)
|
|
{
|
|
MOZ_ASSERT(aDecl, "must be non-null");
|
|
mRule->ChangeDeclaration(aDecl);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsIDocument*
|
|
nsCSSKeyframeStyleDeclaration::DocToUpdate()
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
nsINode*
|
|
nsCSSKeyframeStyleDeclaration::GetParentObject()
|
|
{
|
|
return mRule ? mRule->GetDocument() : nullptr;
|
|
}
|
|
|
|
// -------------------------------------------
|
|
// nsCSSKeyframeRule
|
|
//
|
|
|
|
nsCSSKeyframeRule::nsCSSKeyframeRule(const nsCSSKeyframeRule& aCopy)
|
|
// copy everything except our reference count and mDOMDeclaration
|
|
: Rule(aCopy)
|
|
, mKeys(aCopy.mKeys)
|
|
, mDeclaration(new css::Declaration(*aCopy.mDeclaration))
|
|
{
|
|
mDeclaration->SetOwningRule(this);
|
|
}
|
|
|
|
nsCSSKeyframeRule::~nsCSSKeyframeRule()
|
|
{
|
|
mDeclaration->SetOwningRule(nullptr);
|
|
if (mDOMDeclaration) {
|
|
mDOMDeclaration->DropReference();
|
|
}
|
|
}
|
|
|
|
/* virtual */ already_AddRefed<css::Rule>
|
|
nsCSSKeyframeRule::Clone() const
|
|
{
|
|
RefPtr<css::Rule> clone = new nsCSSKeyframeRule(*this);
|
|
return clone.forget();
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSKeyframeRule)
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSKeyframeRule)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsCSSKeyframeRule)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCSSKeyframeRule)
|
|
if (tmp->mDOMDeclaration) {
|
|
tmp->mDOMDeclaration->DropReference();
|
|
tmp->mDOMDeclaration = nullptr;
|
|
}
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCSSKeyframeRule)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMDeclaration)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
// QueryInterface implementation for nsCSSKeyframeRule
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSKeyframeRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSKeyframeRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozilla::css::Rule)
|
|
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSKeyframeRule)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(nsCSSKeyframeRule, Rule)
|
|
|
|
#ifdef DEBUG
|
|
void
|
|
nsCSSKeyframeRule::List(FILE* out, int32_t aIndent) const
|
|
{
|
|
nsAutoCString str;
|
|
for (int32_t index = aIndent; --index >= 0; ) {
|
|
str.AppendLiteral(" ");
|
|
}
|
|
|
|
nsAutoString tmp;
|
|
DoGetKeyText(tmp);
|
|
AppendUTF16toUTF8(tmp, str);
|
|
str.AppendLiteral(" { ");
|
|
mDeclaration->ToString(tmp);
|
|
AppendUTF16toUTF8(tmp, str);
|
|
str.AppendLiteral("}\n");
|
|
fprintf_stderr(out, "%s", str.get());
|
|
}
|
|
#endif
|
|
|
|
/* virtual */ int32_t
|
|
nsCSSKeyframeRule::GetType() const
|
|
{
|
|
return Rule::KEYFRAME_RULE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframeRule::GetType(uint16_t* aType)
|
|
{
|
|
*aType = nsIDOMCSSRule::KEYFRAME_RULE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframeRule::GetCssText(nsAString& aCssText)
|
|
{
|
|
DoGetKeyText(aCssText);
|
|
aCssText.AppendLiteral(" { ");
|
|
nsAutoString tmp;
|
|
mDeclaration->ToString(tmp);
|
|
aCssText.Append(tmp);
|
|
aCssText.AppendLiteral(" }");
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframeRule::SetCssText(const nsAString& aCssText)
|
|
{
|
|
// FIXME: implement???
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframeRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
|
|
{
|
|
return Rule::GetParentStyleSheet(aSheet);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframeRule::GetParentRule(nsIDOMCSSRule** aParentRule)
|
|
{
|
|
return Rule::GetParentRule(aParentRule);
|
|
}
|
|
|
|
css::Rule*
|
|
nsCSSKeyframeRule::GetCSSRule()
|
|
{
|
|
return Rule::GetCSSRule();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframeRule::GetKeyText(nsAString& aKeyText)
|
|
{
|
|
DoGetKeyText(aKeyText);
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
nsCSSKeyframeRule::DoGetKeyText(nsAString& aKeyText) const
|
|
{
|
|
aKeyText.Truncate();
|
|
uint32_t i = 0, i_end = mKeys.Length();
|
|
MOZ_ASSERT(i_end != 0, "must have some keys");
|
|
for (;;) {
|
|
aKeyText.AppendFloat(mKeys[i] * 100.0f);
|
|
aKeyText.Append(char16_t('%'));
|
|
if (++i == i_end) {
|
|
break;
|
|
}
|
|
aKeyText.AppendLiteral(", ");
|
|
}
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframeRule::SetKeyText(const nsAString& aKeyText)
|
|
{
|
|
nsCSSParser parser;
|
|
|
|
InfallibleTArray<float> newSelectors;
|
|
// FIXME: pass filename and line number
|
|
if (!parser.ParseKeyframeSelectorString(aKeyText, nullptr, 0, newSelectors)) {
|
|
// for now, we don't do anything if the parse fails
|
|
return NS_OK;
|
|
}
|
|
|
|
nsIDocument* doc = GetDocument();
|
|
MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
|
|
|
|
newSelectors.SwapElements(mKeys);
|
|
|
|
CSSStyleSheet* sheet = GetStyleSheet();
|
|
if (sheet) {
|
|
sheet->SetModifiedByChildRule();
|
|
|
|
if (doc) {
|
|
doc->StyleRuleChanged(sheet, this);
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframeRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
|
|
{
|
|
if (!mDOMDeclaration) {
|
|
mDOMDeclaration = new nsCSSKeyframeStyleDeclaration(this);
|
|
}
|
|
NS_ADDREF(*aStyle = mDOMDeclaration);
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
nsCSSKeyframeRule::ChangeDeclaration(css::Declaration* aDeclaration)
|
|
{
|
|
// Our caller already did a BeginUpdate/EndUpdate, but with
|
|
// UPDATE_CONTENT, and we need UPDATE_STYLE to trigger work in
|
|
// PresShell::EndUpdate.
|
|
nsIDocument* doc = GetDocument();
|
|
MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
|
|
|
|
if (aDeclaration != mDeclaration) {
|
|
mDeclaration->SetOwningRule(nullptr);
|
|
mDeclaration = aDeclaration;
|
|
mDeclaration->SetOwningRule(this);
|
|
}
|
|
|
|
CSSStyleSheet* sheet = GetStyleSheet();
|
|
if (sheet) {
|
|
sheet->SetModifiedByChildRule();
|
|
|
|
if (doc) {
|
|
doc->StyleRuleChanged(sheet, this);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* virtual */ size_t
|
|
nsCSSKeyframeRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
|
{
|
|
return aMallocSizeOf(this);
|
|
|
|
// Measurement of the following members may be added later if DMD finds it is
|
|
// worthwhile:
|
|
// - mKeys
|
|
// - mDeclaration
|
|
// - mDOMDeclaration
|
|
}
|
|
|
|
|
|
// -------------------------------------------
|
|
// nsCSSKeyframesRule
|
|
//
|
|
|
|
nsCSSKeyframesRule::nsCSSKeyframesRule(const nsCSSKeyframesRule& aCopy)
|
|
// copy everything except our reference count. GroupRule's copy
|
|
// constructor also doesn't copy the lazily-constructed
|
|
// mRuleCollection.
|
|
: GroupRule(aCopy),
|
|
mName(aCopy.mName)
|
|
{
|
|
}
|
|
|
|
nsCSSKeyframesRule::~nsCSSKeyframesRule()
|
|
{
|
|
}
|
|
|
|
/* virtual */ already_AddRefed<css::Rule>
|
|
nsCSSKeyframesRule::Clone() const
|
|
{
|
|
RefPtr<css::Rule> clone = new nsCSSKeyframesRule(*this);
|
|
return clone.forget();
|
|
}
|
|
|
|
NS_IMPL_ADDREF_INHERITED(nsCSSKeyframesRule, css::GroupRule)
|
|
NS_IMPL_RELEASE_INHERITED(nsCSSKeyframesRule, css::GroupRule)
|
|
|
|
// QueryInterface implementation for nsCSSKeyframesRule
|
|
NS_INTERFACE_MAP_BEGIN(nsCSSKeyframesRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSKeyframesRule)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozilla::css::Rule)
|
|
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSKeyframesRule)
|
|
NS_INTERFACE_MAP_END_INHERITING(GroupRule)
|
|
|
|
#ifdef DEBUG
|
|
void
|
|
nsCSSKeyframesRule::List(FILE* out, int32_t aIndent) const
|
|
{
|
|
nsAutoCString indentStr;
|
|
for (int32_t indent = aIndent; --indent >= 0; ) {
|
|
indentStr.AppendLiteral(" ");
|
|
}
|
|
|
|
fprintf_stderr(out, "%s@keyframes %s {\n",
|
|
indentStr.get(), NS_ConvertUTF16toUTF8(mName).get());
|
|
|
|
GroupRule::List(out, aIndent);
|
|
|
|
fprintf_stderr(out, "%s}\n", indentStr.get());
|
|
}
|
|
#endif
|
|
|
|
/* virtual */ int32_t
|
|
nsCSSKeyframesRule::GetType() const
|
|
{
|
|
return Rule::KEYFRAMES_RULE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframesRule::GetType(uint16_t* aType)
|
|
{
|
|
*aType = nsIDOMCSSRule::KEYFRAMES_RULE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframesRule::GetCssText(nsAString& aCssText)
|
|
{
|
|
aCssText.AssignLiteral("@keyframes ");
|
|
aCssText.Append(mName);
|
|
aCssText.AppendLiteral(" {\n");
|
|
nsAutoString tmp;
|
|
for (uint32_t i = 0, i_end = mRules.Count(); i != i_end; ++i) {
|
|
static_cast<nsCSSKeyframeRule*>(mRules[i])->GetCssText(tmp);
|
|
aCssText.Append(tmp);
|
|
aCssText.Append('\n');
|
|
}
|
|
aCssText.Append('}');
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframesRule::SetCssText(const nsAString& aCssText)
|
|
{
|
|
// FIXME: implement???
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframesRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
|
|
{
|
|
return GroupRule::GetParentStyleSheet(aSheet);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframesRule::GetParentRule(nsIDOMCSSRule** aParentRule)
|
|
{
|
|
return GroupRule::GetParentRule(aParentRule);
|
|
}
|
|
|
|
css::Rule*
|
|
nsCSSKeyframesRule::GetCSSRule()
|
|
{
|
|
return GroupRule::GetCSSRule();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframesRule::GetName(nsAString& aName)
|
|
{
|
|
aName = mName;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframesRule::SetName(const nsAString& aName)
|
|
{
|
|
if (mName == aName) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsIDocument* doc = GetDocument();
|
|
MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
|
|
|
|
mName = aName;
|
|
|
|
CSSStyleSheet* sheet = GetStyleSheet();
|
|
if (sheet) {
|
|
sheet->SetModifiedByChildRule();
|
|
|
|
if (doc) {
|
|
doc->StyleRuleChanged(sheet, this);
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframesRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
|
|
{
|
|
return GroupRule::GetCssRules(aRuleList);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframesRule::AppendRule(const nsAString& aRule)
|
|
{
|
|
// The spec is confusing, and I think we should just append the rule,
|
|
// which also turns out to match WebKit:
|
|
// http://lists.w3.org/Archives/Public/www-style/2011Apr/0034.html
|
|
nsCSSParser parser;
|
|
|
|
// FIXME: pass filename and line number
|
|
RefPtr<nsCSSKeyframeRule> rule =
|
|
parser.ParseKeyframeRule(aRule, nullptr, 0);
|
|
if (rule) {
|
|
nsIDocument* doc = GetDocument();
|
|
MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
|
|
|
|
AppendStyleRule(rule);
|
|
|
|
CSSStyleSheet* sheet = GetStyleSheet();
|
|
if (sheet) {
|
|
sheet->SetModifiedByChildRule();
|
|
|
|
if (doc) {
|
|
doc->StyleRuleChanged(sheet, this);
|
|
}
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
static const uint32_t RULE_NOT_FOUND = uint32_t(-1);
|
|
|
|
uint32_t
|
|
nsCSSKeyframesRule::FindRuleIndexForKey(const nsAString& aKey)
|
|
{
|
|
nsCSSParser parser;
|
|
|
|
InfallibleTArray<float> keys;
|
|
// FIXME: pass filename and line number
|
|
if (parser.ParseKeyframeSelectorString(aKey, nullptr, 0, keys)) {
|
|
// The spec isn't clear, but we'll match on the key list, which
|
|
// mostly matches what WebKit does, except we'll do last-match
|
|
// instead of first-match, and handling parsing differences better.
|
|
// http://lists.w3.org/Archives/Public/www-style/2011Apr/0036.html
|
|
// http://lists.w3.org/Archives/Public/www-style/2011Apr/0037.html
|
|
for (uint32_t i = mRules.Count(); i-- != 0; ) {
|
|
if (static_cast<nsCSSKeyframeRule*>(mRules[i])->GetKeys() == keys) {
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
|
|
return RULE_NOT_FOUND;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframesRule::DeleteRule(const nsAString& aKey)
|
|
{
|
|
uint32_t index = FindRuleIndexForKey(aKey);
|
|
if (index != RULE_NOT_FOUND) {
|
|
nsIDocument* doc = GetDocument();
|
|
MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
|
|
|
|
mRules.RemoveObjectAt(index);
|
|
|
|
CSSStyleSheet* sheet = GetStyleSheet();
|
|
if (sheet) {
|
|
sheet->SetModifiedByChildRule();
|
|
|
|
if (doc) {
|
|
doc->StyleRuleChanged(sheet, this);
|
|
}
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSKeyframesRule::FindRule(const nsAString& aKey,
|
|
nsIDOMCSSKeyframeRule** aResult)
|
|
{
|
|
uint32_t index = FindRuleIndexForKey(aKey);
|
|
if (index == RULE_NOT_FOUND) {
|
|
*aResult = nullptr;
|
|
} else {
|
|
NS_ADDREF(*aResult = static_cast<nsCSSKeyframeRule*>(mRules[index]));
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
// GroupRule interface
|
|
/* virtual */ bool
|
|
nsCSSKeyframesRule::UseForPresentation(nsPresContext* aPresContext,
|
|
nsMediaQueryResultCacheKey& aKey)
|
|
{
|
|
MOZ_ASSERT(false, "should not be called");
|
|
return false;
|
|
}
|
|
|
|
/* virtual */ size_t
|
|
nsCSSKeyframesRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
|
{
|
|
size_t n = aMallocSizeOf(this);
|
|
n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
|
|
|
|
// Measurement of the following members may be added later if DMD finds it is
|
|
// worthwhile:
|
|
// - mName
|
|
|
|
return n;
|
|
}
|
|
|
|
// -------------------------------------------
|
|
// nsCSSPageStyleDeclaration
|
|
//
|
|
|
|
nsCSSPageStyleDeclaration::nsCSSPageStyleDeclaration(nsCSSPageRule* aRule)
|
|
: mRule(aRule)
|
|
{
|
|
}
|
|
|
|
nsCSSPageStyleDeclaration::~nsCSSPageStyleDeclaration()
|
|
{
|
|
NS_ASSERTION(!mRule, "DropReference not called.");
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSPageStyleDeclaration)
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSPageStyleDeclaration)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsCSSPageStyleDeclaration)
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSPageStyleDeclaration)
|
|
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
|
NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration)
|
|
|
|
css::Declaration*
|
|
nsCSSPageStyleDeclaration::GetCSSDeclaration(Operation aOperation)
|
|
{
|
|
if (mRule) {
|
|
return mRule->Declaration();
|
|
} else {
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
void
|
|
nsCSSPageStyleDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
|
|
{
|
|
GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSPageStyleDeclaration::GetParentRule(nsIDOMCSSRule** aParent)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aParent);
|
|
|
|
NS_IF_ADDREF(*aParent = mRule);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsCSSPageStyleDeclaration::SetCSSDeclaration(css::Declaration* aDecl)
|
|
{
|
|
MOZ_ASSERT(aDecl, "must be non-null");
|
|
mRule->ChangeDeclaration(aDecl);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsIDocument*
|
|
nsCSSPageStyleDeclaration::DocToUpdate()
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
nsINode*
|
|
nsCSSPageStyleDeclaration::GetParentObject()
|
|
{
|
|
return mRule ? mRule->GetDocument() : nullptr;
|
|
}
|
|
|
|
// -------------------------------------------
|
|
// nsCSSPageRule
|
|
//
|
|
|
|
nsCSSPageRule::nsCSSPageRule(const nsCSSPageRule& aCopy)
|
|
// copy everything except our reference count and mDOMDeclaration
|
|
: Rule(aCopy)
|
|
, mDeclaration(new css::Declaration(*aCopy.mDeclaration))
|
|
{
|
|
mDeclaration->SetOwningRule(this);
|
|
}
|
|
|
|
nsCSSPageRule::~nsCSSPageRule()
|
|
{
|
|
mDeclaration->SetOwningRule(nullptr);
|
|
if (mDOMDeclaration) {
|
|
mDOMDeclaration->DropReference();
|
|
}
|
|
}
|
|
|
|
/* virtual */ already_AddRefed<css::Rule>
|
|
nsCSSPageRule::Clone() const
|
|
{
|
|
RefPtr<css::Rule> clone = new nsCSSPageRule(*this);
|
|
return clone.forget();
|
|
}
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSPageRule)
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSPageRule)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsCSSPageRule)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCSSPageRule)
|
|
if (tmp->mDOMDeclaration) {
|
|
tmp->mDOMDeclaration->DropReference();
|
|
tmp->mDOMDeclaration = nullptr;
|
|
}
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCSSPageRule)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMDeclaration)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
// QueryInterface implementation for nsCSSPageRule
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSPageRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSPageRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozilla::css::Rule)
|
|
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSPageRule)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(nsCSSPageRule, Rule)
|
|
|
|
#ifdef DEBUG
|
|
void
|
|
nsCSSPageRule::List(FILE* out, int32_t aIndent) const
|
|
{
|
|
nsAutoCString str;
|
|
for (int32_t indent = aIndent; --indent >= 0; ) {
|
|
str.AppendLiteral(" ");
|
|
}
|
|
|
|
str.AppendLiteral("@page { ");
|
|
nsAutoString tmp;
|
|
mDeclaration->ToString(tmp);
|
|
AppendUTF16toUTF8(tmp, str);
|
|
str.AppendLiteral("}\n");
|
|
fprintf_stderr(out, "%s", str.get());
|
|
}
|
|
#endif
|
|
|
|
/* virtual */ int32_t
|
|
nsCSSPageRule::GetType() const
|
|
{
|
|
return Rule::PAGE_RULE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSPageRule::GetType(uint16_t* aType)
|
|
{
|
|
*aType = nsIDOMCSSRule::PAGE_RULE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSPageRule::GetCssText(nsAString& aCssText)
|
|
{
|
|
aCssText.AppendLiteral("@page { ");
|
|
nsAutoString tmp;
|
|
mDeclaration->ToString(tmp);
|
|
aCssText.Append(tmp);
|
|
aCssText.AppendLiteral(" }");
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSPageRule::SetCssText(const nsAString& aCssText)
|
|
{
|
|
// FIXME: implement???
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSPageRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
|
|
{
|
|
return Rule::GetParentStyleSheet(aSheet);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSPageRule::GetParentRule(nsIDOMCSSRule** aParentRule)
|
|
{
|
|
return Rule::GetParentRule(aParentRule);
|
|
}
|
|
|
|
css::Rule*
|
|
nsCSSPageRule::GetCSSRule()
|
|
{
|
|
return Rule::GetCSSRule();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSPageRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
|
|
{
|
|
if (!mDOMDeclaration) {
|
|
mDOMDeclaration = new nsCSSPageStyleDeclaration(this);
|
|
}
|
|
NS_ADDREF(*aStyle = mDOMDeclaration);
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
nsCSSPageRule::ChangeDeclaration(css::Declaration* aDeclaration)
|
|
{
|
|
if (aDeclaration != mDeclaration) {
|
|
mDeclaration->SetOwningRule(nullptr);
|
|
mDeclaration = aDeclaration;
|
|
mDeclaration->SetOwningRule(this);
|
|
}
|
|
|
|
CSSStyleSheet* sheet = GetStyleSheet();
|
|
if (sheet) {
|
|
sheet->SetModifiedByChildRule();
|
|
}
|
|
}
|
|
|
|
/* virtual */ size_t
|
|
nsCSSPageRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
|
{
|
|
return aMallocSizeOf(this);
|
|
}
|
|
|
|
namespace mozilla {
|
|
|
|
CSSSupportsRule::CSSSupportsRule(bool aConditionMet,
|
|
const nsString& aCondition,
|
|
uint32_t aLineNumber, uint32_t aColumnNumber)
|
|
: css::GroupRule(aLineNumber, aColumnNumber)
|
|
, mUseGroup(aConditionMet)
|
|
, mCondition(aCondition)
|
|
{
|
|
}
|
|
|
|
CSSSupportsRule::~CSSSupportsRule()
|
|
{
|
|
}
|
|
|
|
CSSSupportsRule::CSSSupportsRule(const CSSSupportsRule& aCopy)
|
|
: css::GroupRule(aCopy),
|
|
mUseGroup(aCopy.mUseGroup),
|
|
mCondition(aCopy.mCondition)
|
|
{
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
/* virtual */ void
|
|
CSSSupportsRule::List(FILE* out, int32_t aIndent) const
|
|
{
|
|
nsAutoCString indentStr;
|
|
for (int32_t indent = aIndent; --indent >= 0; ) {
|
|
indentStr.AppendLiteral(" ");
|
|
}
|
|
|
|
fprintf_stderr(out, "%s@supports %s {\n",
|
|
indentStr.get(), NS_ConvertUTF16toUTF8(mCondition).get());
|
|
|
|
css::GroupRule::List(out, aIndent);
|
|
|
|
fprintf_stderr(out, "%s}\n", indentStr.get());
|
|
}
|
|
#endif
|
|
|
|
/* virtual */ int32_t
|
|
CSSSupportsRule::GetType() const
|
|
{
|
|
return Rule::SUPPORTS_RULE;
|
|
}
|
|
|
|
/* virtual */ already_AddRefed<mozilla::css::Rule>
|
|
CSSSupportsRule::Clone() const
|
|
{
|
|
RefPtr<css::Rule> clone = new CSSSupportsRule(*this);
|
|
return clone.forget();
|
|
}
|
|
|
|
/* virtual */ bool
|
|
CSSSupportsRule::UseForPresentation(nsPresContext* aPresContext,
|
|
nsMediaQueryResultCacheKey& aKey)
|
|
{
|
|
return mUseGroup;
|
|
}
|
|
|
|
NS_IMPL_ADDREF_INHERITED(CSSSupportsRule, css::GroupRule)
|
|
NS_IMPL_RELEASE_INHERITED(CSSSupportsRule, css::GroupRule)
|
|
|
|
// QueryInterface implementation for CSSSupportsRule
|
|
NS_INTERFACE_MAP_BEGIN(CSSSupportsRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSSupportsRule)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozilla::css::Rule)
|
|
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSSupportsRule)
|
|
NS_INTERFACE_MAP_END_INHERITING(GroupRule)
|
|
|
|
// nsIDOMCSSRule methods
|
|
NS_IMETHODIMP
|
|
CSSSupportsRule::GetType(uint16_t* aType)
|
|
{
|
|
*aType = nsIDOMCSSRule::SUPPORTS_RULE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
CSSSupportsRule::GetCssText(nsAString& aCssText)
|
|
{
|
|
aCssText.AssignLiteral("@supports ");
|
|
aCssText.Append(mCondition);
|
|
css::GroupRule::AppendRulesToCssText(aCssText);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
CSSSupportsRule::SetCssText(const nsAString& aCssText)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
CSSSupportsRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
|
|
{
|
|
return css::GroupRule::GetParentStyleSheet(aSheet);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
CSSSupportsRule::GetParentRule(nsIDOMCSSRule** aParentRule)
|
|
{
|
|
return css::GroupRule::GetParentRule(aParentRule);
|
|
}
|
|
|
|
css::Rule*
|
|
CSSSupportsRule::GetCSSRule()
|
|
{
|
|
return css::GroupRule::GetCSSRule();
|
|
}
|
|
|
|
// nsIDOMCSSGroupingRule methods
|
|
NS_IMETHODIMP
|
|
CSSSupportsRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
|
|
{
|
|
return css::GroupRule::GetCssRules(aRuleList);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
CSSSupportsRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
|
|
{
|
|
return css::GroupRule::InsertRule(aRule, aIndex, _retval);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
CSSSupportsRule::DeleteRule(uint32_t aIndex)
|
|
{
|
|
return css::GroupRule::DeleteRule(aIndex);
|
|
}
|
|
|
|
// nsIDOMCSSConditionRule methods
|
|
NS_IMETHODIMP
|
|
CSSSupportsRule::GetConditionText(nsAString& aConditionText)
|
|
{
|
|
aConditionText.Assign(mCondition);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
CSSSupportsRule::SetConditionText(const nsAString& aConditionText)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/* virtual */ size_t
|
|
CSSSupportsRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
|
{
|
|
size_t n = aMallocSizeOf(this);
|
|
n += css::GroupRule::SizeOfExcludingThis(aMallocSizeOf);
|
|
n += mCondition.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
|
return n;
|
|
}
|
|
|
|
} // namespace mozilla
|
|
|
|
// -------------------------------------------
|
|
// nsCSSCounterStyleRule
|
|
//
|
|
|
|
nsCSSCounterStyleRule::nsCSSCounterStyleRule(const nsCSSCounterStyleRule& aCopy)
|
|
: Rule(aCopy)
|
|
, mName(aCopy.mName)
|
|
, mGeneration(aCopy.mGeneration)
|
|
{
|
|
for (size_t i = 0; i < ArrayLength(mValues); ++i) {
|
|
mValues[i] = aCopy.mValues[i];
|
|
}
|
|
}
|
|
|
|
nsCSSCounterStyleRule::~nsCSSCounterStyleRule()
|
|
{
|
|
}
|
|
|
|
/* virtual */ already_AddRefed<css::Rule>
|
|
nsCSSCounterStyleRule::Clone() const
|
|
{
|
|
RefPtr<css::Rule> clone = new nsCSSCounterStyleRule(*this);
|
|
return clone.forget();
|
|
}
|
|
|
|
nsCSSCounterStyleRule::Getter const
|
|
nsCSSCounterStyleRule::kGetters[] = {
|
|
#define CSS_COUNTER_DESC(name_, method_) &nsCSSCounterStyleRule::Get##method_,
|
|
#include "nsCSSCounterDescList.h"
|
|
#undef CSS_COUNTER_DESC
|
|
};
|
|
|
|
NS_IMPL_ADDREF(nsCSSCounterStyleRule)
|
|
NS_IMPL_RELEASE(nsCSSCounterStyleRule)
|
|
|
|
// QueryInterface implementation for nsCSSCounterStyleRule
|
|
NS_INTERFACE_MAP_BEGIN(nsCSSCounterStyleRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSCounterStyleRule)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozilla::css::Rule)
|
|
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSCounterStyleRule)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
IMPL_STYLE_RULE_INHERIT(nsCSSCounterStyleRule, css::Rule)
|
|
|
|
#ifdef DEBUG
|
|
void
|
|
nsCSSCounterStyleRule::List(FILE* out, int32_t aIndent) const
|
|
{
|
|
nsCString baseInd, descInd;
|
|
for (int32_t indent = aIndent; --indent >= 0; ) {
|
|
baseInd.AppendLiteral(" ");
|
|
}
|
|
descInd = baseInd;
|
|
descInd.AppendLiteral(" ");
|
|
|
|
fprintf_stderr(out, "%s@counter-style %s (rev.%u) {\n",
|
|
baseInd.get(), NS_ConvertUTF16toUTF8(mName).get(),
|
|
mGeneration);
|
|
// TODO
|
|
fprintf_stderr(out, "%s}\n", baseInd.get());
|
|
}
|
|
#endif
|
|
|
|
/* virtual */ int32_t
|
|
nsCSSCounterStyleRule::GetType() const
|
|
{
|
|
return Rule::COUNTER_STYLE_RULE;
|
|
}
|
|
|
|
// nsIDOMCSSRule methods
|
|
NS_IMETHODIMP
|
|
nsCSSCounterStyleRule::GetType(uint16_t* aType)
|
|
{
|
|
*aType = nsIDOMCSSRule::COUNTER_STYLE_RULE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSCounterStyleRule::GetCssText(nsAString& aCssText)
|
|
{
|
|
aCssText.AssignLiteral(u"@counter-style ");
|
|
nsStyleUtil::AppendEscapedCSSIdent(mName, aCssText);
|
|
aCssText.AppendLiteral(u" {\n");
|
|
for (nsCSSCounterDesc id = nsCSSCounterDesc(0);
|
|
id < eCSSCounterDesc_COUNT;
|
|
id = nsCSSCounterDesc(id + 1)) {
|
|
if (mValues[id].GetUnit() != eCSSUnit_Null) {
|
|
nsAutoString tmp;
|
|
(this->*kGetters[id])(tmp);
|
|
aCssText.AppendLiteral(u" ");
|
|
AppendASCIItoUTF16(nsCSSProps::GetStringValue(id), aCssText);
|
|
aCssText.AppendLiteral(u": ");
|
|
aCssText.Append(tmp);
|
|
aCssText.AppendLiteral(u";\n");
|
|
}
|
|
}
|
|
aCssText.AppendLiteral(u"}");
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSCounterStyleRule::SetCssText(const nsAString& aCssText)
|
|
{
|
|
// FIXME: implement???
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSCounterStyleRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
|
|
{
|
|
return Rule::GetParentStyleSheet(aSheet);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSCounterStyleRule::GetParentRule(nsIDOMCSSRule** aParentRule)
|
|
{
|
|
return Rule::GetParentRule(aParentRule);
|
|
}
|
|
|
|
css::Rule*
|
|
nsCSSCounterStyleRule::GetCSSRule()
|
|
{
|
|
return Rule::GetCSSRule();
|
|
}
|
|
|
|
// nsIDOMCSSCounterStyleRule methods
|
|
NS_IMETHODIMP
|
|
nsCSSCounterStyleRule::GetName(nsAString& aName)
|
|
{
|
|
aName.Truncate();
|
|
nsStyleUtil::AppendEscapedCSSIdent(mName, aName);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSCounterStyleRule::SetName(const nsAString& aName)
|
|
{
|
|
nsCSSParser parser;
|
|
nsAutoString name;
|
|
if (parser.ParseCounterStyleName(aName, nullptr, name)) {
|
|
nsIDocument* doc = GetDocument();
|
|
MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
|
|
|
|
mName = name;
|
|
|
|
CSSStyleSheet* sheet = GetStyleSheet();
|
|
if (sheet) {
|
|
sheet->SetModifiedByChildRule();
|
|
if (doc) {
|
|
doc->StyleRuleChanged(sheet, this);
|
|
}
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
int32_t
|
|
nsCSSCounterStyleRule::GetSystem() const
|
|
{
|
|
const nsCSSValue& system = GetDesc(eCSSCounterDesc_System);
|
|
switch (system.GetUnit()) {
|
|
case eCSSUnit_Enumerated:
|
|
return system.GetIntValue();
|
|
case eCSSUnit_Pair:
|
|
return system.GetPairValue().mXValue.GetIntValue();
|
|
default:
|
|
return NS_STYLE_COUNTER_SYSTEM_SYMBOLIC;
|
|
}
|
|
}
|
|
|
|
const nsCSSValue&
|
|
nsCSSCounterStyleRule::GetSystemArgument() const
|
|
{
|
|
const nsCSSValue& system = GetDesc(eCSSCounterDesc_System);
|
|
MOZ_ASSERT(system.GetUnit() == eCSSUnit_Pair,
|
|
"Invalid system value");
|
|
return system.GetPairValue().mYValue;
|
|
}
|
|
|
|
void
|
|
nsCSSCounterStyleRule::SetDesc(nsCSSCounterDesc aDescID, const nsCSSValue& aValue)
|
|
{
|
|
MOZ_ASSERT(aDescID >= 0 && aDescID < eCSSCounterDesc_COUNT,
|
|
"descriptor ID out of range");
|
|
|
|
nsIDocument* doc = GetDocument();
|
|
MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
|
|
|
|
mValues[aDescID] = aValue;
|
|
mGeneration++;
|
|
|
|
CSSStyleSheet* sheet = GetStyleSheet();
|
|
if (sheet) {
|
|
sheet->SetModifiedByChildRule();
|
|
if (doc) {
|
|
doc->StyleRuleChanged(sheet, this);
|
|
}
|
|
}
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSCounterStyleRule::GetSystem(nsAString& aSystem)
|
|
{
|
|
const nsCSSValue& value = GetDesc(eCSSCounterDesc_System);
|
|
if (value.GetUnit() == eCSSUnit_Null) {
|
|
aSystem.Truncate();
|
|
return NS_OK;
|
|
}
|
|
|
|
aSystem = NS_ConvertASCIItoUTF16(nsCSSProps::ValueToKeyword(
|
|
GetSystem(), nsCSSProps::kCounterSystemKTable));
|
|
if (value.GetUnit() == eCSSUnit_Pair) {
|
|
aSystem.Append(' ');
|
|
GetSystemArgument().AppendToString(
|
|
eCSSProperty_UNKNOWN, aSystem, nsCSSValue::eNormalized);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSCounterStyleRule::GetSymbols(nsAString& aSymbols)
|
|
{
|
|
const nsCSSValue& value = GetDesc(eCSSCounterDesc_Symbols);
|
|
|
|
aSymbols.Truncate();
|
|
if (value.GetUnit() == eCSSUnit_List) {
|
|
for (const nsCSSValueList* item = value.GetListValue();
|
|
item; item = item->mNext) {
|
|
item->mValue.AppendToString(eCSSProperty_UNKNOWN,
|
|
aSymbols,
|
|
nsCSSValue::eNormalized);
|
|
if (item->mNext) {
|
|
aSymbols.Append(' ');
|
|
}
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSCounterStyleRule::GetAdditiveSymbols(nsAString& aSymbols)
|
|
{
|
|
const nsCSSValue& value = GetDesc(eCSSCounterDesc_AdditiveSymbols);
|
|
|
|
aSymbols.Truncate();
|
|
if (value.GetUnit() == eCSSUnit_PairList) {
|
|
for (const nsCSSValuePairList* item = value.GetPairListValue();
|
|
item; item = item->mNext) {
|
|
item->mXValue.AppendToString(eCSSProperty_UNKNOWN,
|
|
aSymbols, nsCSSValue::eNormalized);
|
|
aSymbols.Append(' ');
|
|
item->mYValue.AppendToString(eCSSProperty_UNKNOWN,
|
|
aSymbols, nsCSSValue::eNormalized);
|
|
if (item->mNext) {
|
|
aSymbols.AppendLiteral(", ");
|
|
}
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSCounterStyleRule::GetRange(nsAString& aRange)
|
|
{
|
|
const nsCSSValue& value = GetDesc(eCSSCounterDesc_Range);
|
|
|
|
switch (value.GetUnit()) {
|
|
case eCSSUnit_Auto:
|
|
aRange.AssignLiteral(u"auto");
|
|
break;
|
|
|
|
case eCSSUnit_PairList:
|
|
aRange.Truncate();
|
|
for (const nsCSSValuePairList* item = value.GetPairListValue();
|
|
item; item = item->mNext) {
|
|
const nsCSSValue& lower = item->mXValue;
|
|
const nsCSSValue& upper = item->mYValue;
|
|
if (lower.GetUnit() == eCSSUnit_Enumerated) {
|
|
NS_ASSERTION(lower.GetIntValue() ==
|
|
NS_STYLE_COUNTER_RANGE_INFINITE,
|
|
"Unrecognized keyword");
|
|
aRange.AppendLiteral("infinite");
|
|
} else {
|
|
aRange.AppendInt(lower.GetIntValue());
|
|
}
|
|
aRange.Append(' ');
|
|
if (upper.GetUnit() == eCSSUnit_Enumerated) {
|
|
NS_ASSERTION(upper.GetIntValue() ==
|
|
NS_STYLE_COUNTER_RANGE_INFINITE,
|
|
"Unrecognized keyword");
|
|
aRange.AppendLiteral("infinite");
|
|
} else {
|
|
aRange.AppendInt(upper.GetIntValue());
|
|
}
|
|
if (item->mNext) {
|
|
aRange.AppendLiteral(", ");
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
aRange.Truncate();
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCSSCounterStyleRule::GetSpeakAs(nsAString& aSpeakAs)
|
|
{
|
|
const nsCSSValue& value = GetDesc(eCSSCounterDesc_SpeakAs);
|
|
|
|
switch (value.GetUnit()) {
|
|
case eCSSUnit_Enumerated:
|
|
switch (value.GetIntValue()) {
|
|
case NS_STYLE_COUNTER_SPEAKAS_BULLETS:
|
|
aSpeakAs.AssignLiteral(u"bullets");
|
|
break;
|
|
case NS_STYLE_COUNTER_SPEAKAS_NUMBERS:
|
|
aSpeakAs.AssignLiteral(u"numbers");
|
|
break;
|
|
case NS_STYLE_COUNTER_SPEAKAS_WORDS:
|
|
aSpeakAs.AssignLiteral(u"words");
|
|
break;
|
|
case NS_STYLE_COUNTER_SPEAKAS_SPELL_OUT:
|
|
aSpeakAs.AssignLiteral(u"spell-out");
|
|
break;
|
|
default:
|
|
NS_NOTREACHED("Unknown speech synthesis");
|
|
}
|
|
break;
|
|
|
|
case eCSSUnit_Auto:
|
|
case eCSSUnit_Ident:
|
|
aSpeakAs.Truncate();
|
|
value.AppendToString(eCSSProperty_UNKNOWN,
|
|
aSpeakAs, nsCSSValue::eNormalized);
|
|
break;
|
|
|
|
default:
|
|
aSpeakAs.Truncate();
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsCSSCounterStyleRule::GetDescriptor(nsCSSCounterDesc aDescID,
|
|
nsAString& aValue)
|
|
{
|
|
NS_ASSERTION(aDescID == eCSSCounterDesc_Negative ||
|
|
aDescID == eCSSCounterDesc_Prefix ||
|
|
aDescID == eCSSCounterDesc_Suffix ||
|
|
aDescID == eCSSCounterDesc_Pad ||
|
|
aDescID == eCSSCounterDesc_Fallback,
|
|
"Unexpected descriptor");
|
|
const nsCSSValue& value = GetDesc(aDescID);
|
|
aValue.Truncate();
|
|
if (value.GetUnit() != eCSSUnit_Null) {
|
|
value.AppendToString(
|
|
eCSSProperty_UNKNOWN, aValue, nsCSSValue::eNormalized);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
#define CSS_COUNTER_DESC_GETTER(name_) \
|
|
NS_IMETHODIMP \
|
|
nsCSSCounterStyleRule::Get##name_(nsAString& a##name_) \
|
|
{ \
|
|
return GetDescriptor(eCSSCounterDesc_##name_, a##name_);\
|
|
}
|
|
CSS_COUNTER_DESC_GETTER(Negative)
|
|
CSS_COUNTER_DESC_GETTER(Prefix)
|
|
CSS_COUNTER_DESC_GETTER(Suffix)
|
|
CSS_COUNTER_DESC_GETTER(Pad)
|
|
CSS_COUNTER_DESC_GETTER(Fallback)
|
|
#undef CSS_COUNTER_DESC_GETTER
|
|
|
|
/* static */ bool
|
|
nsCSSCounterStyleRule::CheckDescValue(int32_t aSystem,
|
|
nsCSSCounterDesc aDescID,
|
|
const nsCSSValue& aValue)
|
|
{
|
|
switch (aDescID) {
|
|
case eCSSCounterDesc_System:
|
|
if (aValue.GetUnit() != eCSSUnit_Pair) {
|
|
return aValue.GetIntValue() == aSystem;
|
|
} else {
|
|
return aValue.GetPairValue().mXValue.GetIntValue() == aSystem;
|
|
}
|
|
|
|
case eCSSCounterDesc_Symbols:
|
|
switch (aSystem) {
|
|
case NS_STYLE_COUNTER_SYSTEM_NUMERIC:
|
|
case NS_STYLE_COUNTER_SYSTEM_ALPHABETIC:
|
|
// for these two system, the list must contain at least 2 elements
|
|
return aValue.GetListValue()->mNext;
|
|
case NS_STYLE_COUNTER_SYSTEM_EXTENDS:
|
|
// for extends system, no symbols should be set
|
|
return false;
|
|
default:
|
|
return true;
|
|
}
|
|
|
|
case eCSSCounterDesc_AdditiveSymbols:
|
|
switch (aSystem) {
|
|
case NS_STYLE_COUNTER_SYSTEM_EXTENDS:
|
|
return false;
|
|
default:
|
|
return true;
|
|
}
|
|
|
|
default:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
nsresult
|
|
nsCSSCounterStyleRule::SetDescriptor(nsCSSCounterDesc aDescID,
|
|
const nsAString& aValue)
|
|
{
|
|
nsCSSParser parser;
|
|
nsCSSValue value;
|
|
CSSStyleSheet* sheet = GetStyleSheet();
|
|
nsIURI* baseURL = nullptr;
|
|
nsIPrincipal* principal = nullptr;
|
|
if (sheet) {
|
|
baseURL = sheet->GetBaseURI();
|
|
principal = sheet->Principal();
|
|
}
|
|
if (parser.ParseCounterDescriptor(aDescID, aValue, nullptr,
|
|
baseURL, principal, value)) {
|
|
if (CheckDescValue(GetSystem(), aDescID, value)) {
|
|
SetDesc(aDescID, value);
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
#define CSS_COUNTER_DESC_SETTER(name_) \
|
|
NS_IMETHODIMP \
|
|
nsCSSCounterStyleRule::Set##name_(const nsAString& a##name_) \
|
|
{ \
|
|
return SetDescriptor(eCSSCounterDesc_##name_, a##name_); \
|
|
}
|
|
CSS_COUNTER_DESC_SETTER(System)
|
|
CSS_COUNTER_DESC_SETTER(Symbols)
|
|
CSS_COUNTER_DESC_SETTER(AdditiveSymbols)
|
|
CSS_COUNTER_DESC_SETTER(Negative)
|
|
CSS_COUNTER_DESC_SETTER(Prefix)
|
|
CSS_COUNTER_DESC_SETTER(Suffix)
|
|
CSS_COUNTER_DESC_SETTER(Range)
|
|
CSS_COUNTER_DESC_SETTER(Pad)
|
|
CSS_COUNTER_DESC_SETTER(Fallback)
|
|
CSS_COUNTER_DESC_SETTER(SpeakAs)
|
|
#undef CSS_COUNTER_DESC_SETTER
|
|
|
|
/* virtual */ size_t
|
|
nsCSSCounterStyleRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
|
{
|
|
return aMallocSizeOf(this);
|
|
}
|