Line data Source code
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/ServoBindings.h"
8 :
9 : #include "ChildIterator.h"
10 : #include "ErrorReporter.h"
11 : #include "GeckoProfiler.h"
12 : #include "gfxFontFamilyList.h"
13 : #include "nsAnimationManager.h"
14 : #include "nsAttrValueInlines.h"
15 : #include "nsCSSCounterStyleRule.h"
16 : #include "nsCSSFontFaceRule.h"
17 : #include "nsCSSFrameConstructor.h"
18 : #include "nsCSSProps.h"
19 : #include "nsCSSParser.h"
20 : #include "nsCSSPseudoElements.h"
21 : #include "nsCSSRuleProcessor.h"
22 : #include "nsCSSRules.h"
23 : #include "nsContentUtils.h"
24 : #include "nsDOMTokenList.h"
25 : #include "nsDeviceContext.h"
26 : #include "nsIContentInlines.h"
27 : #include "nsIDOMNode.h"
28 : #include "nsIDocumentInlines.h"
29 : #include "nsIFrame.h"
30 : #include "nsINode.h"
31 : #include "nsIPresShell.h"
32 : #include "nsIPresShellInlines.h"
33 : #include "nsIPrincipal.h"
34 : #include "nsIURI.h"
35 : #include "nsFontMetrics.h"
36 : #include "nsHTMLStyleSheet.h"
37 : #include "nsMappedAttributes.h"
38 : #include "nsMediaFeatures.h"
39 : #include "nsNameSpaceManager.h"
40 : #include "nsNetUtil.h"
41 : #include "nsRuleNode.h"
42 : #include "nsString.h"
43 : #include "nsStyleStruct.h"
44 : #include "nsStyleUtil.h"
45 : #include "nsSVGElement.h"
46 : #include "nsTArray.h"
47 : #include "nsTransitionManager.h"
48 :
49 : #include "mozilla/DeclarationBlockInlines.h"
50 : #include "mozilla/EffectCompositor.h"
51 : #include "mozilla/EffectSet.h"
52 : #include "mozilla/EventStates.h"
53 : #include "mozilla/GeckoStyleContext.h"
54 : #include "mozilla/Keyframe.h"
55 : #include "mozilla/Mutex.h"
56 : #include "mozilla/Preferences.h"
57 : #include "mozilla/ServoElementSnapshot.h"
58 : #include "mozilla/ServoRestyleManager.h"
59 : #include "mozilla/StyleAnimationValue.h"
60 : #include "mozilla/SystemGroup.h"
61 : #include "mozilla/ServoMediaList.h"
62 : #include "mozilla/RWLock.h"
63 : #include "mozilla/dom/Element.h"
64 : #include "mozilla/dom/ElementInlines.h"
65 : #include "mozilla/dom/HTMLTableCellElement.h"
66 : #include "mozilla/dom/HTMLBodyElement.h"
67 : #include "mozilla/LookAndFeel.h"
68 : #include "mozilla/URLExtraData.h"
69 :
70 : #if defined(MOZ_MEMORY)
71 : # include "mozmemory.h"
72 : #endif
73 :
74 : using namespace mozilla;
75 : using namespace mozilla::css;
76 : using namespace mozilla::dom;
77 :
78 : #define SERVO_ARC_TYPE(name_, type_) \
79 : already_AddRefed<type_> \
80 : type_##Strong::Consume() { \
81 : RefPtr<type_> result; \
82 : result.swap(mPtr); \
83 : return result.forget(); \
84 : }
85 : #include "mozilla/ServoArcTypeList.h"
86 : #undef SERVO_ARC_TYPE
87 :
88 :
89 : static Mutex* sServoFontMetricsLock = nullptr;
90 : static RWLock* sServoLangFontPrefsLock = nullptr;
91 :
92 : static bool sFramesTimingFunctionEnabled;
93 :
94 : static
95 : const nsFont*
96 0 : ThreadSafeGetDefaultFontHelper(const nsPresContext* aPresContext,
97 : nsIAtom* aLanguage, uint8_t aGenericId)
98 : {
99 0 : bool needsCache = false;
100 : const nsFont* retval;
101 :
102 : {
103 0 : AutoReadLock guard(*sServoLangFontPrefsLock);
104 0 : retval = aPresContext->GetDefaultFont(aGenericId, aLanguage, &needsCache);
105 : }
106 0 : if (!needsCache) {
107 0 : return retval;
108 : }
109 : {
110 0 : AutoWriteLock guard(*sServoLangFontPrefsLock);
111 0 : retval = aPresContext->GetDefaultFont(aGenericId, aLanguage, nullptr);
112 : }
113 0 : return retval;
114 : }
115 :
116 : void
117 12 : AssertIsMainThreadOrServoLangFontPrefsCacheLocked()
118 : {
119 12 : MOZ_ASSERT(NS_IsMainThread() || sServoLangFontPrefsLock->LockedForWritingByCurrentThread());
120 12 : }
121 :
122 : uint32_t
123 0 : Gecko_ChildrenCount(RawGeckoNodeBorrowed aNode)
124 : {
125 0 : return aNode->GetChildCount();
126 : }
127 :
128 : bool
129 0 : Gecko_NodeIsElement(RawGeckoNodeBorrowed aNode)
130 : {
131 0 : return aNode->IsElement();
132 : }
133 :
134 : bool
135 0 : Gecko_IsInDocument(RawGeckoNodeBorrowed aNode)
136 : {
137 0 : return aNode->IsInComposedDoc();
138 : }
139 :
140 : #ifdef MOZ_DEBUG_RUST
141 : bool
142 0 : Gecko_FlattenedTreeParentIsParent(RawGeckoNodeBorrowed aNode)
143 : {
144 : // Servo calls this in debug builds to verify the result of its own
145 : // flattened_tree_parent_is_parent() function.
146 0 : return FlattenedTreeParentIsParent<nsIContent::eForStyle>(aNode);
147 : }
148 : #endif
149 :
150 : /*
151 : * Does this child count as significant for selector matching?
152 : *
153 : * See nsStyleUtil::IsSignificantChild for details.
154 : */
155 : bool
156 0 : Gecko_IsSignificantChild(RawGeckoNodeBorrowed aNode, bool aTextIsSignificant,
157 : bool aWhitespaceIsSignificant)
158 : {
159 0 : return nsStyleUtil::ThreadSafeIsSignificantChild(aNode->AsContent(),
160 : aTextIsSignificant,
161 0 : aWhitespaceIsSignificant);
162 : }
163 :
164 : RawGeckoNodeBorrowedOrNull
165 0 : Gecko_GetLastChild(RawGeckoNodeBorrowed aNode)
166 : {
167 0 : return aNode->GetLastChild();
168 : }
169 :
170 : RawGeckoNodeBorrowedOrNull
171 0 : Gecko_GetFlattenedTreeParentNode(RawGeckoNodeBorrowed aNode)
172 : {
173 0 : MOZ_ASSERT(!FlattenedTreeParentIsParent<nsIContent::eForStyle>(aNode),
174 : "Should have taken the inline path");
175 0 : MOZ_ASSERT(aNode->IsContent(), "Slow path only applies to content");
176 0 : const nsIContent* c = aNode->AsContent();
177 0 : return c->GetFlattenedTreeParentNodeInternal(nsIContent::eForStyle);
178 : }
179 :
180 : RawGeckoElementBorrowedOrNull
181 0 : Gecko_GetBeforeOrAfterPseudo(RawGeckoElementBorrowed aElement, bool aIsBefore)
182 : {
183 0 : MOZ_ASSERT(aElement);
184 0 : MOZ_ASSERT(aElement->HasProperties());
185 :
186 : return aIsBefore
187 : ? nsLayoutUtils::GetBeforePseudo(aElement)
188 0 : : nsLayoutUtils::GetAfterPseudo(aElement);
189 : }
190 :
191 : nsTArray<nsIContent*>*
192 0 : Gecko_GetAnonymousContentForElement(RawGeckoElementBorrowed aElement)
193 : {
194 0 : nsIAnonymousContentCreator* ac = do_QueryFrame(aElement->GetPrimaryFrame());
195 0 : if (!ac) {
196 0 : return nullptr;
197 : }
198 :
199 0 : auto* array = new nsTArray<nsIContent*>();
200 0 : nsContentUtils::AppendNativeAnonymousChildren(aElement, *array, 0);
201 0 : return array;
202 : }
203 :
204 : void
205 0 : Gecko_DestroyAnonymousContentList(nsTArray<nsIContent*>* aAnonContent)
206 : {
207 0 : MOZ_ASSERT(aAnonContent);
208 0 : delete aAnonContent;
209 0 : }
210 :
211 : void
212 0 : Gecko_ConstructStyleChildrenIterator(
213 : RawGeckoElementBorrowed aElement,
214 : RawGeckoStyleChildrenIteratorBorrowedMut aIterator)
215 : {
216 0 : MOZ_ASSERT(aElement);
217 0 : MOZ_ASSERT(aIterator);
218 0 : new (aIterator) StyleChildrenIterator(aElement);
219 0 : }
220 :
221 : void
222 0 : Gecko_DestroyStyleChildrenIterator(
223 : RawGeckoStyleChildrenIteratorBorrowedMut aIterator)
224 : {
225 0 : MOZ_ASSERT(aIterator);
226 :
227 0 : aIterator->~StyleChildrenIterator();
228 0 : }
229 :
230 : nsIContent*
231 0 : Gecko_ElementBindingAnonymousContent(RawGeckoElementBorrowed aElement)
232 : {
233 0 : MOZ_ASSERT(aElement->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR));
234 0 : nsBindingManager* manager = aElement->OwnerDoc()->BindingManager();
235 0 : if (nsXBLBinding* binding = manager->GetBindingWithContent(aElement)) {
236 0 : return binding->GetAnonymousContent();
237 : }
238 0 : return nullptr;
239 : }
240 :
241 : RawGeckoNodeBorrowed
242 0 : Gecko_GetNextStyleChild(RawGeckoStyleChildrenIteratorBorrowedMut aIterator)
243 : {
244 0 : MOZ_ASSERT(aIterator);
245 0 : return aIterator->GetNextChild();
246 : }
247 :
248 : EventStates::ServoType
249 0 : Gecko_ElementState(RawGeckoElementBorrowed aElement)
250 : {
251 0 : return aElement->StyleState().ServoValue();
252 : }
253 :
254 : EventStates::ServoType
255 0 : Gecko_DocumentState(const nsIDocument* aDocument)
256 : {
257 0 : return aDocument->ThreadSafeGetDocumentState().ServoValue();
258 : }
259 :
260 : bool
261 0 : Gecko_IsTextNode(RawGeckoNodeBorrowed aNode)
262 : {
263 0 : return aNode->NodeInfo()->NodeType() == nsIDOMNode::TEXT_NODE;
264 : }
265 :
266 : bool
267 0 : Gecko_IsRootElement(RawGeckoElementBorrowed aElement)
268 : {
269 0 : return aElement->OwnerDoc()->GetRootElement() == aElement;
270 : }
271 :
272 : bool
273 0 : Gecko_MatchesElement(CSSPseudoClassType aType,
274 : RawGeckoElementBorrowed aElement)
275 : {
276 0 : return nsCSSPseudoClasses::MatchesElement(aType, aElement).value();
277 : }
278 :
279 : nsIAtom*
280 0 : Gecko_LocalName(RawGeckoElementBorrowed aElement)
281 : {
282 0 : return aElement->NodeInfo()->NameAtom();
283 : }
284 :
285 : nsIAtom*
286 0 : Gecko_Namespace(RawGeckoElementBorrowed aElement)
287 : {
288 0 : int32_t id = aElement->NodeInfo()->NamespaceID();
289 0 : return nsContentUtils::NameSpaceManager()->NameSpaceURIAtomForServo(id);
290 : }
291 :
292 : nsIAtom*
293 0 : Gecko_GetElementId(RawGeckoElementBorrowed aElement)
294 : {
295 0 : const nsAttrValue* attr = aElement->GetParsedAttr(nsGkAtoms::id);
296 0 : if (attr && attr->Type() == nsAttrValue::eAtom) {
297 0 : return attr->GetAtomValue();
298 : }
299 : // The only case in which we should have a non-atom value here is if it's the
300 : // empty string value.
301 0 : MOZ_ASSERT(!attr || attr->IsEmptyString());
302 0 : return nullptr;
303 : }
304 :
305 : // Dirtiness tracking.
306 : uint32_t
307 0 : Gecko_GetNodeFlags(RawGeckoNodeBorrowed aNode)
308 : {
309 0 : return aNode->GetFlags();
310 : }
311 :
312 : void
313 0 : Gecko_SetNodeFlags(RawGeckoNodeBorrowed aNode, uint32_t aFlags)
314 : {
315 0 : const_cast<nsINode*>(aNode)->SetFlags(aFlags);
316 0 : }
317 :
318 : void
319 0 : Gecko_UnsetNodeFlags(RawGeckoNodeBorrowed aNode, uint32_t aFlags)
320 : {
321 0 : const_cast<nsINode*>(aNode)->UnsetFlags(aFlags);
322 0 : }
323 :
324 : void
325 0 : Gecko_SetOwnerDocumentNeedsStyleFlush(RawGeckoElementBorrowed aElement)
326 : {
327 0 : MOZ_ASSERT(NS_IsMainThread());
328 :
329 0 : if (nsIPresShell* shell = aElement->OwnerDoc()->GetShell()) {
330 0 : shell->EnsureStyleFlush();
331 : }
332 0 : }
333 :
334 : nsStyleContext*
335 0 : Gecko_GetStyleContext(RawGeckoElementBorrowed aElement,
336 : nsIAtom* aPseudoTagOrNull)
337 : {
338 : nsIFrame* relevantFrame =
339 0 : ServoRestyleManager::FrameForPseudoElement(aElement, aPseudoTagOrNull);
340 0 : if (relevantFrame) {
341 0 : return relevantFrame->StyleContext();
342 : }
343 :
344 0 : if (aPseudoTagOrNull) {
345 0 : return nullptr;
346 : }
347 :
348 : // FIXME(emilio): Is there a shorter path?
349 0 : nsIPresShell* shell = aElement->OwnerDoc()->GetShell();
350 0 : NS_ENSURE_TRUE(shell, nullptr);
351 0 : nsCSSFrameConstructor* fc = shell->GetPresContext()->FrameConstructor();
352 :
353 : // NB: This is only called for CalcStyleDifference, and we handle correctly
354 : // the display: none case since Servo still has the older style.
355 0 : return fc->GetDisplayContentsStyleFor(aElement);
356 : }
357 :
358 : CSSPseudoElementType
359 0 : Gecko_GetImplementedPseudo(RawGeckoElementBorrowed aElement)
360 : {
361 0 : return aElement->GetPseudoElementType();
362 : }
363 :
364 : nsChangeHint
365 0 : Gecko_CalcStyleDifference(nsStyleContext* aOldStyleContext,
366 : ServoComputedValuesBorrowed aComputedValues,
367 : bool* aAnyStyleChanged)
368 : {
369 0 : MOZ_ASSERT(aOldStyleContext);
370 0 : MOZ_ASSERT(aComputedValues);
371 :
372 : uint32_t equalStructs, samePointerStructs;
373 : nsChangeHint result =
374 : aOldStyleContext->CalcStyleDifference(aComputedValues,
375 : &equalStructs,
376 0 : &samePointerStructs);
377 0 : *aAnyStyleChanged = equalStructs != NS_STYLE_INHERIT_MASK;
378 0 : return result;
379 : }
380 :
381 : nsChangeHint
382 0 : Gecko_HintsHandledForDescendants(nsChangeHint aHint)
383 : {
384 0 : return aHint & ~NS_HintsNotHandledForDescendantsIn(aHint);
385 : }
386 :
387 : const ServoElementSnapshot*
388 0 : Gecko_GetElementSnapshot(const ServoElementSnapshotTable* aTable,
389 : const Element* aElement)
390 : {
391 0 : MOZ_ASSERT(aTable);
392 0 : MOZ_ASSERT(aElement);
393 :
394 0 : return aTable->Get(const_cast<Element*>(aElement));
395 : }
396 :
397 : RawServoDeclarationBlockStrongBorrowedOrNull
398 0 : Gecko_GetStyleAttrDeclarationBlock(RawGeckoElementBorrowed aElement)
399 : {
400 0 : DeclarationBlock* decl = aElement->GetInlineStyleDeclaration();
401 0 : if (!decl) {
402 0 : return nullptr;
403 : }
404 0 : if (decl->IsGecko()) {
405 : // XXX This can happen when nodes are adopted from a Gecko-style-backend
406 : // document into a Servo-style-backend document. See bug 1330051.
407 0 : NS_WARNING("stylo: requesting a Gecko declaration block?");
408 0 : return nullptr;
409 : }
410 0 : return decl->AsServo()->RefRawStrong();
411 : }
412 :
413 : void
414 0 : Gecko_UnsetDirtyStyleAttr(RawGeckoElementBorrowed aElement)
415 : {
416 0 : DeclarationBlock* decl = aElement->GetInlineStyleDeclaration();
417 0 : if (!decl) {
418 0 : return;
419 : }
420 0 : if (decl->IsGecko()) {
421 : // XXX This can happen when nodes are adopted from a Gecko-style-backend
422 : // document into a Servo-style-backend document. See bug 1330051.
423 0 : NS_WARNING("stylo: requesting a Gecko declaration block?");
424 0 : return;
425 : }
426 0 : decl->UnsetDirty();
427 : }
428 :
429 : RawServoDeclarationBlockStrongBorrowedOrNull
430 0 : Gecko_GetSMILOverrideDeclarationBlock(RawGeckoElementBorrowed aElement)
431 : {
432 : // This function duplicates a lot of the code in
433 : // Gecko_GetStyleAttrDeclarationBlock above because I haven't worked out a way
434 : // to persuade hazard analysis that a pointer-to-lambda is ok yet.
435 0 : MOZ_ASSERT(aElement, "Invalid GeckoElement");
436 :
437 : DeclarationBlock* decl =
438 0 : const_cast<dom::Element*>(aElement)->GetSMILOverrideStyleDeclaration();
439 0 : if (!decl) {
440 0 : return nullptr;
441 : }
442 0 : if (decl->IsGecko()) {
443 : // XXX This can happen when nodes are adopted from a Gecko-style-backend
444 : // document into a Servo-style-backend document. See bug 1330051.
445 0 : NS_WARNING("stylo: requesting a Gecko declaration block?");
446 0 : return nullptr;
447 : }
448 0 : return decl->AsServo()->RefRawStrong();
449 : }
450 :
451 : const RawServoDeclarationBlockStrong*
452 0 : AsRefRawStrong(const RefPtr<RawServoDeclarationBlock>& aDecl)
453 : {
454 : static_assert(sizeof(RefPtr<RawServoDeclarationBlock>) ==
455 : sizeof(RawServoDeclarationBlockStrong),
456 : "RefPtr should just be a pointer");
457 0 : return reinterpret_cast<const RawServoDeclarationBlockStrong*>(&aDecl);
458 : }
459 :
460 : RawServoDeclarationBlockStrongBorrowedOrNull
461 0 : Gecko_GetHTMLPresentationAttrDeclarationBlock(RawGeckoElementBorrowed aElement)
462 : {
463 0 : const nsMappedAttributes* attrs = aElement->GetMappedAttributes();
464 0 : if (!attrs) {
465 0 : auto* svg = nsSVGElement::FromContentOrNull(aElement);
466 0 : if (svg) {
467 0 : if (auto decl = svg->GetContentDeclarationBlock()) {
468 0 : return decl->AsServo()->RefRawStrong();
469 : }
470 : }
471 0 : return nullptr;
472 : }
473 :
474 0 : return AsRefRawStrong(attrs->GetServoStyle());
475 : }
476 :
477 : RawServoDeclarationBlockStrongBorrowedOrNull
478 0 : Gecko_GetExtraContentStyleDeclarations(RawGeckoElementBorrowed aElement)
479 : {
480 0 : if (!aElement->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th)) {
481 0 : return nullptr;
482 : }
483 0 : const HTMLTableCellElement* cell = static_cast<const HTMLTableCellElement*>(aElement);
484 0 : if (nsMappedAttributes* attrs = cell->GetMappedAttributesInheritedFromTable()) {
485 0 : return AsRefRawStrong(attrs->GetServoStyle());
486 : }
487 0 : return nullptr;
488 : }
489 :
490 : RawServoDeclarationBlockStrongBorrowedOrNull
491 0 : Gecko_GetUnvisitedLinkAttrDeclarationBlock(RawGeckoElementBorrowed aElement)
492 : {
493 0 : nsHTMLStyleSheet* sheet = aElement->OwnerDoc()->GetAttributeStyleSheet();
494 0 : if (!sheet) {
495 0 : return nullptr;
496 : }
497 :
498 0 : return AsRefRawStrong(sheet->GetServoUnvisitedLinkDecl());
499 : }
500 :
501 0 : ServoStyleSheet* Gecko_StyleSheet_Clone(
502 : const ServoStyleSheet* aSheet,
503 : const ServoStyleSheet* aNewParentSheet)
504 : {
505 0 : MOZ_ASSERT(aSheet);
506 0 : MOZ_ASSERT(aSheet->GetParentSheet(), "Should only be used for @import");
507 0 : MOZ_ASSERT(aNewParentSheet, "Wat");
508 :
509 : RefPtr<StyleSheet> newSheet =
510 0 : aSheet->Clone(nullptr, nullptr, nullptr, nullptr);
511 :
512 : // NOTE(emilio): This code runs in the StylesheetInner constructor, which
513 : // means that the inner pointer of `aNewParentSheet` still points to the old
514 : // one.
515 : //
516 : // So we _don't_ update neither the parent pointer of the stylesheet, nor the
517 : // child list (yet). This is fixed up in that same constructor.
518 0 : return static_cast<ServoStyleSheet*>(newSheet.forget().take());
519 : }
520 :
521 : void
522 0 : Gecko_StyleSheet_AddRef(const ServoStyleSheet* aSheet)
523 : {
524 0 : MOZ_ASSERT(NS_IsMainThread());
525 0 : const_cast<ServoStyleSheet*>(aSheet)->AddRef();
526 0 : }
527 :
528 : void
529 0 : Gecko_StyleSheet_Release(const ServoStyleSheet* aSheet)
530 : {
531 0 : MOZ_ASSERT(NS_IsMainThread());
532 0 : const_cast<ServoStyleSheet*>(aSheet)->Release();
533 0 : }
534 :
535 : RawServoDeclarationBlockStrongBorrowedOrNull
536 0 : Gecko_GetVisitedLinkAttrDeclarationBlock(RawGeckoElementBorrowed aElement)
537 : {
538 0 : nsHTMLStyleSheet* sheet = aElement->OwnerDoc()->GetAttributeStyleSheet();
539 0 : if (!sheet) {
540 0 : return nullptr;
541 : }
542 :
543 0 : return AsRefRawStrong(sheet->GetServoVisitedLinkDecl());
544 : }
545 :
546 : RawServoDeclarationBlockStrongBorrowedOrNull
547 0 : Gecko_GetActiveLinkAttrDeclarationBlock(RawGeckoElementBorrowed aElement)
548 : {
549 0 : nsHTMLStyleSheet* sheet = aElement->OwnerDoc()->GetAttributeStyleSheet();
550 0 : if (!sheet) {
551 0 : return nullptr;
552 : }
553 :
554 0 : return AsRefRawStrong(sheet->GetServoActiveLinkDecl());
555 : }
556 :
557 : static CSSPseudoElementType
558 0 : GetPseudoTypeFromElementForAnimation(const Element*& aElementOrPseudo) {
559 0 : if (aElementOrPseudo->IsGeneratedContentContainerForBefore()) {
560 0 : aElementOrPseudo = aElementOrPseudo->GetParent()->AsElement();
561 0 : return CSSPseudoElementType::before;
562 : }
563 :
564 0 : if (aElementOrPseudo->IsGeneratedContentContainerForAfter()) {
565 0 : aElementOrPseudo = aElementOrPseudo->GetParent()->AsElement();
566 0 : return CSSPseudoElementType::after;
567 : }
568 :
569 0 : return CSSPseudoElementType::NotPseudo;
570 : }
571 :
572 : bool
573 0 : Gecko_GetAnimationRule(RawGeckoElementBorrowed aElement,
574 : EffectCompositor::CascadeLevel aCascadeLevel,
575 : RawServoAnimationValueMapBorrowedMut aAnimationValues)
576 : {
577 0 : MOZ_ASSERT(aElement);
578 :
579 0 : nsIDocument* doc = aElement->GetComposedDoc();
580 0 : if (!doc || !doc->GetShell()) {
581 0 : return false;
582 : }
583 0 : nsPresContext* presContext = doc->GetShell()->GetPresContext();
584 0 : if (!presContext || !presContext->IsDynamic()) {
585 : // For print or print preview, ignore animations.
586 0 : return false;
587 : }
588 :
589 : CSSPseudoElementType pseudoType =
590 0 : GetPseudoTypeFromElementForAnimation(aElement);
591 :
592 : return presContext->EffectCompositor()
593 0 : ->GetServoAnimationRule(aElement,
594 : pseudoType,
595 : aCascadeLevel,
596 0 : aAnimationValues);
597 : }
598 :
599 : bool
600 0 : Gecko_StyleAnimationsEquals(RawGeckoStyleAnimationListBorrowed aA,
601 : RawGeckoStyleAnimationListBorrowed aB)
602 : {
603 0 : return *aA == *aB;
604 : }
605 :
606 : void
607 0 : Gecko_UpdateAnimations(RawGeckoElementBorrowed aElement,
608 : ServoComputedValuesBorrowedOrNull aOldComputedValues,
609 : ServoComputedValuesBorrowedOrNull aComputedValues,
610 : UpdateAnimationsTasks aTasks)
611 : {
612 0 : MOZ_ASSERT(NS_IsMainThread());
613 0 : MOZ_ASSERT(aElement);
614 :
615 0 : if (!aElement->IsInComposedDoc()) {
616 0 : return;
617 : }
618 :
619 0 : nsPresContext* presContext = nsContentUtils::GetContextForContent(aElement);
620 0 : if (!presContext || !presContext->IsDynamic()) {
621 0 : return;
622 : }
623 :
624 : CSSPseudoElementType pseudoType =
625 0 : GetPseudoTypeFromElementForAnimation(aElement);
626 :
627 0 : if (aTasks & UpdateAnimationsTasks::CSSAnimations) {
628 : presContext->AnimationManager()->
629 0 : UpdateAnimations(const_cast<dom::Element*>(aElement), pseudoType,
630 0 : aComputedValues);
631 : }
632 :
633 : // aComputedValues might be nullptr if the target element is now in a
634 : // display:none subtree. We still call Gecko_UpdateAnimations in this case
635 : // because we need to stop CSS animations in the display:none subtree.
636 : // However, we don't need to update transitions since they are stopped by
637 : // RestyleManager::AnimationsWithDestroyedFrame so we just return early
638 : // here.
639 0 : if (!aComputedValues) {
640 0 : return;
641 : }
642 :
643 0 : if (aTasks & UpdateAnimationsTasks::CSSTransitions) {
644 0 : MOZ_ASSERT(aOldComputedValues);
645 : presContext->TransitionManager()->
646 0 : UpdateTransitions(const_cast<dom::Element*>(aElement), pseudoType,
647 0 : aOldComputedValues, aComputedValues);
648 : }
649 :
650 0 : if (aTasks & UpdateAnimationsTasks::EffectProperties) {
651 0 : presContext->EffectCompositor()->UpdateEffectProperties(
652 0 : aComputedValues, const_cast<dom::Element*>(aElement), pseudoType);
653 : }
654 :
655 0 : if (aTasks & UpdateAnimationsTasks::CascadeResults) {
656 : // This task will be scheduled if we detected any changes to !important
657 : // rules. We post a restyle here so that we can update the cascade
658 : // results in the pre-traversal of the next restyle.
659 : presContext->EffectCompositor()
660 0 : ->RequestRestyle(const_cast<Element*>(aElement),
661 : pseudoType,
662 : EffectCompositor::RestyleType::Standard,
663 0 : EffectCompositor::CascadeLevel::Animations);
664 : }
665 : }
666 :
667 : bool
668 0 : Gecko_ElementHasAnimations(RawGeckoElementBorrowed aElement)
669 : {
670 : CSSPseudoElementType pseudoType =
671 0 : GetPseudoTypeFromElementForAnimation(aElement);
672 :
673 0 : return !!EffectSet::GetEffectSet(aElement, pseudoType);
674 : }
675 :
676 : bool
677 0 : Gecko_ElementHasCSSAnimations(RawGeckoElementBorrowed aElement)
678 : {
679 : CSSPseudoElementType pseudoType =
680 0 : GetPseudoTypeFromElementForAnimation(aElement);
681 : nsAnimationManager::CSSAnimationCollection* collection =
682 : nsAnimationManager::CSSAnimationCollection
683 0 : ::GetAnimationCollection(aElement, pseudoType);
684 :
685 0 : return collection && !collection->mAnimations.IsEmpty();
686 : }
687 :
688 : bool
689 0 : Gecko_ElementHasCSSTransitions(RawGeckoElementBorrowed aElement)
690 : {
691 : CSSPseudoElementType pseudoType =
692 0 : GetPseudoTypeFromElementForAnimation(aElement);
693 : nsTransitionManager::CSSTransitionCollection* collection =
694 : nsTransitionManager::CSSTransitionCollection
695 0 : ::GetAnimationCollection(aElement, pseudoType);
696 :
697 0 : return collection && !collection->mAnimations.IsEmpty();
698 : }
699 :
700 : size_t
701 0 : Gecko_ElementTransitions_Length(RawGeckoElementBorrowed aElement)
702 : {
703 : CSSPseudoElementType pseudoType =
704 0 : GetPseudoTypeFromElementForAnimation(aElement);
705 : nsTransitionManager::CSSTransitionCollection* collection =
706 : nsTransitionManager::CSSTransitionCollection
707 0 : ::GetAnimationCollection(aElement, pseudoType);
708 :
709 0 : return collection ? collection->mAnimations.Length() : 0;
710 : }
711 :
712 : static CSSTransition*
713 0 : GetCurrentTransitionAt(RawGeckoElementBorrowed aElement, size_t aIndex)
714 : {
715 : CSSPseudoElementType pseudoType =
716 0 : GetPseudoTypeFromElementForAnimation(aElement);
717 : nsTransitionManager::CSSTransitionCollection* collection =
718 : nsTransitionManager::CSSTransitionCollection
719 0 : ::GetAnimationCollection(aElement, pseudoType);
720 0 : if (!collection) {
721 0 : return nullptr;
722 : }
723 0 : nsTArray<RefPtr<CSSTransition>>& transitions = collection->mAnimations;
724 0 : return aIndex < transitions.Length()
725 0 : ? transitions[aIndex].get()
726 0 : : nullptr;
727 : }
728 :
729 : nsCSSPropertyID
730 0 : Gecko_ElementTransitions_PropertyAt(RawGeckoElementBorrowed aElement,
731 : size_t aIndex)
732 : {
733 0 : CSSTransition* transition = GetCurrentTransitionAt(aElement, aIndex);
734 0 : return transition ? transition->TransitionProperty()
735 0 : : nsCSSPropertyID::eCSSProperty_UNKNOWN;
736 : }
737 :
738 : RawServoAnimationValueBorrowedOrNull
739 0 : Gecko_ElementTransitions_EndValueAt(RawGeckoElementBorrowed aElement,
740 : size_t aIndex)
741 : {
742 : CSSTransition* transition = GetCurrentTransitionAt(aElement,
743 0 : aIndex);
744 0 : return transition ? transition->ToValue().mServo.get() : nullptr;
745 : }
746 :
747 : double
748 0 : Gecko_GetProgressFromComputedTiming(RawGeckoComputedTimingBorrowed aComputedTiming)
749 : {
750 0 : return aComputedTiming->mProgress.Value();
751 : }
752 :
753 : double
754 0 : Gecko_GetPositionInSegment(RawGeckoAnimationPropertySegmentBorrowed aSegment,
755 : double aProgress,
756 : ComputedTimingFunction::BeforeFlag aBeforeFlag)
757 : {
758 0 : MOZ_ASSERT(aSegment->mFromKey < aSegment->mToKey,
759 : "The segment from key should be less than to key");
760 :
761 : double positionInSegment =
762 0 : (aProgress - aSegment->mFromKey) / (aSegment->mToKey - aSegment->mFromKey);
763 :
764 0 : return ComputedTimingFunction::GetPortion(aSegment->mTimingFunction,
765 : positionInSegment,
766 0 : aBeforeFlag);
767 : }
768 :
769 : bool
770 0 : Gecko_IsFramesTimingEnabled() {
771 0 : return sFramesTimingFunctionEnabled;
772 : }
773 :
774 : RawServoAnimationValueBorrowedOrNull
775 0 : Gecko_AnimationGetBaseStyle(void* aBaseStyles, nsCSSPropertyID aProperty)
776 : {
777 : auto base =
778 : static_cast<nsRefPtrHashtable<nsUint32HashKey, RawServoAnimationValue>*>
779 0 : (aBaseStyles);
780 0 : return base->GetWeak(aProperty);
781 : }
782 :
783 : void
784 0 : Gecko_StyleTransition_SetUnsupportedProperty(StyleTransition* aTransition,
785 : nsIAtom* aAtom)
786 : {
787 : nsCSSPropertyID id =
788 0 : nsCSSProps::LookupProperty(nsDependentAtomString(aAtom),
789 0 : CSSEnabledState::eForAllContent);
790 0 : if (id == eCSSProperty_UNKNOWN || id == eCSSPropertyExtra_variable) {
791 0 : aTransition->SetUnknownProperty(id, aAtom);
792 : } else {
793 0 : aTransition->SetProperty(id);
794 : }
795 0 : }
796 :
797 : void
798 0 : Gecko_FillAllBackgroundLists(nsStyleImageLayers* aLayers, uint32_t aMaxLen)
799 : {
800 0 : nsRuleNode::FillAllBackgroundLists(*aLayers, aMaxLen);
801 0 : }
802 :
803 : void
804 0 : Gecko_FillAllMaskLists(nsStyleImageLayers* aLayers, uint32_t aMaxLen)
805 : {
806 0 : nsRuleNode::FillAllMaskLists(*aLayers, aMaxLen);
807 0 : }
808 :
809 : RawGeckoElementBorrowedOrNull
810 0 : Gecko_GetBody(RawGeckoPresContextBorrowed aPresContext)
811 : {
812 0 : return aPresContext->Document()->GetBodyElement();
813 : }
814 :
815 0 : nscolor Gecko_GetLookAndFeelSystemColor(int32_t aId,
816 : RawGeckoPresContextBorrowed aPresContext)
817 : {
818 0 : bool useStandinsForNativeColors = aPresContext && !aPresContext->IsChrome();
819 : nscolor result;
820 0 : LookAndFeel::ColorID colorId = static_cast<LookAndFeel::ColorID>(aId);
821 0 : LookAndFeel::GetColor(colorId, useStandinsForNativeColors, &result);
822 0 : return result;
823 : }
824 :
825 : bool
826 0 : Gecko_MatchStringArgPseudo(RawGeckoElementBorrowed aElement,
827 : CSSPseudoClassType aType,
828 : const char16_t* aIdent,
829 : bool* aSetSlowSelectorFlag)
830 : {
831 0 : EventStates dummyMask; // mask is never read because we pass aDependence=nullptr
832 : return nsCSSRuleProcessor::StringPseudoMatches(aElement, aType, aIdent,
833 0 : aElement->OwnerDoc(), true,
834 0 : dummyMask, aSetSlowSelectorFlag, nullptr);
835 : }
836 :
837 : bool
838 0 : Gecko_MatchLang(RawGeckoElementBorrowed aElement,
839 : nsIAtom* aOverrideLang,
840 : bool aHasOverrideLang,
841 : const char16_t* aValue)
842 : {
843 0 : MOZ_ASSERT(!(aOverrideLang && !aHasOverrideLang),
844 : "aHasOverrideLang should only be set when aOverrideLang is null");
845 :
846 0 : if (!aHasOverrideLang) {
847 : return nsCSSRuleProcessor::LangPseudoMatches(aElement, nullptr, false,
848 0 : aValue, aElement->OwnerDoc());
849 : }
850 :
851 : return nsCSSRuleProcessor::LangPseudoMatches(aElement, aOverrideLang, true,
852 0 : aValue, aElement->OwnerDoc());
853 : }
854 :
855 : nsIAtom*
856 0 : Gecko_GetXMLLangValue(RawGeckoElementBorrowed aElement)
857 : {
858 : const nsAttrValue* attr =
859 0 : aElement->GetParsedAttr(nsGkAtoms::lang, kNameSpaceID_XML);
860 :
861 0 : if (!attr) {
862 0 : return nullptr;
863 : }
864 :
865 0 : MOZ_ASSERT(attr->Type() == nsAttrValue::eAtom);
866 :
867 0 : nsCOMPtr<nsIAtom> atom = attr->GetAtomValue();
868 0 : return atom.forget().take();
869 : }
870 :
871 : nsIDocument::DocumentTheme
872 0 : Gecko_GetDocumentLWTheme(const nsIDocument* aDocument)
873 : {
874 0 : return aDocument->ThreadSafeGetDocumentLWTheme();
875 : }
876 :
877 : template <typename Implementor>
878 : static nsIAtom*
879 0 : AtomAttrValue(Implementor* aElement, nsIAtom* aName)
880 : {
881 0 : const nsAttrValue* attr = aElement->GetParsedAttr(aName);
882 0 : return attr ? attr->GetAtomValue() : nullptr;
883 : }
884 :
885 : template <typename Implementor>
886 : static nsIAtom*
887 0 : LangValue(Implementor* aElement)
888 : {
889 : // TODO(emilio): Deduplicate a bit with nsIContent::GetLang().
890 : const nsAttrValue* attr =
891 0 : aElement->GetParsedAttr(nsGkAtoms::lang, kNameSpaceID_XML);
892 0 : if (!attr && aElement->SupportsLangAttr()) {
893 0 : attr = aElement->GetParsedAttr(nsGkAtoms::lang);
894 : }
895 :
896 0 : if (!attr) {
897 0 : return nullptr;
898 : }
899 :
900 0 : MOZ_ASSERT(attr->Type() == nsAttrValue::eAtom);
901 0 : nsCOMPtr<nsIAtom> atom = attr->GetAtomValue();
902 0 : return atom.forget().take();
903 : }
904 :
905 : template <typename Implementor, typename MatchFn>
906 : static bool
907 0 : DoMatch(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName, MatchFn aMatch)
908 : {
909 0 : if (aNS) {
910 : int32_t ns = nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNS,
911 0 : aElement->IsInChromeDocument());
912 0 : NS_ENSURE_TRUE(ns != kNameSpaceID_Unknown, false);
913 0 : const nsAttrValue* value = aElement->GetParsedAttr(aName, ns);
914 0 : return value && aMatch(value);
915 : }
916 : // No namespace means any namespace - we have to check them all. :-(
917 0 : BorrowedAttrInfo attrInfo;
918 0 : for (uint32_t i = 0; (attrInfo = aElement->GetAttrInfoAt(i)); ++i) {
919 0 : if (attrInfo.mName->LocalName() != aName) {
920 0 : continue;
921 : }
922 0 : if (aMatch(attrInfo.mValue)) {
923 0 : return true;
924 : }
925 : }
926 0 : return false;
927 : }
928 :
929 : template <typename Implementor>
930 : static bool
931 0 : HasAttr(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName)
932 : {
933 0 : auto match = [](const nsAttrValue* aValue) { return true; };
934 0 : return DoMatch(aElement, aNS, aName, match);
935 : }
936 :
937 : template <typename Implementor>
938 : static bool
939 0 : AttrEquals(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName, nsIAtom* aStr,
940 : bool aIgnoreCase)
941 : {
942 0 : auto match = [aStr, aIgnoreCase](const nsAttrValue* aValue) {
943 0 : return aValue->Equals(aStr, aIgnoreCase ? eIgnoreCase : eCaseMatters);
944 0 : };
945 0 : return DoMatch(aElement, aNS, aName, match);
946 : }
947 :
948 : #define WITH_COMPARATOR(ignore_case_, c_, expr_) \
949 : if (ignore_case_) { \
950 : const nsCaseInsensitiveStringComparator c_ \
951 : = nsCaseInsensitiveStringComparator(); \
952 : return expr_; \
953 : } else { \
954 : const nsDefaultStringComparator c_; \
955 : return expr_; \
956 : }
957 :
958 :
959 : template <typename Implementor>
960 : static bool
961 0 : AttrDashEquals(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
962 : nsIAtom* aStr, bool aIgnoreCase)
963 : {
964 0 : auto match = [aStr, aIgnoreCase](const nsAttrValue* aValue) {
965 0 : nsAutoString str;
966 0 : aValue->ToString(str);
967 0 : WITH_COMPARATOR(aIgnoreCase, c,
968 : nsStyleUtil::DashMatchCompare(str, nsDependentAtomString(aStr), c))
969 0 : };
970 0 : return DoMatch(aElement, aNS, aName, match);
971 : }
972 :
973 : template <typename Implementor>
974 : static bool
975 0 : AttrIncludes(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
976 : nsIAtom* aStr, bool aIgnoreCase)
977 : {
978 0 : auto match = [aStr, aIgnoreCase](const nsAttrValue* aValue) {
979 0 : nsAutoString str;
980 0 : aValue->ToString(str);
981 0 : WITH_COMPARATOR(aIgnoreCase, c,
982 : nsStyleUtil::ValueIncludes(str, nsDependentAtomString(aStr), c))
983 0 : };
984 0 : return DoMatch(aElement, aNS, aName, match);
985 : }
986 :
987 : template <typename Implementor>
988 : static bool
989 0 : AttrHasSubstring(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
990 : nsIAtom* aStr, bool aIgnoreCase)
991 : {
992 0 : auto match = [aStr, aIgnoreCase](const nsAttrValue* aValue) {
993 0 : nsAutoString str;
994 0 : aValue->ToString(str);
995 0 : WITH_COMPARATOR(aIgnoreCase, c,
996 : FindInReadable(nsDependentAtomString(aStr), str, c))
997 0 : };
998 0 : return DoMatch(aElement, aNS, aName, match);
999 : }
1000 :
1001 : template <typename Implementor>
1002 : static bool
1003 0 : AttrHasPrefix(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
1004 : nsIAtom* aStr, bool aIgnoreCase)
1005 : {
1006 0 : auto match = [aStr, aIgnoreCase](const nsAttrValue* aValue) {
1007 0 : nsAutoString str;
1008 0 : aValue->ToString(str);
1009 0 : WITH_COMPARATOR(aIgnoreCase, c,
1010 : StringBeginsWith(str, nsDependentAtomString(aStr), c))
1011 0 : };
1012 0 : return DoMatch(aElement, aNS, aName, match);
1013 : }
1014 :
1015 : template <typename Implementor>
1016 : static bool
1017 0 : AttrHasSuffix(Implementor* aElement, nsIAtom* aNS, nsIAtom* aName,
1018 : nsIAtom* aStr, bool aIgnoreCase)
1019 : {
1020 0 : auto match = [aStr, aIgnoreCase](const nsAttrValue* aValue) {
1021 0 : nsAutoString str;
1022 0 : aValue->ToString(str);
1023 0 : WITH_COMPARATOR(aIgnoreCase, c,
1024 : StringEndsWith(str, nsDependentAtomString(aStr), c))
1025 0 : };
1026 0 : return DoMatch(aElement, aNS, aName, match);
1027 : }
1028 :
1029 : /**
1030 : * Gets the class or class list (if any) of the implementor. The calling
1031 : * convention here is rather hairy, and is optimized for getting Servo the
1032 : * information it needs for hot calls.
1033 : *
1034 : * The return value indicates the number of classes. If zero, neither outparam
1035 : * is valid. If one, the class_ outparam is filled with the atom of the class.
1036 : * If two or more, the classList outparam is set to point to an array of atoms
1037 : * representing the class list.
1038 : *
1039 : * The array is borrowed and the atoms are not addrefed. These values can be
1040 : * invalidated by any DOM mutation. Use them in a tight scope.
1041 : */
1042 : template <typename Implementor>
1043 : static uint32_t
1044 0 : ClassOrClassList(Implementor* aElement, nsIAtom** aClass, nsIAtom*** aClassList)
1045 : {
1046 0 : const nsAttrValue* attr = aElement->GetClasses();
1047 0 : if (!attr) {
1048 0 : return 0;
1049 : }
1050 :
1051 : // For class values with only whitespace, Gecko just stores a string. For the
1052 : // purposes of the style system, there is no class in this case.
1053 0 : if (attr->Type() == nsAttrValue::eString) {
1054 0 : MOZ_ASSERT(nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
1055 : attr->GetStringValue()).IsEmpty());
1056 0 : return 0;
1057 : }
1058 :
1059 : // Single tokens are generally stored as an atom. Check that case.
1060 0 : if (attr->Type() == nsAttrValue::eAtom) {
1061 0 : *aClass = attr->GetAtomValue();
1062 0 : return 1;
1063 : }
1064 :
1065 : // At this point we should have an atom array. It is likely, but not
1066 : // guaranteed, that we have two or more elements in the array.
1067 0 : MOZ_ASSERT(attr->Type() == nsAttrValue::eAtomArray);
1068 0 : nsTArray<nsCOMPtr<nsIAtom>>* atomArray = attr->GetAtomArrayValue();
1069 0 : uint32_t length = atomArray->Length();
1070 :
1071 : // Special case: zero elements.
1072 0 : if (length == 0) {
1073 0 : return 0;
1074 : }
1075 :
1076 : // Special case: one element.
1077 0 : if (length == 1) {
1078 0 : *aClass = atomArray->ElementAt(0);
1079 0 : return 1;
1080 : }
1081 :
1082 : // General case: Two or more elements.
1083 : //
1084 : // Note: We could also expose this array as an array of nsCOMPtrs, since
1085 : // bindgen knows what those look like, and eliminate the reinterpret_cast.
1086 : // But it's not obvious that that would be preferable.
1087 : static_assert(sizeof(nsCOMPtr<nsIAtom>) == sizeof(nsIAtom*), "Bad simplification");
1088 : static_assert(alignof(nsCOMPtr<nsIAtom>) == alignof(nsIAtom*), "Bad simplification");
1089 :
1090 0 : nsCOMPtr<nsIAtom>* elements = atomArray->Elements();
1091 0 : nsIAtom** rawElements = reinterpret_cast<nsIAtom**>(elements);
1092 0 : *aClassList = rawElements;
1093 0 : return atomArray->Length();
1094 : }
1095 :
1096 : #define SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(prefix_, implementor_) \
1097 : nsIAtom* prefix_##AtomAttrValue(implementor_ aElement, nsIAtom* aName) \
1098 : { \
1099 : return AtomAttrValue(aElement, aName); \
1100 : } \
1101 : nsIAtom* prefix_##LangValue(implementor_ aElement) \
1102 : { \
1103 : return LangValue(aElement); \
1104 : } \
1105 : bool prefix_##HasAttr(implementor_ aElement, nsIAtom* aNS, nsIAtom* aName) \
1106 : { \
1107 : return HasAttr(aElement, aNS, aName); \
1108 : } \
1109 : bool prefix_##AttrEquals(implementor_ aElement, nsIAtom* aNS, \
1110 : nsIAtom* aName, nsIAtom* aStr, bool aIgnoreCase) \
1111 : { \
1112 : return AttrEquals(aElement, aNS, aName, aStr, aIgnoreCase); \
1113 : } \
1114 : bool prefix_##AttrDashEquals(implementor_ aElement, nsIAtom* aNS, \
1115 : nsIAtom* aName, nsIAtom* aStr, bool aIgnoreCase) \
1116 : { \
1117 : return AttrDashEquals(aElement, aNS, aName, aStr, aIgnoreCase); \
1118 : } \
1119 : bool prefix_##AttrIncludes(implementor_ aElement, nsIAtom* aNS, \
1120 : nsIAtom* aName, nsIAtom* aStr, bool aIgnoreCase) \
1121 : { \
1122 : return AttrIncludes(aElement, aNS, aName, aStr, aIgnoreCase); \
1123 : } \
1124 : bool prefix_##AttrHasSubstring(implementor_ aElement, nsIAtom* aNS, \
1125 : nsIAtom* aName, nsIAtom* aStr, bool aIgnoreCase)\
1126 : { \
1127 : return AttrHasSubstring(aElement, aNS, aName, aStr, aIgnoreCase); \
1128 : } \
1129 : bool prefix_##AttrHasPrefix(implementor_ aElement, nsIAtom* aNS, \
1130 : nsIAtom* aName, nsIAtom* aStr, bool aIgnoreCase) \
1131 : { \
1132 : return AttrHasPrefix(aElement, aNS, aName, aStr, aIgnoreCase); \
1133 : } \
1134 : bool prefix_##AttrHasSuffix(implementor_ aElement, nsIAtom* aNS, \
1135 : nsIAtom* aName, nsIAtom* aStr, bool aIgnoreCase) \
1136 : { \
1137 : return AttrHasSuffix(aElement, aNS, aName, aStr, aIgnoreCase); \
1138 : } \
1139 : uint32_t prefix_##ClassOrClassList(implementor_ aElement, nsIAtom** aClass, \
1140 : nsIAtom*** aClassList) \
1141 : { \
1142 : return ClassOrClassList(aElement, aClass, aClassList); \
1143 : }
1144 :
1145 0 : SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_, RawGeckoElementBorrowed)
1146 0 : SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_Snapshot, const ServoElementSnapshot*)
1147 :
1148 : #undef SERVO_IMPL_ELEMENT_ATTR_MATCHING_FUNCTIONS
1149 :
1150 : nsIAtom*
1151 0 : Gecko_Atomize(const char* aString, uint32_t aLength)
1152 : {
1153 0 : return NS_Atomize(nsDependentCSubstring(aString, aLength)).take();
1154 : }
1155 :
1156 : nsIAtom*
1157 0 : Gecko_Atomize16(const nsAString* aString)
1158 : {
1159 0 : return NS_Atomize(*aString).take();
1160 : }
1161 :
1162 : void
1163 0 : Gecko_AddRefAtom(nsIAtom* aAtom)
1164 : {
1165 0 : NS_ADDREF(aAtom);
1166 0 : }
1167 :
1168 : void
1169 0 : Gecko_ReleaseAtom(nsIAtom* aAtom)
1170 : {
1171 0 : NS_RELEASE(aAtom);
1172 0 : }
1173 :
1174 : const uint16_t*
1175 0 : Gecko_GetAtomAsUTF16(nsIAtom* aAtom, uint32_t* aLength)
1176 : {
1177 : static_assert(sizeof(char16_t) == sizeof(uint16_t), "Servo doesn't know what a char16_t is");
1178 0 : MOZ_ASSERT(aAtom);
1179 0 : *aLength = aAtom->GetLength();
1180 :
1181 : // We need to manually cast from char16ptr_t to const char16_t* to handle the
1182 : // MOZ_USE_CHAR16_WRAPPER we use on WIndows.
1183 0 : return reinterpret_cast<const uint16_t*>(static_cast<const char16_t*>(aAtom->GetUTF16String()));
1184 : }
1185 :
1186 : bool
1187 0 : Gecko_AtomEqualsUTF8(nsIAtom* aAtom, const char* aString, uint32_t aLength)
1188 : {
1189 : // XXXbholley: We should be able to do this without converting, I just can't
1190 : // find the right thing to call.
1191 0 : nsDependentAtomString atomStr(aAtom);
1192 0 : NS_ConvertUTF8toUTF16 inStr(nsDependentCSubstring(aString, aLength));
1193 0 : return atomStr.Equals(inStr);
1194 : }
1195 :
1196 : bool
1197 0 : Gecko_AtomEqualsUTF8IgnoreCase(nsIAtom* aAtom, const char* aString, uint32_t aLength)
1198 : {
1199 : // XXXbholley: We should be able to do this without converting, I just can't
1200 : // find the right thing to call.
1201 0 : nsDependentAtomString atomStr(aAtom);
1202 0 : NS_ConvertUTF8toUTF16 inStr(nsDependentCSubstring(aString, aLength));
1203 0 : return nsContentUtils::EqualsIgnoreASCIICase(atomStr, inStr);
1204 : }
1205 :
1206 : void
1207 0 : Gecko_EnsureMozBorderColors(nsStyleBorder* aBorder)
1208 : {
1209 0 : aBorder->EnsureBorderColors();
1210 0 : }
1211 :
1212 0 : void Gecko_ClearMozBorderColors(nsStyleBorder* aBorder, mozilla::Side aSide)
1213 : {
1214 0 : aBorder->ClearBorderColors(aSide);
1215 0 : }
1216 :
1217 : void
1218 0 : Gecko_AppendMozBorderColors(nsStyleBorder* aBorder, mozilla::Side aSide,
1219 : nscolor aColor)
1220 : {
1221 0 : aBorder->AppendBorderColor(aSide, aColor);
1222 0 : }
1223 :
1224 : void
1225 0 : Gecko_CopyMozBorderColors(nsStyleBorder* aDest, const nsStyleBorder* aSrc,
1226 : mozilla::Side aSide)
1227 : {
1228 0 : if (aSrc->mBorderColors) {
1229 0 : aDest->CopyBorderColorsFrom(aSrc->mBorderColors[aSide], aSide);
1230 : }
1231 0 : }
1232 :
1233 : const nsBorderColors*
1234 0 : Gecko_GetMozBorderColors(const nsStyleBorder* aBorder, mozilla::Side aSide)
1235 : {
1236 0 : MOZ_ASSERT(aBorder);
1237 0 : return aBorder->mBorderColors ? aBorder->mBorderColors[aSide] : nullptr;
1238 : }
1239 :
1240 : void
1241 0 : Gecko_FontFamilyList_Clear(FontFamilyList* aList) {
1242 0 : aList->Clear();
1243 0 : }
1244 :
1245 : void
1246 0 : Gecko_FontFamilyList_AppendNamed(FontFamilyList* aList, nsIAtom* aName, bool aQuoted)
1247 : {
1248 0 : FontFamilyName family;
1249 0 : aName->ToString(family.mName);
1250 0 : if (aQuoted) {
1251 0 : family.mType = eFamily_named_quoted;
1252 : }
1253 :
1254 0 : aList->Append(family);
1255 0 : }
1256 :
1257 : void
1258 0 : Gecko_FontFamilyList_AppendGeneric(FontFamilyList* aList, FontFamilyType aType)
1259 : {
1260 0 : aList->Append(FontFamilyName(aType));
1261 0 : }
1262 :
1263 : void
1264 0 : Gecko_CopyFontFamilyFrom(nsFont* dst, const nsFont* src)
1265 : {
1266 0 : dst->fontlist = src->fontlist;
1267 0 : }
1268 :
1269 : void
1270 0 : Gecko_nsFont_InitSystem(nsFont* aDest, int32_t aFontId,
1271 : const nsStyleFont* aFont, RawGeckoPresContextBorrowed aPresContext)
1272 : {
1273 0 : const nsFont* defaultVariableFont = ThreadSafeGetDefaultFontHelper(aPresContext, aFont->mLanguage,
1274 0 : kPresContext_DefaultVariableFont_ID);
1275 :
1276 : // We have passed uninitialized memory to this function,
1277 : // initialize it. We can't simply return an nsFont because then
1278 : // we need to know its size beforehand. Servo cannot initialize nsFont
1279 : // itself, so this will do.
1280 0 : nsFont* system = new (aDest) nsFont(*defaultVariableFont);
1281 :
1282 0 : MOZ_RELEASE_ASSERT(system);
1283 :
1284 0 : *aDest = *defaultVariableFont;
1285 0 : LookAndFeel::FontID fontID = static_cast<LookAndFeel::FontID>(aFontId);
1286 :
1287 0 : MutexAutoLock lock(*sServoFontMetricsLock);
1288 0 : nsRuleNode::ComputeSystemFont(aDest, fontID, aPresContext, defaultVariableFont);
1289 0 : }
1290 :
1291 : void
1292 0 : Gecko_nsFont_Destroy(nsFont* aDest)
1293 : {
1294 0 : aDest->~nsFont();
1295 0 : }
1296 :
1297 :
1298 : void
1299 0 : Gecko_ClearAlternateValues(nsFont* aFont, size_t aLength)
1300 : {
1301 0 : aFont->alternateValues.Clear();
1302 0 : aFont->alternateValues.SetCapacity(aLength);
1303 0 : }
1304 :
1305 : void
1306 0 : Gecko_AppendAlternateValues(nsFont* aFont, uint32_t aAlternateName, nsIAtom* aAtom)
1307 : {
1308 0 : aFont->alternateValues.AppendElement(gfxAlternateValue {
1309 : aAlternateName,
1310 0 : nsDependentAtomString(aAtom)
1311 0 : });
1312 0 : }
1313 :
1314 : void
1315 0 : Gecko_CopyAlternateValuesFrom(nsFont* aDest, const nsFont* aSrc)
1316 : {
1317 0 : aDest->alternateValues.Clear();
1318 0 : aDest->alternateValues.AppendElements(aSrc->alternateValues);
1319 0 : }
1320 :
1321 : void
1322 0 : Gecko_SetImageOrientation(nsStyleVisibility* aVisibility,
1323 : double aRadians, bool aFlip)
1324 : {
1325 : aVisibility->mImageOrientation =
1326 0 : nsStyleImageOrientation::CreateAsAngleAndFlip(aRadians, aFlip);
1327 0 : }
1328 :
1329 : void
1330 0 : Gecko_SetImageOrientationAsFromImage(nsStyleVisibility* aVisibility)
1331 : {
1332 0 : aVisibility->mImageOrientation = nsStyleImageOrientation::CreateAsFromImage();
1333 0 : }
1334 :
1335 : void
1336 0 : Gecko_CopyImageOrientationFrom(nsStyleVisibility* aDst,
1337 : const nsStyleVisibility* aSrc)
1338 : {
1339 0 : aDst->mImageOrientation = aSrc->mImageOrientation;
1340 0 : }
1341 :
1342 : void
1343 0 : Gecko_SetCounterStyleToName(CounterStylePtr* aPtr, nsIAtom* aName,
1344 : RawGeckoPresContextBorrowed aPresContext)
1345 : {
1346 : // Try resolving the counter style if possible, and keep it unresolved
1347 : // otherwise.
1348 0 : CounterStyleManager* manager = aPresContext->CounterStyleManager();
1349 0 : nsCOMPtr<nsIAtom> name = already_AddRefed<nsIAtom>(aName);
1350 0 : if (CounterStyle* style = manager->GetCounterStyle(name)) {
1351 0 : *aPtr = style;
1352 : } else {
1353 0 : *aPtr = name.forget();
1354 : }
1355 0 : }
1356 :
1357 : void
1358 0 : Gecko_SetCounterStyleToSymbols(CounterStylePtr* aPtr, uint8_t aSymbolsType,
1359 : nsACString const* const* aSymbols,
1360 : uint32_t aSymbolsCount)
1361 : {
1362 0 : nsTArray<nsString> symbols(aSymbolsCount);
1363 0 : for (uint32_t i = 0; i < aSymbolsCount; i++) {
1364 0 : symbols.AppendElement(NS_ConvertUTF8toUTF16(*aSymbols[i]));
1365 : }
1366 0 : *aPtr = new AnonymousCounterStyle(aSymbolsType, Move(symbols));
1367 0 : }
1368 :
1369 : void
1370 0 : Gecko_SetCounterStyleToString(CounterStylePtr* aPtr, const nsACString* aSymbol)
1371 : {
1372 0 : *aPtr = new AnonymousCounterStyle(NS_ConvertUTF8toUTF16(*aSymbol));
1373 0 : }
1374 :
1375 : void
1376 0 : Gecko_CopyCounterStyle(CounterStylePtr* aDst, const CounterStylePtr* aSrc)
1377 : {
1378 0 : *aDst = *aSrc;
1379 0 : }
1380 :
1381 : already_AddRefed<css::URLValue>
1382 0 : ServoBundledURI::IntoCssUrl()
1383 : {
1384 0 : if (!mURLString) {
1385 0 : return nullptr;
1386 : }
1387 :
1388 0 : MOZ_ASSERT(mExtraData->GetReferrer());
1389 0 : MOZ_ASSERT(mExtraData->GetPrincipal());
1390 :
1391 0 : NS_ConvertUTF8toUTF16 url(reinterpret_cast<const char*>(mURLString),
1392 0 : mURLStringLength);
1393 :
1394 : RefPtr<css::URLValue> urlValue =
1395 0 : new css::URLValue(url, do_AddRef(mExtraData));
1396 0 : return urlValue.forget();
1397 : }
1398 :
1399 : void
1400 0 : Gecko_SetNullImageValue(nsStyleImage* aImage)
1401 : {
1402 0 : MOZ_ASSERT(aImage);
1403 0 : aImage->SetNull();
1404 0 : }
1405 :
1406 : void
1407 0 : Gecko_SetGradientImageValue(nsStyleImage* aImage, nsStyleGradient* aGradient)
1408 : {
1409 0 : MOZ_ASSERT(aImage);
1410 0 : aImage->SetGradientData(aGradient);
1411 0 : }
1412 :
1413 0 : NS_IMPL_THREADSAFE_FFI_REFCOUNTING(mozilla::css::ImageValue, ImageValue);
1414 :
1415 : static already_AddRefed<nsStyleImageRequest>
1416 0 : CreateStyleImageRequest(nsStyleImageRequest::Mode aModeFlags,
1417 : mozilla::css::ImageValue* aImageValue)
1418 : {
1419 : RefPtr<nsStyleImageRequest> req =
1420 0 : new nsStyleImageRequest(aModeFlags, aImageValue);
1421 0 : return req.forget();
1422 : }
1423 :
1424 : mozilla::css::ImageValue*
1425 0 : Gecko_ImageValue_Create(ServoBundledURI aURI)
1426 : {
1427 0 : NS_ConvertUTF8toUTF16 url(reinterpret_cast<const char*>(aURI.mURLString),
1428 0 : aURI.mURLStringLength);
1429 :
1430 : RefPtr<css::ImageValue> value(
1431 0 : new css::ImageValue(url, do_AddRef(aURI.mExtraData)));
1432 0 : return value.forget().take();
1433 : }
1434 :
1435 : void
1436 0 : Gecko_SetLayerImageImageValue(nsStyleImage* aImage,
1437 : mozilla::css::ImageValue* aImageValue)
1438 : {
1439 0 : MOZ_ASSERT(aImage && aImageValue);
1440 :
1441 : RefPtr<nsStyleImageRequest> req =
1442 0 : CreateStyleImageRequest(nsStyleImageRequest::Mode::Track, aImageValue);
1443 0 : aImage->SetImageRequest(req.forget());
1444 0 : }
1445 :
1446 : void
1447 0 : Gecko_SetImageElement(nsStyleImage* aImage, nsIAtom* aAtom) {
1448 0 : MOZ_ASSERT(aImage);
1449 0 : aImage->SetElementId(do_AddRef(aAtom));
1450 0 : }
1451 :
1452 : void
1453 0 : Gecko_CopyImageValueFrom(nsStyleImage* aImage, const nsStyleImage* aOther)
1454 : {
1455 0 : MOZ_ASSERT(aImage);
1456 0 : MOZ_ASSERT(aOther);
1457 :
1458 0 : *aImage = *aOther;
1459 0 : }
1460 :
1461 : void
1462 0 : Gecko_InitializeImageCropRect(nsStyleImage* aImage)
1463 : {
1464 0 : MOZ_ASSERT(aImage);
1465 0 : aImage->SetCropRect(MakeUnique<nsStyleSides>());
1466 0 : }
1467 :
1468 : void
1469 0 : Gecko_SetCursorArrayLength(nsStyleUserInterface* aStyleUI, size_t aLen)
1470 : {
1471 0 : aStyleUI->mCursorImages.Clear();
1472 0 : aStyleUI->mCursorImages.SetLength(aLen);
1473 0 : }
1474 :
1475 : void
1476 0 : Gecko_SetCursorImageValue(nsCursorImage* aCursor,
1477 : mozilla::css::ImageValue* aImageValue)
1478 : {
1479 0 : MOZ_ASSERT(aCursor && aImageValue);
1480 :
1481 : aCursor->mImage =
1482 0 : CreateStyleImageRequest(nsStyleImageRequest::Mode::Discard, aImageValue);
1483 0 : }
1484 :
1485 : void
1486 0 : Gecko_CopyCursorArrayFrom(nsStyleUserInterface* aDest,
1487 : const nsStyleUserInterface* aSrc)
1488 : {
1489 0 : aDest->mCursorImages = aSrc->mCursorImages;
1490 0 : }
1491 :
1492 : void
1493 0 : Gecko_SetContentDataImageValue(nsStyleContentData* aContent,
1494 : mozilla::css::ImageValue* aImageValue)
1495 : {
1496 0 : MOZ_ASSERT(aContent && aImageValue);
1497 :
1498 : RefPtr<nsStyleImageRequest> req =
1499 0 : CreateStyleImageRequest(nsStyleImageRequest::Mode::Track, aImageValue);
1500 0 : aContent->SetImageRequest(req.forget());
1501 0 : }
1502 :
1503 : nsStyleContentData::CounterFunction*
1504 0 : Gecko_SetCounterFunction(nsStyleContentData* aContent, nsStyleContentType aType)
1505 : {
1506 : RefPtr<nsStyleContentData::CounterFunction>
1507 0 : counterFunc = new nsStyleContentData::CounterFunction();
1508 0 : nsStyleContentData::CounterFunction* ptr = counterFunc;
1509 0 : aContent->SetCounters(aType, counterFunc.forget());
1510 0 : return ptr;
1511 : }
1512 :
1513 : nsStyleGradient*
1514 0 : Gecko_CreateGradient(uint8_t aShape,
1515 : uint8_t aSize,
1516 : bool aRepeating,
1517 : bool aLegacySyntax,
1518 : bool aMozLegacySyntax,
1519 : uint32_t aStopCount)
1520 : {
1521 0 : nsStyleGradient* result = new nsStyleGradient();
1522 :
1523 0 : result->mShape = aShape;
1524 0 : result->mSize = aSize;
1525 0 : result->mRepeating = aRepeating;
1526 0 : result->mLegacySyntax = aLegacySyntax;
1527 0 : result->mMozLegacySyntax = aMozLegacySyntax;
1528 :
1529 0 : result->mAngle.SetNoneValue();
1530 0 : result->mBgPosX.SetNoneValue();
1531 0 : result->mBgPosY.SetNoneValue();
1532 0 : result->mRadiusX.SetNoneValue();
1533 0 : result->mRadiusY.SetNoneValue();
1534 :
1535 0 : nsStyleGradientStop dummyStop;
1536 0 : dummyStop.mLocation.SetNoneValue();
1537 0 : dummyStop.mColor = NS_RGB(0, 0, 0);
1538 0 : dummyStop.mIsInterpolationHint = 0;
1539 :
1540 0 : for (uint32_t i = 0; i < aStopCount; i++) {
1541 0 : result->mStops.AppendElement(dummyStop);
1542 : }
1543 :
1544 0 : return result;
1545 : }
1546 :
1547 : const mozilla::css::URLValueData*
1548 0 : Gecko_GetURLValue(const nsStyleImage* aImage)
1549 : {
1550 0 : MOZ_ASSERT(aImage && aImage->GetType() == eStyleImageType_Image);
1551 0 : return aImage->GetURLValue();
1552 : }
1553 :
1554 : nsIAtom*
1555 0 : Gecko_GetImageElement(const nsStyleImage* aImage)
1556 : {
1557 0 : MOZ_ASSERT(aImage && aImage->GetType() == eStyleImageType_Element);
1558 0 : return const_cast<nsIAtom*>(aImage->GetElementId());
1559 : }
1560 :
1561 : const nsStyleGradient*
1562 0 : Gecko_GetGradientImageValue(const nsStyleImage* aImage)
1563 : {
1564 0 : MOZ_ASSERT(aImage && aImage->GetType() == eStyleImageType_Gradient);
1565 0 : return aImage->GetGradientData();
1566 : }
1567 :
1568 : void
1569 0 : Gecko_SetListStyleImageNone(nsStyleList* aList)
1570 : {
1571 0 : aList->mListStyleImage = nullptr;
1572 0 : }
1573 :
1574 : void
1575 0 : Gecko_SetListStyleImageImageValue(nsStyleList* aList,
1576 : mozilla::css::ImageValue* aImageValue)
1577 : {
1578 0 : MOZ_ASSERT(aList && aImageValue);
1579 :
1580 : aList->mListStyleImage =
1581 0 : CreateStyleImageRequest(nsStyleImageRequest::Mode(0), aImageValue);
1582 0 : }
1583 :
1584 : void
1585 0 : Gecko_CopyListStyleImageFrom(nsStyleList* aList, const nsStyleList* aSource)
1586 : {
1587 0 : aList->mListStyleImage = aSource->mListStyleImage;
1588 0 : }
1589 :
1590 : void
1591 0 : Gecko_EnsureTArrayCapacity(void* aArray, size_t aCapacity, size_t aElemSize)
1592 : {
1593 : auto base =
1594 : reinterpret_cast<nsTArray_base<nsTArrayInfallibleAllocator,
1595 0 : nsTArray_CopyWithMemutils>*>(aArray);
1596 :
1597 0 : base->EnsureCapacity<nsTArrayInfallibleAllocator>(aCapacity, aElemSize);
1598 0 : }
1599 :
1600 : void
1601 0 : Gecko_ClearPODTArray(void* aArray, size_t aElementSize, size_t aElementAlign)
1602 : {
1603 : auto base =
1604 : reinterpret_cast<nsTArray_base<nsTArrayInfallibleAllocator,
1605 0 : nsTArray_CopyWithMemutils>*>(aArray);
1606 :
1607 0 : base->template ShiftData<nsTArrayInfallibleAllocator>(0, base->Length(), 0,
1608 0 : aElementSize, aElementAlign);
1609 0 : }
1610 :
1611 0 : void Gecko_SetStyleGridTemplateArrayLengths(nsStyleGridTemplate* aValue,
1612 : uint32_t aTrackSizes)
1613 : {
1614 0 : aValue->mMinTrackSizingFunctions.SetLength(aTrackSizes);
1615 0 : aValue->mMaxTrackSizingFunctions.SetLength(aTrackSizes);
1616 0 : aValue->mLineNameLists.SetLength(aTrackSizes + 1);
1617 0 : }
1618 :
1619 0 : void Gecko_SetGridTemplateLineNamesLength(nsStyleGridTemplate* aValue,
1620 : uint32_t aNames)
1621 : {
1622 0 : aValue->mLineNameLists.SetLength(aNames);
1623 0 : }
1624 :
1625 0 : void Gecko_ResizeTArrayForStrings(nsTArray<nsString>* aArray, uint32_t aLength)
1626 : {
1627 0 : aArray->SetLength(aLength);
1628 0 : }
1629 :
1630 : void
1631 0 : Gecko_CopyStyleGridTemplateValues(nsStyleGridTemplate* aGridTemplate,
1632 : const nsStyleGridTemplate* aOther)
1633 : {
1634 0 : *aGridTemplate = *aOther;
1635 0 : }
1636 :
1637 : mozilla::css::GridTemplateAreasValue*
1638 0 : Gecko_NewGridTemplateAreasValue(uint32_t aAreas, uint32_t aTemplates, uint32_t aColumns)
1639 : {
1640 0 : RefPtr<mozilla::css::GridTemplateAreasValue> value = new mozilla::css::GridTemplateAreasValue;
1641 0 : value->mNamedAreas.SetLength(aAreas);
1642 0 : value->mTemplates.SetLength(aTemplates);
1643 0 : value->mNColumns = aColumns;
1644 0 : return value.forget().take();
1645 : }
1646 :
1647 0 : NS_IMPL_THREADSAFE_FFI_REFCOUNTING(mozilla::css::GridTemplateAreasValue, GridTemplateAreasValue);
1648 :
1649 : void
1650 0 : Gecko_ClearAndResizeStyleContents(nsStyleContent* aContent, uint32_t aHowMany)
1651 : {
1652 0 : aContent->AllocateContents(aHowMany);
1653 0 : }
1654 :
1655 : void
1656 0 : Gecko_CopyStyleContentsFrom(nsStyleContent* aContent, const nsStyleContent* aOther)
1657 : {
1658 0 : uint32_t count = aOther->ContentCount();
1659 :
1660 0 : aContent->AllocateContents(count);
1661 :
1662 0 : for (uint32_t i = 0; i < count; ++i) {
1663 0 : aContent->ContentAt(i) = aOther->ContentAt(i);
1664 : }
1665 0 : }
1666 :
1667 : void
1668 0 : Gecko_ClearAndResizeCounterIncrements(nsStyleContent* aContent, uint32_t aHowMany)
1669 : {
1670 0 : aContent->AllocateCounterIncrements(aHowMany);
1671 0 : }
1672 :
1673 : void
1674 0 : Gecko_CopyCounterIncrementsFrom(nsStyleContent* aContent, const nsStyleContent* aOther)
1675 : {
1676 0 : uint32_t count = aOther->CounterIncrementCount();
1677 :
1678 0 : aContent->AllocateCounterIncrements(count);
1679 :
1680 0 : for (uint32_t i = 0; i < count; ++i) {
1681 0 : const nsStyleCounterData& data = aOther->CounterIncrementAt(i);
1682 0 : aContent->SetCounterIncrementAt(i, data.mCounter, data.mValue);
1683 : }
1684 0 : }
1685 :
1686 : void
1687 0 : Gecko_ClearAndResizeCounterResets(nsStyleContent* aContent, uint32_t aHowMany)
1688 : {
1689 0 : aContent->AllocateCounterResets(aHowMany);
1690 0 : }
1691 :
1692 : void
1693 0 : Gecko_CopyCounterResetsFrom(nsStyleContent* aContent, const nsStyleContent* aOther)
1694 : {
1695 0 : uint32_t count = aOther->CounterResetCount();
1696 :
1697 0 : aContent->AllocateCounterResets(count);
1698 :
1699 0 : for (uint32_t i = 0; i < count; ++i) {
1700 0 : const nsStyleCounterData& data = aOther->CounterResetAt(i);
1701 0 : aContent->SetCounterResetAt(i, data.mCounter, data.mValue);
1702 : }
1703 0 : }
1704 :
1705 : void
1706 0 : Gecko_EnsureImageLayersLength(nsStyleImageLayers* aLayers, size_t aLen,
1707 : nsStyleImageLayers::LayerType aLayerType)
1708 : {
1709 0 : size_t oldLength = aLayers->mLayers.Length();
1710 :
1711 0 : aLayers->mLayers.EnsureLengthAtLeast(aLen);
1712 :
1713 0 : for (size_t i = oldLength; i < aLen; ++i) {
1714 0 : aLayers->mLayers[i].Initialize(aLayerType);
1715 : }
1716 0 : }
1717 :
1718 : void
1719 0 : Gecko_EnsureStyleAnimationArrayLength(void* aArray, size_t aLen)
1720 : {
1721 : auto base =
1722 0 : static_cast<nsStyleAutoArray<StyleAnimation>*>(aArray);
1723 :
1724 0 : size_t oldLength = base->Length();
1725 :
1726 0 : base->EnsureLengthAtLeast(aLen);
1727 :
1728 0 : for (size_t i = oldLength; i < aLen; ++i) {
1729 0 : (*base)[i].SetInitialValues();
1730 : }
1731 0 : }
1732 :
1733 : void
1734 0 : Gecko_EnsureStyleTransitionArrayLength(void* aArray, size_t aLen)
1735 : {
1736 : auto base =
1737 0 : reinterpret_cast<nsStyleAutoArray<StyleTransition>*>(aArray);
1738 :
1739 0 : size_t oldLength = base->Length();
1740 :
1741 0 : base->EnsureLengthAtLeast(aLen);
1742 :
1743 0 : for (size_t i = oldLength; i < aLen; ++i) {
1744 0 : (*base)[i].SetInitialValues();
1745 : }
1746 0 : }
1747 :
1748 : void
1749 0 : Gecko_ClearWillChange(nsStyleDisplay* aDisplay, size_t aLength)
1750 : {
1751 0 : aDisplay->mWillChange.Clear();
1752 0 : aDisplay->mWillChange.SetCapacity(aLength);
1753 0 : }
1754 :
1755 : void
1756 0 : Gecko_AppendWillChange(nsStyleDisplay* aDisplay, nsIAtom* aAtom)
1757 : {
1758 0 : aDisplay->mWillChange.AppendElement(aAtom);
1759 0 : }
1760 :
1761 : void
1762 0 : Gecko_CopyWillChangeFrom(nsStyleDisplay* aDest, nsStyleDisplay* aSrc)
1763 : {
1764 0 : aDest->mWillChange.Clear();
1765 0 : aDest->mWillChange.AppendElements(aSrc->mWillChange);
1766 0 : }
1767 :
1768 : enum class KeyframeSearchDirection {
1769 : Forwards,
1770 : Backwards,
1771 : };
1772 :
1773 : enum class KeyframeInsertPosition {
1774 : Prepend,
1775 : LastForOffset,
1776 : };
1777 :
1778 : static Keyframe*
1779 0 : GetOrCreateKeyframe(nsTArray<Keyframe>* aKeyframes,
1780 : float aOffset,
1781 : const nsTimingFunction* aTimingFunction,
1782 : KeyframeSearchDirection aSearchDirection,
1783 : KeyframeInsertPosition aInsertPosition)
1784 : {
1785 0 : MOZ_ASSERT(aKeyframes, "The keyframe array should be valid");
1786 0 : MOZ_ASSERT(aTimingFunction, "The timing function should be valid");
1787 0 : MOZ_ASSERT(aOffset >= 0. && aOffset <= 1.,
1788 : "The offset should be in the range of [0.0, 1.0]");
1789 :
1790 : size_t keyframeIndex;
1791 0 : switch (aSearchDirection) {
1792 : case KeyframeSearchDirection::Forwards:
1793 0 : if (nsAnimationManager::FindMatchingKeyframe(*aKeyframes,
1794 : aOffset,
1795 : *aTimingFunction,
1796 : keyframeIndex)) {
1797 0 : return &(*aKeyframes)[keyframeIndex];
1798 : }
1799 0 : break;
1800 : case KeyframeSearchDirection::Backwards:
1801 0 : if (nsAnimationManager::FindMatchingKeyframe(Reversed(*aKeyframes),
1802 : aOffset,
1803 : *aTimingFunction,
1804 : keyframeIndex)) {
1805 0 : return &(*aKeyframes)[aKeyframes->Length() - 1 - keyframeIndex];
1806 : }
1807 0 : keyframeIndex = aKeyframes->Length() - 1;
1808 0 : break;
1809 : }
1810 :
1811 : Keyframe* keyframe =
1812 0 : aKeyframes->InsertElementAt(
1813 : aInsertPosition == KeyframeInsertPosition::Prepend
1814 : ? 0
1815 0 : : keyframeIndex);
1816 0 : keyframe->mOffset.emplace(aOffset);
1817 0 : if (aTimingFunction->mType != nsTimingFunction::Type::Linear) {
1818 0 : keyframe->mTimingFunction.emplace();
1819 0 : keyframe->mTimingFunction->Init(*aTimingFunction);
1820 : }
1821 :
1822 0 : return keyframe;
1823 : }
1824 :
1825 : Keyframe*
1826 0 : Gecko_GetOrCreateKeyframeAtStart(nsTArray<Keyframe>* aKeyframes,
1827 : float aOffset,
1828 : const nsTimingFunction* aTimingFunction)
1829 : {
1830 0 : MOZ_ASSERT(aKeyframes->IsEmpty() ||
1831 : aKeyframes->ElementAt(0).mOffset.value() >= aOffset,
1832 : "The offset should be less than or equal to the first keyframe's "
1833 : "offset if there are exisiting keyframes");
1834 :
1835 : return GetOrCreateKeyframe(aKeyframes,
1836 : aOffset,
1837 : aTimingFunction,
1838 : KeyframeSearchDirection::Forwards,
1839 0 : KeyframeInsertPosition::Prepend);
1840 : }
1841 :
1842 : Keyframe*
1843 0 : Gecko_GetOrCreateInitialKeyframe(nsTArray<Keyframe>* aKeyframes,
1844 : const nsTimingFunction* aTimingFunction)
1845 : {
1846 : return GetOrCreateKeyframe(aKeyframes,
1847 : 0.,
1848 : aTimingFunction,
1849 : KeyframeSearchDirection::Forwards,
1850 0 : KeyframeInsertPosition::LastForOffset);
1851 : }
1852 :
1853 : Keyframe*
1854 0 : Gecko_GetOrCreateFinalKeyframe(nsTArray<Keyframe>* aKeyframes,
1855 : const nsTimingFunction* aTimingFunction)
1856 : {
1857 : return GetOrCreateKeyframe(aKeyframes,
1858 : 1.,
1859 : aTimingFunction,
1860 : KeyframeSearchDirection::Backwards,
1861 0 : KeyframeInsertPosition::LastForOffset);
1862 : }
1863 :
1864 : void
1865 0 : Gecko_ResetStyleCoord(nsStyleUnit* aUnit, nsStyleUnion* aValue)
1866 : {
1867 0 : nsStyleCoord::Reset(*aUnit, *aValue);
1868 0 : }
1869 :
1870 : void
1871 0 : Gecko_SetStyleCoordCalcValue(nsStyleUnit* aUnit, nsStyleUnion* aValue, nsStyleCoord::CalcValue aCalc)
1872 : {
1873 : // Calc units should be cleaned up first
1874 0 : MOZ_ASSERT(*aUnit != nsStyleUnit::eStyleUnit_Calc);
1875 0 : nsStyleCoord::Calc* calcRef = new nsStyleCoord::Calc();
1876 0 : calcRef->mLength = aCalc.mLength;
1877 0 : calcRef->mPercent = aCalc.mPercent;
1878 0 : calcRef->mHasPercent = aCalc.mHasPercent;
1879 0 : *aUnit = nsStyleUnit::eStyleUnit_Calc;
1880 0 : aValue->mPointer = calcRef;
1881 0 : calcRef->AddRef();
1882 0 : }
1883 :
1884 : void
1885 0 : Gecko_CopyShapeSourceFrom(mozilla::StyleShapeSource* aDst, const mozilla::StyleShapeSource* aSrc)
1886 : {
1887 0 : MOZ_ASSERT(aDst);
1888 0 : MOZ_ASSERT(aSrc);
1889 :
1890 0 : *aDst = *aSrc;
1891 0 : }
1892 :
1893 : void
1894 0 : Gecko_DestroyShapeSource(mozilla::StyleShapeSource* aShape)
1895 : {
1896 0 : aShape->~StyleShapeSource();
1897 0 : }
1898 :
1899 : void
1900 0 : Gecko_StyleShapeSource_SetURLValue(mozilla::StyleShapeSource* aShape, ServoBundledURI aURI)
1901 : {
1902 0 : RefPtr<css::URLValue> url = aURI.IntoCssUrl();
1903 0 : aShape->SetURL(url.get());
1904 0 : }
1905 :
1906 : mozilla::StyleBasicShape*
1907 0 : Gecko_NewBasicShape(mozilla::StyleBasicShapeType aType)
1908 : {
1909 0 : RefPtr<StyleBasicShape> ptr = new mozilla::StyleBasicShape(aType);
1910 0 : return ptr.forget().take();
1911 : }
1912 :
1913 : void
1914 0 : Gecko_ResetFilters(nsStyleEffects* effects, size_t new_len)
1915 : {
1916 0 : effects->mFilters.Clear();
1917 0 : effects->mFilters.SetLength(new_len);
1918 0 : }
1919 :
1920 : void
1921 0 : Gecko_CopyFiltersFrom(nsStyleEffects* aSrc, nsStyleEffects* aDest)
1922 : {
1923 0 : aDest->mFilters = aSrc->mFilters;
1924 0 : }
1925 :
1926 : void
1927 0 : Gecko_nsStyleFilter_SetURLValue(nsStyleFilter* aEffects, ServoBundledURI aURI)
1928 : {
1929 0 : RefPtr<css::URLValue> url = aURI.IntoCssUrl();
1930 0 : aEffects->SetURL(url.get());
1931 0 : }
1932 :
1933 : void
1934 0 : Gecko_nsStyleSVGPaint_CopyFrom(nsStyleSVGPaint* aDest, const nsStyleSVGPaint* aSrc)
1935 : {
1936 0 : *aDest = *aSrc;
1937 0 : }
1938 :
1939 : void
1940 0 : Gecko_nsStyleSVGPaint_SetURLValue(nsStyleSVGPaint* aPaint, ServoBundledURI aURI)
1941 : {
1942 0 : RefPtr<css::URLValue> url = aURI.IntoCssUrl();
1943 0 : aPaint->SetPaintServer(url.get());
1944 0 : }
1945 :
1946 0 : void Gecko_nsStyleSVGPaint_Reset(nsStyleSVGPaint* aPaint)
1947 : {
1948 0 : aPaint->SetNone();
1949 0 : }
1950 :
1951 : void
1952 0 : Gecko_nsStyleSVG_SetDashArrayLength(nsStyleSVG* aSvg, uint32_t aLen)
1953 : {
1954 0 : aSvg->mStrokeDasharray.Clear();
1955 0 : aSvg->mStrokeDasharray.SetLength(aLen);
1956 0 : }
1957 :
1958 : void
1959 0 : Gecko_nsStyleSVG_CopyDashArray(nsStyleSVG* aDst, const nsStyleSVG* aSrc)
1960 : {
1961 0 : aDst->mStrokeDasharray = aSrc->mStrokeDasharray;
1962 0 : }
1963 :
1964 : void
1965 0 : Gecko_nsStyleSVG_SetContextPropertiesLength(nsStyleSVG* aSvg, uint32_t aLen)
1966 : {
1967 0 : aSvg->mContextProps.Clear();
1968 0 : aSvg->mContextProps.SetLength(aLen);
1969 0 : }
1970 :
1971 : void
1972 0 : Gecko_nsStyleSVG_CopyContextProperties(nsStyleSVG* aDst, const nsStyleSVG* aSrc)
1973 : {
1974 0 : aDst->mContextProps = aSrc->mContextProps;
1975 0 : aDst->mContextPropsBits = aSrc->mContextPropsBits;
1976 0 : }
1977 :
1978 :
1979 : css::URLValue*
1980 0 : Gecko_NewURLValue(ServoBundledURI aURI)
1981 : {
1982 0 : RefPtr<css::URLValue> url = aURI.IntoCssUrl();
1983 0 : return url.forget().take();
1984 : }
1985 :
1986 0 : NS_IMPL_THREADSAFE_FFI_REFCOUNTING(css::URLValue, CSSURLValue);
1987 :
1988 0 : NS_IMPL_THREADSAFE_FFI_REFCOUNTING(URLExtraData, URLExtraData);
1989 :
1990 0 : NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsStyleCoord::Calc, Calc);
1991 :
1992 : nsCSSShadowArray*
1993 0 : Gecko_NewCSSShadowArray(uint32_t aLen)
1994 : {
1995 0 : RefPtr<nsCSSShadowArray> arr = new(aLen) nsCSSShadowArray(aLen);
1996 0 : return arr.forget().take();
1997 : }
1998 :
1999 0 : NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsCSSShadowArray, CSSShadowArray);
2000 :
2001 : nsStyleQuoteValues*
2002 0 : Gecko_NewStyleQuoteValues(uint32_t aLen)
2003 : {
2004 0 : RefPtr<nsStyleQuoteValues> values = new nsStyleQuoteValues;
2005 0 : values->mQuotePairs.SetLength(aLen);
2006 0 : return values.forget().take();
2007 : }
2008 :
2009 0 : NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsStyleQuoteValues, QuoteValues);
2010 :
2011 : nsCSSValueSharedList*
2012 0 : Gecko_NewCSSValueSharedList(uint32_t aLen)
2013 : {
2014 0 : RefPtr<nsCSSValueSharedList> list = new nsCSSValueSharedList;
2015 0 : if (aLen == 0) {
2016 0 : return list.forget().take();
2017 : }
2018 :
2019 0 : list->mHead = new nsCSSValueList;
2020 0 : nsCSSValueList* cur = list->mHead;
2021 0 : for (uint32_t i = 0; i < aLen - 1; i++) {
2022 0 : cur->mNext = new nsCSSValueList;
2023 0 : cur = cur->mNext;
2024 : }
2025 :
2026 0 : return list.forget().take();
2027 : }
2028 :
2029 : nsCSSValueSharedList*
2030 0 : Gecko_NewNoneTransform()
2031 : {
2032 0 : RefPtr<nsCSSValueSharedList> list = new nsCSSValueSharedList;
2033 0 : list->mHead = new nsCSSValueList;
2034 0 : list->mHead->mValue.SetNoneValue();
2035 0 : return list.forget().take();
2036 : }
2037 :
2038 : void
2039 0 : Gecko_CSSValue_SetAbsoluteLength(nsCSSValueBorrowedMut aCSSValue, nscoord aLen)
2040 : {
2041 0 : MOZ_ASSERT(aCSSValue->GetUnit() == eCSSUnit_Null || aCSSValue->IsLengthUnit());
2042 : // The call below could trigger refcounting if aCSSValue were a
2043 : // FontFamilyList, but we just asserted that it's not. So we can
2044 : // whitelist this for static analysis.
2045 0 : aCSSValue->SetIntegerCoordValue(aLen);
2046 0 : }
2047 :
2048 : nscoord
2049 0 : Gecko_CSSValue_GetAbsoluteLength(nsCSSValueBorrowed aCSSValue)
2050 : {
2051 : // SetIntegerCoordValue() which is used in Gecko_CSSValue_SetAbsoluteLength()
2052 : // converts values by nsPresContext::AppUnitsToFloatCSSPixels() and stores
2053 : // values in eCSSUnit_Pixel unit. We need to convert the values back to app
2054 : // units by GetPixelLength().
2055 0 : MOZ_ASSERT(aCSSValue->GetUnit() == eCSSUnit_Pixel,
2056 : "The unit should be eCSSUnit_Pixel");
2057 0 : return aCSSValue->GetPixelLength();
2058 : }
2059 :
2060 : void
2061 0 : Gecko_CSSValue_SetNumber(nsCSSValueBorrowedMut aCSSValue, float aNumber)
2062 : {
2063 0 : aCSSValue->SetFloatValue(aNumber, eCSSUnit_Number);
2064 0 : }
2065 :
2066 : float
2067 0 : Gecko_CSSValue_GetNumber(nsCSSValueBorrowed aCSSValue)
2068 : {
2069 0 : return aCSSValue->GetFloatValue();
2070 : }
2071 :
2072 : void
2073 0 : Gecko_CSSValue_SetKeyword(nsCSSValueBorrowedMut aCSSValue, nsCSSKeyword aKeyword)
2074 : {
2075 0 : aCSSValue->SetEnumValue(aKeyword);
2076 0 : }
2077 :
2078 : nsCSSKeyword
2079 0 : Gecko_CSSValue_GetKeyword(nsCSSValueBorrowed aCSSValue)
2080 : {
2081 0 : return aCSSValue->GetKeywordValue();
2082 : }
2083 :
2084 : void
2085 0 : Gecko_CSSValue_SetPercentage(nsCSSValueBorrowedMut aCSSValue, float aPercent)
2086 : {
2087 0 : aCSSValue->SetPercentValue(aPercent);
2088 0 : }
2089 :
2090 : float
2091 0 : Gecko_CSSValue_GetPercentage(nsCSSValueBorrowed aCSSValue)
2092 : {
2093 0 : return aCSSValue->GetPercentValue();
2094 : }
2095 :
2096 : void
2097 0 : Gecko_CSSValue_SetCalc(nsCSSValueBorrowedMut aCSSValue, nsStyleCoord::CalcValue aCalc)
2098 : {
2099 0 : aCSSValue->SetCalcValue(&aCalc);
2100 0 : }
2101 :
2102 : nsStyleCoord::CalcValue
2103 0 : Gecko_CSSValue_GetCalc(nsCSSValueBorrowed aCSSValue)
2104 : {
2105 0 : return aCSSValue->GetCalcValue();
2106 : }
2107 :
2108 : void
2109 0 : Gecko_CSSValue_SetFunction(nsCSSValueBorrowedMut aCSSValue, int32_t aLen)
2110 : {
2111 0 : nsCSSValue::Array* arr = nsCSSValue::Array::Create(aLen);
2112 0 : aCSSValue->SetArrayValue(arr, eCSSUnit_Function);
2113 0 : }
2114 :
2115 : void
2116 0 : Gecko_CSSValue_SetString(nsCSSValueBorrowedMut aCSSValue,
2117 : const uint8_t* aString, uint32_t aLength,
2118 : nsCSSUnit aUnit)
2119 : {
2120 0 : MOZ_ASSERT(aCSSValue->GetUnit() == eCSSUnit_Null);
2121 0 : nsString string;
2122 : nsDependentCSubstring slice(reinterpret_cast<const char*>(aString),
2123 0 : aLength);
2124 0 : AppendUTF8toUTF16(slice, string);
2125 0 : aCSSValue->SetStringValue(string, aUnit);
2126 0 : }
2127 :
2128 : void
2129 0 : Gecko_CSSValue_SetStringFromAtom(nsCSSValueBorrowedMut aCSSValue,
2130 : nsIAtom* aAtom, nsCSSUnit aUnit)
2131 : {
2132 0 : aCSSValue->SetStringValue(nsDependentAtomString(aAtom), aUnit);
2133 0 : }
2134 :
2135 : void
2136 0 : Gecko_CSSValue_SetAtomIdent(nsCSSValueBorrowedMut aCSSValue, nsIAtom* aAtom)
2137 : {
2138 0 : aCSSValue->SetAtomIdentValue(already_AddRefed<nsIAtom>(aAtom));
2139 0 : }
2140 :
2141 : void
2142 0 : Gecko_CSSValue_SetArray(nsCSSValueBorrowedMut aCSSValue, int32_t aLength)
2143 : {
2144 0 : MOZ_ASSERT(aCSSValue->GetUnit() == eCSSUnit_Null);
2145 : RefPtr<nsCSSValue::Array> array
2146 0 : = nsCSSValue::Array::Create(aLength);
2147 0 : aCSSValue->SetArrayValue(array, eCSSUnit_Array);
2148 0 : }
2149 :
2150 : void
2151 0 : Gecko_CSSValue_SetURL(nsCSSValueBorrowedMut aCSSValue,
2152 : ServoBundledURI aURI)
2153 : {
2154 0 : MOZ_ASSERT(aCSSValue->GetUnit() == eCSSUnit_Null);
2155 0 : RefPtr<css::URLValue> url = aURI.IntoCssUrl();
2156 0 : aCSSValue->SetURLValue(url.get());
2157 0 : }
2158 :
2159 : void
2160 0 : Gecko_CSSValue_SetInt(nsCSSValueBorrowedMut aCSSValue,
2161 : int32_t aInteger, nsCSSUnit aUnit)
2162 : {
2163 0 : aCSSValue->SetIntValue(aInteger, aUnit);
2164 0 : }
2165 :
2166 : nsCSSValueBorrowedMut
2167 0 : Gecko_CSSValue_GetArrayItem(nsCSSValueBorrowedMut aCSSValue, int32_t aIndex)
2168 : {
2169 0 : return &aCSSValue->GetArrayValue()->Item(aIndex);
2170 : }
2171 :
2172 : nsCSSValueBorrowed
2173 0 : Gecko_CSSValue_GetArrayItemConst(nsCSSValueBorrowed aCSSValue, int32_t aIndex)
2174 : {
2175 0 : return &aCSSValue->GetArrayValue()->Item(aIndex);
2176 : }
2177 :
2178 : void
2179 0 : Gecko_CSSValue_SetPair(nsCSSValueBorrowedMut aCSSValue,
2180 : nsCSSValueBorrowed aXValue, nsCSSValueBorrowed aYValue)
2181 : {
2182 0 : MOZ_ASSERT(NS_IsMainThread());
2183 0 : aCSSValue->SetPairValue(*aXValue, *aYValue);
2184 0 : }
2185 :
2186 : void
2187 0 : Gecko_CSSValue_SetList(nsCSSValueBorrowedMut aCSSValue, uint32_t aLen)
2188 : {
2189 0 : MOZ_ASSERT(NS_IsMainThread());
2190 0 : nsCSSValueList* item = aCSSValue->SetListValue();
2191 0 : for (uint32_t i = 1; i < aLen; ++i) {
2192 0 : item->mNext = new nsCSSValueList;
2193 0 : item = item->mNext;
2194 : }
2195 0 : }
2196 :
2197 : void
2198 0 : Gecko_CSSValue_SetPairList(nsCSSValueBorrowedMut aCSSValue, uint32_t aLen)
2199 : {
2200 0 : MOZ_ASSERT(NS_IsMainThread());
2201 0 : nsCSSValuePairList* item = aCSSValue->SetPairListValue();
2202 0 : for (uint32_t i = 1; i < aLen; ++i) {
2203 0 : item->mNext = new nsCSSValuePairList;
2204 0 : item = item->mNext;
2205 : }
2206 0 : }
2207 :
2208 : void
2209 0 : Gecko_CSSValue_InitSharedList(nsCSSValueBorrowedMut aCSSValue,
2210 : uint32_t aLen)
2211 : {
2212 0 : MOZ_ASSERT(aLen > 0, "Must create at least one nsCSSValueList (mHead)");
2213 :
2214 0 : nsCSSValueSharedList* list = new nsCSSValueSharedList;
2215 0 : aCSSValue->SetSharedListValue(list);
2216 0 : list->mHead = new nsCSSValueList;
2217 0 : nsCSSValueList* cur = list->mHead;
2218 0 : for (uint32_t i = 1; i < aLen; ++i) {
2219 0 : cur->mNext = new nsCSSValueList;
2220 0 : cur = cur->mNext;
2221 : }
2222 0 : }
2223 :
2224 : bool
2225 0 : Gecko_PropertyId_IsPrefEnabled(nsCSSPropertyID id)
2226 : {
2227 0 : return nsCSSProps::IsEnabled(id);
2228 : }
2229 :
2230 : void
2231 0 : Gecko_CSSValue_Drop(nsCSSValueBorrowedMut aCSSValue)
2232 : {
2233 0 : aCSSValue->~nsCSSValue();
2234 0 : }
2235 :
2236 : void
2237 0 : Gecko_nsStyleFont_SetLang(nsStyleFont* aFont, nsIAtom* aAtom)
2238 : {
2239 0 : already_AddRefed<nsIAtom> atom = already_AddRefed<nsIAtom>(aAtom);
2240 0 : aFont->mLanguage = atom;
2241 0 : aFont->mExplicitLanguage = true;
2242 0 : }
2243 :
2244 : void
2245 0 : Gecko_nsStyleFont_CopyLangFrom(nsStyleFont* aFont, const nsStyleFont* aSource)
2246 : {
2247 0 : aFont->mLanguage = aSource->mLanguage;
2248 0 : }
2249 :
2250 : void
2251 0 : Gecko_nsStyleFont_FixupNoneGeneric(nsStyleFont* aFont,
2252 : RawGeckoPresContextBorrowed aPresContext)
2253 : {
2254 0 : const nsFont* defaultVariableFont = ThreadSafeGetDefaultFontHelper(aPresContext, aFont->mLanguage,
2255 0 : kPresContext_DefaultVariableFont_ID);
2256 0 : nsRuleNode::FixupNoneGeneric(&aFont->mFont, aPresContext,
2257 0 : aFont->mGenericID, defaultVariableFont);
2258 0 : }
2259 :
2260 : void
2261 0 : Gecko_nsStyleFont_PrefillDefaultForGeneric(nsStyleFont* aFont,
2262 : RawGeckoPresContextBorrowed aPresContext,
2263 : uint8_t aGenericId)
2264 : {
2265 0 : const nsFont* defaultFont = ThreadSafeGetDefaultFontHelper(aPresContext, aFont->mLanguage,
2266 0 : aGenericId);
2267 0 : aFont->mFont.fontlist = defaultFont->fontlist;
2268 0 : }
2269 :
2270 : void
2271 0 : Gecko_nsStyleFont_FixupMinFontSize(nsStyleFont* aFont,
2272 : RawGeckoPresContextBorrowed aPresContext)
2273 : {
2274 : nscoord minFontSize;
2275 0 : bool needsCache = false;
2276 :
2277 : {
2278 0 : AutoReadLock guard(*sServoLangFontPrefsLock);
2279 0 : minFontSize = aPresContext->MinFontSize(aFont->mLanguage, &needsCache);
2280 : }
2281 :
2282 0 : if (needsCache) {
2283 0 : AutoWriteLock guard(*sServoLangFontPrefsLock);
2284 0 : minFontSize = aPresContext->MinFontSize(aFont->mLanguage, nullptr);
2285 : }
2286 :
2287 0 : nsRuleNode::ApplyMinFontSize(aFont, aPresContext, minFontSize);
2288 0 : }
2289 :
2290 : void
2291 0 : FontSizePrefs::CopyFrom(const LangGroupFontPrefs& prefs)
2292 : {
2293 0 : mDefaultVariableSize = prefs.mDefaultVariableFont.size;
2294 0 : mDefaultFixedSize = prefs.mDefaultFixedFont.size;
2295 0 : mDefaultSerifSize = prefs.mDefaultSerifFont.size;
2296 0 : mDefaultSansSerifSize = prefs.mDefaultSansSerifFont.size;
2297 0 : mDefaultMonospaceSize = prefs.mDefaultMonospaceFont.size;
2298 0 : mDefaultCursiveSize = prefs.mDefaultCursiveFont.size;
2299 0 : mDefaultFantasySize = prefs.mDefaultFantasyFont.size;
2300 0 : }
2301 :
2302 : FontSizePrefs
2303 0 : Gecko_GetBaseSize(nsIAtom* aLanguage)
2304 : {
2305 0 : LangGroupFontPrefs prefs;
2306 0 : nsCOMPtr<nsIAtom> langGroupAtom = StaticPresData::Get()->GetUncachedLangGroup(aLanguage);
2307 :
2308 0 : prefs.Initialize(langGroupAtom);
2309 : FontSizePrefs sizes;
2310 0 : sizes.CopyFrom(prefs);
2311 :
2312 0 : return sizes;
2313 : }
2314 :
2315 : RawGeckoElementBorrowedOrNull
2316 0 : Gecko_GetBindingParent(RawGeckoElementBorrowed aElement)
2317 : {
2318 0 : nsIContent* parent = aElement->GetBindingParent();
2319 0 : return parent ? parent->AsElement() : nullptr;
2320 : }
2321 :
2322 : RawGeckoXBLBindingBorrowedOrNull
2323 0 : Gecko_GetXBLBinding(RawGeckoElementBorrowed aElement)
2324 : {
2325 0 : return aElement->GetXBLBinding();
2326 : }
2327 :
2328 : RawServoStyleSetBorrowedOrNull
2329 0 : Gecko_XBLBinding_GetRawServoStyleSet(RawGeckoXBLBindingBorrowed aXBLBinding)
2330 : {
2331 0 : const ServoStyleSet* set = aXBLBinding->GetServoStyleSet();
2332 0 : return set ? set->RawSet() : nullptr;
2333 : }
2334 :
2335 : bool
2336 0 : Gecko_XBLBinding_InheritsStyle(RawGeckoXBLBindingBorrowed aXBLBinding)
2337 : {
2338 0 : return aXBLBinding->InheritsStyle();
2339 : }
2340 :
2341 : void
2342 0 : InitializeServo()
2343 : {
2344 0 : URLExtraData::InitDummy();
2345 0 : Servo_Initialize(URLExtraData::Dummy());
2346 :
2347 0 : sServoFontMetricsLock = new Mutex("Gecko_GetFontMetrics");
2348 0 : sServoLangFontPrefsLock = new RWLock("nsPresContext::GetDefaultFont");
2349 :
2350 : Preferences::AddBoolVarCache(&sFramesTimingFunctionEnabled,
2351 0 : "layout.css.frames-timing.enabled");
2352 0 : }
2353 :
2354 : void
2355 0 : ShutdownServo()
2356 : {
2357 0 : delete sServoFontMetricsLock;
2358 0 : delete sServoLangFontPrefsLock;
2359 0 : Servo_Shutdown();
2360 0 : }
2361 :
2362 : namespace mozilla {
2363 :
2364 : void
2365 0 : AssertIsMainThreadOrServoFontMetricsLocked()
2366 : {
2367 0 : if (!NS_IsMainThread()) {
2368 0 : MOZ_ASSERT(sServoFontMetricsLock);
2369 0 : sServoFontMetricsLock->AssertCurrentThreadOwns();
2370 : }
2371 0 : }
2372 :
2373 : } // namespace mozilla
2374 :
2375 : GeckoFontMetrics
2376 0 : Gecko_GetFontMetrics(RawGeckoPresContextBorrowed aPresContext,
2377 : bool aIsVertical,
2378 : const nsStyleFont* aFont,
2379 : nscoord aFontSize,
2380 : bool aUseUserFontSet)
2381 : {
2382 0 : MutexAutoLock lock(*sServoFontMetricsLock);
2383 : GeckoFontMetrics ret;
2384 :
2385 : // Getting font metrics can require some main thread only work to be
2386 : // done, such as work that needs to touch non-threadsafe refcounted
2387 : // objects (like the DOM FontFace/FontFaceSet objects), network loads, etc.
2388 : //
2389 : // To handle this work, font code checks whether we are in a Servo traversal
2390 : // and if so, appends PostTraversalTasks to the current ServoStyleSet
2391 : // to be performed immediately after the traversal is finished. This
2392 : // works well for starting downloadable font loads, since we don't have
2393 : // those fonts available to get metrics for anyway. Platform fonts and
2394 : // ArrayBuffer-backed FontFace objects are handled synchronously.
2395 :
2396 0 : nsPresContext* presContext = const_cast<nsPresContext*>(aPresContext);
2397 0 : presContext->SetUsesExChUnits(true);
2398 0 : RefPtr<nsFontMetrics> fm = nsRuleNode::GetMetricsFor(presContext, aIsVertical,
2399 : aFont, aFontSize,
2400 0 : aUseUserFontSet);
2401 0 : ret.mXSize = fm->XHeight();
2402 : gfxFloat zeroWidth = fm->GetThebesFontGroup()->GetFirstValidFont()->
2403 0 : GetMetrics(fm->Orientation()).zeroOrAveCharWidth;
2404 0 : ret.mChSize = ceil(aPresContext->AppUnitsPerDevPixel() * zeroWidth);
2405 0 : return ret;
2406 : }
2407 :
2408 : int32_t
2409 0 : Gecko_GetAppUnitsPerPhysicalInch(RawGeckoPresContextBorrowed aPresContext)
2410 : {
2411 0 : nsPresContext* presContext = const_cast<nsPresContext*>(aPresContext);
2412 0 : return presContext->DeviceContext()->AppUnitsPerPhysicalInch();
2413 : }
2414 :
2415 : ServoStyleSheet*
2416 0 : Gecko_LoadStyleSheet(css::Loader* aLoader,
2417 : ServoStyleSheet* aParent,
2418 : css::LoaderReusableStyleSheets* aReusableSheets,
2419 : RawGeckoURLExtraData* aBaseURLData,
2420 : const uint8_t* aURLString,
2421 : uint32_t aURLStringLength,
2422 : RawServoMediaListStrong aMediaList)
2423 : {
2424 0 : MOZ_ASSERT(NS_IsMainThread());
2425 0 : MOZ_ASSERT(aLoader, "Should've catched this before");
2426 0 : MOZ_ASSERT(aParent, "Only used for @import, so parent should exist!");
2427 0 : MOZ_ASSERT(aURLString, "Invalid URLs shouldn't be loaded!");
2428 0 : MOZ_ASSERT(aBaseURLData, "Need base URL data");
2429 :
2430 0 : RefPtr<dom::MediaList> media = new ServoMediaList(aMediaList.Consume());
2431 : nsDependentCSubstring urlSpec(reinterpret_cast<const char*>(aURLString),
2432 0 : aURLStringLength);
2433 0 : nsCOMPtr<nsIURI> uri;
2434 0 : nsresult rv = NS_NewURI(getter_AddRefs(uri), urlSpec, nullptr,
2435 0 : aBaseURLData->BaseURI());
2436 :
2437 0 : StyleSheet* previousFirstChild = aParent->GetFirstChild();
2438 0 : if (NS_SUCCEEDED(rv)) {
2439 0 : rv = aLoader->LoadChildSheet(aParent, uri, media, nullptr, aReusableSheets);
2440 : }
2441 :
2442 0 : if (NS_FAILED(rv) ||
2443 0 : !aParent->GetFirstChild() ||
2444 0 : aParent->GetFirstChild() == previousFirstChild) {
2445 : // Servo and Gecko have different ideas of what a valid URL is, so we might
2446 : // get in here with a URL string that NS_NewURI can't handle. If so,
2447 : // silently do nothing. Eventually we should be able to assert that the
2448 : // NS_NewURI succeeds, here.
2449 : RefPtr<ServoStyleSheet> emptySheet =
2450 0 : aParent->CreateEmptyChildSheet(media.forget());
2451 0 : aParent->PrependStyleSheet(emptySheet);
2452 0 : return emptySheet.forget().take();
2453 : }
2454 :
2455 : RefPtr<ServoStyleSheet> sheet =
2456 0 : static_cast<ServoStyleSheet*>(aParent->GetFirstChild());
2457 0 : return sheet.forget().take();
2458 : }
2459 :
2460 : const nsMediaFeature*
2461 0 : Gecko_GetMediaFeatures()
2462 : {
2463 0 : return nsMediaFeatures::features;
2464 : }
2465 :
2466 : nsCSSKeyword
2467 0 : Gecko_LookupCSSKeyword(const uint8_t* aString, uint32_t aLength)
2468 : {
2469 0 : MOZ_ASSERT(NS_IsMainThread());
2470 :
2471 0 : nsDependentCSubstring keyword(reinterpret_cast<const char*>(aString), aLength);
2472 0 : return nsCSSKeywords::LookupKeyword(keyword);
2473 : }
2474 :
2475 : const char*
2476 0 : Gecko_CSSKeywordString(nsCSSKeyword aKeyword, uint32_t* aLength)
2477 : {
2478 0 : MOZ_ASSERT(NS_IsMainThread());
2479 0 : MOZ_ASSERT(aLength);
2480 0 : const nsCString& value = nsCSSKeywords::GetStringValue(aKeyword);
2481 0 : *aLength = value.Length();
2482 0 : return value.get();
2483 : }
2484 :
2485 : nsCSSFontFaceRule*
2486 0 : Gecko_CSSFontFaceRule_Create(uint32_t aLine, uint32_t aColumn)
2487 : {
2488 0 : RefPtr<nsCSSFontFaceRule> rule = new nsCSSFontFaceRule(aLine, aColumn);
2489 0 : return rule.forget().take();
2490 : }
2491 :
2492 : nsCSSFontFaceRule*
2493 0 : Gecko_CSSFontFaceRule_Clone(const nsCSSFontFaceRule* aRule)
2494 : {
2495 0 : RefPtr<css::Rule> rule = aRule->Clone();
2496 0 : return static_cast<nsCSSFontFaceRule*>(rule.forget().take());
2497 : }
2498 :
2499 : void
2500 0 : Gecko_CSSFontFaceRule_GetCssText(const nsCSSFontFaceRule* aRule,
2501 : nsAString* aResult)
2502 : {
2503 : // GetCSSText serializes nsCSSValues, which have a heap write
2504 : // hazard when dealing with color values (nsCSSKeywords::AddRefTable)
2505 : // We only serialize on the main thread; assert to convince the analysis
2506 : // and prevent accidentally calling this elsewhere
2507 0 : MOZ_ASSERT(NS_IsMainThread());
2508 :
2509 0 : aRule->GetCssText(*aResult);
2510 0 : }
2511 :
2512 : void
2513 0 : Gecko_AddPropertyToSet(nsCSSPropertyIDSetBorrowedMut aPropertySet,
2514 : nsCSSPropertyID aProperty)
2515 : {
2516 0 : aPropertySet->AddProperty(aProperty);
2517 0 : }
2518 :
2519 : int32_t
2520 0 : Gecko_RegisterNamespace(nsIAtom* aNamespace)
2521 : {
2522 : int32_t id;
2523 :
2524 0 : MOZ_ASSERT(NS_IsMainThread());
2525 :
2526 0 : nsAutoString str;
2527 0 : aNamespace->ToString(str);
2528 0 : nsresult rv = nsContentUtils::NameSpaceManager()->RegisterNameSpace(str, id);
2529 :
2530 0 : if (NS_FAILED(rv)) {
2531 0 : return -1;
2532 : }
2533 0 : return id;
2534 : }
2535 :
2536 0 : NS_IMPL_FFI_REFCOUNTING(nsCSSFontFaceRule, CSSFontFaceRule);
2537 :
2538 : nsCSSCounterStyleRule*
2539 0 : Gecko_CSSCounterStyle_Create(nsIAtom* aName)
2540 : {
2541 0 : RefPtr<nsCSSCounterStyleRule> rule = new nsCSSCounterStyleRule(aName, 0, 0);
2542 0 : return rule.forget().take();
2543 : }
2544 :
2545 : nsCSSCounterStyleRule*
2546 0 : Gecko_CSSCounterStyle_Clone(const nsCSSCounterStyleRule* aRule)
2547 : {
2548 0 : RefPtr<css::Rule> rule = aRule->Clone();
2549 0 : return static_cast<nsCSSCounterStyleRule*>(rule.forget().take());
2550 : }
2551 :
2552 : void
2553 0 : Gecko_CSSCounterStyle_GetCssText(const nsCSSCounterStyleRule* aRule,
2554 : nsAString* aResult)
2555 : {
2556 0 : MOZ_ASSERT(NS_IsMainThread());
2557 0 : aRule->GetCssText(*aResult);
2558 0 : }
2559 :
2560 0 : NS_IMPL_FFI_REFCOUNTING(nsCSSCounterStyleRule, CSSCounterStyleRule);
2561 :
2562 0 : NS_IMPL_THREADSAFE_FFI_REFCOUNTING(nsCSSValueSharedList, CSSValueSharedList);
2563 :
2564 : #define STYLE_STRUCT(name, checkdata_cb) \
2565 : \
2566 : void \
2567 : Gecko_Construct_Default_nsStyle##name(nsStyle##name* ptr, \
2568 : const nsPresContext* pres_context) \
2569 : { \
2570 : new (ptr) nsStyle##name(pres_context); \
2571 : } \
2572 : \
2573 : void \
2574 : Gecko_CopyConstruct_nsStyle##name(nsStyle##name* ptr, \
2575 : const nsStyle##name* other) \
2576 : { \
2577 : new (ptr) nsStyle##name(*other); \
2578 : } \
2579 : \
2580 : void \
2581 : Gecko_Destroy_nsStyle##name(nsStyle##name* ptr) \
2582 : { \
2583 : ptr->~nsStyle##name(); \
2584 : }
2585 :
2586 : void
2587 0 : Gecko_Construct_nsStyleVariables(nsStyleVariables* ptr)
2588 : {
2589 0 : new (ptr) nsStyleVariables();
2590 0 : }
2591 :
2592 : void
2593 0 : Gecko_RegisterProfilerThread(const char* name)
2594 : {
2595 : char stackTop;
2596 0 : profiler_register_thread(name, &stackTop);
2597 0 : }
2598 :
2599 : void
2600 0 : Gecko_UnregisterProfilerThread()
2601 : {
2602 0 : profiler_unregister_thread();
2603 0 : }
2604 :
2605 : bool
2606 0 : Gecko_DocumentRule_UseForPresentation(RawGeckoPresContextBorrowed aPresContext,
2607 : const nsACString* aPattern,
2608 : css::URLMatchingFunction aURLMatchingFunction)
2609 : {
2610 0 : MOZ_ASSERT(NS_IsMainThread());
2611 :
2612 0 : nsIDocument *doc = aPresContext->Document();
2613 0 : nsIURI *docURI = doc->GetDocumentURI();
2614 0 : nsAutoCString docURISpec;
2615 0 : if (docURI) {
2616 : // If GetSpec fails (due to OOM) just skip these URI-specific CSS rules.
2617 0 : nsresult rv = docURI->GetSpec(docURISpec);
2618 0 : NS_ENSURE_SUCCESS(rv, false);
2619 : }
2620 :
2621 : return css::DocumentRule::UseForPresentation(doc, docURI, docURISpec,
2622 0 : *aPattern, aURLMatchingFunction);
2623 : }
2624 :
2625 : void
2626 0 : Gecko_SetJemallocThreadLocalArena(bool enabled)
2627 : {
2628 : #if defined(MOZ_MEMORY)
2629 : // At this point we convert |enabled| from a plain C++ bool to a
2630 : // |jemalloc_bool|, so be on the safe side.
2631 0 : jemalloc_thread_local_arena(!!enabled);
2632 : #endif
2633 0 : }
2634 :
2635 : #include "nsStyleStructList.h"
2636 :
2637 : #undef STYLE_STRUCT
2638 :
2639 : #ifndef MOZ_STYLO
2640 : #define SERVO_BINDING_FUNC(name_, return_, ...) \
2641 : return_ name_(__VA_ARGS__) { \
2642 : MOZ_CRASH("stylo: shouldn't be calling " #name_ "in a non-stylo build"); \
2643 : }
2644 : #include "ServoBindingList.h"
2645 : #undef SERVO_BINDING_FUNC
2646 : #endif
2647 :
2648 : ErrorReporter*
2649 0 : Gecko_CreateCSSErrorReporter(ServoStyleSheet* sheet,
2650 : Loader* loader,
2651 : nsIURI* uri)
2652 : {
2653 0 : MOZ_ASSERT(NS_IsMainThread());
2654 0 : return new ErrorReporter(sheet, loader, uri);
2655 : }
2656 :
2657 : void
2658 0 : Gecko_DestroyCSSErrorReporter(ErrorReporter* reporter)
2659 : {
2660 0 : delete reporter;
2661 0 : }
2662 :
2663 : void
2664 0 : Gecko_ReportUnexpectedCSSError(ErrorReporter* reporter,
2665 : const char* message,
2666 : const char* param,
2667 : uint32_t paramLen,
2668 : const char* source,
2669 : uint32_t sourceLen,
2670 : uint32_t lineNumber,
2671 : uint32_t colNumber,
2672 : nsIURI* uri)
2673 : {
2674 0 : MOZ_ASSERT(NS_IsMainThread());
2675 :
2676 0 : nsDependentCSubstring paramValue(param, paramLen);
2677 0 : nsAutoString wideParam = NS_ConvertUTF8toUTF16(paramValue);
2678 0 : reporter->ReportUnexpectedUnescaped(message, wideParam);
2679 0 : nsDependentCSubstring sourceValue(source, sourceLen);
2680 0 : reporter->OutputError(lineNumber, colNumber, sourceValue);
2681 0 : }
|