summaryrefslogtreecommitdiffstats
path: root/layout/style/CSSKeyframeRule.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'layout/style/CSSKeyframeRule.cpp')
-rw-r--r--layout/style/CSSKeyframeRule.cpp220
1 files changed, 220 insertions, 0 deletions
diff --git a/layout/style/CSSKeyframeRule.cpp b/layout/style/CSSKeyframeRule.cpp
new file mode 100644
index 0000000000..e6ae2bada0
--- /dev/null
+++ b/layout/style/CSSKeyframeRule.cpp
@@ -0,0 +1,220 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#include "mozilla/dom/CSSKeyframeRule.h"
+
+#include "mozilla/DeclarationBlock.h"
+#include "mozilla/dom/CSSKeyframeRuleBinding.h"
+#include "nsDOMCSSDeclaration.h"
+
+namespace mozilla::dom {
+
+// -------------------------------------------
+// CSSKeyframeDeclaration
+//
+
+class CSSKeyframeDeclaration : public nsDOMCSSDeclaration {
+ public:
+ explicit CSSKeyframeDeclaration(CSSKeyframeRule* aRule) : mRule(aRule) {
+ mDecls =
+ new DeclarationBlock(Servo_Keyframe_GetStyle(aRule->Raw()).Consume());
+ mDecls->SetOwningRule(aRule);
+ }
+
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS_AMBIGUOUS(CSSKeyframeDeclaration,
+ nsICSSDeclaration)
+
+ css::Rule* GetParentRule() final { return mRule; }
+
+ void DropReference() {
+ mRule = nullptr;
+ mDecls->SetOwningRule(nullptr);
+ }
+
+ DeclarationBlock* GetOrCreateCSSDeclaration(
+ Operation aOperation, DeclarationBlock** aCreated) final {
+ if (aOperation != Operation::Read && mRule) {
+ if (StyleSheet* sheet = mRule->GetStyleSheet()) {
+ sheet->WillDirty();
+ }
+ }
+ return mDecls;
+ }
+ nsresult SetCSSDeclaration(DeclarationBlock* aDecls,
+ MutationClosureData* aClosureData) final {
+ if (!mRule) {
+ return NS_OK;
+ }
+ mRule->UpdateRule([this, aDecls]() {
+ if (mDecls != aDecls) {
+ mDecls->SetOwningRule(nullptr);
+ mDecls = aDecls;
+ mDecls->SetOwningRule(mRule);
+ Servo_Keyframe_SetStyle(mRule->Raw(), mDecls->Raw());
+ }
+ });
+ return NS_OK;
+ }
+ ParsingEnvironment GetParsingEnvironment(
+ nsIPrincipal* aSubjectPrincipal) const final {
+ return GetParsingEnvironmentForRule(mRule, StyleCssRuleType::Keyframe);
+ }
+ Document* DocToUpdate() final { return nullptr; }
+
+ nsINode* GetAssociatedNode() const final {
+ return mRule ? mRule->GetAssociatedDocumentOrShadowRoot() : nullptr;
+ }
+
+ nsISupports* GetParentObject() const final {
+ return mRule ? mRule->GetParentObject() : nullptr;
+ }
+
+ size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
+ size_t n = aMallocSizeOf(this);
+ // TODO we may want to add size of mDecls as well
+ return n;
+ }
+
+ void SetRawAfterClone(StyleLockedKeyframe* aKeyframe) {
+ mDecls->SetOwningRule(nullptr);
+ mDecls = new DeclarationBlock(Servo_Keyframe_GetStyle(aKeyframe).Consume());
+ mDecls->SetOwningRule(mRule);
+ }
+
+ private:
+ virtual ~CSSKeyframeDeclaration() {
+ MOZ_ASSERT(!mRule, "Backpointer should have been cleared");
+ }
+
+ CSSKeyframeRule* mRule;
+ RefPtr<DeclarationBlock> mDecls;
+};
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(CSSKeyframeDeclaration)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(CSSKeyframeDeclaration)
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(CSSKeyframeDeclaration)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CSSKeyframeDeclaration)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration)
+
+// -------------------------------------------
+// CSSKeyframeRule
+//
+
+CSSKeyframeRule::CSSKeyframeRule(already_AddRefed<StyleLockedKeyframe> aRaw,
+ StyleSheet* aSheet, css::Rule* aParentRule,
+ uint32_t aLine, uint32_t aColumn)
+ : css::Rule(aSheet, aParentRule, aLine, aColumn), mRaw(aRaw) {}
+
+CSSKeyframeRule::~CSSKeyframeRule() {
+ if (mDeclaration) {
+ mDeclaration->DropReference();
+ }
+}
+
+NS_IMPL_ADDREF_INHERITED(CSSKeyframeRule, css::Rule)
+NS_IMPL_RELEASE_INHERITED(CSSKeyframeRule, css::Rule)
+
+// QueryInterface implementation for nsCSSKeyframeRule
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CSSKeyframeRule)
+NS_INTERFACE_MAP_END_INHERITING(css::Rule)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(CSSKeyframeRule)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(CSSKeyframeRule, css::Rule)
+ if (tmp->mDeclaration) {
+ tmp->mDeclaration->DropReference();
+ tmp->mDeclaration = nullptr;
+ }
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(CSSKeyframeRule, css::Rule)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDeclaration)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+bool CSSKeyframeRule::IsCCLeaf() const {
+ return Rule::IsCCLeaf() && !mDeclaration;
+}
+
+StyleCssRuleType CSSKeyframeRule::Type() const {
+ return StyleCssRuleType::Keyframe;
+}
+
+void CSSKeyframeRule::SetRawAfterClone(RefPtr<StyleLockedKeyframe> aRaw) {
+ mRaw = std::move(aRaw);
+
+ if (mDeclaration) {
+ mDeclaration->SetRawAfterClone(mRaw);
+ }
+}
+
+#ifdef DEBUG
+/* virtual */
+void CSSKeyframeRule::List(FILE* out, int32_t aIndent) const {
+ nsAutoCString str;
+ for (int32_t i = 0; i < aIndent; i++) {
+ str.AppendLiteral(" ");
+ }
+ Servo_Keyframe_Debug(mRaw, &str);
+ fprintf_stderr(out, "%s\n", str.get());
+}
+#endif
+
+template <typename Func>
+void CSSKeyframeRule::UpdateRule(Func aCallback) {
+ if (IsReadOnly()) {
+ return;
+ }
+
+ StyleSheet* sheet = GetStyleSheet();
+ if (sheet) {
+ sheet->WillDirty();
+ }
+
+ aCallback();
+
+ if (sheet) {
+ sheet->RuleChanged(this, StyleRuleChangeKind::Generic);
+ }
+}
+
+void CSSKeyframeRule::GetKeyText(nsACString& aKeyText) {
+ Servo_Keyframe_GetKeyText(mRaw, &aKeyText);
+}
+
+void CSSKeyframeRule::SetKeyText(const nsACString& aKeyText) {
+ UpdateRule(
+ [this, &aKeyText]() { Servo_Keyframe_SetKeyText(mRaw, &aKeyText); });
+}
+
+void CSSKeyframeRule::GetCssText(nsACString& aCssText) const {
+ Servo_Keyframe_GetCssText(mRaw, &aCssText);
+}
+
+nsICSSDeclaration* CSSKeyframeRule::Style() {
+ if (!mDeclaration) {
+ mDeclaration = new CSSKeyframeDeclaration(this);
+ }
+ return mDeclaration;
+}
+
+size_t CSSKeyframeRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
+ size_t n = aMallocSizeOf(this);
+ if (mDeclaration) {
+ n += mDeclaration->SizeOfIncludingThis(aMallocSizeOf);
+ }
+ return n;
+}
+
+/* virtual */
+JSObject* CSSKeyframeRule::WrapObject(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto) {
+ return CSSKeyframeRule_Binding::Wrap(aCx, this, aGivenProto);
+}
+
+} // namespace mozilla::dom