1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "mozilla/ServoElementSnapshot.h"
8 #include "mozilla/GeckoBindings.h"
9 #include "mozilla/dom/Element.h"
10 #include "nsIContentInlines.h"
11 #include "nsContentUtils.h"
12 
13 namespace mozilla {
14 
ServoElementSnapshot(const Element & aElement)15 ServoElementSnapshot::ServoElementSnapshot(const Element& aElement)
16     : mState(0),
17       mContains(Flags(0)),
18       mIsTableBorderNonzero(false),
19       mIsMozBrowserFrame(false),
20       mIsSelectListBox(false),
21       mClassAttributeChanged(false),
22       mIdAttributeChanged(false) {
23   MOZ_COUNT_CTOR(ServoElementSnapshot);
24   MOZ_ASSERT(NS_IsMainThread());
25   mIsInChromeDocument = nsContentUtils::IsChromeDoc(aElement.OwnerDoc());
26   mSupportsLangAttr = aElement.SupportsLangAttr();
27 }
28 
AddOtherPseudoClassState(const Element & aElement)29 void ServoElementSnapshot::AddOtherPseudoClassState(const Element& aElement) {
30   if (HasOtherPseudoClassState()) {
31     return;
32   }
33 
34   mIsTableBorderNonzero = Gecko_IsTableBorderNonzero(&aElement);
35   mIsMozBrowserFrame = Gecko_IsBrowserFrame(&aElement);
36   mIsSelectListBox = Gecko_IsSelectListBox(&aElement);
37 
38   mContains |= Flags::OtherPseudoClassState;
39 }
40 
AddAttrs(const Element & aElement,int32_t aNameSpaceID,nsAtom * aAttribute)41 void ServoElementSnapshot::AddAttrs(const Element& aElement,
42                                     int32_t aNameSpaceID, nsAtom* aAttribute) {
43   if (aNameSpaceID == kNameSpaceID_None) {
44     if (aAttribute == nsGkAtoms::_class) {
45       if (mClassAttributeChanged) {
46         return;
47       }
48       mClassAttributeChanged = true;
49     } else if (aAttribute == nsGkAtoms::id) {
50       if (mIdAttributeChanged) {
51         return;
52       }
53       mIdAttributeChanged = true;
54     }
55   }
56 
57   if (!mChangedAttrNames.Contains(aAttribute)) {
58     mChangedAttrNames.AppendElement(aAttribute);
59   }
60 
61   if (HasAttrs()) {
62     return;
63   }
64 
65   uint32_t attrCount = aElement.GetAttrCount();
66   mAttrs.SetCapacity(attrCount);
67   for (uint32_t i = 0; i < attrCount; ++i) {
68     const BorrowedAttrInfo info = aElement.GetAttrInfoAt(i);
69     MOZ_ASSERT(info);
70     mAttrs.AppendElement(AttrArray::InternalAttr{*info.mName, *info.mValue});
71   }
72 
73   mContains |= Flags::Attributes;
74   if (aElement.HasID()) {
75     mContains |= Flags::Id;
76   }
77 
78   if (const nsAttrValue* classValue = aElement.GetClasses()) {
79     // FIXME(emilio): It's pretty unfortunate that this is only relevant for
80     // SVG, yet it's a somewhat expensive copy. We should be able to do
81     // better!
82     mClass = *classValue;
83     mContains |= Flags::MaybeClass;
84   }
85 }
86 
87 }  // namespace mozilla
88