layout/style/nsCSSRules.cpp

branch
TOR_BUG_9701
changeset 11
deefc01c0e14
equal deleted inserted replaced
-1:000000000000 0:d6a5a74a38a8
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 /* rules in a CSS stylesheet other than style rules (e.g., @import rules) */
7
8 #include "mozilla/Attributes.h"
9
10 #include "nsCSSRules.h"
11 #include "nsCSSValue.h"
12 #include "mozilla/MemoryReporting.h"
13 #include "mozilla/css/ImportRule.h"
14 #include "mozilla/css/NameSpaceRule.h"
15
16 #include "nsString.h"
17 #include "nsIAtom.h"
18
19 #include "nsCSSProps.h"
20 #include "nsCSSStyleSheet.h"
21
22 #include "nsCOMPtr.h"
23 #include "nsIDOMCSSStyleSheet.h"
24 #include "nsIMediaList.h"
25 #include "nsICSSRuleList.h"
26 #include "nsIDocument.h"
27 #include "nsPresContext.h"
28
29 #include "nsContentUtils.h"
30 #include "nsError.h"
31 #include "nsStyleUtil.h"
32 #include "mozilla/css/Declaration.h"
33 #include "nsCSSParser.h"
34 #include "nsPrintfCString.h"
35 #include "nsDOMClassInfoID.h"
36 #include "mozilla/dom/CSSStyleDeclarationBinding.h"
37 #include "StyleRule.h"
38 #include "nsFont.h"
39 #include "nsIURI.h"
40 #include "mozAutoDocUpdate.h"
41
42 using namespace mozilla;
43
44 #define IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(class_, super_) \
45 /* virtual */ nsIDOMCSSRule* class_::GetDOMRule() \
46 { return this; } \
47 /* virtual */ nsIDOMCSSRule* class_::GetExistingDOMRule() \
48 { return this; }
49 #define IMPL_STYLE_RULE_INHERIT_MAP_RULE_INFO_INTO(class_, super_) \
50 /* virtual */ void class_::MapRuleInfoInto(nsRuleData* aRuleData) \
51 { NS_ABORT_IF_FALSE(false, "should not be called"); }
52
53 #define IMPL_STYLE_RULE_INHERIT(class_, super_) \
54 IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(class_, super_) \
55 IMPL_STYLE_RULE_INHERIT_MAP_RULE_INFO_INTO(class_, super_)
56
57 // base class for all rule types in a CSS style sheet
58
59 namespace mozilla {
60 namespace css {
61
62 nsCSSStyleSheet*
63 Rule::GetStyleSheet() const
64 {
65 if (!(mSheet & 0x1)) {
66 return reinterpret_cast<nsCSSStyleSheet*>(mSheet);
67 }
68
69 return nullptr;
70 }
71
72 nsHTMLCSSStyleSheet*
73 Rule::GetHTMLCSSStyleSheet() const
74 {
75 if (mSheet & 0x1) {
76 return reinterpret_cast<nsHTMLCSSStyleSheet*>(mSheet & ~uintptr_t(0x1));
77 }
78
79 return nullptr;
80 }
81
82 /* virtual */ void
83 Rule::SetStyleSheet(nsCSSStyleSheet* aSheet)
84 {
85 // We don't reference count this up reference. The style sheet
86 // will tell us when it's going away or when we're detached from
87 // it.
88 mSheet = reinterpret_cast<uintptr_t>(aSheet);
89 }
90
91 void
92 Rule::SetHTMLCSSStyleSheet(nsHTMLCSSStyleSheet* aSheet)
93 {
94 // We don't reference count this up reference. The style sheet
95 // will tell us when it's going away or when we're detached from
96 // it.
97 mSheet = reinterpret_cast<uintptr_t>(aSheet);
98 mSheet |= 0x1;
99 }
100
101 nsresult
102 Rule::GetParentRule(nsIDOMCSSRule** aParentRule)
103 {
104 if (mParentRule) {
105 NS_IF_ADDREF(*aParentRule = mParentRule->GetDOMRule());
106 } else {
107 *aParentRule = nullptr;
108 }
109 return NS_OK;
110 }
111
112 nsresult
113 Rule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
114 {
115 NS_ENSURE_ARG_POINTER(aSheet);
116
117 NS_IF_ADDREF(*aSheet = GetStyleSheet());
118 return NS_OK;
119 }
120
121 size_t
122 Rule::SizeOfCOMArrayElementIncludingThis(css::Rule* aElement,
123 MallocSizeOf aMallocSizeOf,
124 void* aData)
125 {
126 return aElement->SizeOfIncludingThis(aMallocSizeOf);
127 }
128
129 // -------------------------------
130 // Style Rule List for group rules
131 //
132
133 class GroupRuleRuleList MOZ_FINAL : public nsICSSRuleList
134 {
135 public:
136 GroupRuleRuleList(GroupRule *aGroupRule);
137
138 NS_DECL_ISUPPORTS
139
140 virtual nsIDOMCSSRule*
141 IndexedGetter(uint32_t aIndex, bool& aFound) MOZ_OVERRIDE;
142 virtual uint32_t
143 Length() MOZ_OVERRIDE;
144
145 void DropReference() { mGroupRule = nullptr; }
146
147 private:
148 ~GroupRuleRuleList();
149
150 private:
151 GroupRule* mGroupRule;
152 };
153
154 GroupRuleRuleList::GroupRuleRuleList(GroupRule *aGroupRule)
155 {
156 // Not reference counted to avoid circular references.
157 // The rule will tell us when its going away.
158 mGroupRule = aGroupRule;
159 }
160
161 GroupRuleRuleList::~GroupRuleRuleList()
162 {
163 }
164
165 // QueryInterface implementation for GroupRuleRuleList
166 NS_INTERFACE_MAP_BEGIN(GroupRuleRuleList)
167 NS_INTERFACE_MAP_ENTRY(nsICSSRuleList)
168 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRuleList)
169 NS_INTERFACE_MAP_ENTRY(nsISupports)
170 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSRuleList)
171 NS_INTERFACE_MAP_END
172
173
174 NS_IMPL_ADDREF(GroupRuleRuleList)
175 NS_IMPL_RELEASE(GroupRuleRuleList)
176
177 uint32_t
178 GroupRuleRuleList::Length()
179 {
180 if (!mGroupRule) {
181 return 0;
182 }
183
184 return SafeCast<uint32_t>(mGroupRule->StyleRuleCount());
185 }
186
187 nsIDOMCSSRule*
188 GroupRuleRuleList::IndexedGetter(uint32_t aIndex, bool& aFound)
189 {
190 aFound = false;
191
192 if (mGroupRule) {
193 nsRefPtr<Rule> rule = mGroupRule->GetStyleRuleAt(aIndex);
194 if (rule) {
195 aFound = true;
196 return rule->GetDOMRule();
197 }
198 }
199
200 return nullptr;
201 }
202
203 } // namespace css
204 } // namespace mozilla
205
206 // -------------------------------------------
207 // CharsetRule
208 //
209
210 // Must be outside namespace
211 DOMCI_DATA(CSSCharsetRule, css::CharsetRule)
212
213 namespace mozilla {
214 namespace css {
215
216 CharsetRule::CharsetRule(const nsAString& aEncoding)
217 : Rule(),
218 mEncoding(aEncoding)
219 {
220 }
221
222 CharsetRule::CharsetRule(const CharsetRule& aCopy)
223 : Rule(aCopy),
224 mEncoding(aCopy.mEncoding)
225 {
226 }
227
228 NS_IMPL_ADDREF(CharsetRule)
229 NS_IMPL_RELEASE(CharsetRule)
230
231 // QueryInterface implementation for CharsetRule
232 NS_INTERFACE_MAP_BEGIN(CharsetRule)
233 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
234 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
235 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSCharsetRule)
236 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
237 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSCharsetRule)
238 NS_INTERFACE_MAP_END
239
240 IMPL_STYLE_RULE_INHERIT(CharsetRule, Rule)
241
242 #ifdef DEBUG
243 /* virtual */ void
244 CharsetRule::List(FILE* out, int32_t aIndent) const
245 {
246 // Indent
247 for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out);
248
249 fputs("@charset \"", out);
250 fputs(NS_LossyConvertUTF16toASCII(mEncoding).get(), out);
251 fputs("\"\n", out);
252 }
253 #endif
254
255 /* virtual */ int32_t
256 CharsetRule::GetType() const
257 {
258 return Rule::CHARSET_RULE;
259 }
260
261 /* virtual */ already_AddRefed<Rule>
262 CharsetRule::Clone() const
263 {
264 nsRefPtr<Rule> clone = new CharsetRule(*this);
265 return clone.forget();
266 }
267
268 NS_IMETHODIMP
269 CharsetRule::GetEncoding(nsAString& aEncoding)
270 {
271 aEncoding = mEncoding;
272 return NS_OK;
273 }
274
275 NS_IMETHODIMP
276 CharsetRule::SetEncoding(const nsAString& aEncoding)
277 {
278 mEncoding = aEncoding;
279 return NS_OK;
280 }
281
282 NS_IMETHODIMP
283 CharsetRule::GetType(uint16_t* aType)
284 {
285 *aType = nsIDOMCSSRule::CHARSET_RULE;
286 return NS_OK;
287 }
288
289 NS_IMETHODIMP
290 CharsetRule::GetCssText(nsAString& aCssText)
291 {
292 aCssText.AssignLiteral("@charset \"");
293 aCssText.Append(mEncoding);
294 aCssText.AppendLiteral("\";");
295 return NS_OK;
296 }
297
298 NS_IMETHODIMP
299 CharsetRule::SetCssText(const nsAString& aCssText)
300 {
301 return NS_ERROR_NOT_IMPLEMENTED;
302 }
303
304 NS_IMETHODIMP
305 CharsetRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
306 {
307 return Rule::GetParentStyleSheet(aSheet);
308 }
309
310 NS_IMETHODIMP
311 CharsetRule::GetParentRule(nsIDOMCSSRule** aParentRule)
312 {
313 return Rule::GetParentRule(aParentRule);
314 }
315
316 /* virtual */ size_t
317 CharsetRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
318 {
319 return aMallocSizeOf(this);
320
321 // Measurement of the following members may be added later if DMD finds it is
322 // worthwhile:
323 // - mEncoding
324 }
325
326 // -------------------------------------------
327 // ImportRule
328 //
329
330 ImportRule::ImportRule(nsMediaList* aMedia, const nsString& aURLSpec)
331 : Rule()
332 , mURLSpec(aURLSpec)
333 , mMedia(aMedia)
334 {
335 // XXXbz This is really silly.... the mMedia here will be replaced
336 // with itself if we manage to load a sheet. Which should really
337 // never fail nowadays, in sane cases.
338 }
339
340 ImportRule::ImportRule(const ImportRule& aCopy)
341 : Rule(aCopy),
342 mURLSpec(aCopy.mURLSpec)
343 {
344 // Whether or not an @import rule has a null sheet is a permanent
345 // property of that @import rule, since it is null only if the target
346 // sheet failed security checks.
347 if (aCopy.mChildSheet) {
348 nsRefPtr<nsCSSStyleSheet> sheet =
349 aCopy.mChildSheet->Clone(nullptr, this, nullptr, nullptr);
350 SetSheet(sheet);
351 // SetSheet sets mMedia appropriately
352 }
353 }
354
355 ImportRule::~ImportRule()
356 {
357 if (mChildSheet) {
358 mChildSheet->SetOwnerRule(nullptr);
359 }
360 }
361
362 NS_IMPL_ADDREF(ImportRule)
363 NS_IMPL_RELEASE(ImportRule)
364
365 // QueryInterface implementation for ImportRule
366 NS_INTERFACE_MAP_BEGIN(ImportRule)
367 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
368 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
369 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSImportRule)
370 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
371 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSImportRule)
372 NS_INTERFACE_MAP_END
373
374 IMPL_STYLE_RULE_INHERIT(ImportRule, Rule)
375
376 #ifdef DEBUG
377 /* virtual */ void
378 ImportRule::List(FILE* out, int32_t aIndent) const
379 {
380 // Indent
381 for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out);
382
383 fputs("@import \"", out);
384 fputs(NS_LossyConvertUTF16toASCII(mURLSpec).get(), out);
385 fputs("\" ", out);
386
387 nsAutoString mediaText;
388 mMedia->GetText(mediaText);
389 fputs(NS_LossyConvertUTF16toASCII(mediaText).get(), out);
390 fputs("\n", out);
391 }
392 #endif
393
394 /* virtual */ int32_t
395 ImportRule::GetType() const
396 {
397 return Rule::IMPORT_RULE;
398 }
399
400 /* virtual */ already_AddRefed<Rule>
401 ImportRule::Clone() const
402 {
403 nsRefPtr<Rule> clone = new ImportRule(*this);
404 return clone.forget();
405 }
406
407 void
408 ImportRule::SetSheet(nsCSSStyleSheet* aSheet)
409 {
410 NS_PRECONDITION(aSheet, "null arg");
411
412 // set the new sheet
413 mChildSheet = aSheet;
414 aSheet->SetOwnerRule(this);
415
416 // set our medialist to be the same as the sheet's medialist
417 mMedia = mChildSheet->Media();
418 }
419
420 NS_IMETHODIMP
421 ImportRule::GetType(uint16_t* aType)
422 {
423 NS_ENSURE_ARG_POINTER(aType);
424 *aType = nsIDOMCSSRule::IMPORT_RULE;
425 return NS_OK;
426 }
427
428 NS_IMETHODIMP
429 ImportRule::GetCssText(nsAString& aCssText)
430 {
431 aCssText.AssignLiteral("@import url(");
432 nsStyleUtil::AppendEscapedCSSString(mURLSpec, aCssText);
433 aCssText.Append(NS_LITERAL_STRING(")"));
434 if (mMedia) {
435 nsAutoString mediaText;
436 mMedia->GetText(mediaText);
437 if (!mediaText.IsEmpty()) {
438 aCssText.AppendLiteral(" ");
439 aCssText.Append(mediaText);
440 }
441 }
442 aCssText.AppendLiteral(";");
443 return NS_OK;
444 }
445
446 NS_IMETHODIMP
447 ImportRule::SetCssText(const nsAString& aCssText)
448 {
449 return NS_ERROR_NOT_IMPLEMENTED;
450 }
451
452 NS_IMETHODIMP
453 ImportRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
454 {
455 return Rule::GetParentStyleSheet(aSheet);
456 }
457
458 NS_IMETHODIMP
459 ImportRule::GetParentRule(nsIDOMCSSRule** aParentRule)
460 {
461 return Rule::GetParentRule(aParentRule);
462 }
463
464 NS_IMETHODIMP
465 ImportRule::GetHref(nsAString & aHref)
466 {
467 aHref = mURLSpec;
468 return NS_OK;
469 }
470
471 NS_IMETHODIMP
472 ImportRule::GetMedia(nsIDOMMediaList * *aMedia)
473 {
474 NS_ENSURE_ARG_POINTER(aMedia);
475
476 NS_IF_ADDREF(*aMedia = mMedia);
477 return NS_OK;
478 }
479
480 NS_IMETHODIMP
481 ImportRule::GetStyleSheet(nsIDOMCSSStyleSheet * *aStyleSheet)
482 {
483 NS_ENSURE_ARG_POINTER(aStyleSheet);
484
485 NS_IF_ADDREF(*aStyleSheet = mChildSheet);
486 return NS_OK;
487 }
488
489 /* virtual */ size_t
490 ImportRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
491 {
492 return aMallocSizeOf(this);
493
494 // Measurement of the following members may be added later if DMD finds it is
495 // worthwhile:
496 // - mURLSpec
497 //
498 // The following members are not measured:
499 // - mMedia, because it is measured via nsCSSStyleSheet::mMedia
500 // - mChildSheet, because it is measured via nsCSSStyleSheetInner::mSheets
501 }
502
503 } // namespace css
504 } // namespace mozilla
505
506 // must be outside the namespace
507 DOMCI_DATA(CSSImportRule, css::ImportRule)
508
509 namespace mozilla {
510 namespace css {
511
512 GroupRule::GroupRule()
513 : Rule()
514 {
515 }
516
517 static bool
518 SetParentRuleReference(Rule* aRule, void* aParentRule)
519 {
520 GroupRule* parentRule = static_cast<GroupRule*>(aParentRule);
521 aRule->SetParentRule(parentRule);
522 return true;
523 }
524
525 GroupRule::GroupRule(const GroupRule& aCopy)
526 : Rule(aCopy)
527 {
528 const_cast<GroupRule&>(aCopy).mRules.EnumerateForwards(GroupRule::CloneRuleInto, &mRules);
529 mRules.EnumerateForwards(SetParentRuleReference, this);
530 }
531
532 GroupRule::~GroupRule()
533 {
534 NS_ABORT_IF_FALSE(!mSheet, "SetStyleSheet should have been called");
535 mRules.EnumerateForwards(SetParentRuleReference, nullptr);
536 if (mRuleCollection) {
537 mRuleCollection->DropReference();
538 }
539 }
540
541 NS_IMPL_CYCLE_COLLECTING_ADDREF(GroupRule)
542 NS_IMPL_CYCLE_COLLECTING_RELEASE(GroupRule)
543
544 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GroupRule)
545 NS_INTERFACE_MAP_END
546
547 IMPL_STYLE_RULE_INHERIT_MAP_RULE_INFO_INTO(GroupRule, Rule)
548
549 static bool
550 SetStyleSheetReference(Rule* aRule, void* aSheet)
551 {
552 nsCSSStyleSheet* sheet = (nsCSSStyleSheet*)aSheet;
553 aRule->SetStyleSheet(sheet);
554 return true;
555 }
556
557 NS_IMPL_CYCLE_COLLECTION_CLASS(GroupRule)
558
559 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(GroupRule)
560 tmp->mRules.EnumerateForwards(SetParentRuleReference, nullptr);
561 // If tmp does not have a stylesheet, neither do its descendants. In that
562 // case, don't try to null out their stylesheet, to avoid O(N^2) behavior in
563 // depth of group rule nesting. But if tmp _does_ have a stylesheet (which
564 // can happen if it gets unlinked earlier than its owning stylesheet), then we
565 // need to null out the stylesheet pointer on descendants now, before we clear
566 // tmp->mRules.
567 if (tmp->GetStyleSheet()) {
568 tmp->mRules.EnumerateForwards(SetStyleSheetReference, nullptr);
569 }
570 tmp->mRules.Clear();
571 if (tmp->mRuleCollection) {
572 tmp->mRuleCollection->DropReference();
573 tmp->mRuleCollection = nullptr;
574 }
575 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
576
577 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(GroupRule)
578 const nsCOMArray<Rule>& rules = tmp->mRules;
579 for (int32_t i = 0, count = rules.Count(); i < count; ++i) {
580 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mRules[i]");
581 cb.NoteXPCOMChild(rules[i]->GetExistingDOMRule());
582 }
583 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRuleCollection)
584 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
585
586 /* virtual */ void
587 GroupRule::SetStyleSheet(nsCSSStyleSheet* aSheet)
588 {
589 // Don't set the sheet on the kids if it's already the same as the sheet we
590 // already have. This is needed to avoid O(N^2) behavior in group nesting
591 // depth when seting the sheet to null during unlink, if we happen to unlin in
592 // order from most nested rule up to least nested rule.
593 if (aSheet != GetStyleSheet()) {
594 mRules.EnumerateForwards(SetStyleSheetReference, aSheet);
595 Rule::SetStyleSheet(aSheet);
596 }
597 }
598
599 #ifdef DEBUG
600 /* virtual */ void
601 GroupRule::List(FILE* out, int32_t aIndent) const
602 {
603 fputs(" {\n", out);
604
605 for (int32_t index = 0, count = mRules.Count(); index < count; ++index) {
606 mRules.ObjectAt(index)->List(out, aIndent + 1);
607 }
608
609 for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out);
610 fputs("}\n", out);
611 }
612 #endif
613
614 void
615 GroupRule::AppendStyleRule(Rule* aRule)
616 {
617 mRules.AppendObject(aRule);
618 nsCSSStyleSheet* sheet = GetStyleSheet();
619 aRule->SetStyleSheet(sheet);
620 aRule->SetParentRule(this);
621 if (sheet) {
622 sheet->SetModifiedByChildRule();
623 }
624 }
625
626 Rule*
627 GroupRule::GetStyleRuleAt(int32_t aIndex) const
628 {
629 return mRules.SafeObjectAt(aIndex);
630 }
631
632 bool
633 GroupRule::EnumerateRulesForwards(RuleEnumFunc aFunc, void * aData) const
634 {
635 return
636 const_cast<GroupRule*>(this)->mRules.EnumerateForwards(aFunc, aData);
637 }
638
639 /*
640 * The next two methods (DeleteStyleRuleAt and InsertStyleRuleAt)
641 * should never be called unless you have first called WillDirty() on
642 * the parents stylesheet. After they are called, DidDirty() needs to
643 * be called on the sheet
644 */
645 nsresult
646 GroupRule::DeleteStyleRuleAt(uint32_t aIndex)
647 {
648 Rule* rule = mRules.SafeObjectAt(aIndex);
649 if (rule) {
650 rule->SetStyleSheet(nullptr);
651 rule->SetParentRule(nullptr);
652 }
653 return mRules.RemoveObjectAt(aIndex) ? NS_OK : NS_ERROR_ILLEGAL_VALUE;
654 }
655
656 nsresult
657 GroupRule::InsertStyleRuleAt(uint32_t aIndex, Rule* aRule)
658 {
659 aRule->SetStyleSheet(GetStyleSheet());
660 aRule->SetParentRule(this);
661 if (! mRules.InsertObjectAt(aRule, aIndex)) {
662 return NS_ERROR_FAILURE;
663 }
664 return NS_OK;
665 }
666
667 nsresult
668 GroupRule::ReplaceStyleRule(Rule* aOld, Rule* aNew)
669 {
670 int32_t index = mRules.IndexOf(aOld);
671 NS_ENSURE_TRUE(index != -1, NS_ERROR_UNEXPECTED);
672 mRules.ReplaceObjectAt(aNew, index);
673 aNew->SetStyleSheet(GetStyleSheet());
674 aNew->SetParentRule(this);
675 aOld->SetStyleSheet(nullptr);
676 aOld->SetParentRule(nullptr);
677 return NS_OK;
678 }
679
680 void
681 GroupRule::AppendRulesToCssText(nsAString& aCssText)
682 {
683 aCssText.AppendLiteral(" {\n");
684
685 // get all the rules
686 for (int32_t index = 0, count = mRules.Count(); index < count; ++index) {
687 Rule* rule = mRules.ObjectAt(index);
688 nsIDOMCSSRule* domRule = rule->GetDOMRule();
689 if (domRule) {
690 nsAutoString cssText;
691 domRule->GetCssText(cssText);
692 aCssText.Append(NS_LITERAL_STRING(" ") +
693 cssText +
694 NS_LITERAL_STRING("\n"));
695 }
696 }
697
698 aCssText.AppendLiteral("}");
699 }
700
701 // nsIDOMCSSMediaRule or nsIDOMCSSMozDocumentRule methods
702 nsresult
703 GroupRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
704 {
705 if (!mRuleCollection) {
706 mRuleCollection = new css::GroupRuleRuleList(this);
707 }
708
709 NS_ADDREF(*aRuleList = mRuleCollection);
710 return NS_OK;
711 }
712
713 nsresult
714 GroupRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
715 {
716 nsCSSStyleSheet* sheet = GetStyleSheet();
717 NS_ENSURE_TRUE(sheet, NS_ERROR_FAILURE);
718
719 if (aIndex > uint32_t(mRules.Count()))
720 return NS_ERROR_DOM_INDEX_SIZE_ERR;
721
722 NS_ASSERTION(uint32_t(mRules.Count()) <= INT32_MAX,
723 "Too many style rules!");
724
725 return sheet->InsertRuleIntoGroup(aRule, this, aIndex, _retval);
726 }
727
728 nsresult
729 GroupRule::DeleteRule(uint32_t aIndex)
730 {
731 nsCSSStyleSheet* sheet = GetStyleSheet();
732 NS_ENSURE_TRUE(sheet, NS_ERROR_FAILURE);
733
734 if (aIndex >= uint32_t(mRules.Count()))
735 return NS_ERROR_DOM_INDEX_SIZE_ERR;
736
737 NS_ASSERTION(uint32_t(mRules.Count()) <= INT32_MAX,
738 "Too many style rules!");
739
740 return sheet->DeleteRuleFromGroup(this, aIndex);
741 }
742
743 /* virtual */ size_t
744 GroupRule::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
745 {
746 return mRules.SizeOfExcludingThis(Rule::SizeOfCOMArrayElementIncludingThis,
747 aMallocSizeOf);
748
749 // Measurement of the following members may be added later if DMD finds it is
750 // worthwhile:
751 // - mRuleCollection
752 }
753
754
755 // -------------------------------------------
756 // nsICSSMediaRule
757 //
758 MediaRule::MediaRule()
759 {
760 }
761
762 MediaRule::MediaRule(const MediaRule& aCopy)
763 : GroupRule(aCopy)
764 {
765 if (aCopy.mMedia) {
766 mMedia = aCopy.mMedia->Clone();
767 // XXXldb This doesn't really make sense.
768 mMedia->SetStyleSheet(aCopy.GetStyleSheet());
769 }
770 }
771
772 MediaRule::~MediaRule()
773 {
774 if (mMedia) {
775 mMedia->SetStyleSheet(nullptr);
776 }
777 }
778
779 NS_IMPL_ADDREF_INHERITED(MediaRule, GroupRule)
780 NS_IMPL_RELEASE_INHERITED(MediaRule, GroupRule)
781
782 // QueryInterface implementation for MediaRule
783 NS_INTERFACE_MAP_BEGIN(MediaRule)
784 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
785 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
786 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule)
787 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule)
788 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMediaRule)
789 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
790 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSMediaRule)
791 NS_INTERFACE_MAP_END_INHERITING(GroupRule)
792
793 /* virtual */ void
794 MediaRule::SetStyleSheet(nsCSSStyleSheet* aSheet)
795 {
796 if (mMedia) {
797 // Set to null so it knows it's leaving one sheet and joining another.
798 mMedia->SetStyleSheet(nullptr);
799 mMedia->SetStyleSheet(aSheet);
800 }
801
802 GroupRule::SetStyleSheet(aSheet);
803 }
804
805 #ifdef DEBUG
806 /* virtual */ void
807 MediaRule::List(FILE* out, int32_t aIndent) const
808 {
809 for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out);
810
811 nsAutoString buffer;
812
813 fputs("@media ", out);
814
815 if (mMedia) {
816 nsAutoString mediaText;
817 mMedia->GetText(mediaText);
818 fputs(NS_LossyConvertUTF16toASCII(mediaText).get(), out);
819 }
820
821 GroupRule::List(out, aIndent);
822 }
823 #endif
824
825 /* virtual */ int32_t
826 MediaRule::GetType() const
827 {
828 return Rule::MEDIA_RULE;
829 }
830
831 /* virtual */ already_AddRefed<Rule>
832 MediaRule::Clone() const
833 {
834 nsRefPtr<Rule> clone = new MediaRule(*this);
835 return clone.forget();
836 }
837
838 nsresult
839 MediaRule::SetMedia(nsMediaList* aMedia)
840 {
841 mMedia = aMedia;
842 if (aMedia)
843 mMedia->SetStyleSheet(GetStyleSheet());
844 return NS_OK;
845 }
846
847 // nsIDOMCSSRule methods
848 NS_IMETHODIMP
849 MediaRule::GetType(uint16_t* aType)
850 {
851 *aType = nsIDOMCSSRule::MEDIA_RULE;
852 return NS_OK;
853 }
854
855 NS_IMETHODIMP
856 MediaRule::GetCssText(nsAString& aCssText)
857 {
858 aCssText.AssignLiteral("@media ");
859 AppendConditionText(aCssText);
860 GroupRule::AppendRulesToCssText(aCssText);
861 return NS_OK;
862 }
863
864 NS_IMETHODIMP
865 MediaRule::SetCssText(const nsAString& aCssText)
866 {
867 return NS_ERROR_NOT_IMPLEMENTED;
868 }
869
870 NS_IMETHODIMP
871 MediaRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
872 {
873 return GroupRule::GetParentStyleSheet(aSheet);
874 }
875
876 NS_IMETHODIMP
877 MediaRule::GetParentRule(nsIDOMCSSRule** aParentRule)
878 {
879 return GroupRule::GetParentRule(aParentRule);
880 }
881
882 // nsIDOMCSSGroupingRule methods
883 NS_IMETHODIMP
884 MediaRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
885 {
886 return GroupRule::GetCssRules(aRuleList);
887 }
888
889 NS_IMETHODIMP
890 MediaRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
891 {
892 return GroupRule::InsertRule(aRule, aIndex, _retval);
893 }
894
895 NS_IMETHODIMP
896 MediaRule::DeleteRule(uint32_t aIndex)
897 {
898 return GroupRule::DeleteRule(aIndex);
899 }
900
901 // nsIDOMCSSConditionRule methods
902 NS_IMETHODIMP
903 MediaRule::GetConditionText(nsAString& aConditionText)
904 {
905 aConditionText.Truncate(0);
906 AppendConditionText(aConditionText);
907 return NS_OK;
908 }
909
910 NS_IMETHODIMP
911 MediaRule::SetConditionText(const nsAString& aConditionText)
912 {
913 if (!mMedia) {
914 nsRefPtr<nsMediaList> media = new nsMediaList();
915 media->SetStyleSheet(GetStyleSheet());
916 nsresult rv = media->SetMediaText(aConditionText);
917 if (NS_SUCCEEDED(rv)) {
918 mMedia = media;
919 }
920 return rv;
921 }
922
923 return mMedia->SetMediaText(aConditionText);
924 }
925
926 // nsIDOMCSSMediaRule methods
927 NS_IMETHODIMP
928 MediaRule::GetMedia(nsIDOMMediaList* *aMedia)
929 {
930 NS_ENSURE_ARG_POINTER(aMedia);
931 NS_IF_ADDREF(*aMedia = mMedia);
932 return NS_OK;
933 }
934
935 // GroupRule interface
936 /* virtual */ bool
937 MediaRule::UseForPresentation(nsPresContext* aPresContext,
938 nsMediaQueryResultCacheKey& aKey)
939 {
940 if (mMedia) {
941 return mMedia->Matches(aPresContext, &aKey);
942 }
943 return true;
944 }
945
946 /* virtual */ size_t
947 MediaRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
948 {
949 size_t n = aMallocSizeOf(this);
950 n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
951
952 // Measurement of the following members may be added later if DMD finds it is
953 // worthwhile:
954 // - mMedia
955
956 return n;
957 }
958
959 void
960 MediaRule::AppendConditionText(nsAString& aOutput)
961 {
962 if (mMedia) {
963 nsAutoString mediaText;
964 mMedia->GetText(mediaText);
965 aOutput.Append(mediaText);
966 }
967 }
968
969 } // namespace css
970 } // namespace mozilla
971
972 // Must be outside namespace
973 DOMCI_DATA(CSSMediaRule, css::MediaRule)
974
975 namespace mozilla {
976 namespace css {
977
978 DocumentRule::DocumentRule()
979 {
980 }
981
982 DocumentRule::DocumentRule(const DocumentRule& aCopy)
983 : GroupRule(aCopy)
984 , mURLs(new URL(*aCopy.mURLs))
985 {
986 }
987
988 DocumentRule::~DocumentRule()
989 {
990 }
991
992 NS_IMPL_ADDREF_INHERITED(DocumentRule, GroupRule)
993 NS_IMPL_RELEASE_INHERITED(DocumentRule, GroupRule)
994
995 // QueryInterface implementation for DocumentRule
996 NS_INTERFACE_MAP_BEGIN(DocumentRule)
997 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
998 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
999 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule)
1000 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule)
1001 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSMozDocumentRule)
1002 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
1003 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSMozDocumentRule)
1004 NS_INTERFACE_MAP_END_INHERITING(GroupRule)
1005
1006 #ifdef DEBUG
1007 /* virtual */ void
1008 DocumentRule::List(FILE* out, int32_t aIndent) const
1009 {
1010 for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out);
1011
1012 nsAutoCString str;
1013 str.AssignLiteral("@-moz-document ");
1014 for (URL *url = mURLs; url; url = url->next) {
1015 switch (url->func) {
1016 case eURL:
1017 str.AppendLiteral("url(\"");
1018 break;
1019 case eURLPrefix:
1020 str.AppendLiteral("url-prefix(\"");
1021 break;
1022 case eDomain:
1023 str.AppendLiteral("domain(\"");
1024 break;
1025 case eRegExp:
1026 str.AppendLiteral("regexp(\"");
1027 break;
1028 }
1029 nsAutoCString escapedURL(url->url);
1030 escapedURL.ReplaceSubstring("\"", "\\\""); // escape quotes
1031 str.Append(escapedURL);
1032 str.AppendLiteral("\"), ");
1033 }
1034 str.Cut(str.Length() - 2, 1); // remove last ,
1035 fputs(str.get(), out);
1036
1037 GroupRule::List(out, aIndent);
1038 }
1039 #endif
1040
1041 /* virtual */ int32_t
1042 DocumentRule::GetType() const
1043 {
1044 return Rule::DOCUMENT_RULE;
1045 }
1046
1047 /* virtual */ already_AddRefed<Rule>
1048 DocumentRule::Clone() const
1049 {
1050 nsRefPtr<Rule> clone = new DocumentRule(*this);
1051 return clone.forget();
1052 }
1053
1054 // nsIDOMCSSRule methods
1055 NS_IMETHODIMP
1056 DocumentRule::GetType(uint16_t* aType)
1057 {
1058 // XXX What should really happen here?
1059 *aType = nsIDOMCSSRule::UNKNOWN_RULE;
1060 return NS_OK;
1061 }
1062
1063 NS_IMETHODIMP
1064 DocumentRule::GetCssText(nsAString& aCssText)
1065 {
1066 aCssText.AssignLiteral("@-moz-document ");
1067 AppendConditionText(aCssText);
1068 GroupRule::AppendRulesToCssText(aCssText);
1069 return NS_OK;
1070 }
1071
1072 NS_IMETHODIMP
1073 DocumentRule::SetCssText(const nsAString& aCssText)
1074 {
1075 return NS_ERROR_NOT_IMPLEMENTED;
1076 }
1077
1078 NS_IMETHODIMP
1079 DocumentRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
1080 {
1081 return GroupRule::GetParentStyleSheet(aSheet);
1082 }
1083
1084 NS_IMETHODIMP
1085 DocumentRule::GetParentRule(nsIDOMCSSRule** aParentRule)
1086 {
1087 return GroupRule::GetParentRule(aParentRule);
1088 }
1089
1090 // nsIDOMCSSGroupingRule methods
1091 NS_IMETHODIMP
1092 DocumentRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
1093 {
1094 return GroupRule::GetCssRules(aRuleList);
1095 }
1096
1097 NS_IMETHODIMP
1098 DocumentRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
1099 {
1100 return GroupRule::InsertRule(aRule, aIndex, _retval);
1101 }
1102
1103 NS_IMETHODIMP
1104 DocumentRule::DeleteRule(uint32_t aIndex)
1105 {
1106 return GroupRule::DeleteRule(aIndex);
1107 }
1108
1109 // nsIDOMCSSConditionRule methods
1110 NS_IMETHODIMP
1111 DocumentRule::GetConditionText(nsAString& aConditionText)
1112 {
1113 aConditionText.Truncate(0);
1114 AppendConditionText(aConditionText);
1115 return NS_OK;
1116 }
1117
1118 NS_IMETHODIMP
1119 DocumentRule::SetConditionText(const nsAString& aConditionText)
1120 {
1121 return NS_ERROR_NOT_IMPLEMENTED;
1122 }
1123
1124 // GroupRule interface
1125 /* virtual */ bool
1126 DocumentRule::UseForPresentation(nsPresContext* aPresContext,
1127 nsMediaQueryResultCacheKey& aKey)
1128 {
1129 nsIDocument *doc = aPresContext->Document();
1130 nsIURI *docURI = doc->GetDocumentURI();
1131 nsAutoCString docURISpec;
1132 if (docURI)
1133 docURI->GetSpec(docURISpec);
1134
1135 for (URL *url = mURLs; url; url = url->next) {
1136 switch (url->func) {
1137 case eURL: {
1138 if (docURISpec == url->url)
1139 return true;
1140 } break;
1141 case eURLPrefix: {
1142 if (StringBeginsWith(docURISpec, url->url))
1143 return true;
1144 } break;
1145 case eDomain: {
1146 nsAutoCString host;
1147 if (docURI)
1148 docURI->GetHost(host);
1149 int32_t lenDiff = host.Length() - url->url.Length();
1150 if (lenDiff == 0) {
1151 if (host == url->url)
1152 return true;
1153 } else {
1154 if (StringEndsWith(host, url->url) &&
1155 host.CharAt(lenDiff - 1) == '.')
1156 return true;
1157 }
1158 } break;
1159 case eRegExp: {
1160 NS_ConvertUTF8toUTF16 spec(docURISpec);
1161 NS_ConvertUTF8toUTF16 regex(url->url);
1162 if (nsContentUtils::IsPatternMatching(spec, regex, doc)) {
1163 return true;
1164 }
1165 } break;
1166 }
1167 }
1168
1169 return false;
1170 }
1171
1172 DocumentRule::URL::~URL()
1173 {
1174 NS_CSS_DELETE_LIST_MEMBER(DocumentRule::URL, this, next);
1175 }
1176
1177 /* virtual */ size_t
1178 DocumentRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
1179 {
1180 size_t n = aMallocSizeOf(this);
1181 n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
1182
1183 // Measurement of the following members may be added later if DMD finds it is
1184 // worthwhile:
1185 // - mURLs
1186
1187 return n;
1188 }
1189
1190 void
1191 DocumentRule::AppendConditionText(nsAString& aCssText)
1192 {
1193 for (URL *url = mURLs; url; url = url->next) {
1194 switch (url->func) {
1195 case eURL:
1196 aCssText.AppendLiteral("url(");
1197 break;
1198 case eURLPrefix:
1199 aCssText.AppendLiteral("url-prefix(");
1200 break;
1201 case eDomain:
1202 aCssText.AppendLiteral("domain(");
1203 break;
1204 case eRegExp:
1205 aCssText.AppendLiteral("regexp(");
1206 break;
1207 }
1208 nsStyleUtil::AppendEscapedCSSString(NS_ConvertUTF8toUTF16(url->url),
1209 aCssText);
1210 aCssText.AppendLiteral("), ");
1211 }
1212 aCssText.Truncate(aCssText.Length() - 2); // remove last ", "
1213 }
1214
1215 } // namespace css
1216 } // namespace mozilla
1217
1218 // Must be outside namespace
1219 DOMCI_DATA(CSSMozDocumentRule, css::DocumentRule)
1220
1221 // -------------------------------------------
1222 // NameSpaceRule
1223 //
1224
1225 namespace mozilla {
1226 namespace css {
1227
1228 NameSpaceRule::NameSpaceRule(nsIAtom* aPrefix, const nsString& aURLSpec)
1229 : Rule(),
1230 mPrefix(aPrefix),
1231 mURLSpec(aURLSpec)
1232 {
1233 }
1234
1235 NameSpaceRule::NameSpaceRule(const NameSpaceRule& aCopy)
1236 : Rule(aCopy),
1237 mPrefix(aCopy.mPrefix),
1238 mURLSpec(aCopy.mURLSpec)
1239 {
1240 }
1241
1242 NameSpaceRule::~NameSpaceRule()
1243 {
1244 }
1245
1246 NS_IMPL_ADDREF(NameSpaceRule)
1247 NS_IMPL_RELEASE(NameSpaceRule)
1248
1249 // QueryInterface implementation for NameSpaceRule
1250 NS_INTERFACE_MAP_BEGIN(NameSpaceRule)
1251 if (aIID.Equals(NS_GET_IID(css::NameSpaceRule))) {
1252 *aInstancePtr = this;
1253 NS_ADDREF_THIS();
1254 return NS_OK;
1255 }
1256 else
1257 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
1258 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
1259 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
1260 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSNameSpaceRule)
1261 NS_INTERFACE_MAP_END
1262
1263 IMPL_STYLE_RULE_INHERIT(NameSpaceRule, Rule)
1264
1265 #ifdef DEBUG
1266 /* virtual */ void
1267 NameSpaceRule::List(FILE* out, int32_t aIndent) const
1268 {
1269 for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out);
1270
1271 nsAutoString buffer;
1272
1273 fputs("@namespace ", out);
1274
1275 if (mPrefix) {
1276 mPrefix->ToString(buffer);
1277 fputs(NS_LossyConvertUTF16toASCII(buffer).get(), out);
1278 fputs(" ", out);
1279 }
1280
1281 fputs("url(", out);
1282 fputs(NS_LossyConvertUTF16toASCII(mURLSpec).get(), out);
1283 fputs(")\n", out);
1284 }
1285 #endif
1286
1287 /* virtual */ int32_t
1288 NameSpaceRule::GetType() const
1289 {
1290 return Rule::NAMESPACE_RULE;
1291 }
1292
1293 /* virtual */ already_AddRefed<Rule>
1294 NameSpaceRule::Clone() const
1295 {
1296 nsRefPtr<Rule> clone = new NameSpaceRule(*this);
1297 return clone.forget();
1298 }
1299
1300 NS_IMETHODIMP
1301 NameSpaceRule::GetType(uint16_t* aType)
1302 {
1303 *aType = nsIDOMCSSRule::NAMESPACE_RULE;
1304 return NS_OK;
1305 }
1306
1307 NS_IMETHODIMP
1308 NameSpaceRule::GetCssText(nsAString& aCssText)
1309 {
1310 aCssText.AssignLiteral("@namespace ");
1311 if (mPrefix) {
1312 aCssText.Append(nsDependentAtomString(mPrefix) + NS_LITERAL_STRING(" "));
1313 }
1314 aCssText.AppendLiteral("url(");
1315 nsStyleUtil::AppendEscapedCSSString(mURLSpec, aCssText);
1316 aCssText.Append(NS_LITERAL_STRING(");"));
1317 return NS_OK;
1318 }
1319
1320 NS_IMETHODIMP
1321 NameSpaceRule::SetCssText(const nsAString& aCssText)
1322 {
1323 return NS_ERROR_NOT_IMPLEMENTED;
1324 }
1325
1326 NS_IMETHODIMP
1327 NameSpaceRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
1328 {
1329 return Rule::GetParentStyleSheet(aSheet);
1330 }
1331
1332 NS_IMETHODIMP
1333 NameSpaceRule::GetParentRule(nsIDOMCSSRule** aParentRule)
1334 {
1335 return Rule::GetParentRule(aParentRule);
1336 }
1337
1338 /* virtual */ size_t
1339 NameSpaceRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
1340 {
1341 return aMallocSizeOf(this);
1342
1343 // Measurement of the following members may be added later if DMD finds it is
1344 // worthwhile:
1345 // - mPrefix
1346 // - mURLSpec
1347 }
1348
1349
1350 } // namespace css
1351 } // namespace mozilla
1352
1353 // Must be outside namespace
1354 DOMCI_DATA(CSSNameSpaceRule, css::NameSpaceRule)
1355
1356 // -------------------------------------------
1357 // nsCSSFontFaceStyleDecl and related routines
1358 //
1359
1360 // A src: descriptor is represented as an array value; each entry in
1361 // the array can be eCSSUnit_URL, eCSSUnit_Local_Font, or
1362 // eCSSUnit_Font_Format. Blocks of eCSSUnit_Font_Format may appear
1363 // only after one of the first two. (css3-fonts only contemplates
1364 // annotating URLs with formats, but we handle the general case.)
1365 static void
1366 AppendSerializedFontSrc(const nsCSSValue& src, nsAString & aResult)
1367 {
1368 NS_PRECONDITION(src.GetUnit() == eCSSUnit_Array,
1369 "improper value unit for src:");
1370
1371 const nsCSSValue::Array& sources = *src.GetArrayValue();
1372 size_t i = 0;
1373
1374 while (i < sources.Count()) {
1375 nsAutoString formats;
1376
1377 if (sources[i].GetUnit() == eCSSUnit_URL) {
1378 aResult.AppendLiteral("url(");
1379 nsDependentString url(sources[i].GetOriginalURLValue());
1380 nsStyleUtil::AppendEscapedCSSString(url, aResult);
1381 aResult.AppendLiteral(")");
1382 } else if (sources[i].GetUnit() == eCSSUnit_Local_Font) {
1383 aResult.AppendLiteral("local(");
1384 nsDependentString local(sources[i].GetStringBufferValue());
1385 nsStyleUtil::AppendEscapedCSSString(local, aResult);
1386 aResult.AppendLiteral(")");
1387 } else {
1388 NS_NOTREACHED("entry in src: descriptor with improper unit");
1389 i++;
1390 continue;
1391 }
1392
1393 i++;
1394 formats.Truncate();
1395 while (i < sources.Count() &&
1396 sources[i].GetUnit() == eCSSUnit_Font_Format) {
1397 formats.Append('"');
1398 formats.Append(sources[i].GetStringBufferValue());
1399 formats.AppendLiteral("\", ");
1400 i++;
1401 }
1402 if (formats.Length() > 0) {
1403 formats.Truncate(formats.Length() - 2); // remove the last comma
1404 aResult.AppendLiteral(" format(");
1405 aResult.Append(formats);
1406 aResult.Append(')');
1407 }
1408 aResult.AppendLiteral(", ");
1409 }
1410 aResult.Truncate(aResult.Length() - 2); // remove the last comma-space
1411 }
1412
1413 // print all characters with at least four hex digits
1414 static void
1415 AppendSerializedUnicodePoint(uint32_t aCode, nsACString &aBuf)
1416 {
1417 aBuf.Append(nsPrintfCString("%04X", aCode));
1418 }
1419
1420 // A unicode-range: descriptor is represented as an array of integers,
1421 // to be interpreted as a sequence of pairs: min max min max ...
1422 // It is in source order. (Possibly it should be sorted and overlaps
1423 // consolidated, but right now we don't do that.)
1424 static void
1425 AppendSerializedUnicodeRange(nsCSSValue const & aValue,
1426 nsAString & aResult)
1427 {
1428 NS_PRECONDITION(aValue.GetUnit() == eCSSUnit_Null ||
1429 aValue.GetUnit() == eCSSUnit_Array,
1430 "improper value unit for unicode-range:");
1431 aResult.Truncate();
1432 if (aValue.GetUnit() != eCSSUnit_Array)
1433 return;
1434
1435 nsCSSValue::Array const & sources = *aValue.GetArrayValue();
1436 nsAutoCString buf;
1437
1438 NS_ABORT_IF_FALSE(sources.Count() % 2 == 0,
1439 "odd number of entries in a unicode-range: array");
1440
1441 for (uint32_t i = 0; i < sources.Count(); i += 2) {
1442 uint32_t min = sources[i].GetIntValue();
1443 uint32_t max = sources[i+1].GetIntValue();
1444
1445 // We don't try to replicate the U+XX?? notation.
1446 buf.AppendLiteral("U+");
1447 AppendSerializedUnicodePoint(min, buf);
1448
1449 if (min != max) {
1450 buf.Append('-');
1451 AppendSerializedUnicodePoint(max, buf);
1452 }
1453 buf.AppendLiteral(", ");
1454 }
1455 buf.Truncate(buf.Length() - 2); // remove the last comma-space
1456 CopyASCIItoUTF16(buf, aResult);
1457 }
1458
1459 // Mapping from nsCSSFontDesc codes to nsCSSFontFaceStyleDecl fields.
1460 nsCSSValue nsCSSFontFaceStyleDecl::* const
1461 nsCSSFontFaceStyleDecl::Fields[] = {
1462 #define CSS_FONT_DESC(name_, method_) &nsCSSFontFaceStyleDecl::m##method_,
1463 #include "nsCSSFontDescList.h"
1464 #undef CSS_FONT_DESC
1465 };
1466
1467 // QueryInterface implementation for nsCSSFontFaceStyleDecl
1468 NS_INTERFACE_MAP_BEGIN(nsCSSFontFaceStyleDecl)
1469 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
1470 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSStyleDeclaration)
1471 NS_INTERFACE_MAP_ENTRY(nsICSSDeclaration)
1472 NS_INTERFACE_MAP_ENTRY(nsISupports)
1473 // We forward the cycle collection interfaces to ContainingRule(), which is
1474 // never null (in fact, we're part of that object!)
1475 if (aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) ||
1476 aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) {
1477 return ContainingRule()->QueryInterface(aIID, aInstancePtr);
1478 }
1479 else
1480 NS_INTERFACE_MAP_END
1481
1482 NS_IMPL_ADDREF_USING_AGGREGATOR(nsCSSFontFaceStyleDecl, ContainingRule())
1483 NS_IMPL_RELEASE_USING_AGGREGATOR(nsCSSFontFaceStyleDecl, ContainingRule())
1484
1485 // helper for string GetPropertyValue and RemovePropertyValue
1486 nsresult
1487 nsCSSFontFaceStyleDecl::GetPropertyValue(nsCSSFontDesc aFontDescID,
1488 nsAString & aResult) const
1489 {
1490 NS_ENSURE_ARG_RANGE(aFontDescID, eCSSFontDesc_UNKNOWN,
1491 eCSSFontDesc_COUNT - 1);
1492
1493 aResult.Truncate();
1494 if (aFontDescID == eCSSFontDesc_UNKNOWN)
1495 return NS_OK;
1496
1497 const nsCSSValue& val = this->*nsCSSFontFaceStyleDecl::Fields[aFontDescID];
1498
1499 if (val.GetUnit() == eCSSUnit_Null) {
1500 // Avoid having to check no-value in the Family and Src cases below.
1501 return NS_OK;
1502 }
1503
1504 switch (aFontDescID) {
1505 case eCSSFontDesc_Family: {
1506 // we don't use nsCSSValue::AppendToString here because it doesn't
1507 // canonicalize the way we want, and anyway it's overkill when
1508 // we know we have eCSSUnit_String
1509 NS_ASSERTION(val.GetUnit() == eCSSUnit_String, "unexpected unit");
1510 nsDependentString family(val.GetStringBufferValue());
1511 nsStyleUtil::AppendEscapedCSSString(family, aResult);
1512 return NS_OK;
1513 }
1514
1515 case eCSSFontDesc_Style:
1516 val.AppendToString(eCSSProperty_font_style, aResult,
1517 nsCSSValue::eNormalized);
1518 return NS_OK;
1519
1520 case eCSSFontDesc_Weight:
1521 val.AppendToString(eCSSProperty_font_weight, aResult,
1522 nsCSSValue::eNormalized);
1523 return NS_OK;
1524
1525 case eCSSFontDesc_Stretch:
1526 val.AppendToString(eCSSProperty_font_stretch, aResult,
1527 nsCSSValue::eNormalized);
1528 return NS_OK;
1529
1530 case eCSSFontDesc_FontFeatureSettings:
1531 nsStyleUtil::AppendFontFeatureSettings(val, aResult);
1532 return NS_OK;
1533
1534 case eCSSFontDesc_FontLanguageOverride:
1535 val.AppendToString(eCSSProperty_font_language_override, aResult,
1536 nsCSSValue::eNormalized);
1537 return NS_OK;
1538
1539 case eCSSFontDesc_Src:
1540 AppendSerializedFontSrc(val, aResult);
1541 return NS_OK;
1542
1543 case eCSSFontDesc_UnicodeRange:
1544 AppendSerializedUnicodeRange(val, aResult);
1545 return NS_OK;
1546
1547 case eCSSFontDesc_UNKNOWN:
1548 case eCSSFontDesc_COUNT:
1549 ;
1550 }
1551 NS_NOTREACHED("nsCSSFontFaceStyleDecl::GetPropertyValue: "
1552 "out-of-range value got to the switch");
1553 return NS_ERROR_INVALID_ARG;
1554 }
1555
1556
1557 // attribute DOMString cssText;
1558 NS_IMETHODIMP
1559 nsCSSFontFaceStyleDecl::GetCssText(nsAString & aCssText)
1560 {
1561 nsAutoString descStr;
1562
1563 aCssText.Truncate();
1564 for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
1565 id < eCSSFontDesc_COUNT;
1566 id = nsCSSFontDesc(id + 1)) {
1567 if ((this->*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit()
1568 != eCSSUnit_Null &&
1569 NS_SUCCEEDED(GetPropertyValue(id, descStr))) {
1570 NS_ASSERTION(descStr.Length() > 0,
1571 "GetCssText: non-null unit, empty property value");
1572 aCssText.AppendLiteral(" ");
1573 aCssText.AppendASCII(nsCSSProps::GetStringValue(id).get());
1574 aCssText.AppendLiteral(": ");
1575 aCssText.Append(descStr);
1576 aCssText.AppendLiteral(";\n");
1577 }
1578 }
1579 return NS_OK;
1580 }
1581
1582 NS_IMETHODIMP
1583 nsCSSFontFaceStyleDecl::SetCssText(const nsAString & aCssText)
1584 {
1585 return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
1586 }
1587
1588 // DOMString getPropertyValue (in DOMString propertyName);
1589 NS_IMETHODIMP
1590 nsCSSFontFaceStyleDecl::GetPropertyValue(const nsAString & propertyName,
1591 nsAString & aResult)
1592 {
1593 return GetPropertyValue(nsCSSProps::LookupFontDesc(propertyName), aResult);
1594 }
1595
1596 NS_IMETHODIMP
1597 nsCSSFontFaceStyleDecl::GetAuthoredPropertyValue(const nsAString& propertyName,
1598 nsAString& aResult)
1599 {
1600 // We don't return any authored property values different from
1601 // GetPropertyValue, currently.
1602 return GetPropertyValue(nsCSSProps::LookupFontDesc(propertyName), aResult);
1603 }
1604
1605 // nsIDOMCSSValue getPropertyCSSValue (in DOMString propertyName);
1606 already_AddRefed<dom::CSSValue>
1607 nsCSSFontFaceStyleDecl::GetPropertyCSSValue(const nsAString & propertyName,
1608 ErrorResult& aRv)
1609 {
1610 // ??? nsDOMCSSDeclaration returns null/NS_OK, but that seems wrong.
1611 aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
1612 return nullptr;
1613 }
1614
1615 // DOMString removeProperty (in DOMString propertyName) raises (DOMException);
1616 NS_IMETHODIMP
1617 nsCSSFontFaceStyleDecl::RemoveProperty(const nsAString & propertyName,
1618 nsAString & aResult)
1619 {
1620 nsCSSFontDesc descID = nsCSSProps::LookupFontDesc(propertyName);
1621 NS_ASSERTION(descID >= eCSSFontDesc_UNKNOWN &&
1622 descID < eCSSFontDesc_COUNT,
1623 "LookupFontDesc returned value out of range");
1624
1625 if (descID == eCSSFontDesc_UNKNOWN) {
1626 aResult.Truncate();
1627 } else {
1628 nsresult rv = GetPropertyValue(descID, aResult);
1629 NS_ENSURE_SUCCESS(rv, rv);
1630 (this->*nsCSSFontFaceStyleDecl::Fields[descID]).Reset();
1631 }
1632 return NS_OK;
1633 }
1634
1635 // DOMString getPropertyPriority (in DOMString propertyName);
1636 NS_IMETHODIMP
1637 nsCSSFontFaceStyleDecl::GetPropertyPriority(const nsAString & propertyName,
1638 nsAString & aResult)
1639 {
1640 // font descriptors do not have priorities at present
1641 aResult.Truncate();
1642 return NS_OK;
1643 }
1644
1645 // void setProperty (in DOMString propertyName, in DOMString value,
1646 // in DOMString priority) raises (DOMException);
1647 NS_IMETHODIMP
1648 nsCSSFontFaceStyleDecl::SetProperty(const nsAString & propertyName,
1649 const nsAString & value,
1650 const nsAString & priority)
1651 {
1652 return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
1653 }
1654
1655 // readonly attribute unsigned long length;
1656 NS_IMETHODIMP
1657 nsCSSFontFaceStyleDecl::GetLength(uint32_t *aLength)
1658 {
1659 uint32_t len = 0;
1660 for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
1661 id < eCSSFontDesc_COUNT;
1662 id = nsCSSFontDesc(id + 1))
1663 if ((this->*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit() != eCSSUnit_Null)
1664 len++;
1665
1666 *aLength = len;
1667 return NS_OK;
1668 }
1669
1670 // DOMString item (in unsigned long index);
1671 NS_IMETHODIMP
1672 nsCSSFontFaceStyleDecl::Item(uint32_t aIndex, nsAString& aReturn)
1673 {
1674 bool found;
1675 IndexedGetter(aIndex, found, aReturn);
1676 if (!found) {
1677 aReturn.Truncate();
1678 }
1679 return NS_OK;
1680 }
1681
1682 void
1683 nsCSSFontFaceStyleDecl::IndexedGetter(uint32_t index, bool& aFound, nsAString & aResult)
1684 {
1685 int32_t nset = -1;
1686 for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
1687 id < eCSSFontDesc_COUNT;
1688 id = nsCSSFontDesc(id + 1)) {
1689 if ((this->*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit()
1690 != eCSSUnit_Null) {
1691 nset++;
1692 if (nset == int32_t(index)) {
1693 aFound = true;
1694 aResult.AssignASCII(nsCSSProps::GetStringValue(id).get());
1695 return;
1696 }
1697 }
1698 }
1699 aFound = false;
1700 }
1701
1702 // readonly attribute nsIDOMCSSRule parentRule;
1703 NS_IMETHODIMP
1704 nsCSSFontFaceStyleDecl::GetParentRule(nsIDOMCSSRule** aParentRule)
1705 {
1706 NS_IF_ADDREF(*aParentRule = ContainingRule()->GetDOMRule());
1707 return NS_OK;
1708 }
1709
1710 NS_IMETHODIMP
1711 nsCSSFontFaceStyleDecl::GetPropertyValue(const nsCSSProperty aPropID,
1712 nsAString& aValue)
1713 {
1714 return
1715 GetPropertyValue(NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(aPropID)),
1716 aValue);
1717 }
1718
1719 NS_IMETHODIMP
1720 nsCSSFontFaceStyleDecl::SetPropertyValue(const nsCSSProperty aPropID,
1721 const nsAString& aValue)
1722 {
1723 return SetProperty(NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(aPropID)),
1724 aValue, EmptyString());
1725 }
1726
1727 nsINode*
1728 nsCSSFontFaceStyleDecl::GetParentObject()
1729 {
1730 return ContainingRule()->GetDocument();
1731 }
1732
1733 JSObject*
1734 nsCSSFontFaceStyleDecl::WrapObject(JSContext *cx)
1735 {
1736 return mozilla::dom::CSSStyleDeclarationBinding::Wrap(cx, this);
1737 }
1738
1739 // -------------------------------------------
1740 // nsCSSFontFaceRule
1741 //
1742
1743 /* virtual */ already_AddRefed<css::Rule>
1744 nsCSSFontFaceRule::Clone() const
1745 {
1746 nsRefPtr<css::Rule> clone = new nsCSSFontFaceRule(*this);
1747 return clone.forget();
1748 }
1749
1750 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSFontFaceRule)
1751 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSFontFaceRule)
1752
1753 NS_IMPL_CYCLE_COLLECTION_CLASS(nsCSSFontFaceRule)
1754
1755 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsCSSFontFaceRule)
1756 // Trace the wrapper for our declaration. This just expands out
1757 // NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER which we can't use
1758 // directly because the wrapper is on the declaration, not on us.
1759 tmp->mDecl.TraceWrapper(aCallbacks, aClosure);
1760 NS_IMPL_CYCLE_COLLECTION_TRACE_END
1761
1762 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCSSFontFaceRule)
1763 // Unlink the wrapper for our declaraton. This just expands out
1764 // NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER which we can't use
1765 // directly because the wrapper is on the declaration, not on us.
1766 tmp->mDecl.ReleaseWrapper(static_cast<nsISupports*>(p));
1767 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
1768
1769 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCSSFontFaceRule)
1770 // Just NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS here: that will call
1771 // into our Trace hook, where we do the right thing with declarations
1772 // already.
1773 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
1774 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
1775
1776 DOMCI_DATA(CSSFontFaceRule, nsCSSFontFaceRule)
1777
1778 // QueryInterface implementation for nsCSSFontFaceRule
1779 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSFontFaceRule)
1780 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
1781 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSFontFaceRule)
1782 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
1783 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
1784 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSFontFaceRule)
1785 NS_INTERFACE_MAP_END
1786
1787 IMPL_STYLE_RULE_INHERIT(nsCSSFontFaceRule, Rule)
1788
1789 #ifdef DEBUG
1790 void
1791 nsCSSFontFaceRule::List(FILE* out, int32_t aIndent) const
1792 {
1793 nsCString baseInd, descInd;
1794 for (int32_t indent = aIndent; --indent >= 0; ) {
1795 baseInd.AppendLiteral(" ");
1796 descInd.AppendLiteral(" ");
1797 }
1798 descInd.AppendLiteral(" ");
1799
1800 nsString descStr;
1801
1802 fprintf(out, "%s@font-face {\n", baseInd.get());
1803 for (nsCSSFontDesc id = nsCSSFontDesc(eCSSFontDesc_UNKNOWN + 1);
1804 id < eCSSFontDesc_COUNT;
1805 id = nsCSSFontDesc(id + 1))
1806 if ((mDecl.*nsCSSFontFaceStyleDecl::Fields[id]).GetUnit()
1807 != eCSSUnit_Null) {
1808 if (NS_FAILED(mDecl.GetPropertyValue(id, descStr)))
1809 descStr.AssignLiteral("#<serialization error>");
1810 else if (descStr.Length() == 0)
1811 descStr.AssignLiteral("#<serialization missing>");
1812 fprintf(out, "%s%s: %s\n",
1813 descInd.get(), nsCSSProps::GetStringValue(id).get(),
1814 NS_ConvertUTF16toUTF8(descStr).get());
1815 }
1816 fprintf(out, "%s}\n", baseInd.get());
1817 }
1818 #endif
1819
1820 /* virtual */ int32_t
1821 nsCSSFontFaceRule::GetType() const
1822 {
1823 return Rule::FONT_FACE_RULE;
1824 }
1825
1826 NS_IMETHODIMP
1827 nsCSSFontFaceRule::GetType(uint16_t* aType)
1828 {
1829 *aType = nsIDOMCSSRule::FONT_FACE_RULE;
1830 return NS_OK;
1831 }
1832
1833 NS_IMETHODIMP
1834 nsCSSFontFaceRule::GetCssText(nsAString& aCssText)
1835 {
1836 nsAutoString propText;
1837 mDecl.GetCssText(propText);
1838
1839 aCssText.AssignLiteral("@font-face {\n");
1840 aCssText.Append(propText);
1841 aCssText.Append('}');
1842 return NS_OK;
1843 }
1844
1845 NS_IMETHODIMP
1846 nsCSSFontFaceRule::SetCssText(const nsAString& aCssText)
1847 {
1848 return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
1849 }
1850
1851 NS_IMETHODIMP
1852 nsCSSFontFaceRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
1853 {
1854 return Rule::GetParentStyleSheet(aSheet);
1855 }
1856
1857 NS_IMETHODIMP
1858 nsCSSFontFaceRule::GetParentRule(nsIDOMCSSRule** aParentRule)
1859 {
1860 return Rule::GetParentRule(aParentRule);
1861 }
1862
1863 NS_IMETHODIMP
1864 nsCSSFontFaceRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
1865 {
1866 NS_IF_ADDREF(*aStyle = &mDecl);
1867 return NS_OK;
1868 }
1869
1870 // Arguably these should forward to nsCSSFontFaceStyleDecl methods.
1871 void
1872 nsCSSFontFaceRule::SetDesc(nsCSSFontDesc aDescID, nsCSSValue const & aValue)
1873 {
1874 NS_PRECONDITION(aDescID > eCSSFontDesc_UNKNOWN &&
1875 aDescID < eCSSFontDesc_COUNT,
1876 "aDescID out of range in nsCSSFontFaceRule::SetDesc");
1877
1878 // FIXME: handle dynamic changes
1879
1880 mDecl.*nsCSSFontFaceStyleDecl::Fields[aDescID] = aValue;
1881 }
1882
1883 void
1884 nsCSSFontFaceRule::GetDesc(nsCSSFontDesc aDescID, nsCSSValue & aValue)
1885 {
1886 NS_PRECONDITION(aDescID > eCSSFontDesc_UNKNOWN &&
1887 aDescID < eCSSFontDesc_COUNT,
1888 "aDescID out of range in nsCSSFontFaceRule::GetDesc");
1889
1890 aValue = mDecl.*nsCSSFontFaceStyleDecl::Fields[aDescID];
1891 }
1892
1893 /* virtual */ size_t
1894 nsCSSFontFaceRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
1895 {
1896 return aMallocSizeOf(this);
1897
1898 // Measurement of the following members may be added later if DMD finds it is
1899 // worthwhile:
1900 // - mDecl
1901 }
1902
1903
1904 // -----------------------------------
1905 // nsCSSFontFeatureValuesRule
1906 //
1907
1908 /* virtual */ already_AddRefed<css::Rule>
1909 nsCSSFontFeatureValuesRule::Clone() const
1910 {
1911 nsRefPtr<css::Rule> clone = new nsCSSFontFeatureValuesRule(*this);
1912 return clone.forget();
1913 }
1914
1915 NS_IMPL_ADDREF(nsCSSFontFeatureValuesRule)
1916 NS_IMPL_RELEASE(nsCSSFontFeatureValuesRule)
1917
1918 DOMCI_DATA(CSSFontFeatureValuesRule, nsCSSFontFeatureValuesRule)
1919
1920 // QueryInterface implementation for nsCSSFontFeatureValuesRule
1921 NS_INTERFACE_MAP_BEGIN(nsCSSFontFeatureValuesRule)
1922 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
1923 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSFontFeatureValuesRule)
1924 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
1925 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
1926 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSFontFeatureValuesRule)
1927 NS_INTERFACE_MAP_END
1928
1929 IMPL_STYLE_RULE_INHERIT(nsCSSFontFeatureValuesRule, Rule)
1930
1931 static void
1932 FamilyListToString(const nsTArray<nsString>& aFamilyList, nsAString& aOutStr)
1933 {
1934 uint32_t i, n = aFamilyList.Length();
1935
1936 for (i = 0; i < n; i++) {
1937 nsStyleUtil::AppendEscapedCSSString(aFamilyList[i], aOutStr);
1938 if (i != n - 1) {
1939 aOutStr.AppendLiteral(", ");
1940 }
1941 }
1942 }
1943
1944 static void
1945 FeatureValuesToString(
1946 const nsTArray<gfxFontFeatureValueSet::FeatureValues>& aFeatureValues,
1947 nsAString& aOutStr)
1948 {
1949 uint32_t i, n;
1950
1951 // append values
1952 n = aFeatureValues.Length();
1953 for (i = 0; i < n; i++) {
1954 const gfxFontFeatureValueSet::FeatureValues& fv = aFeatureValues[i];
1955
1956 // @alternate
1957 aOutStr.AppendLiteral(" @");
1958 nsAutoString functAlt;
1959 nsStyleUtil::GetFunctionalAlternatesName(fv.alternate, functAlt);
1960 aOutStr.Append(functAlt);
1961 aOutStr.AppendLiteral(" {");
1962
1963 // for each ident-values tuple
1964 uint32_t j, numValues = fv.valuelist.Length();
1965 for (j = 0; j < numValues; j++) {
1966 aOutStr.AppendLiteral(" ");
1967 const gfxFontFeatureValueSet::ValueList& vlist = fv.valuelist[j];
1968 nsStyleUtil::AppendEscapedCSSIdent(vlist.name, aOutStr);
1969 aOutStr.AppendLiteral(":");
1970
1971 uint32_t k, numSelectors = vlist.featureSelectors.Length();
1972 for (k = 0; k < numSelectors; k++) {
1973 aOutStr.AppendLiteral(" ");
1974 aOutStr.AppendInt(vlist.featureSelectors[k]);
1975 }
1976
1977 aOutStr.AppendLiteral(";");
1978 }
1979 aOutStr.AppendLiteral(" }\n");
1980 }
1981 }
1982
1983 static void
1984 FontFeatureValuesRuleToString(
1985 const nsTArray<nsString>& aFamilyList,
1986 const nsTArray<gfxFontFeatureValueSet::FeatureValues>& aFeatureValues,
1987 nsAString& aOutStr)
1988 {
1989 aOutStr.AssignLiteral("@font-feature-values ");
1990 nsAutoString familyListStr, valueTextStr;
1991 FamilyListToString(aFamilyList, familyListStr);
1992 aOutStr.Append(familyListStr);
1993 aOutStr.AppendLiteral(" {\n");
1994 FeatureValuesToString(aFeatureValues, valueTextStr);
1995 aOutStr.Append(valueTextStr);
1996 aOutStr.AppendLiteral("}");
1997 }
1998
1999 #ifdef DEBUG
2000 void
2001 nsCSSFontFeatureValuesRule::List(FILE* out, int32_t aIndent) const
2002 {
2003 nsAutoString text;
2004 FontFeatureValuesRuleToString(mFamilyList, mFeatureValues, text);
2005 NS_ConvertUTF16toUTF8 utf8(text);
2006
2007 // replace newlines with newlines plus indent spaces
2008 char* indent = new char[(aIndent + 1) * 2];
2009 int32_t i;
2010 for (i = 1; i < (aIndent + 1) * 2 - 1; i++) {
2011 indent[i] = 0x20;
2012 }
2013 indent[0] = 0xa;
2014 indent[aIndent * 2 + 1] = 0;
2015 utf8.ReplaceSubstring("\n", indent);
2016 delete [] indent;
2017
2018 for (i = aIndent; --i >= 0; ) fputs(" ", out);
2019 fprintf(out, "%s\n", utf8.get());
2020 }
2021 #endif
2022
2023 /* virtual */ int32_t
2024 nsCSSFontFeatureValuesRule::GetType() const
2025 {
2026 return Rule::FONT_FEATURE_VALUES_RULE;
2027 }
2028
2029 NS_IMETHODIMP
2030 nsCSSFontFeatureValuesRule::GetType(uint16_t* aType)
2031 {
2032 *aType = nsIDOMCSSRule::FONT_FEATURE_VALUES_RULE;
2033 return NS_OK;
2034 }
2035
2036 NS_IMETHODIMP
2037 nsCSSFontFeatureValuesRule::GetCssText(nsAString& aCssText)
2038 {
2039 FontFeatureValuesRuleToString(mFamilyList, mFeatureValues, aCssText);
2040 return NS_OK;
2041 }
2042
2043 NS_IMETHODIMP
2044 nsCSSFontFeatureValuesRule::SetCssText(const nsAString& aCssText)
2045 {
2046 // FIXME: implement???
2047 return NS_ERROR_NOT_IMPLEMENTED;
2048 }
2049
2050 NS_IMETHODIMP
2051 nsCSSFontFeatureValuesRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
2052 {
2053 return Rule::GetParentStyleSheet(aSheet);
2054 }
2055
2056 NS_IMETHODIMP
2057 nsCSSFontFeatureValuesRule::GetParentRule(nsIDOMCSSRule** aParentRule)
2058 {
2059 return Rule::GetParentRule(aParentRule);
2060 }
2061
2062 NS_IMETHODIMP
2063 nsCSSFontFeatureValuesRule::GetFontFamily(nsAString& aFontFamily)
2064 {
2065 FamilyListToString(mFamilyList, aFontFamily);
2066 return NS_OK;
2067 }
2068
2069 NS_IMETHODIMP
2070 nsCSSFontFeatureValuesRule::SetFontFamily(const nsAString& aFontFamily)
2071 {
2072 return NS_ERROR_NOT_IMPLEMENTED;
2073 }
2074
2075 NS_IMETHODIMP
2076 nsCSSFontFeatureValuesRule::GetValueText(nsAString& aValueText)
2077 {
2078 FeatureValuesToString(mFeatureValues, aValueText);
2079 return NS_OK;
2080 }
2081
2082 NS_IMETHODIMP
2083 nsCSSFontFeatureValuesRule::SetValueText(const nsAString& aValueText)
2084 {
2085 return NS_ERROR_NOT_IMPLEMENTED;
2086 }
2087
2088 struct MakeFamilyArray {
2089 MakeFamilyArray(nsTArray<nsString>& aFamilyArray)
2090 : familyArray(aFamilyArray), hasGeneric(false)
2091 {}
2092
2093 static bool
2094 AddFamily(const nsString& aFamily, bool aGeneric, void* aData)
2095 {
2096 MakeFamilyArray *familyArr = reinterpret_cast<MakeFamilyArray*> (aData);
2097 if (!aGeneric && !aFamily.IsEmpty()) {
2098 familyArr->familyArray.AppendElement(aFamily);
2099 }
2100 if (aGeneric) {
2101 familyArr->hasGeneric = true;
2102 }
2103 return true;
2104 }
2105
2106 nsTArray<nsString>& familyArray;
2107 bool hasGeneric;
2108 };
2109
2110 void
2111 nsCSSFontFeatureValuesRule::SetFamilyList(const nsAString& aFamilyList,
2112 bool& aContainsGeneric)
2113 {
2114 nsFont font(aFamilyList, 0, 0, 0, 0, 0, 0);
2115 MakeFamilyArray families(mFamilyList);
2116 font.EnumerateFamilies(MakeFamilyArray::AddFamily, (void*) &families);
2117 aContainsGeneric = families.hasGeneric;
2118 }
2119
2120 void
2121 nsCSSFontFeatureValuesRule::AddValueList(int32_t aVariantAlternate,
2122 nsTArray<gfxFontFeatureValueSet::ValueList>& aValueList)
2123 {
2124 uint32_t i, len = mFeatureValues.Length();
2125 bool foundAlternate = false;
2126
2127 // add to an existing list for a given property value
2128 for (i = 0; i < len; i++) {
2129 gfxFontFeatureValueSet::FeatureValues& f = mFeatureValues.ElementAt(i);
2130
2131 if (f.alternate == uint32_t(aVariantAlternate)) {
2132 f.valuelist.AppendElements(aValueList);
2133 foundAlternate = true;
2134 break;
2135 }
2136 }
2137
2138 // create a new list for a given property value
2139 if (!foundAlternate) {
2140 gfxFontFeatureValueSet::FeatureValues &f = *mFeatureValues.AppendElement();
2141 f.alternate = aVariantAlternate;
2142 f.valuelist.AppendElements(aValueList);
2143 }
2144 }
2145
2146 size_t
2147 nsCSSFontFeatureValuesRule::SizeOfIncludingThis(
2148 MallocSizeOf aMallocSizeOf) const
2149 {
2150 return aMallocSizeOf(this);
2151 }
2152
2153 // -------------------------------------------
2154 // nsCSSKeyframeStyleDeclaration
2155 //
2156
2157 nsCSSKeyframeStyleDeclaration::nsCSSKeyframeStyleDeclaration(nsCSSKeyframeRule *aRule)
2158 : mRule(aRule)
2159 {
2160 }
2161
2162 nsCSSKeyframeStyleDeclaration::~nsCSSKeyframeStyleDeclaration()
2163 {
2164 NS_ASSERTION(!mRule, "DropReference not called.");
2165 }
2166
2167 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSKeyframeStyleDeclaration)
2168 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSKeyframeStyleDeclaration)
2169
2170 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsCSSKeyframeStyleDeclaration)
2171
2172 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSKeyframeStyleDeclaration)
2173 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
2174 NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration)
2175
2176 css::Declaration*
2177 nsCSSKeyframeStyleDeclaration::GetCSSDeclaration(bool aAllocate)
2178 {
2179 if (mRule) {
2180 return mRule->Declaration();
2181 } else {
2182 return nullptr;
2183 }
2184 }
2185
2186 void
2187 nsCSSKeyframeStyleDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
2188 {
2189 GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv);
2190 }
2191
2192 NS_IMETHODIMP
2193 nsCSSKeyframeStyleDeclaration::GetParentRule(nsIDOMCSSRule **aParent)
2194 {
2195 NS_ENSURE_ARG_POINTER(aParent);
2196
2197 NS_IF_ADDREF(*aParent = mRule);
2198 return NS_OK;
2199 }
2200
2201 nsresult
2202 nsCSSKeyframeStyleDeclaration::SetCSSDeclaration(css::Declaration* aDecl)
2203 {
2204 NS_ABORT_IF_FALSE(aDecl, "must be non-null");
2205 mRule->ChangeDeclaration(aDecl);
2206 return NS_OK;
2207 }
2208
2209 nsIDocument*
2210 nsCSSKeyframeStyleDeclaration::DocToUpdate()
2211 {
2212 return nullptr;
2213 }
2214
2215 nsINode*
2216 nsCSSKeyframeStyleDeclaration::GetParentObject()
2217 {
2218 return mRule ? mRule->GetDocument() : nullptr;
2219 }
2220
2221 // -------------------------------------------
2222 // nsCSSKeyframeRule
2223 //
2224
2225 nsCSSKeyframeRule::nsCSSKeyframeRule(const nsCSSKeyframeRule& aCopy)
2226 // copy everything except our reference count and mDOMDeclaration
2227 : Rule(aCopy)
2228 , mKeys(aCopy.mKeys)
2229 , mDeclaration(new css::Declaration(*aCopy.mDeclaration))
2230 {
2231 }
2232
2233 nsCSSKeyframeRule::~nsCSSKeyframeRule()
2234 {
2235 if (mDOMDeclaration) {
2236 mDOMDeclaration->DropReference();
2237 }
2238 }
2239
2240 /* virtual */ already_AddRefed<css::Rule>
2241 nsCSSKeyframeRule::Clone() const
2242 {
2243 nsRefPtr<css::Rule> clone = new nsCSSKeyframeRule(*this);
2244 return clone.forget();
2245 }
2246
2247 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSKeyframeRule)
2248 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSKeyframeRule)
2249
2250 NS_IMPL_CYCLE_COLLECTION_CLASS(nsCSSKeyframeRule)
2251
2252 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCSSKeyframeRule)
2253 if (tmp->mDOMDeclaration) {
2254 tmp->mDOMDeclaration->DropReference();
2255 tmp->mDOMDeclaration = nullptr;
2256 }
2257 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
2258 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCSSKeyframeRule)
2259 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMDeclaration)
2260 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
2261
2262 DOMCI_DATA(MozCSSKeyframeRule, nsCSSKeyframeRule)
2263
2264 // QueryInterface implementation for nsCSSKeyframeRule
2265 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSKeyframeRule)
2266 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
2267 NS_INTERFACE_MAP_ENTRY(nsIDOMMozCSSKeyframeRule)
2268 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
2269 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
2270 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozCSSKeyframeRule)
2271 NS_INTERFACE_MAP_END
2272
2273 IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(nsCSSKeyframeRule, Rule)
2274
2275 /* virtual */ void
2276 nsCSSKeyframeRule::MapRuleInfoInto(nsRuleData* aRuleData)
2277 {
2278 // We need to implement MapRuleInfoInto because the animation manager
2279 // constructs a rule node pointing to us in order to compute the
2280 // styles it needs to animate.
2281
2282 // The spec says that !important declarations should just be ignored
2283 NS_ASSERTION(!mDeclaration->HasImportantData(),
2284 "Keyframe rules has !important data");
2285
2286 mDeclaration->MapNormalRuleInfoInto(aRuleData);
2287 }
2288
2289 #ifdef DEBUG
2290 void
2291 nsCSSKeyframeRule::List(FILE* out, int32_t aIndent) const
2292 {
2293 for (int32_t index = aIndent; --index >= 0; ) fputs(" ", out);
2294
2295 nsAutoString tmp;
2296 DoGetKeyText(tmp);
2297 fputs(NS_ConvertUTF16toUTF8(tmp).get(), out);
2298 fputs(" ", out);
2299 mDeclaration->List(out, aIndent);
2300 fputs("\n", out);
2301 }
2302 #endif
2303
2304 /* virtual */ int32_t
2305 nsCSSKeyframeRule::GetType() const
2306 {
2307 return Rule::KEYFRAME_RULE;
2308 }
2309
2310 NS_IMETHODIMP
2311 nsCSSKeyframeRule::GetType(uint16_t* aType)
2312 {
2313 *aType = nsIDOMCSSRule::KEYFRAME_RULE;
2314 return NS_OK;
2315 }
2316
2317 NS_IMETHODIMP
2318 nsCSSKeyframeRule::GetCssText(nsAString& aCssText)
2319 {
2320 DoGetKeyText(aCssText);
2321 aCssText.AppendLiteral(" { ");
2322 nsAutoString tmp;
2323 mDeclaration->ToString(tmp);
2324 aCssText.Append(tmp);
2325 aCssText.AppendLiteral(" }");
2326 return NS_OK;
2327 }
2328
2329 NS_IMETHODIMP
2330 nsCSSKeyframeRule::SetCssText(const nsAString& aCssText)
2331 {
2332 // FIXME: implement???
2333 return NS_ERROR_NOT_IMPLEMENTED;
2334 }
2335
2336 NS_IMETHODIMP
2337 nsCSSKeyframeRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
2338 {
2339 return Rule::GetParentStyleSheet(aSheet);
2340 }
2341
2342 NS_IMETHODIMP
2343 nsCSSKeyframeRule::GetParentRule(nsIDOMCSSRule** aParentRule)
2344 {
2345 return Rule::GetParentRule(aParentRule);
2346 }
2347
2348 NS_IMETHODIMP
2349 nsCSSKeyframeRule::GetKeyText(nsAString& aKeyText)
2350 {
2351 DoGetKeyText(aKeyText);
2352 return NS_OK;
2353 }
2354
2355 void
2356 nsCSSKeyframeRule::DoGetKeyText(nsAString& aKeyText) const
2357 {
2358 aKeyText.Truncate();
2359 uint32_t i = 0, i_end = mKeys.Length();
2360 NS_ABORT_IF_FALSE(i_end != 0, "must have some keys");
2361 for (;;) {
2362 aKeyText.AppendFloat(mKeys[i] * 100.0f);
2363 aKeyText.Append(char16_t('%'));
2364 if (++i == i_end) {
2365 break;
2366 }
2367 aKeyText.AppendLiteral(", ");
2368 }
2369 }
2370
2371 NS_IMETHODIMP
2372 nsCSSKeyframeRule::SetKeyText(const nsAString& aKeyText)
2373 {
2374 nsCSSParser parser;
2375
2376 InfallibleTArray<float> newSelectors;
2377 // FIXME: pass filename and line number
2378 if (!parser.ParseKeyframeSelectorString(aKeyText, nullptr, 0, newSelectors)) {
2379 // for now, we don't do anything if the parse fails
2380 return NS_OK;
2381 }
2382
2383 nsIDocument* doc = GetDocument();
2384 MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
2385
2386 newSelectors.SwapElements(mKeys);
2387
2388 nsCSSStyleSheet* sheet = GetStyleSheet();
2389 if (sheet) {
2390 sheet->SetModifiedByChildRule();
2391
2392 if (doc) {
2393 doc->StyleRuleChanged(sheet, this, this);
2394 }
2395 }
2396
2397 return NS_OK;
2398 }
2399
2400 NS_IMETHODIMP
2401 nsCSSKeyframeRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
2402 {
2403 if (!mDOMDeclaration) {
2404 mDOMDeclaration = new nsCSSKeyframeStyleDeclaration(this);
2405 }
2406 NS_ADDREF(*aStyle = mDOMDeclaration);
2407 return NS_OK;
2408 }
2409
2410 void
2411 nsCSSKeyframeRule::ChangeDeclaration(css::Declaration* aDeclaration)
2412 {
2413 // Our caller already did a BeginUpdate/EndUpdate, but with
2414 // UPDATE_CONTENT, and we need UPDATE_STYLE to trigger work in
2415 // PresShell::EndUpdate.
2416 nsIDocument* doc = GetDocument();
2417 MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
2418
2419 // Be careful to not assign to an nsAutoPtr if we would be assigning
2420 // the thing it already holds.
2421 if (aDeclaration != mDeclaration) {
2422 mDeclaration = aDeclaration;
2423 }
2424
2425 nsCSSStyleSheet* sheet = GetStyleSheet();
2426 if (sheet) {
2427 sheet->SetModifiedByChildRule();
2428
2429 if (doc) {
2430 doc->StyleRuleChanged(sheet, this, this);
2431 }
2432 }
2433 }
2434
2435 /* virtual */ size_t
2436 nsCSSKeyframeRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
2437 {
2438 return aMallocSizeOf(this);
2439
2440 // Measurement of the following members may be added later if DMD finds it is
2441 // worthwhile:
2442 // - mKeys
2443 // - mDeclaration
2444 // - mDOMDeclaration
2445 }
2446
2447
2448 // -------------------------------------------
2449 // nsCSSKeyframesRule
2450 //
2451
2452 nsCSSKeyframesRule::nsCSSKeyframesRule(const nsCSSKeyframesRule& aCopy)
2453 // copy everything except our reference count. GroupRule's copy
2454 // constructor also doesn't copy the lazily-constructed
2455 // mRuleCollection.
2456 : GroupRule(aCopy),
2457 mName(aCopy.mName)
2458 {
2459 }
2460
2461 nsCSSKeyframesRule::~nsCSSKeyframesRule()
2462 {
2463 }
2464
2465 /* virtual */ already_AddRefed<css::Rule>
2466 nsCSSKeyframesRule::Clone() const
2467 {
2468 nsRefPtr<css::Rule> clone = new nsCSSKeyframesRule(*this);
2469 return clone.forget();
2470 }
2471
2472 NS_IMPL_ADDREF_INHERITED(nsCSSKeyframesRule, css::GroupRule)
2473 NS_IMPL_RELEASE_INHERITED(nsCSSKeyframesRule, css::GroupRule)
2474
2475 DOMCI_DATA(MozCSSKeyframesRule, nsCSSKeyframesRule)
2476
2477 // QueryInterface implementation for nsCSSKeyframesRule
2478 NS_INTERFACE_MAP_BEGIN(nsCSSKeyframesRule)
2479 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
2480 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
2481 NS_INTERFACE_MAP_ENTRY(nsIDOMMozCSSKeyframesRule)
2482 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
2483 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozCSSKeyframesRule)
2484 NS_INTERFACE_MAP_END_INHERITING(GroupRule)
2485
2486 #ifdef DEBUG
2487 void
2488 nsCSSKeyframesRule::List(FILE* out, int32_t aIndent) const
2489 {
2490 for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out);
2491
2492 fprintf(out, "@keyframes %s", NS_ConvertUTF16toUTF8(mName).get());
2493 GroupRule::List(out, aIndent);
2494 }
2495 #endif
2496
2497 /* virtual */ int32_t
2498 nsCSSKeyframesRule::GetType() const
2499 {
2500 return Rule::KEYFRAMES_RULE;
2501 }
2502
2503 NS_IMETHODIMP
2504 nsCSSKeyframesRule::GetType(uint16_t* aType)
2505 {
2506 *aType = nsIDOMCSSRule::KEYFRAMES_RULE;
2507 return NS_OK;
2508 }
2509
2510 NS_IMETHODIMP
2511 nsCSSKeyframesRule::GetCssText(nsAString& aCssText)
2512 {
2513 aCssText.AssignLiteral("@keyframes ");
2514 aCssText.Append(mName);
2515 aCssText.AppendLiteral(" {\n");
2516 nsAutoString tmp;
2517 for (uint32_t i = 0, i_end = mRules.Count(); i != i_end; ++i) {
2518 static_cast<nsCSSKeyframeRule*>(mRules[i])->GetCssText(tmp);
2519 aCssText.Append(tmp);
2520 aCssText.AppendLiteral("\n");
2521 }
2522 aCssText.AppendLiteral("}");
2523 return NS_OK;
2524 }
2525
2526 NS_IMETHODIMP
2527 nsCSSKeyframesRule::SetCssText(const nsAString& aCssText)
2528 {
2529 // FIXME: implement???
2530 return NS_ERROR_NOT_IMPLEMENTED;
2531 }
2532
2533 NS_IMETHODIMP
2534 nsCSSKeyframesRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
2535 {
2536 return GroupRule::GetParentStyleSheet(aSheet);
2537 }
2538
2539 NS_IMETHODIMP
2540 nsCSSKeyframesRule::GetParentRule(nsIDOMCSSRule** aParentRule)
2541 {
2542 return GroupRule::GetParentRule(aParentRule);
2543 }
2544
2545 NS_IMETHODIMP
2546 nsCSSKeyframesRule::GetName(nsAString& aName)
2547 {
2548 aName = mName;
2549 return NS_OK;
2550 }
2551
2552 NS_IMETHODIMP
2553 nsCSSKeyframesRule::SetName(const nsAString& aName)
2554 {
2555 if (mName == aName) {
2556 return NS_OK;
2557 }
2558
2559 nsIDocument* doc = GetDocument();
2560 MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
2561
2562 mName = aName;
2563
2564 nsCSSStyleSheet* sheet = GetStyleSheet();
2565 if (sheet) {
2566 sheet->SetModifiedByChildRule();
2567
2568 if (doc) {
2569 doc->StyleRuleChanged(sheet, this, this);
2570 }
2571 }
2572
2573 return NS_OK;
2574 }
2575
2576 NS_IMETHODIMP
2577 nsCSSKeyframesRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
2578 {
2579 return GroupRule::GetCssRules(aRuleList);
2580 }
2581
2582 NS_IMETHODIMP
2583 nsCSSKeyframesRule::AppendRule(const nsAString& aRule)
2584 {
2585 // The spec is confusing, and I think we should just append the rule,
2586 // which also turns out to match WebKit:
2587 // http://lists.w3.org/Archives/Public/www-style/2011Apr/0034.html
2588 nsCSSParser parser;
2589
2590 // FIXME: pass filename and line number
2591 nsRefPtr<nsCSSKeyframeRule> rule =
2592 parser.ParseKeyframeRule(aRule, nullptr, 0);
2593 if (rule) {
2594 nsIDocument* doc = GetDocument();
2595 MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
2596
2597 AppendStyleRule(rule);
2598
2599 nsCSSStyleSheet* sheet = GetStyleSheet();
2600 if (sheet) {
2601 sheet->SetModifiedByChildRule();
2602
2603 if (doc) {
2604 doc->StyleRuleChanged(sheet, this, this);
2605 }
2606 }
2607 }
2608
2609 return NS_OK;
2610 }
2611
2612 static const uint32_t RULE_NOT_FOUND = uint32_t(-1);
2613
2614 uint32_t
2615 nsCSSKeyframesRule::FindRuleIndexForKey(const nsAString& aKey)
2616 {
2617 nsCSSParser parser;
2618
2619 InfallibleTArray<float> keys;
2620 // FIXME: pass filename and line number
2621 if (parser.ParseKeyframeSelectorString(aKey, nullptr, 0, keys)) {
2622 // The spec isn't clear, but we'll match on the key list, which
2623 // mostly matches what WebKit does, except we'll do last-match
2624 // instead of first-match, and handling parsing differences better.
2625 // http://lists.w3.org/Archives/Public/www-style/2011Apr/0036.html
2626 // http://lists.w3.org/Archives/Public/www-style/2011Apr/0037.html
2627 for (uint32_t i = mRules.Count(); i-- != 0; ) {
2628 if (static_cast<nsCSSKeyframeRule*>(mRules[i])->GetKeys() == keys) {
2629 return i;
2630 }
2631 }
2632 }
2633
2634 return RULE_NOT_FOUND;
2635 }
2636
2637 NS_IMETHODIMP
2638 nsCSSKeyframesRule::DeleteRule(const nsAString& aKey)
2639 {
2640 uint32_t index = FindRuleIndexForKey(aKey);
2641 if (index != RULE_NOT_FOUND) {
2642 nsIDocument* doc = GetDocument();
2643 MOZ_AUTO_DOC_UPDATE(doc, UPDATE_STYLE, true);
2644
2645 mRules.RemoveObjectAt(index);
2646
2647 nsCSSStyleSheet* sheet = GetStyleSheet();
2648 if (sheet) {
2649 sheet->SetModifiedByChildRule();
2650
2651 if (doc) {
2652 doc->StyleRuleChanged(sheet, this, this);
2653 }
2654 }
2655 }
2656 return NS_OK;
2657 }
2658
2659 NS_IMETHODIMP
2660 nsCSSKeyframesRule::FindRule(const nsAString& aKey,
2661 nsIDOMMozCSSKeyframeRule** aResult)
2662 {
2663 uint32_t index = FindRuleIndexForKey(aKey);
2664 if (index == RULE_NOT_FOUND) {
2665 *aResult = nullptr;
2666 } else {
2667 NS_ADDREF(*aResult = static_cast<nsCSSKeyframeRule*>(mRules[index]));
2668 }
2669 return NS_OK;
2670 }
2671
2672 // GroupRule interface
2673 /* virtual */ bool
2674 nsCSSKeyframesRule::UseForPresentation(nsPresContext* aPresContext,
2675 nsMediaQueryResultCacheKey& aKey)
2676 {
2677 NS_ABORT_IF_FALSE(false, "should not be called");
2678 return false;
2679 }
2680
2681 /* virtual */ size_t
2682 nsCSSKeyframesRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
2683 {
2684 size_t n = aMallocSizeOf(this);
2685 n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
2686
2687 // Measurement of the following members may be added later if DMD finds it is
2688 // worthwhile:
2689 // - mName
2690
2691 return n;
2692 }
2693
2694 // -------------------------------------------
2695 // nsCSSPageStyleDeclaration
2696 //
2697
2698 nsCSSPageStyleDeclaration::nsCSSPageStyleDeclaration(nsCSSPageRule* aRule)
2699 : mRule(aRule)
2700 {
2701 }
2702
2703 nsCSSPageStyleDeclaration::~nsCSSPageStyleDeclaration()
2704 {
2705 NS_ASSERTION(!mRule, "DropReference not called.");
2706 }
2707
2708 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSPageStyleDeclaration)
2709 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSPageStyleDeclaration)
2710
2711 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsCSSPageStyleDeclaration)
2712
2713 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSPageStyleDeclaration)
2714 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
2715 NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration)
2716
2717 css::Declaration*
2718 nsCSSPageStyleDeclaration::GetCSSDeclaration(bool aAllocate)
2719 {
2720 if (mRule) {
2721 return mRule->Declaration();
2722 } else {
2723 return nullptr;
2724 }
2725 }
2726
2727 void
2728 nsCSSPageStyleDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
2729 {
2730 GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv);
2731 }
2732
2733 NS_IMETHODIMP
2734 nsCSSPageStyleDeclaration::GetParentRule(nsIDOMCSSRule** aParent)
2735 {
2736 NS_ENSURE_ARG_POINTER(aParent);
2737
2738 NS_IF_ADDREF(*aParent = mRule);
2739 return NS_OK;
2740 }
2741
2742 nsresult
2743 nsCSSPageStyleDeclaration::SetCSSDeclaration(css::Declaration* aDecl)
2744 {
2745 NS_ABORT_IF_FALSE(aDecl, "must be non-null");
2746 mRule->ChangeDeclaration(aDecl);
2747 return NS_OK;
2748 }
2749
2750 nsIDocument*
2751 nsCSSPageStyleDeclaration::DocToUpdate()
2752 {
2753 return nullptr;
2754 }
2755
2756 nsINode*
2757 nsCSSPageStyleDeclaration::GetParentObject()
2758 {
2759 return mRule ? mRule->GetDocument() : nullptr;
2760 }
2761
2762 // -------------------------------------------
2763 // nsCSSPageRule
2764 //
2765
2766 nsCSSPageRule::nsCSSPageRule(const nsCSSPageRule& aCopy)
2767 // copy everything except our reference count and mDOMDeclaration
2768 : Rule(aCopy)
2769 , mDeclaration(new css::Declaration(*aCopy.mDeclaration))
2770 {
2771 }
2772
2773 nsCSSPageRule::~nsCSSPageRule()
2774 {
2775 if (mDOMDeclaration) {
2776 mDOMDeclaration->DropReference();
2777 }
2778 }
2779
2780 /* virtual */ already_AddRefed<css::Rule>
2781 nsCSSPageRule::Clone() const
2782 {
2783 nsRefPtr<css::Rule> clone = new nsCSSPageRule(*this);
2784 return clone.forget();
2785 }
2786
2787 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCSSPageRule)
2788 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCSSPageRule)
2789
2790 NS_IMPL_CYCLE_COLLECTION_CLASS(nsCSSPageRule)
2791
2792 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCSSPageRule)
2793 if (tmp->mDOMDeclaration) {
2794 tmp->mDOMDeclaration->DropReference();
2795 tmp->mDOMDeclaration = nullptr;
2796 }
2797 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
2798 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCSSPageRule)
2799 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMDeclaration)
2800 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
2801
2802 DOMCI_DATA(CSSPageRule, nsCSSPageRule)
2803
2804 // QueryInterface implementation for nsCSSPageRule
2805 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCSSPageRule)
2806 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
2807 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSPageRule)
2808 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
2809 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
2810 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSPageRule)
2811 NS_INTERFACE_MAP_END
2812
2813 IMPL_STYLE_RULE_INHERIT_GET_DOM_RULE_WEAK(nsCSSPageRule, Rule)
2814
2815 #ifdef DEBUG
2816 void
2817 nsCSSPageRule::List(FILE* out, int32_t aIndent) const
2818 {
2819 for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out);
2820
2821 fputs("@page ", out);
2822 mDeclaration->List(out, aIndent);
2823 fputs("\n", out);
2824 }
2825 #endif
2826
2827 /* virtual */ int32_t
2828 nsCSSPageRule::GetType() const
2829 {
2830 return Rule::PAGE_RULE;
2831 }
2832
2833 NS_IMETHODIMP
2834 nsCSSPageRule::GetType(uint16_t* aType)
2835 {
2836 *aType = nsIDOMCSSRule::PAGE_RULE;
2837 return NS_OK;
2838 }
2839
2840 NS_IMETHODIMP
2841 nsCSSPageRule::GetCssText(nsAString& aCssText)
2842 {
2843 aCssText.AppendLiteral("@page { ");
2844 nsAutoString tmp;
2845 mDeclaration->ToString(tmp);
2846 aCssText.Append(tmp);
2847 aCssText.AppendLiteral(" }");
2848 return NS_OK;
2849 }
2850
2851 NS_IMETHODIMP
2852 nsCSSPageRule::SetCssText(const nsAString& aCssText)
2853 {
2854 // FIXME: implement???
2855 return NS_ERROR_NOT_IMPLEMENTED;
2856 }
2857
2858 NS_IMETHODIMP
2859 nsCSSPageRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
2860 {
2861 return Rule::GetParentStyleSheet(aSheet);
2862 }
2863
2864 NS_IMETHODIMP
2865 nsCSSPageRule::GetParentRule(nsIDOMCSSRule** aParentRule)
2866 {
2867 return Rule::GetParentRule(aParentRule);
2868 }
2869
2870 css::ImportantRule*
2871 nsCSSPageRule::GetImportantRule()
2872 {
2873 if (!mDeclaration->HasImportantData()) {
2874 return nullptr;
2875 }
2876 if (!mImportantRule) {
2877 mImportantRule = new css::ImportantRule(mDeclaration);
2878 }
2879 return mImportantRule;
2880 }
2881
2882 /* virtual */ void
2883 nsCSSPageRule::MapRuleInfoInto(nsRuleData* aRuleData)
2884 {
2885 mDeclaration->MapNormalRuleInfoInto(aRuleData);
2886 }
2887
2888 NS_IMETHODIMP
2889 nsCSSPageRule::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
2890 {
2891 if (!mDOMDeclaration) {
2892 mDOMDeclaration = new nsCSSPageStyleDeclaration(this);
2893 }
2894 NS_ADDREF(*aStyle = mDOMDeclaration);
2895 return NS_OK;
2896 }
2897
2898 void
2899 nsCSSPageRule::ChangeDeclaration(css::Declaration* aDeclaration)
2900 {
2901 mImportantRule = nullptr;
2902 // Be careful to not assign to an nsAutoPtr if we would be assigning
2903 // the thing it already holds.
2904 if (aDeclaration != mDeclaration) {
2905 mDeclaration = aDeclaration;
2906 }
2907
2908 nsCSSStyleSheet* sheet = GetStyleSheet();
2909 if (sheet) {
2910 sheet->SetModifiedByChildRule();
2911 }
2912 }
2913
2914 /* virtual */ size_t
2915 nsCSSPageRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
2916 {
2917 return aMallocSizeOf(this);
2918 }
2919
2920 namespace mozilla {
2921
2922 CSSSupportsRule::CSSSupportsRule(bool aConditionMet,
2923 const nsString& aCondition)
2924 : mUseGroup(aConditionMet),
2925 mCondition(aCondition)
2926 {
2927 }
2928
2929 CSSSupportsRule::CSSSupportsRule(const CSSSupportsRule& aCopy)
2930 : css::GroupRule(aCopy),
2931 mUseGroup(aCopy.mUseGroup),
2932 mCondition(aCopy.mCondition)
2933 {
2934 }
2935
2936 #ifdef DEBUG
2937 /* virtual */ void
2938 CSSSupportsRule::List(FILE* out, int32_t aIndent) const
2939 {
2940 for (int32_t indent = aIndent; --indent >= 0; ) fputs(" ", out);
2941
2942 fputs("@supports ", out);
2943 fputs(NS_ConvertUTF16toUTF8(mCondition).get(), out);
2944 css::GroupRule::List(out, aIndent);
2945 }
2946 #endif
2947
2948 /* virtual */ int32_t
2949 CSSSupportsRule::GetType() const
2950 {
2951 return Rule::SUPPORTS_RULE;
2952 }
2953
2954 /* virtual */ already_AddRefed<mozilla::css::Rule>
2955 CSSSupportsRule::Clone() const
2956 {
2957 nsRefPtr<css::Rule> clone = new CSSSupportsRule(*this);
2958 return clone.forget();
2959 }
2960
2961 /* virtual */ bool
2962 CSSSupportsRule::UseForPresentation(nsPresContext* aPresContext,
2963 nsMediaQueryResultCacheKey& aKey)
2964 {
2965 return mUseGroup;
2966 }
2967
2968 NS_IMPL_ADDREF_INHERITED(CSSSupportsRule, css::GroupRule)
2969 NS_IMPL_RELEASE_INHERITED(CSSSupportsRule, css::GroupRule)
2970
2971 // QueryInterface implementation for CSSSupportsRule
2972 NS_INTERFACE_MAP_BEGIN(CSSSupportsRule)
2973 NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
2974 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
2975 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule)
2976 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule)
2977 NS_INTERFACE_MAP_ENTRY(nsIDOMCSSSupportsRule)
2978 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
2979 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSSupportsRule)
2980 NS_INTERFACE_MAP_END_INHERITING(GroupRule)
2981
2982 // nsIDOMCSSRule methods
2983 NS_IMETHODIMP
2984 CSSSupportsRule::GetType(uint16_t* aType)
2985 {
2986 *aType = nsIDOMCSSRule::SUPPORTS_RULE;
2987 return NS_OK;
2988 }
2989
2990 NS_IMETHODIMP
2991 CSSSupportsRule::GetCssText(nsAString& aCssText)
2992 {
2993 aCssText.AssignLiteral("@supports ");
2994 aCssText.Append(mCondition);
2995 css::GroupRule::AppendRulesToCssText(aCssText);
2996 return NS_OK;
2997 }
2998
2999 NS_IMETHODIMP
3000 CSSSupportsRule::SetCssText(const nsAString& aCssText)
3001 {
3002 return NS_ERROR_NOT_IMPLEMENTED;
3003 }
3004
3005 NS_IMETHODIMP
3006 CSSSupportsRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
3007 {
3008 return css::GroupRule::GetParentStyleSheet(aSheet);
3009 }
3010
3011 NS_IMETHODIMP
3012 CSSSupportsRule::GetParentRule(nsIDOMCSSRule** aParentRule)
3013 {
3014 return css::GroupRule::GetParentRule(aParentRule);
3015 }
3016
3017 // nsIDOMCSSGroupingRule methods
3018 NS_IMETHODIMP
3019 CSSSupportsRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
3020 {
3021 return css::GroupRule::GetCssRules(aRuleList);
3022 }
3023
3024 NS_IMETHODIMP
3025 CSSSupportsRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
3026 {
3027 return css::GroupRule::InsertRule(aRule, aIndex, _retval);
3028 }
3029
3030 NS_IMETHODIMP
3031 CSSSupportsRule::DeleteRule(uint32_t aIndex)
3032 {
3033 return css::GroupRule::DeleteRule(aIndex);
3034 }
3035
3036 // nsIDOMCSSConditionRule methods
3037 NS_IMETHODIMP
3038 CSSSupportsRule::GetConditionText(nsAString& aConditionText)
3039 {
3040 aConditionText.Assign(mCondition);
3041 return NS_OK;
3042 }
3043
3044 NS_IMETHODIMP
3045 CSSSupportsRule::SetConditionText(const nsAString& aConditionText)
3046 {
3047 return NS_ERROR_NOT_IMPLEMENTED;
3048 }
3049
3050 /* virtual */ size_t
3051 CSSSupportsRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
3052 {
3053 size_t n = aMallocSizeOf(this);
3054 n += css::GroupRule::SizeOfExcludingThis(aMallocSizeOf);
3055 n += mCondition.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
3056 return n;
3057 }
3058
3059 } // namespace mozilla
3060
3061 // Must be outside namespace
3062 DOMCI_DATA(CSSSupportsRule, mozilla::CSSSupportsRule)

mercurial