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 : /* DOM object returned from element.getComputedStyle() */
8 :
9 : #include "nsComputedDOMStyle.h"
10 :
11 : #include "mozilla/ArrayUtils.h"
12 : #include "mozilla/Preferences.h"
13 :
14 : #include "nsError.h"
15 : #include "nsIDOMCSSPrimitiveValue.h"
16 : #include "nsIFrame.h"
17 : #include "nsIFrameInlines.h"
18 : #include "nsStyleContext.h"
19 : #include "nsIScrollableFrame.h"
20 : #include "nsContentUtils.h"
21 : #include "nsIContent.h"
22 :
23 : #include "nsDOMCSSRect.h"
24 : #include "nsDOMCSSRGBColor.h"
25 : #include "nsDOMCSSValueList.h"
26 : #include "nsFlexContainerFrame.h"
27 : #include "nsGridContainerFrame.h"
28 : #include "nsGkAtoms.h"
29 : #include "mozilla/ReflowInput.h"
30 : #include "nsStyleUtil.h"
31 : #include "nsStyleStructInlines.h"
32 : #include "nsROCSSPrimitiveValue.h"
33 :
34 : #include "nsPresContext.h"
35 : #include "nsIDocument.h"
36 :
37 : #include "nsCSSPseudoElements.h"
38 : #include "mozilla/StyleSetHandle.h"
39 : #include "mozilla/StyleSetHandleInlines.h"
40 : #include "mozilla/GeckoRestyleManager.h"
41 : #include "mozilla/RestyleManagerInlines.h"
42 : #include "imgIRequest.h"
43 : #include "nsLayoutUtils.h"
44 : #include "nsCSSKeywords.h"
45 : #include "nsStyleCoord.h"
46 : #include "nsDisplayList.h"
47 : #include "nsDOMCSSDeclaration.h"
48 : #include "nsStyleTransformMatrix.h"
49 : #include "mozilla/dom/Element.h"
50 : #include "prtime.h"
51 : #include "nsWrapperCacheInlines.h"
52 : #include "mozilla/AppUnits.h"
53 : #include <algorithm>
54 : #include "nsStyleContextInlines.h"
55 :
56 : using namespace mozilla;
57 : using namespace mozilla::dom;
58 :
59 : #if defined(DEBUG_bzbarsky) || defined(DEBUG_caillon)
60 : #define DEBUG_ComputedDOMStyle
61 : #endif
62 :
63 : /*
64 : * This is the implementation of the readonly CSSStyleDeclaration that is
65 : * returned by the getComputedStyle() function.
66 : */
67 :
68 : already_AddRefed<nsComputedDOMStyle>
69 4 : NS_NewComputedDOMStyle(dom::Element* aElement, const nsAString& aPseudoElt,
70 : nsIPresShell* aPresShell,
71 : nsComputedDOMStyle::StyleType aStyleType,
72 : nsComputedDOMStyle::AnimationFlag aFlag)
73 : {
74 8 : RefPtr<nsComputedDOMStyle> computedStyle;
75 : computedStyle = new nsComputedDOMStyle(aElement, aPseudoElt,
76 4 : aPresShell, aStyleType, aFlag);
77 8 : return computedStyle.forget();
78 : }
79 :
80 : static nsDOMCSSValueList*
81 0 : GetROCSSValueList(bool aCommaDelimited)
82 : {
83 0 : return new nsDOMCSSValueList(aCommaDelimited, true);
84 : }
85 :
86 : template<typename T>
87 : already_AddRefed<CSSValue>
88 0 : GetBackgroundList(T nsStyleImageLayers::Layer::* aMember,
89 : uint32_t nsStyleImageLayers::* aCount,
90 : const nsStyleImageLayers& aLayers,
91 : const nsCSSProps::KTableEntry aTable[])
92 : {
93 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
94 :
95 0 : for (uint32_t i = 0, i_end = aLayers.*aCount; i < i_end; ++i) {
96 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
97 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(aLayers.mLayers[i].*aMember, aTable));
98 0 : valueList->AppendCSSValue(val.forget());
99 : }
100 :
101 0 : return valueList.forget();
102 : }
103 :
104 : /**
105 : * An object that represents the ordered set of properties that are exposed on
106 : * an nsComputedDOMStyle object and how their computed values can be obtained.
107 : */
108 : struct nsComputedStyleMap
109 : {
110 : friend class nsComputedDOMStyle;
111 :
112 : struct Entry
113 : {
114 : // Create a pointer-to-member-function type.
115 : typedef already_AddRefed<CSSValue> (nsComputedDOMStyle::*ComputeMethod)();
116 :
117 : nsCSSPropertyID mProperty;
118 : ComputeMethod mGetter;
119 :
120 4 : bool IsLayoutFlushNeeded() const
121 : {
122 4 : return nsCSSProps::PropHasFlags(mProperty,
123 4 : CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH);
124 : }
125 :
126 286 : bool IsEnabled() const
127 : {
128 286 : return nsCSSProps::IsEnabled(mProperty, CSSEnabledState::eForAllContent);
129 : }
130 : };
131 :
132 : // We define this enum just to count the total number of properties that can
133 : // be exposed on an nsComputedDOMStyle, including properties that may be
134 : // disabled.
135 : enum {
136 : #define COMPUTED_STYLE_PROP(prop_, method_) \
137 : eComputedStyleProperty_##prop_,
138 : #include "nsComputedDOMStylePropertyList.h"
139 : #undef COMPUTED_STYLE_PROP
140 : eComputedStyleProperty_COUNT
141 : };
142 :
143 : /**
144 : * Returns the number of properties that should be exposed on an
145 : * nsComputedDOMStyle, ecxluding any disabled properties.
146 : */
147 0 : uint32_t Length()
148 : {
149 0 : Update();
150 0 : return mExposedPropertyCount;
151 : }
152 :
153 : /**
154 : * Returns the property at the given index in the list of properties
155 : * that should be exposed on an nsComputedDOMStyle, excluding any
156 : * disabled properties.
157 : */
158 0 : nsCSSPropertyID PropertyAt(uint32_t aIndex)
159 : {
160 0 : Update();
161 0 : return kEntries[EntryIndex(aIndex)].mProperty;
162 : }
163 :
164 : /**
165 : * Searches for and returns the computed style map entry for the given
166 : * property, or nullptr if the property is not exposed on nsComputedDOMStyle
167 : * or is currently disabled.
168 : */
169 4 : const Entry* FindEntryForProperty(nsCSSPropertyID aPropID)
170 : {
171 4 : Update();
172 233 : for (uint32_t i = 0; i < mExposedPropertyCount; i++) {
173 233 : const Entry* entry = &kEntries[EntryIndex(i)];
174 233 : if (entry->mProperty == aPropID) {
175 4 : return entry;
176 : }
177 : }
178 0 : return nullptr;
179 : }
180 :
181 : /**
182 : * Records that mIndexMap needs updating, due to prefs changing that could
183 : * affect the set of properties exposed on an nsComputedDOMStyle.
184 : */
185 0 : void MarkDirty() { mExposedPropertyCount = 0; }
186 :
187 : // The member variables are public so that we can use an initializer in
188 : // nsComputedDOMStyle::GetComputedStyleMap. Use the member functions
189 : // above to get information from this object.
190 :
191 : /**
192 : * An entry for each property that can be exposed on an nsComputedDOMStyle.
193 : */
194 : const Entry kEntries[eComputedStyleProperty_COUNT];
195 :
196 : /**
197 : * The number of properties that should be exposed on an nsComputedDOMStyle.
198 : * This will be less than eComputedStyleProperty_COUNT if some property
199 : * prefs are disabled. A value of 0 indicates that it and mIndexMap are out
200 : * of date.
201 : */
202 : uint32_t mExposedPropertyCount;
203 :
204 : /**
205 : * A map of indexes on the nsComputedDOMStyle object to indexes into kEntries.
206 : */
207 : uint32_t mIndexMap[eComputedStyleProperty_COUNT];
208 :
209 : private:
210 : /**
211 : * Returns whether mExposedPropertyCount and mIndexMap are out of date.
212 : */
213 4 : bool IsDirty() { return mExposedPropertyCount == 0; }
214 :
215 : /**
216 : * Updates mExposedPropertyCount and mIndexMap to take into account properties
217 : * whose prefs are currently disabled.
218 : */
219 : void Update();
220 :
221 : /**
222 : * Maps an nsComputedDOMStyle indexed getter index to an index into kEntries.
223 : */
224 233 : uint32_t EntryIndex(uint32_t aIndex) const
225 : {
226 233 : MOZ_ASSERT(aIndex < mExposedPropertyCount);
227 233 : return mIndexMap[aIndex];
228 : }
229 : };
230 :
231 : void
232 4 : nsComputedStyleMap::Update()
233 : {
234 4 : if (!IsDirty()) {
235 3 : return;
236 : }
237 :
238 1 : uint32_t index = 0;
239 287 : for (uint32_t i = 0; i < eComputedStyleProperty_COUNT; i++) {
240 286 : if (kEntries[i].IsEnabled()) {
241 278 : mIndexMap[index++] = i;
242 : }
243 : }
244 1 : mExposedPropertyCount = index;
245 : }
246 :
247 4 : nsComputedDOMStyle::nsComputedDOMStyle(dom::Element* aElement,
248 : const nsAString& aPseudoElt,
249 : nsIPresShell* aPresShell,
250 : StyleType aStyleType,
251 4 : AnimationFlag aFlag)
252 : : mDocumentWeak(nullptr)
253 : , mOuterFrame(nullptr)
254 : , mInnerFrame(nullptr)
255 : , mPresShell(nullptr)
256 : , mStyleType(aStyleType)
257 : , mStyleContextGeneration(0)
258 : , mExposeVisitedStyle(false)
259 : , mResolvedStyleContext(false)
260 4 : , mAnimationFlag(aFlag)
261 : {
262 4 : MOZ_ASSERT(aElement && aPresShell);
263 :
264 4 : mDocumentWeak = do_GetWeakReference(aPresShell->GetDocument());
265 4 : mContent = aElement;
266 4 : mPseudo = nsCSSPseudoElements::GetPseudoAtom(aPseudoElt);
267 :
268 4 : MOZ_ASSERT(aPresShell->GetPresContext());
269 4 : }
270 :
271 0 : nsComputedDOMStyle::~nsComputedDOMStyle()
272 : {
273 0 : ClearStyleContext();
274 0 : }
275 :
276 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsComputedDOMStyle)
277 :
278 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsComputedDOMStyle)
279 0 : tmp->ClearStyleContext(); // remove observer before clearing mContent
280 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mContent)
281 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
282 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
283 :
284 4 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsComputedDOMStyle)
285 4 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContent)
286 4 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
287 :
288 8 : NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsComputedDOMStyle)
289 :
290 0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsComputedDOMStyle)
291 0 : return tmp->HasKnownLiveWrapper();
292 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
293 :
294 0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsComputedDOMStyle)
295 0 : return tmp->HasKnownLiveWrapper();
296 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
297 :
298 0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsComputedDOMStyle)
299 0 : return tmp->HasKnownLiveWrapper();
300 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
301 :
302 : // QueryInterface implementation for nsComputedDOMStyle
303 40 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsComputedDOMStyle)
304 4 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
305 0 : NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
306 0 : NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration)
307 :
308 :
309 8 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsComputedDOMStyle)
310 4 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsComputedDOMStyle)
311 :
312 : NS_IMETHODIMP
313 4 : nsComputedDOMStyle::GetPropertyValue(const nsCSSPropertyID aPropID,
314 : nsAString& aValue)
315 : {
316 : // This is mostly to avoid code duplication with GetPropertyCSSValue(); if
317 : // perf ever becomes an issue here (doubtful), we can look into changing
318 : // this.
319 : return GetPropertyValue(
320 8 : NS_ConvertASCIItoUTF16(nsCSSProps::GetStringValue(aPropID)),
321 8 : aValue);
322 : }
323 :
324 : NS_IMETHODIMP
325 0 : nsComputedDOMStyle::SetPropertyValue(const nsCSSPropertyID aPropID,
326 : const nsAString& aValue)
327 : {
328 0 : return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
329 : }
330 :
331 : NS_IMETHODIMP
332 0 : nsComputedDOMStyle::GetCssText(nsAString& aCssText)
333 : {
334 0 : aCssText.Truncate();
335 :
336 0 : return NS_OK;
337 : }
338 :
339 : NS_IMETHODIMP
340 0 : nsComputedDOMStyle::SetCssText(const nsAString& aCssText)
341 : {
342 0 : return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
343 : }
344 :
345 : NS_IMETHODIMP
346 0 : nsComputedDOMStyle::GetLength(uint32_t* aLength)
347 : {
348 0 : NS_PRECONDITION(aLength, "Null aLength! Prepare to die!");
349 :
350 0 : uint32_t length = GetComputedStyleMap()->Length();
351 :
352 : // Make sure we have up to date style so that we can include custom
353 : // properties.
354 0 : UpdateCurrentStyleSources(false);
355 0 : if (mStyleContext) {
356 0 : length += mStyleContext->IsServo()
357 0 : ? Servo_GetCustomPropertiesCount(mStyleContext->ComputedValues())
358 0 : : StyleVariables()->mVariables.Count();
359 : }
360 :
361 0 : *aLength = length;
362 :
363 0 : ClearCurrentStyleSources();
364 :
365 0 : return NS_OK;
366 : }
367 :
368 : NS_IMETHODIMP
369 0 : nsComputedDOMStyle::GetParentRule(nsIDOMCSSRule** aParentRule)
370 : {
371 0 : *aParentRule = nullptr;
372 :
373 0 : return NS_OK;
374 : }
375 :
376 : NS_IMETHODIMP
377 4 : nsComputedDOMStyle::GetPropertyValue(const nsAString& aPropertyName,
378 : nsAString& aReturn)
379 : {
380 4 : aReturn.Truncate();
381 :
382 8 : ErrorResult error;
383 8 : RefPtr<CSSValue> val = GetPropertyCSSValue(aPropertyName, error);
384 4 : if (error.Failed()) {
385 0 : return error.StealNSResult();
386 : }
387 :
388 4 : if (val) {
389 8 : nsString text;
390 4 : val->GetCssText(text, error);
391 4 : aReturn.Assign(text);
392 4 : return error.StealNSResult();
393 : }
394 :
395 0 : return NS_OK;
396 : }
397 :
398 : NS_IMETHODIMP
399 0 : nsComputedDOMStyle::GetAuthoredPropertyValue(const nsAString& aPropertyName,
400 : nsAString& aReturn)
401 : {
402 : // Authored style doesn't make sense to return from computed DOM style,
403 : // so just return whatever GetPropertyValue() returns.
404 0 : return GetPropertyValue(aPropertyName, aReturn);
405 : }
406 :
407 : /* static */
408 : already_AddRefed<nsStyleContext>
409 0 : nsComputedDOMStyle::GetStyleContext(Element* aElement,
410 : nsIAtom* aPseudo,
411 : nsIPresShell* aPresShell,
412 : StyleType aStyleType)
413 : {
414 : // If the content has a pres shell, we must use it. Otherwise we'd
415 : // potentially mix rule trees by using the wrong pres shell's style
416 : // set. Using the pres shell from the content also means that any
417 : // content that's actually *in* a document will get the style from the
418 : // correct document.
419 0 : nsCOMPtr<nsIPresShell> presShell = GetPresShellForContent(aElement);
420 0 : if (!presShell) {
421 0 : presShell = aPresShell;
422 0 : if (!presShell)
423 0 : return nullptr;
424 : }
425 :
426 0 : presShell->FlushPendingNotifications(FlushType::Style);
427 :
428 0 : return GetStyleContextNoFlush(aElement, aPseudo, presShell, aStyleType);
429 : }
430 :
431 : namespace {
432 : class MOZ_STACK_CLASS StyleResolver final
433 : {
434 : public:
435 237 : StyleResolver(nsPresContext* aPresContext,
436 : nsComputedDOMStyle::AnimationFlag aAnimationFlag)
437 237 : : mAnimationFlag(aAnimationFlag)
438 : {
439 237 : MOZ_ASSERT(aPresContext);
440 :
441 : // Nothing to do if we are going to resolve style *with* animation.
442 237 : if (mAnimationFlag == nsComputedDOMStyle::eWithAnimation) {
443 237 : return;
444 : }
445 :
446 : // Set SkipAnimationRules flag if we are going to resolve style without
447 : // animation.
448 0 : if (aPresContext->RestyleManager()->IsGecko()) {
449 0 : mRestyleManager = aPresContext->RestyleManager()->AsGecko();
450 :
451 0 : mOldSkipAnimationRules = mRestyleManager->SkipAnimationRules();
452 0 : mRestyleManager->SetSkipAnimationRules(true);
453 : } else {
454 0 : NS_WARNING("stylo: can't skip animaition rules yet");
455 : }
456 : }
457 :
458 : already_AddRefed<nsStyleContext>
459 237 : ResolveWithAnimation(StyleSetHandle aStyleSet,
460 : Element* aElement,
461 : CSSPseudoElementType aType,
462 : nsStyleContext* aParentContext,
463 : nsComputedDOMStyle::StyleType aStyleType,
464 : bool aInDocWithShell)
465 : {
466 237 : MOZ_ASSERT(mAnimationFlag == nsComputedDOMStyle::eWithAnimation,
467 : "AnimationFlag should be eWithAnimation");
468 :
469 474 : RefPtr<nsStyleContext> result;
470 :
471 237 : if (aType != CSSPseudoElementType::NotPseudo) {
472 0 : nsIFrame* frame = nsLayoutUtils::GetStyleFrame(aElement);
473 : Element* pseudoElement =
474 0 : frame && aInDocWithShell ? frame->GetPseudoElement(aType) : nullptr;
475 0 : result = aStyleSet->ResolvePseudoElementStyle(aElement, aType,
476 : aParentContext,
477 0 : pseudoElement);
478 : } else {
479 474 : result = aStyleSet->ResolveStyleFor(aElement, aParentContext,
480 237 : LazyComputeBehavior::Allow);
481 : }
482 237 : if (aStyleType == nsComputedDOMStyle::StyleType::eDefaultOnly) {
483 : // We really only want the user and UA rules. Filter out the other ones.
484 0 : nsTArray< nsCOMPtr<nsIStyleRule> > rules;
485 0 : for (nsRuleNode* ruleNode = result->RuleNode();
486 0 : !ruleNode->IsRoot();
487 : ruleNode = ruleNode->GetParent()) {
488 0 : if (ruleNode->GetLevel() == SheetType::Agent ||
489 0 : ruleNode->GetLevel() == SheetType::User) {
490 0 : rules.AppendElement(ruleNode->GetRule());
491 : }
492 : }
493 :
494 : // We want to build a list of user/ua rules that is in order from least to
495 : // most important, so we have to reverse the list.
496 : // Integer division to get "stop" is purposeful here: if length is odd, we
497 : // don't have to do anything with the middle element of the array.
498 0 : for (uint32_t i = 0, length = rules.Length(), stop = length / 2;
499 0 : i < stop; ++i) {
500 0 : rules[i].swap(rules[length - i - 1]);
501 : }
502 :
503 0 : result = aStyleSet->AsGecko()->ResolveStyleForRules(aParentContext,
504 0 : rules);
505 : }
506 474 : return result.forget();
507 : }
508 :
509 : already_AddRefed<nsStyleContext>
510 0 : ResolveWithoutAnimation(StyleSetHandle aStyleSet,
511 : Element* aElement,
512 : CSSPseudoElementType aType,
513 : nsStyleContext* aParentContext,
514 : bool aInDocWithShell)
515 : {
516 0 : MOZ_ASSERT(!aStyleSet->IsServo(),
517 : "Servo backend should not use this function");
518 0 : MOZ_ASSERT(mAnimationFlag == nsComputedDOMStyle::eWithoutAnimation,
519 : "AnimationFlag should be eWithoutAnimation");
520 :
521 0 : RefPtr<nsStyleContext> result;
522 :
523 0 : if (aType != CSSPseudoElementType::NotPseudo) {
524 0 : nsIFrame* frame = nsLayoutUtils::GetStyleFrame(aElement);
525 : Element* pseudoElement =
526 0 : frame && aInDocWithShell ? frame->GetPseudoElement(aType) : nullptr;
527 : result =
528 0 : aStyleSet->AsGecko()->ResolvePseudoElementStyleWithoutAnimation(
529 : aElement, aType,
530 : aParentContext,
531 0 : pseudoElement);
532 : } else {
533 : result =
534 0 : aStyleSet->AsGecko()->ResolveStyleWithoutAnimation(aElement,
535 0 : aParentContext);
536 : }
537 0 : return result.forget();
538 : }
539 :
540 237 : ~StyleResolver()
541 237 : {
542 237 : if (mRestyleManager) {
543 0 : mRestyleManager->SetSkipAnimationRules(mOldSkipAnimationRules);
544 : }
545 237 : }
546 :
547 : private:
548 : GeckoRestyleManager* mRestyleManager = nullptr;
549 : bool mOldSkipAnimationRules = false;
550 : nsComputedDOMStyle::AnimationFlag mAnimationFlag;
551 : };
552 : }
553 :
554 : /**
555 : * The following function checks whether we need to explicitly resolve the style
556 : * again, even though we have a style context coming from the frame.
557 : *
558 : * This basically checks whether the style is or may be under a ::first-line or
559 : * ::first-letter frame, in which case we can't return the frame style, and we
560 : * need to resolve it. See bug 505515.
561 : */
562 : static bool
563 127 : MustReresolveStyle(const nsStyleContext* aContext)
564 : {
565 127 : MOZ_ASSERT(aContext);
566 :
567 127 : if (aContext->HasPseudoElementData()) {
568 0 : if (!aContext->GetPseudo() ||
569 0 : aContext->IsServo()) {
570 : // TODO(emilio): When ::first-line is supported in Servo, we may want to
571 : // fix this to avoid re-resolving pseudo-element styles.
572 0 : return true;
573 : }
574 :
575 0 : return aContext->GetParent() &&
576 0 : aContext->GetParent()->HasPseudoElementData();
577 : }
578 :
579 127 : return false;
580 : }
581 :
582 : already_AddRefed<nsStyleContext>
583 360 : nsComputedDOMStyle::DoGetStyleContextNoFlush(Element* aElement,
584 : nsIAtom* aPseudo,
585 : nsIPresShell* aPresShell,
586 : StyleType aStyleType,
587 : AnimationFlag aAnimationFlag)
588 : {
589 360 : MOZ_ASSERT(aElement, "NULL element");
590 : // If the content has a pres shell, we must use it. Otherwise we'd
591 : // potentially mix rule trees by using the wrong pres shell's style
592 : // set. Using the pres shell from the content also means that any
593 : // content that's actually *in* a document will get the style from the
594 : // correct document.
595 360 : nsIPresShell *presShell = GetPresShellForContent(aElement);
596 360 : bool inDocWithShell = true;
597 360 : if (!presShell) {
598 2 : inDocWithShell = false;
599 2 : presShell = aPresShell;
600 2 : if (!presShell)
601 0 : return nullptr;
602 : }
603 :
604 360 : auto pseudoType = CSSPseudoElementType::NotPseudo;
605 360 : if (aPseudo) {
606 : pseudoType = nsCSSPseudoElements::
607 0 : GetPseudoType(aPseudo, CSSEnabledState::eIgnoreEnabledState);
608 0 : if (pseudoType >= CSSPseudoElementType::Count) {
609 0 : return nullptr;
610 : }
611 : }
612 :
613 : // XXX the !aElement->IsHTMLElement(nsGkAtoms::area)
614 : // check is needed due to bug 135040 (to avoid using
615 : // mPrimaryFrame). Remove it once that's fixed.
616 718 : if (inDocWithShell &&
617 718 : aStyleType == eAll &&
618 358 : !aElement->IsHTMLElement(nsGkAtoms::area)) {
619 358 : nsIFrame* frame = nullptr;
620 358 : if (aPseudo == nsCSSPseudoElements::before) {
621 0 : frame = nsLayoutUtils::GetBeforeFrame(aElement);
622 358 : } else if (aPseudo == nsCSSPseudoElements::after) {
623 0 : frame = nsLayoutUtils::GetAfterFrame(aElement);
624 358 : } else if (!aPseudo) {
625 358 : frame = nsLayoutUtils::GetStyleFrame(aElement);
626 : }
627 358 : if (frame) {
628 123 : nsStyleContext* result = frame->StyleContext();
629 : // Don't use the style context if it was influenced by
630 : // pseudo-elements, since then it's not the primary style
631 : // for this element / pseudo.
632 123 : if (!MustReresolveStyle(result)) {
633 : // The existing style context may have animation styles so check if we
634 : // need to remove them.
635 123 : if (aAnimationFlag == eWithoutAnimation) {
636 0 : nsPresContext* presContext = presShell->GetPresContext();
637 0 : MOZ_ASSERT(presContext, "Should have a prescontext if we have a frame");
638 0 : if (presContext && presContext->StyleSet()->IsGecko()) {
639 0 : nsStyleSet* styleSet = presContext->StyleSet()->AsGecko();
640 : return styleSet->ResolveStyleByRemovingAnimation(
641 0 : aElement, result, eRestyle_AllHintsWithAnimations);
642 : } else {
643 : RefPtr<ServoComputedValues> baseComputedValues =
644 0 : presContext->StyleSet()->AsServo()->
645 0 : GetBaseComputedValuesForElement(
646 0 : aElement, pseudoType, result->ComputedValues());
647 0 : return ServoStyleContext::Create(nullptr, presContext, aPseudo,
648 0 : pseudoType, baseComputedValues.forget());
649 : }
650 : }
651 :
652 : // this function returns an addrefed style context
653 246 : RefPtr<nsStyleContext> ret = result;
654 123 : return ret.forget();
655 : }
656 : }
657 : }
658 :
659 : // No frame has been created, or we have a pseudo, or we're looking
660 : // for the default style, so resolve the style ourselves.
661 :
662 237 : nsPresContext* presContext = presShell->GetPresContext();
663 237 : if (!presContext)
664 0 : return nullptr;
665 :
666 237 : StyleSetHandle styleSet = presShell->StyleSet();
667 :
668 : // For Servo, compute the result directly without recursively building up
669 : // a throwaway style context chain.
670 237 : if (ServoStyleSet* servoSet = styleSet->GetAsServo()) {
671 : StyleRuleInclusion rules = aStyleType == eDefaultOnly
672 0 : ? StyleRuleInclusion::DefaultOnly
673 0 : : StyleRuleInclusion::All;
674 : RefPtr<nsStyleContext> result =
675 0 : servoSet->ResolveTransientStyle(aElement, aPseudo, pseudoType, rules);
676 0 : if (aAnimationFlag == eWithAnimation) {
677 0 : return result.forget();
678 : }
679 :
680 : RefPtr<ServoComputedValues> baseComputedValues =
681 0 : servoSet->GetBaseComputedValuesForElement(
682 0 : aElement, pseudoType, result->ComputedValues());
683 0 : return ServoStyleContext::Create(nullptr, presContext, aPseudo,
684 0 : pseudoType, baseComputedValues.forget());
685 : }
686 :
687 474 : RefPtr<nsStyleContext> parentContext;
688 237 : nsIContent* parent = aPseudo ? aElement : aElement->GetParent();
689 : // Don't resolve parent context for document fragments.
690 237 : if (parent && parent->IsElement()) {
691 470 : parentContext = GetStyleContextNoFlush(parent->AsElement(), nullptr,
692 235 : aPresShell, aStyleType);
693 : }
694 :
695 474 : StyleResolver styleResolver(presContext, aAnimationFlag);
696 :
697 237 : if (aAnimationFlag == eWithAnimation) {
698 : return styleResolver.ResolveWithAnimation(styleSet,
699 : aElement, pseudoType,
700 : parentContext,
701 : aStyleType,
702 237 : inDocWithShell);
703 : }
704 :
705 : return styleResolver.ResolveWithoutAnimation(styleSet,
706 : aElement, pseudoType,
707 : parentContext,
708 0 : inDocWithShell);
709 : }
710 :
711 : nsMargin
712 0 : nsComputedDOMStyle::GetAdjustedValuesForBoxSizing()
713 : {
714 : // We want the width/height of whatever parts 'width' or 'height' controls,
715 : // which can be different depending on the value of the 'box-sizing' property.
716 0 : const nsStylePosition* stylePos = StylePosition();
717 :
718 0 : nsMargin adjustment;
719 0 : if (stylePos->mBoxSizing == StyleBoxSizing::Border) {
720 0 : adjustment = mInnerFrame->GetUsedBorderAndPadding();
721 : }
722 :
723 0 : return adjustment;
724 : }
725 :
726 : /* static */
727 : nsIPresShell*
728 368 : nsComputedDOMStyle::GetPresShellForContent(const nsIContent* aContent)
729 : {
730 368 : nsIDocument* composedDoc = aContent->GetComposedDoc();
731 368 : if (!composedDoc)
732 2 : return nullptr;
733 :
734 366 : return composedDoc->GetShell();
735 : }
736 :
737 : // nsDOMCSSDeclaration abstract methods which should never be called
738 : // on a nsComputedDOMStyle object, but must be defined to avoid
739 : // compile errors.
740 : DeclarationBlock*
741 0 : nsComputedDOMStyle::GetCSSDeclaration(Operation)
742 : {
743 0 : NS_RUNTIMEABORT("called nsComputedDOMStyle::GetCSSDeclaration");
744 0 : return nullptr;
745 : }
746 :
747 : nsresult
748 0 : nsComputedDOMStyle::SetCSSDeclaration(DeclarationBlock*)
749 : {
750 0 : NS_RUNTIMEABORT("called nsComputedDOMStyle::SetCSSDeclaration");
751 0 : return NS_ERROR_FAILURE;
752 : }
753 :
754 : nsIDocument*
755 0 : nsComputedDOMStyle::DocToUpdate()
756 : {
757 0 : NS_RUNTIMEABORT("called nsComputedDOMStyle::DocToUpdate");
758 0 : return nullptr;
759 : }
760 :
761 : void
762 0 : nsComputedDOMStyle::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
763 : {
764 0 : NS_RUNTIMEABORT("called nsComputedDOMStyle::GetCSSParsingEnvironment");
765 : // Just in case NS_RUNTIMEABORT ever stops killing us for some reason
766 0 : aCSSParseEnv.mPrincipal = nullptr;
767 0 : }
768 :
769 : nsDOMCSSDeclaration::ServoCSSParsingEnvironment
770 0 : nsComputedDOMStyle::GetServoCSSParsingEnvironment() const
771 : {
772 0 : MOZ_CRASH("called nsComputedDOMStyle::GetServoCSSParsingEnvironment");
773 : }
774 :
775 : void
776 4 : nsComputedDOMStyle::ClearStyleContext()
777 : {
778 4 : if (mResolvedStyleContext) {
779 0 : mResolvedStyleContext = false;
780 0 : mContent->RemoveMutationObserver(this);
781 : }
782 4 : mStyleContext = nullptr;
783 4 : }
784 :
785 : void
786 0 : nsComputedDOMStyle::SetResolvedStyleContext(RefPtr<nsStyleContext>&& aContext,
787 : uint64_t aGeneration)
788 : {
789 0 : if (!mResolvedStyleContext) {
790 0 : mResolvedStyleContext = true;
791 0 : mContent->AddMutationObserver(this);
792 : }
793 0 : mStyleContext = aContext;
794 0 : mStyleContextGeneration = aGeneration;
795 0 : }
796 :
797 : void
798 4 : nsComputedDOMStyle::SetFrameStyleContext(nsStyleContext* aContext,
799 : uint64_t aGeneration)
800 : {
801 4 : ClearStyleContext();
802 4 : mStyleContext = aContext;
803 4 : mStyleContextGeneration = aGeneration;
804 4 : }
805 :
806 : void
807 4 : nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush)
808 : {
809 8 : nsCOMPtr<nsIDocument> document = do_QueryReferent(mDocumentWeak);
810 4 : if (!document) {
811 0 : ClearStyleContext();
812 0 : return;
813 : }
814 :
815 : // Flush _before_ getting the presshell, since that could create a new
816 : // presshell. Also note that we want to flush the style on the document
817 : // we're computing style in, not on the document mContent is in -- the two
818 : // may be different.
819 8 : document->FlushPendingNotifications(
820 8 : aNeedsLayoutFlush ? FlushType::Layout : FlushType::Style);
821 : #ifdef DEBUG
822 4 : mFlushedPendingReflows = aNeedsLayoutFlush;
823 : #endif
824 :
825 4 : mPresShell = document->GetShell();
826 4 : if (!mPresShell || !mPresShell->GetPresContext()) {
827 0 : ClearStyleContext();
828 0 : return;
829 : }
830 :
831 : // We need to use GetUndisplayedRestyleGeneration instead of
832 : // GetRestyleGeneration, because the caching of mStyleContext is an
833 : // optimization that is useful only for displayed elements.
834 : // For undisplayed elements we need to take into account any DOM changes that
835 : // might cause a restyle, because Servo will not increase the generation for
836 : // undisplayed elements.
837 : // As for Gecko, GetUndisplayedRestyleGeneration is effectively equal to
838 : // GetRestyleGeneration, since the generation is incremented whenever we
839 : // process restyles.
840 : uint64_t currentGeneration =
841 4 : mPresShell->GetPresContext()->GetUndisplayedRestyleGeneration();
842 :
843 4 : if (mStyleContext) {
844 : // We can't rely on the undisplayed restyle generation if
845 : // mContent is out-of-document, since that generation is not
846 : // incremented for DOM changes on out-of-document elements.
847 : // So we always need to update the style context to ensure it
848 : // it up-to-date.
849 0 : if (mStyleContextGeneration == currentGeneration
850 0 : && mContent->IsInComposedDoc()) {
851 : // Our cached style context is still valid.
852 0 : return;
853 : }
854 : // We've processed some restyles, so the cached style context might
855 : // be out of date.
856 0 : mStyleContext = nullptr;
857 : }
858 :
859 : // XXX the !mContent->IsHTMLElement(nsGkAtoms::area)
860 : // check is needed due to bug 135040 (to avoid using
861 : // mPrimaryFrame). Remove it once that's fixed.
862 4 : if (mStyleType == eAll && !mContent->IsHTMLElement(nsGkAtoms::area)) {
863 4 : mOuterFrame = nullptr;
864 :
865 4 : if (!mPseudo) {
866 4 : mOuterFrame = mContent->GetPrimaryFrame();
867 0 : } else if (mPseudo == nsCSSPseudoElements::before ||
868 0 : mPseudo == nsCSSPseudoElements::after) {
869 0 : nsIAtom* property = mPseudo == nsCSSPseudoElements::before
870 0 : ? nsGkAtoms::beforePseudoProperty
871 0 : : nsGkAtoms::afterPseudoProperty;
872 :
873 0 : auto* pseudo = static_cast<Element*>(mContent->GetProperty(property));
874 0 : mOuterFrame = pseudo ? pseudo->GetPrimaryFrame() : nullptr;
875 : }
876 :
877 4 : mInnerFrame = mOuterFrame;
878 4 : if (mOuterFrame) {
879 4 : LayoutFrameType type = mOuterFrame->Type();
880 4 : if (type == LayoutFrameType::TableWrapper) {
881 : // If the frame is a table wrapper frame then we should get the style
882 : // from the inner table frame.
883 0 : mInnerFrame = mOuterFrame->PrincipalChildList().FirstChild();
884 0 : NS_ASSERTION(mInnerFrame, "table wrapper must have an inner");
885 0 : NS_ASSERTION(!mInnerFrame->GetNextSibling(),
886 : "table wrapper frames should have just one child, "
887 : "the inner table");
888 : }
889 :
890 4 : SetFrameStyleContext(mInnerFrame->StyleContext(), currentGeneration);
891 4 : NS_ASSERTION(mStyleContext, "Frame without style context?");
892 : }
893 : }
894 :
895 4 : if (!mStyleContext || MustReresolveStyle(mStyleContext)) {
896 : #ifdef DEBUG
897 0 : if (mStyleContext && mStyleContext->IsGecko()) {
898 : // We want to check that going through this path because of
899 : // HasPseudoElementData is rare, because it slows us down a good
900 : // bit. So check that we're really inside something associated
901 : // with a pseudo-element that contains elements. (We also allow
902 : // the element to be NAC, just in case some chrome JS calls
903 : // getComputedStyle on a NAC-implemented pseudo.)
904 0 : nsStyleContext* topWithPseudoElementData = mStyleContext;
905 0 : while (topWithPseudoElementData->GetParent()->HasPseudoElementData()) {
906 0 : topWithPseudoElementData = topWithPseudoElementData->GetParent();
907 : }
908 0 : CSSPseudoElementType pseudo = topWithPseudoElementData->GetPseudoType();
909 0 : nsIAtom* pseudoAtom = nsCSSPseudoElements::GetPseudoAtom(pseudo);
910 : nsAutoString assertMsg(
911 0 : NS_LITERAL_STRING("we should be in a pseudo-element that is expected to contain elements ("));
912 0 : assertMsg.Append(nsDependentString(pseudoAtom->GetUTF16String()));
913 0 : assertMsg.Append(')');
914 0 : NS_ASSERTION(nsCSSPseudoElements::PseudoElementContainsElements(pseudo) ||
915 : mContent->IsNativeAnonymous(),
916 : NS_LossyConvertUTF16toASCII(assertMsg).get());
917 : }
918 : #endif
919 : // Need to resolve a style context
920 : RefPtr<nsStyleContext> resolvedStyleContext =
921 0 : nsComputedDOMStyle::GetStyleContext(mContent->AsElement(),
922 : mPseudo,
923 : mPresShell,
924 0 : mStyleType);
925 0 : if (!resolvedStyleContext) {
926 0 : ClearStyleContext();
927 0 : return;
928 : }
929 :
930 : // No need to re-get the generation, even though GetStyleContext
931 : // will flush, since we flushed style at the top of this function.
932 0 : NS_ASSERTION(mPresShell &&
933 : currentGeneration ==
934 : mPresShell->GetPresContext()->GetUndisplayedRestyleGeneration(),
935 : "why should we have flushed style again?");
936 :
937 0 : SetResolvedStyleContext(Move(resolvedStyleContext), currentGeneration);
938 0 : NS_ASSERTION(mPseudo || !mStyleContext->HasPseudoElementData(),
939 : "should not have pseudo-element data");
940 : }
941 :
942 4 : if (mAnimationFlag == eWithoutAnimation) {
943 : // We will support Servo in bug 1311257.
944 0 : MOZ_ASSERT(mPresShell->StyleSet()->IsGecko(),
945 : "eWithoutAnimationRules support Gecko only");
946 0 : nsStyleSet* styleSet = mPresShell->StyleSet()->AsGecko();
947 : RefPtr<nsStyleContext> unanimatedStyleContext =
948 0 : styleSet->ResolveStyleByRemovingAnimation(
949 0 : mContent->AsElement(), mStyleContext, eRestyle_AllHintsWithAnimations);
950 0 : SetResolvedStyleContext(Move(unanimatedStyleContext), currentGeneration);
951 : }
952 :
953 : // mExposeVisitedStyle is set to true only by testing APIs that
954 : // require chrome privilege.
955 4 : MOZ_ASSERT(!mExposeVisitedStyle || nsContentUtils::IsCallerChrome(),
956 : "mExposeVisitedStyle set incorrectly");
957 4 : if (mExposeVisitedStyle && mStyleContext->RelevantLinkVisited()) {
958 0 : nsStyleContext *styleIfVisited = mStyleContext->GetStyleIfVisited();
959 0 : if (styleIfVisited) {
960 0 : mStyleContext = styleIfVisited;
961 : }
962 : }
963 : }
964 :
965 : void
966 4 : nsComputedDOMStyle::ClearCurrentStyleSources()
967 : {
968 4 : mOuterFrame = nullptr;
969 4 : mInnerFrame = nullptr;
970 4 : mPresShell = nullptr;
971 :
972 : // Release the current style context if we got it off the frame.
973 : // For a style context we resolved, keep it around so that we
974 : // can re-use it next time this object is queried.
975 4 : if (!mResolvedStyleContext) {
976 4 : mStyleContext = nullptr;
977 : }
978 4 : }
979 :
980 : already_AddRefed<CSSValue>
981 4 : nsComputedDOMStyle::GetPropertyCSSValue(const nsAString& aPropertyName, ErrorResult& aRv)
982 : {
983 : nsCSSPropertyID prop =
984 4 : nsCSSProps::LookupProperty(aPropertyName, CSSEnabledState::eForAllContent);
985 :
986 : bool needsLayoutFlush;
987 : nsComputedStyleMap::Entry::ComputeMethod getter;
988 :
989 4 : if (prop == eCSSPropertyExtra_variable) {
990 0 : needsLayoutFlush = false;
991 0 : getter = nullptr;
992 : } else {
993 : // We don't (for now, anyway, though it may make sense to change it
994 : // for all aliases, including those in nsCSSPropAliasList) want
995 : // aliases to be enumerable (via GetLength and IndexedGetter), so
996 : // handle them here rather than adding entries to
997 : // GetQueryablePropertyMap.
998 8 : if (prop != eCSSProperty_UNKNOWN &&
999 4 : nsCSSProps::PropHasFlags(prop, CSS_PROPERTY_IS_ALIAS)) {
1000 0 : const nsCSSPropertyID* subprops = nsCSSProps::SubpropertyEntryFor(prop);
1001 0 : MOZ_ASSERT(subprops[1] == eCSSProperty_UNKNOWN,
1002 : "must have list of length 1");
1003 0 : prop = subprops[0];
1004 : }
1005 :
1006 : const nsComputedStyleMap::Entry* propEntry =
1007 4 : GetComputedStyleMap()->FindEntryForProperty(prop);
1008 :
1009 4 : if (!propEntry) {
1010 : #ifdef DEBUG_ComputedDOMStyle
1011 : NS_WARNING(PromiseFlatCString(NS_ConvertUTF16toUTF8(aPropertyName) +
1012 : NS_LITERAL_CSTRING(" is not queryable!")).get());
1013 : #endif
1014 :
1015 : // NOTE: For branches, we should flush here for compatibility!
1016 0 : return nullptr;
1017 : }
1018 :
1019 4 : needsLayoutFlush = propEntry->IsLayoutFlushNeeded();
1020 4 : getter = propEntry->mGetter;
1021 : }
1022 :
1023 4 : UpdateCurrentStyleSources(needsLayoutFlush);
1024 4 : if (!mStyleContext) {
1025 0 : aRv.Throw(NS_ERROR_NOT_AVAILABLE);
1026 0 : return nullptr;
1027 : }
1028 :
1029 8 : RefPtr<CSSValue> val;
1030 4 : if (prop == eCSSPropertyExtra_variable) {
1031 0 : val = DoGetCustomProperty(aPropertyName);
1032 : } else {
1033 : // Call our pointer-to-member-function.
1034 4 : val = (this->*getter)();
1035 : }
1036 :
1037 4 : ClearCurrentStyleSources();
1038 :
1039 4 : return val.forget();
1040 : }
1041 :
1042 : NS_IMETHODIMP
1043 0 : nsComputedDOMStyle::RemoveProperty(const nsAString& aPropertyName,
1044 : nsAString& aReturn)
1045 : {
1046 0 : return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
1047 : }
1048 :
1049 :
1050 : NS_IMETHODIMP
1051 0 : nsComputedDOMStyle::GetPropertyPriority(const nsAString& aPropertyName,
1052 : nsAString& aReturn)
1053 : {
1054 0 : aReturn.Truncate();
1055 :
1056 0 : return NS_OK;
1057 : }
1058 :
1059 : NS_IMETHODIMP
1060 0 : nsComputedDOMStyle::SetProperty(const nsAString& aPropertyName,
1061 : const nsAString& aValue,
1062 : const nsAString& aPriority)
1063 : {
1064 0 : return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
1065 : }
1066 :
1067 : NS_IMETHODIMP
1068 0 : nsComputedDOMStyle::Item(uint32_t aIndex, nsAString& aReturn)
1069 : {
1070 0 : return nsDOMCSSDeclaration::Item(aIndex, aReturn);
1071 : }
1072 :
1073 : void
1074 0 : nsComputedDOMStyle::IndexedGetter(uint32_t aIndex,
1075 : bool& aFound,
1076 : nsAString& aPropName)
1077 : {
1078 0 : nsComputedStyleMap* map = GetComputedStyleMap();
1079 0 : uint32_t length = map->Length();
1080 :
1081 0 : if (aIndex < length) {
1082 0 : aFound = true;
1083 0 : CopyASCIItoUTF16(nsCSSProps::GetStringValue(map->PropertyAt(aIndex)),
1084 0 : aPropName);
1085 0 : return;
1086 : }
1087 :
1088 : // Custom properties are exposed with indexed properties just after all
1089 : // of the built-in properties.
1090 0 : UpdateCurrentStyleSources(false);
1091 0 : if (!mStyleContext) {
1092 0 : aFound = false;
1093 0 : return;
1094 : }
1095 :
1096 0 : bool isServo = mStyleContext->IsServo();
1097 :
1098 : const nsStyleVariables* variables = isServo
1099 0 : ? nullptr
1100 0 : : StyleVariables();
1101 :
1102 : const uint32_t count = isServo
1103 0 : ? Servo_GetCustomPropertiesCount(mStyleContext->ComputedValues())
1104 0 : : variables->mVariables.Count();
1105 :
1106 0 : const uint32_t index = aIndex - length;
1107 0 : if (index < count) {
1108 0 : aFound = true;
1109 0 : nsString varName;
1110 0 : if (isServo) {
1111 0 : Servo_GetCustomPropertyNameAt(mStyleContext->ComputedValues(),
1112 0 : index, &varName);
1113 : } else {
1114 0 : variables->mVariables.GetVariableAt(index, varName);
1115 : }
1116 0 : aPropName.AssignLiteral("--");
1117 0 : aPropName.Append(varName);
1118 : } else {
1119 0 : aFound = false;
1120 : }
1121 :
1122 0 : ClearCurrentStyleSources();
1123 : }
1124 :
1125 : // Property getters...
1126 :
1127 : already_AddRefed<CSSValue>
1128 0 : nsComputedDOMStyle::DoGetBinding()
1129 : {
1130 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1131 :
1132 0 : const nsStyleDisplay* display = StyleDisplay();
1133 :
1134 0 : if (display->mBinding) {
1135 0 : val->SetURI(display->mBinding->GetURI());
1136 : } else {
1137 0 : val->SetIdent(eCSSKeyword_none);
1138 : }
1139 :
1140 0 : return val.forget();
1141 : }
1142 :
1143 : already_AddRefed<CSSValue>
1144 0 : nsComputedDOMStyle::DoGetClear()
1145 : {
1146 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1147 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mBreakType,
1148 0 : nsCSSProps::kClearKTable));
1149 0 : return val.forget();
1150 : }
1151 :
1152 : already_AddRefed<CSSValue>
1153 0 : nsComputedDOMStyle::DoGetFloat()
1154 : {
1155 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1156 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mFloat,
1157 0 : nsCSSProps::kFloatKTable));
1158 0 : return val.forget();
1159 : }
1160 :
1161 : already_AddRefed<CSSValue>
1162 0 : nsComputedDOMStyle::DoGetBottom()
1163 : {
1164 0 : return GetOffsetWidthFor(eSideBottom);
1165 : }
1166 :
1167 : already_AddRefed<CSSValue>
1168 0 : nsComputedDOMStyle::DoGetStackSizing()
1169 : {
1170 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1171 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleXUL()->mStackSizing,
1172 0 : nsCSSProps::kStackSizingKTable));
1173 0 : return val.forget();
1174 : }
1175 :
1176 : void
1177 3 : nsComputedDOMStyle::SetToRGBAColor(nsROCSSPrimitiveValue* aValue,
1178 : nscolor aColor)
1179 : {
1180 3 : nsROCSSPrimitiveValue *red = new nsROCSSPrimitiveValue;
1181 3 : nsROCSSPrimitiveValue *green = new nsROCSSPrimitiveValue;
1182 3 : nsROCSSPrimitiveValue *blue = new nsROCSSPrimitiveValue;
1183 3 : nsROCSSPrimitiveValue *alpha = new nsROCSSPrimitiveValue;
1184 :
1185 3 : uint8_t a = NS_GET_A(aColor);
1186 : nsDOMCSSRGBColor *rgbColor =
1187 3 : new nsDOMCSSRGBColor(red, green, blue, alpha, a < 255);
1188 :
1189 3 : red->SetNumber(NS_GET_R(aColor));
1190 3 : green->SetNumber(NS_GET_G(aColor));
1191 3 : blue->SetNumber(NS_GET_B(aColor));
1192 3 : alpha->SetNumber(nsStyleUtil::ColorComponentToFloat(a));
1193 :
1194 3 : aValue->SetColor(rgbColor);
1195 3 : }
1196 :
1197 : void
1198 0 : nsComputedDOMStyle::SetValueFromComplexColor(nsROCSSPrimitiveValue* aValue,
1199 : const StyleComplexColor& aColor)
1200 : {
1201 0 : SetToRGBAColor(aValue, StyleColor()->CalcComplexColor(aColor));
1202 0 : }
1203 :
1204 : already_AddRefed<CSSValue>
1205 3 : nsComputedDOMStyle::DoGetColor()
1206 : {
1207 6 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1208 3 : SetToRGBAColor(val, StyleColor()->mColor);
1209 6 : return val.forget();
1210 : }
1211 :
1212 : already_AddRefed<CSSValue>
1213 0 : nsComputedDOMStyle::DoGetColorAdjust()
1214 : {
1215 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1216 0 : val->SetIdent(
1217 0 : nsCSSProps::ValueToKeywordEnum(StyleVisibility()->mColorAdjust,
1218 0 : nsCSSProps::kColorAdjustKTable));
1219 0 : return val.forget();
1220 : }
1221 :
1222 : already_AddRefed<CSSValue>
1223 0 : nsComputedDOMStyle::DoGetOpacity()
1224 : {
1225 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1226 0 : val->SetNumber(StyleEffects()->mOpacity);
1227 0 : return val.forget();
1228 : }
1229 :
1230 : already_AddRefed<CSSValue>
1231 0 : nsComputedDOMStyle::DoGetColumnCount()
1232 : {
1233 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1234 :
1235 0 : const nsStyleColumn* column = StyleColumn();
1236 :
1237 0 : if (column->mColumnCount == NS_STYLE_COLUMN_COUNT_AUTO) {
1238 0 : val->SetIdent(eCSSKeyword_auto);
1239 : } else {
1240 0 : val->SetNumber(column->mColumnCount);
1241 : }
1242 :
1243 0 : return val.forget();
1244 : }
1245 :
1246 : already_AddRefed<CSSValue>
1247 0 : nsComputedDOMStyle::DoGetColumnWidth()
1248 : {
1249 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1250 :
1251 : // XXX fix the auto case. When we actually have a column frame, I think
1252 : // we should return the computed column width.
1253 0 : SetValueToCoord(val, StyleColumn()->mColumnWidth, true);
1254 0 : return val.forget();
1255 : }
1256 :
1257 : already_AddRefed<CSSValue>
1258 0 : nsComputedDOMStyle::DoGetColumnGap()
1259 : {
1260 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1261 :
1262 0 : const nsStyleColumn* column = StyleColumn();
1263 0 : if (column->mColumnGap.GetUnit() == eStyleUnit_Normal) {
1264 0 : val->SetAppUnits(StyleFont()->mFont.size);
1265 : } else {
1266 0 : SetValueToCoord(val, StyleColumn()->mColumnGap, true);
1267 : }
1268 :
1269 0 : return val.forget();
1270 : }
1271 :
1272 : already_AddRefed<CSSValue>
1273 0 : nsComputedDOMStyle::DoGetColumnFill()
1274 : {
1275 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1276 0 : val->SetIdent(
1277 0 : nsCSSProps::ValueToKeywordEnum(StyleColumn()->mColumnFill,
1278 0 : nsCSSProps::kColumnFillKTable));
1279 0 : return val.forget();
1280 : }
1281 :
1282 : already_AddRefed<CSSValue>
1283 0 : nsComputedDOMStyle::DoGetColumnSpan()
1284 : {
1285 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1286 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleColumn()->mColumnSpan,
1287 0 : nsCSSProps::kColumnSpanKTable));
1288 0 : return val.forget();
1289 : }
1290 :
1291 : already_AddRefed<CSSValue>
1292 0 : nsComputedDOMStyle::DoGetColumnRuleWidth()
1293 : {
1294 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1295 0 : val->SetAppUnits(StyleColumn()->GetComputedColumnRuleWidth());
1296 0 : return val.forget();
1297 : }
1298 :
1299 : already_AddRefed<CSSValue>
1300 0 : nsComputedDOMStyle::DoGetColumnRuleStyle()
1301 : {
1302 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1303 0 : val->SetIdent(
1304 0 : nsCSSProps::ValueToKeywordEnum(StyleColumn()->mColumnRuleStyle,
1305 0 : nsCSSProps::kBorderStyleKTable));
1306 0 : return val.forget();
1307 : }
1308 :
1309 : already_AddRefed<CSSValue>
1310 0 : nsComputedDOMStyle::DoGetColumnRuleColor()
1311 : {
1312 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1313 0 : SetValueFromComplexColor(val, StyleColumn()->mColumnRuleColor);
1314 0 : return val.forget();
1315 : }
1316 :
1317 : static void
1318 0 : AppendCounterStyle(CounterStyle* aStyle, nsAString& aString)
1319 : {
1320 0 : AnonymousCounterStyle* anonymous = aStyle->AsAnonymous();
1321 0 : if (!anonymous) {
1322 : // want SetIdent
1323 0 : nsString type;
1324 0 : aStyle->GetStyleName(type);
1325 0 : nsStyleUtil::AppendEscapedCSSIdent(type, aString);
1326 0 : } else if (anonymous->IsSingleString()) {
1327 0 : const nsTArray<nsString>& symbols = anonymous->GetSymbols();
1328 0 : MOZ_ASSERT(symbols.Length() == 1);
1329 0 : nsStyleUtil::AppendEscapedCSSString(symbols[0], aString);
1330 : } else {
1331 0 : aString.AppendLiteral("symbols(");
1332 :
1333 0 : uint8_t system = anonymous->GetSystem();
1334 0 : NS_ASSERTION(system == NS_STYLE_COUNTER_SYSTEM_CYCLIC ||
1335 : system == NS_STYLE_COUNTER_SYSTEM_NUMERIC ||
1336 : system == NS_STYLE_COUNTER_SYSTEM_ALPHABETIC ||
1337 : system == NS_STYLE_COUNTER_SYSTEM_SYMBOLIC ||
1338 : system == NS_STYLE_COUNTER_SYSTEM_FIXED,
1339 : "Invalid system for anonymous counter style.");
1340 0 : if (system != NS_STYLE_COUNTER_SYSTEM_SYMBOLIC) {
1341 0 : AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(
1342 0 : system, nsCSSProps::kCounterSystemKTable), aString);
1343 0 : aString.Append(' ');
1344 : }
1345 :
1346 0 : const nsTArray<nsString>& symbols = anonymous->GetSymbols();
1347 0 : NS_ASSERTION(symbols.Length() > 0,
1348 : "No symbols in the anonymous counter style");
1349 0 : for (size_t i = 0, iend = symbols.Length(); i < iend; i++) {
1350 0 : nsStyleUtil::AppendEscapedCSSString(symbols[i], aString);
1351 0 : aString.Append(' ');
1352 : }
1353 0 : aString.Replace(aString.Length() - 1, 1, char16_t(')'));
1354 : }
1355 0 : }
1356 :
1357 : already_AddRefed<CSSValue>
1358 0 : nsComputedDOMStyle::DoGetContent()
1359 : {
1360 0 : const nsStyleContent *content = StyleContent();
1361 :
1362 0 : if (content->ContentCount() == 0) {
1363 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1364 0 : val->SetIdent(eCSSKeyword_none);
1365 0 : return val.forget();
1366 : }
1367 :
1368 0 : if (content->ContentCount() == 1 &&
1369 0 : content->ContentAt(0).GetType() == eStyleContentType_AltContent) {
1370 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1371 0 : val->SetIdent(eCSSKeyword__moz_alt_content);
1372 0 : return val.forget();
1373 : }
1374 :
1375 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
1376 :
1377 0 : for (uint32_t i = 0, i_end = content->ContentCount(); i < i_end; ++i) {
1378 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1379 :
1380 0 : const nsStyleContentData &data = content->ContentAt(i);
1381 0 : nsStyleContentType type = data.GetType();
1382 0 : switch (type) {
1383 : case eStyleContentType_String: {
1384 0 : nsAutoString str;
1385 : nsStyleUtil::AppendEscapedCSSString(
1386 0 : nsDependentString(data.GetString()), str);
1387 0 : val->SetString(str);
1388 0 : break;
1389 : }
1390 : case eStyleContentType_Image: {
1391 0 : nsCOMPtr<nsIURI> uri;
1392 0 : if (imgRequestProxy* image = data.GetImage()) {
1393 0 : image->GetURI(getter_AddRefs(uri));
1394 : }
1395 0 : val->SetURI(uri);
1396 0 : break;
1397 : }
1398 : case eStyleContentType_Attr: {
1399 0 : nsAutoString str;
1400 : nsStyleUtil::AppendEscapedCSSIdent(
1401 0 : nsDependentString(data.GetString()), str);
1402 0 : val->SetString(str, nsIDOMCSSPrimitiveValue::CSS_ATTR);
1403 0 : break;
1404 : }
1405 : case eStyleContentType_Counter:
1406 : case eStyleContentType_Counters: {
1407 : /* FIXME: counters should really use an object */
1408 0 : nsAutoString str;
1409 0 : if (type == eStyleContentType_Counter) {
1410 0 : str.AppendLiteral("counter(");
1411 : }
1412 : else {
1413 0 : str.AppendLiteral("counters(");
1414 : }
1415 0 : nsStyleContentData::CounterFunction* counters = data.GetCounters();
1416 0 : nsStyleUtil::AppendEscapedCSSIdent(counters->mIdent, str);
1417 0 : if (type == eStyleContentType_Counters) {
1418 0 : str.AppendLiteral(", ");
1419 0 : nsStyleUtil::AppendEscapedCSSString(counters->mSeparator, str);
1420 : }
1421 0 : if (counters->mCounterStyle != CounterStyleManager::GetDecimalStyle()) {
1422 0 : str.AppendLiteral(", ");
1423 0 : AppendCounterStyle(counters->mCounterStyle, str);
1424 : }
1425 :
1426 0 : str.Append(char16_t(')'));
1427 0 : val->SetString(str, nsIDOMCSSPrimitiveValue::CSS_COUNTER);
1428 0 : break;
1429 : }
1430 : case eStyleContentType_OpenQuote:
1431 0 : val->SetIdent(eCSSKeyword_open_quote);
1432 0 : break;
1433 : case eStyleContentType_CloseQuote:
1434 0 : val->SetIdent(eCSSKeyword_close_quote);
1435 0 : break;
1436 : case eStyleContentType_NoOpenQuote:
1437 0 : val->SetIdent(eCSSKeyword_no_open_quote);
1438 0 : break;
1439 : case eStyleContentType_NoCloseQuote:
1440 0 : val->SetIdent(eCSSKeyword_no_close_quote);
1441 0 : break;
1442 : case eStyleContentType_AltContent:
1443 : default:
1444 0 : NS_NOTREACHED("unexpected type");
1445 0 : break;
1446 : }
1447 0 : valueList->AppendCSSValue(val.forget());
1448 : }
1449 :
1450 0 : return valueList.forget();
1451 : }
1452 :
1453 : already_AddRefed<CSSValue>
1454 0 : nsComputedDOMStyle::DoGetCounterIncrement()
1455 : {
1456 0 : const nsStyleContent *content = StyleContent();
1457 :
1458 0 : if (content->CounterIncrementCount() == 0) {
1459 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1460 0 : val->SetIdent(eCSSKeyword_none);
1461 0 : return val.forget();
1462 : }
1463 :
1464 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
1465 :
1466 0 : for (uint32_t i = 0, i_end = content->CounterIncrementCount(); i < i_end; ++i) {
1467 0 : RefPtr<nsROCSSPrimitiveValue> name = new nsROCSSPrimitiveValue;
1468 0 : RefPtr<nsROCSSPrimitiveValue> value = new nsROCSSPrimitiveValue;
1469 :
1470 0 : const nsStyleCounterData& data = content->CounterIncrementAt(i);
1471 0 : nsAutoString escaped;
1472 0 : nsStyleUtil::AppendEscapedCSSIdent(data.mCounter, escaped);
1473 0 : name->SetString(escaped);
1474 0 : value->SetNumber(data.mValue); // XXX This should really be integer
1475 :
1476 0 : valueList->AppendCSSValue(name.forget());
1477 0 : valueList->AppendCSSValue(value.forget());
1478 : }
1479 :
1480 0 : return valueList.forget();
1481 : }
1482 :
1483 : /* Convert the stored representation into a list of two values and then hand
1484 : * it back.
1485 : */
1486 : already_AddRefed<CSSValue>
1487 0 : nsComputedDOMStyle::DoGetTransformOrigin()
1488 : {
1489 : /* We need to build up a list of two values. We'll call them
1490 : * width and height.
1491 : */
1492 :
1493 : /* Store things as a value list */
1494 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
1495 :
1496 : /* Now, get the values. */
1497 0 : const nsStyleDisplay* display = StyleDisplay();
1498 :
1499 0 : RefPtr<nsROCSSPrimitiveValue> width = new nsROCSSPrimitiveValue;
1500 0 : SetValueToCoord(width, display->mTransformOrigin[0], false,
1501 0 : &nsComputedDOMStyle::GetFrameBoundsWidthForTransform);
1502 0 : valueList->AppendCSSValue(width.forget());
1503 :
1504 0 : RefPtr<nsROCSSPrimitiveValue> height = new nsROCSSPrimitiveValue;
1505 0 : SetValueToCoord(height, display->mTransformOrigin[1], false,
1506 0 : &nsComputedDOMStyle::GetFrameBoundsHeightForTransform);
1507 0 : valueList->AppendCSSValue(height.forget());
1508 :
1509 0 : if (display->mTransformOrigin[2].GetUnit() != eStyleUnit_Coord ||
1510 0 : display->mTransformOrigin[2].GetCoordValue() != 0) {
1511 0 : RefPtr<nsROCSSPrimitiveValue> depth = new nsROCSSPrimitiveValue;
1512 0 : SetValueToCoord(depth, display->mTransformOrigin[2], false,
1513 0 : nullptr);
1514 0 : valueList->AppendCSSValue(depth.forget());
1515 : }
1516 :
1517 0 : return valueList.forget();
1518 : }
1519 :
1520 : /* Convert the stored representation into a list of two values and then hand
1521 : * it back.
1522 : */
1523 : already_AddRefed<CSSValue>
1524 0 : nsComputedDOMStyle::DoGetPerspectiveOrigin()
1525 : {
1526 : /* We need to build up a list of two values. We'll call them
1527 : * width and height.
1528 : */
1529 :
1530 : /* Store things as a value list */
1531 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
1532 :
1533 : /* Now, get the values. */
1534 0 : const nsStyleDisplay* display = StyleDisplay();
1535 :
1536 0 : RefPtr<nsROCSSPrimitiveValue> width = new nsROCSSPrimitiveValue;
1537 0 : SetValueToCoord(width, display->mPerspectiveOrigin[0], false,
1538 0 : &nsComputedDOMStyle::GetFrameBoundsWidthForTransform);
1539 0 : valueList->AppendCSSValue(width.forget());
1540 :
1541 0 : RefPtr<nsROCSSPrimitiveValue> height = new nsROCSSPrimitiveValue;
1542 0 : SetValueToCoord(height, display->mPerspectiveOrigin[1], false,
1543 0 : &nsComputedDOMStyle::GetFrameBoundsHeightForTransform);
1544 0 : valueList->AppendCSSValue(height.forget());
1545 :
1546 0 : return valueList.forget();
1547 : }
1548 :
1549 : already_AddRefed<CSSValue>
1550 0 : nsComputedDOMStyle::DoGetPerspective()
1551 : {
1552 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1553 0 : SetValueToCoord(val, StyleDisplay()->mChildPerspective, false);
1554 0 : return val.forget();
1555 : }
1556 :
1557 : already_AddRefed<CSSValue>
1558 0 : nsComputedDOMStyle::DoGetBackfaceVisibility()
1559 : {
1560 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1561 0 : val->SetIdent(
1562 0 : nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mBackfaceVisibility,
1563 0 : nsCSSProps::kBackfaceVisibilityKTable));
1564 0 : return val.forget();
1565 : }
1566 :
1567 : already_AddRefed<CSSValue>
1568 0 : nsComputedDOMStyle::DoGetTransformStyle()
1569 : {
1570 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1571 0 : val->SetIdent(
1572 0 : nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mTransformStyle,
1573 0 : nsCSSProps::kTransformStyleKTable));
1574 0 : return val.forget();
1575 : }
1576 :
1577 : already_AddRefed<CSSValue>
1578 0 : nsComputedDOMStyle::DoGetTransform()
1579 : {
1580 0 : const nsStyleDisplay* display = StyleDisplay();
1581 0 : return GetTransformValue(display->mSpecifiedTransform);
1582 : }
1583 :
1584 : already_AddRefed<CSSValue>
1585 0 : nsComputedDOMStyle::DoGetTransformBox()
1586 : {
1587 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1588 0 : val->SetIdent(
1589 0 : nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mTransformBox,
1590 0 : nsCSSProps::kTransformBoxKTable));
1591 0 : return val.forget();
1592 : }
1593 :
1594 : /* static */ already_AddRefed<nsROCSSPrimitiveValue>
1595 0 : nsComputedDOMStyle::MatrixToCSSValue(const mozilla::gfx::Matrix4x4& matrix)
1596 : {
1597 0 : bool is3D = !matrix.Is2D();
1598 :
1599 0 : nsAutoString resultString(NS_LITERAL_STRING("matrix"));
1600 0 : if (is3D) {
1601 0 : resultString.AppendLiteral("3d");
1602 : }
1603 :
1604 0 : resultString.Append('(');
1605 0 : resultString.AppendFloat(matrix._11);
1606 0 : resultString.AppendLiteral(", ");
1607 0 : resultString.AppendFloat(matrix._12);
1608 0 : resultString.AppendLiteral(", ");
1609 0 : if (is3D) {
1610 0 : resultString.AppendFloat(matrix._13);
1611 0 : resultString.AppendLiteral(", ");
1612 0 : resultString.AppendFloat(matrix._14);
1613 0 : resultString.AppendLiteral(", ");
1614 : }
1615 0 : resultString.AppendFloat(matrix._21);
1616 0 : resultString.AppendLiteral(", ");
1617 0 : resultString.AppendFloat(matrix._22);
1618 0 : resultString.AppendLiteral(", ");
1619 0 : if (is3D) {
1620 0 : resultString.AppendFloat(matrix._23);
1621 0 : resultString.AppendLiteral(", ");
1622 0 : resultString.AppendFloat(matrix._24);
1623 0 : resultString.AppendLiteral(", ");
1624 0 : resultString.AppendFloat(matrix._31);
1625 0 : resultString.AppendLiteral(", ");
1626 0 : resultString.AppendFloat(matrix._32);
1627 0 : resultString.AppendLiteral(", ");
1628 0 : resultString.AppendFloat(matrix._33);
1629 0 : resultString.AppendLiteral(", ");
1630 0 : resultString.AppendFloat(matrix._34);
1631 0 : resultString.AppendLiteral(", ");
1632 : }
1633 0 : resultString.AppendFloat(matrix._41);
1634 0 : resultString.AppendLiteral(", ");
1635 0 : resultString.AppendFloat(matrix._42);
1636 0 : if (is3D) {
1637 0 : resultString.AppendLiteral(", ");
1638 0 : resultString.AppendFloat(matrix._43);
1639 0 : resultString.AppendLiteral(", ");
1640 0 : resultString.AppendFloat(matrix._44);
1641 : }
1642 0 : resultString.Append(')');
1643 :
1644 : /* Create a value to hold our result. */
1645 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1646 :
1647 0 : val->SetString(resultString);
1648 0 : return val.forget();
1649 : }
1650 :
1651 : already_AddRefed<CSSValue>
1652 0 : nsComputedDOMStyle::DoGetCounterReset()
1653 : {
1654 0 : const nsStyleContent *content = StyleContent();
1655 :
1656 0 : if (content->CounterResetCount() == 0) {
1657 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1658 0 : val->SetIdent(eCSSKeyword_none);
1659 0 : return val.forget();
1660 : }
1661 :
1662 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
1663 :
1664 0 : for (uint32_t i = 0, i_end = content->CounterResetCount(); i < i_end; ++i) {
1665 0 : RefPtr<nsROCSSPrimitiveValue> name = new nsROCSSPrimitiveValue;
1666 0 : RefPtr<nsROCSSPrimitiveValue> value = new nsROCSSPrimitiveValue;
1667 :
1668 0 : const nsStyleCounterData& data = content->CounterResetAt(i);
1669 0 : nsAutoString escaped;
1670 0 : nsStyleUtil::AppendEscapedCSSIdent(data.mCounter, escaped);
1671 0 : name->SetString(escaped);
1672 0 : value->SetNumber(data.mValue); // XXX This should really be integer
1673 :
1674 0 : valueList->AppendCSSValue(name.forget());
1675 0 : valueList->AppendCSSValue(value.forget());
1676 : }
1677 :
1678 0 : return valueList.forget();
1679 : }
1680 :
1681 : already_AddRefed<CSSValue>
1682 0 : nsComputedDOMStyle::DoGetQuotes()
1683 : {
1684 0 : const auto& quotePairs = StyleList()->GetQuotePairs();
1685 :
1686 0 : if (quotePairs.IsEmpty()) {
1687 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1688 0 : val->SetIdent(eCSSKeyword_none);
1689 0 : return val.forget();
1690 : }
1691 :
1692 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
1693 :
1694 0 : for (const auto& quotePair : quotePairs) {
1695 0 : RefPtr<nsROCSSPrimitiveValue> openVal = new nsROCSSPrimitiveValue;
1696 0 : RefPtr<nsROCSSPrimitiveValue> closeVal = new nsROCSSPrimitiveValue;
1697 :
1698 0 : nsAutoString s;
1699 0 : nsStyleUtil::AppendEscapedCSSString(quotePair.first, s);
1700 0 : openVal->SetString(s);
1701 0 : s.Truncate();
1702 0 : nsStyleUtil::AppendEscapedCSSString(quotePair.second, s);
1703 0 : closeVal->SetString(s);
1704 :
1705 0 : valueList->AppendCSSValue(openVal.forget());
1706 0 : valueList->AppendCSSValue(closeVal.forget());
1707 : }
1708 :
1709 0 : return valueList.forget();
1710 : }
1711 :
1712 : already_AddRefed<CSSValue>
1713 0 : nsComputedDOMStyle::DoGetFontFamily()
1714 : {
1715 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1716 :
1717 0 : const nsStyleFont* font = StyleFont();
1718 0 : nsAutoString fontlistStr;
1719 0 : nsStyleUtil::AppendEscapedCSSFontFamilyList(font->mFont.fontlist,
1720 0 : fontlistStr);
1721 0 : val->SetString(fontlistStr);
1722 0 : return val.forget();
1723 : }
1724 :
1725 : already_AddRefed<CSSValue>
1726 0 : nsComputedDOMStyle::DoGetFontSize()
1727 : {
1728 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1729 :
1730 : // Note: StyleFont()->mSize is the 'computed size';
1731 : // StyleFont()->mFont.size is the 'actual size'
1732 0 : val->SetAppUnits(StyleFont()->mSize);
1733 0 : return val.forget();
1734 : }
1735 :
1736 : already_AddRefed<CSSValue>
1737 0 : nsComputedDOMStyle::DoGetFontSizeAdjust()
1738 : {
1739 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1740 :
1741 0 : const nsStyleFont *font = StyleFont();
1742 :
1743 0 : if (font->mFont.sizeAdjust >= 0.0f) {
1744 0 : val->SetNumber(font->mFont.sizeAdjust);
1745 : } else {
1746 0 : val->SetIdent(eCSSKeyword_none);
1747 : }
1748 :
1749 0 : return val.forget();
1750 : }
1751 :
1752 : already_AddRefed<CSSValue>
1753 0 : nsComputedDOMStyle::DoGetOsxFontSmoothing()
1754 : {
1755 0 : if (nsContentUtils::ShouldResistFingerprinting(
1756 0 : mPresShell->GetPresContext()->GetDocShell()))
1757 0 : return nullptr;
1758 :
1759 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1760 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleFont()->mFont.smoothing,
1761 0 : nsCSSProps::kFontSmoothingKTable));
1762 0 : return val.forget();
1763 : }
1764 :
1765 : already_AddRefed<CSSValue>
1766 0 : nsComputedDOMStyle::DoGetFontStretch()
1767 : {
1768 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1769 :
1770 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleFont()->mFont.stretch,
1771 0 : nsCSSProps::kFontStretchKTable));
1772 :
1773 0 : return val.forget();
1774 : }
1775 :
1776 : already_AddRefed<CSSValue>
1777 0 : nsComputedDOMStyle::DoGetFontStyle()
1778 : {
1779 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1780 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleFont()->mFont.style,
1781 0 : nsCSSProps::kFontStyleKTable));
1782 0 : return val.forget();
1783 : }
1784 :
1785 : already_AddRefed<CSSValue>
1786 0 : nsComputedDOMStyle::DoGetFontWeight()
1787 : {
1788 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1789 :
1790 0 : const nsStyleFont* font = StyleFont();
1791 :
1792 0 : uint16_t weight = font->mFont.weight;
1793 0 : NS_ASSERTION(weight % 100 == 0, "unexpected value of font-weight");
1794 0 : val->SetNumber(weight);
1795 :
1796 0 : return val.forget();
1797 : }
1798 :
1799 : already_AddRefed<CSSValue>
1800 0 : nsComputedDOMStyle::DoGetFontFeatureSettings()
1801 : {
1802 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1803 :
1804 0 : const nsStyleFont* font = StyleFont();
1805 0 : if (font->mFont.fontFeatureSettings.IsEmpty()) {
1806 0 : val->SetIdent(eCSSKeyword_normal);
1807 : } else {
1808 0 : nsAutoString result;
1809 0 : nsStyleUtil::AppendFontFeatureSettings(font->mFont.fontFeatureSettings,
1810 0 : result);
1811 0 : val->SetString(result);
1812 : }
1813 0 : return val.forget();
1814 : }
1815 :
1816 : already_AddRefed<CSSValue>
1817 0 : nsComputedDOMStyle::DoGetFontVariationSettings()
1818 : {
1819 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1820 :
1821 0 : const nsStyleFont* font = StyleFont();
1822 0 : if (font->mFont.fontVariationSettings.IsEmpty()) {
1823 0 : val->SetIdent(eCSSKeyword_normal);
1824 : } else {
1825 0 : nsAutoString result;
1826 0 : nsStyleUtil::AppendFontVariationSettings(font->mFont.fontVariationSettings,
1827 0 : result);
1828 0 : val->SetString(result);
1829 : }
1830 0 : return val.forget();
1831 : }
1832 :
1833 : already_AddRefed<CSSValue>
1834 0 : nsComputedDOMStyle::DoGetFontKerning()
1835 : {
1836 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1837 0 : val->SetIdent(
1838 0 : nsCSSProps::ValueToKeywordEnum(StyleFont()->mFont.kerning,
1839 0 : nsCSSProps::kFontKerningKTable));
1840 0 : return val.forget();
1841 : }
1842 :
1843 : static void
1844 0 : SerializeLanguageOverride(uint32_t aLanguageOverride, nsAString& aResult)
1845 : {
1846 0 : aResult.Truncate();
1847 : uint32_t i;
1848 0 : for (i = 0; i < 4 ; i++) {
1849 0 : char16_t ch = aLanguageOverride >> 24;
1850 0 : MOZ_ASSERT(nsCRT::IsAscii(ch),
1851 : "Invalid tags, we should've handled this during computing!");
1852 0 : aResult.Append(ch);
1853 0 : aLanguageOverride = aLanguageOverride << 8;
1854 : }
1855 : // strip trailing whitespaces
1856 0 : while (i > 0 && aResult[i - 1] == ' ') {
1857 0 : i--;
1858 : }
1859 0 : aResult.Truncate(i);
1860 0 : }
1861 :
1862 : already_AddRefed<CSSValue>
1863 0 : nsComputedDOMStyle::DoGetFontLanguageOverride()
1864 : {
1865 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1866 :
1867 0 : const nsStyleFont* font = StyleFont();
1868 0 : if (font->mFont.languageOverride == 0) {
1869 0 : val->SetIdent(eCSSKeyword_normal);
1870 : } else {
1871 0 : nsAutoString serializedStr, escapedStr;
1872 0 : SerializeLanguageOverride(font->mFont.languageOverride, serializedStr);
1873 0 : nsStyleUtil::AppendEscapedCSSString(serializedStr, escapedStr);
1874 0 : val->SetString(escapedStr);
1875 : }
1876 0 : return val.forget();
1877 : }
1878 :
1879 : already_AddRefed<CSSValue>
1880 0 : nsComputedDOMStyle::DoGetFontSynthesis()
1881 : {
1882 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1883 :
1884 0 : int32_t intValue = StyleFont()->mFont.synthesis;
1885 :
1886 0 : if (0 == intValue) {
1887 0 : val->SetIdent(eCSSKeyword_none);
1888 : } else {
1889 0 : nsAutoString valueStr;
1890 :
1891 : nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_font_synthesis,
1892 : intValue, NS_FONT_SYNTHESIS_WEIGHT,
1893 0 : NS_FONT_SYNTHESIS_STYLE, valueStr);
1894 0 : val->SetString(valueStr);
1895 : }
1896 :
1897 0 : return val.forget();
1898 : }
1899 :
1900 : // return a value *only* for valid longhand values from CSS 2.1, either
1901 : // normal or small-caps only
1902 : already_AddRefed<CSSValue>
1903 0 : nsComputedDOMStyle::DoGetFontVariant()
1904 : {
1905 0 : const nsFont& f = StyleFont()->mFont;
1906 :
1907 : // if any of the other font-variant subproperties other than
1908 : // font-variant-caps are not normal then can't calculate a computed value
1909 0 : if (f.variantAlternates || f.variantEastAsian || f.variantLigatures ||
1910 0 : f.variantNumeric || f.variantPosition) {
1911 0 : return nullptr;
1912 : }
1913 :
1914 : nsCSSKeyword keyword;
1915 0 : switch (f.variantCaps) {
1916 : case 0:
1917 0 : keyword = eCSSKeyword_normal;
1918 0 : break;
1919 : case NS_FONT_VARIANT_CAPS_SMALLCAPS:
1920 0 : keyword = eCSSKeyword_small_caps;
1921 0 : break;
1922 : default:
1923 0 : return nullptr;
1924 : }
1925 :
1926 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1927 0 : val->SetIdent(keyword);
1928 0 : return val.forget();
1929 : }
1930 :
1931 : already_AddRefed<CSSValue>
1932 0 : nsComputedDOMStyle::DoGetFontVariantAlternates()
1933 : {
1934 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1935 :
1936 0 : int32_t intValue = StyleFont()->mFont.variantAlternates;
1937 :
1938 0 : if (0 == intValue) {
1939 0 : val->SetIdent(eCSSKeyword_normal);
1940 0 : return val.forget();
1941 : }
1942 :
1943 : // first, include enumerated values
1944 0 : nsAutoString valueStr;
1945 :
1946 0 : nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_font_variant_alternates,
1947 : intValue & NS_FONT_VARIANT_ALTERNATES_ENUMERATED_MASK,
1948 : NS_FONT_VARIANT_ALTERNATES_HISTORICAL,
1949 0 : NS_FONT_VARIANT_ALTERNATES_HISTORICAL, valueStr);
1950 :
1951 : // next, include functional values if present
1952 0 : if (intValue & NS_FONT_VARIANT_ALTERNATES_FUNCTIONAL_MASK) {
1953 0 : nsStyleUtil::SerializeFunctionalAlternates(StyleFont()->mFont.alternateValues,
1954 0 : valueStr);
1955 : }
1956 :
1957 0 : val->SetString(valueStr);
1958 0 : return val.forget();
1959 : }
1960 :
1961 : already_AddRefed<CSSValue>
1962 0 : nsComputedDOMStyle::DoGetFontVariantCaps()
1963 : {
1964 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1965 :
1966 0 : int32_t intValue = StyleFont()->mFont.variantCaps;
1967 :
1968 0 : if (0 == intValue) {
1969 0 : val->SetIdent(eCSSKeyword_normal);
1970 : } else {
1971 0 : val->SetIdent(
1972 0 : nsCSSProps::ValueToKeywordEnum(intValue,
1973 0 : nsCSSProps::kFontVariantCapsKTable));
1974 : }
1975 :
1976 0 : return val.forget();
1977 : }
1978 :
1979 : already_AddRefed<CSSValue>
1980 0 : nsComputedDOMStyle::DoGetFontVariantEastAsian()
1981 : {
1982 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
1983 :
1984 0 : int32_t intValue = StyleFont()->mFont.variantEastAsian;
1985 :
1986 0 : if (0 == intValue) {
1987 0 : val->SetIdent(eCSSKeyword_normal);
1988 : } else {
1989 0 : nsAutoString valueStr;
1990 :
1991 : nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_font_variant_east_asian,
1992 : intValue, NS_FONT_VARIANT_EAST_ASIAN_JIS78,
1993 0 : NS_FONT_VARIANT_EAST_ASIAN_RUBY, valueStr);
1994 0 : val->SetString(valueStr);
1995 : }
1996 :
1997 0 : return val.forget();
1998 : }
1999 :
2000 : already_AddRefed<CSSValue>
2001 0 : nsComputedDOMStyle::DoGetFontVariantLigatures()
2002 : {
2003 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2004 :
2005 0 : int32_t intValue = StyleFont()->mFont.variantLigatures;
2006 :
2007 0 : if (0 == intValue) {
2008 0 : val->SetIdent(eCSSKeyword_normal);
2009 0 : } else if (NS_FONT_VARIANT_LIGATURES_NONE == intValue) {
2010 0 : val->SetIdent(eCSSKeyword_none);
2011 : } else {
2012 0 : nsAutoString valueStr;
2013 :
2014 : nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_font_variant_ligatures,
2015 : intValue, NS_FONT_VARIANT_LIGATURES_NONE,
2016 0 : NS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL, valueStr);
2017 0 : val->SetString(valueStr);
2018 : }
2019 :
2020 0 : return val.forget();
2021 : }
2022 :
2023 : already_AddRefed<CSSValue>
2024 0 : nsComputedDOMStyle::DoGetFontVariantNumeric()
2025 : {
2026 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2027 :
2028 0 : int32_t intValue = StyleFont()->mFont.variantNumeric;
2029 :
2030 0 : if (0 == intValue) {
2031 0 : val->SetIdent(eCSSKeyword_normal);
2032 : } else {
2033 0 : nsAutoString valueStr;
2034 :
2035 : nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_font_variant_numeric,
2036 : intValue, NS_FONT_VARIANT_NUMERIC_LINING,
2037 0 : NS_FONT_VARIANT_NUMERIC_ORDINAL, valueStr);
2038 0 : val->SetString(valueStr);
2039 : }
2040 :
2041 0 : return val.forget();
2042 : }
2043 :
2044 : already_AddRefed<CSSValue>
2045 0 : nsComputedDOMStyle::DoGetFontVariantPosition()
2046 : {
2047 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2048 :
2049 0 : int32_t intValue = StyleFont()->mFont.variantPosition;
2050 :
2051 0 : if (0 == intValue) {
2052 0 : val->SetIdent(eCSSKeyword_normal);
2053 : } else {
2054 0 : val->SetIdent(
2055 0 : nsCSSProps::ValueToKeywordEnum(intValue,
2056 0 : nsCSSProps::kFontVariantPositionKTable));
2057 : }
2058 :
2059 0 : return val.forget();
2060 : }
2061 :
2062 : already_AddRefed<CSSValue>
2063 0 : nsComputedDOMStyle::DoGetBackgroundAttachment()
2064 : {
2065 : return GetBackgroundList(&nsStyleImageLayers::Layer::mAttachment,
2066 : &nsStyleImageLayers::mAttachmentCount,
2067 0 : StyleBackground()->mImage,
2068 0 : nsCSSProps::kImageLayerAttachmentKTable);
2069 : }
2070 :
2071 : already_AddRefed<CSSValue>
2072 0 : nsComputedDOMStyle::DoGetBackgroundClip()
2073 : {
2074 : return GetBackgroundList(&nsStyleImageLayers::Layer::mClip,
2075 : &nsStyleImageLayers::mClipCount,
2076 0 : StyleBackground()->mImage,
2077 0 : nsCSSProps::kBackgroundClipKTable);
2078 : }
2079 :
2080 : already_AddRefed<CSSValue>
2081 0 : nsComputedDOMStyle::DoGetBackgroundColor()
2082 : {
2083 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2084 0 : SetValueFromComplexColor(val, StyleBackground()->mBackgroundColor);
2085 0 : return val.forget();
2086 : }
2087 :
2088 : static void
2089 0 : SetValueToCalc(const nsStyleCoord::CalcValue* aCalc,
2090 : nsROCSSPrimitiveValue* aValue)
2091 : {
2092 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2093 0 : nsAutoString tmp, result;
2094 :
2095 0 : result.AppendLiteral("calc(");
2096 :
2097 0 : val->SetAppUnits(aCalc->mLength);
2098 0 : val->GetCssText(tmp);
2099 0 : result.Append(tmp);
2100 :
2101 0 : if (aCalc->mHasPercent) {
2102 0 : result.AppendLiteral(" + ");
2103 :
2104 0 : val->SetPercent(aCalc->mPercent);
2105 0 : val->GetCssText(tmp);
2106 0 : result.Append(tmp);
2107 : }
2108 :
2109 0 : result.Append(')');
2110 :
2111 0 : aValue->SetString(result); // not really SetString
2112 0 : }
2113 :
2114 : static void
2115 0 : AppendCSSGradientLength(const nsStyleCoord& aValue,
2116 : nsROCSSPrimitiveValue* aPrimitive,
2117 : nsAString& aString)
2118 : {
2119 0 : nsAutoString tokenString;
2120 0 : if (aValue.IsCalcUnit())
2121 0 : SetValueToCalc(aValue.GetCalcValue(), aPrimitive);
2122 0 : else if (aValue.GetUnit() == eStyleUnit_Coord)
2123 0 : aPrimitive->SetAppUnits(aValue.GetCoordValue());
2124 : else
2125 0 : aPrimitive->SetPercent(aValue.GetPercentValue());
2126 0 : aPrimitive->GetCssText(tokenString);
2127 0 : aString.Append(tokenString);
2128 0 : }
2129 :
2130 : static void
2131 0 : AppendCSSGradientToBoxPosition(const nsStyleGradient* aGradient,
2132 : nsAString& aString,
2133 : bool& aNeedSep)
2134 : {
2135 : // This function only supports box position keywords. Make sure we're not
2136 : // calling it with inputs that would have coordinates that aren't
2137 : // representable with box-position keywords.
2138 0 : MOZ_ASSERT(aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR &&
2139 : !(aGradient->mLegacySyntax && aGradient->mMozLegacySyntax),
2140 : "Only call me for linear-gradient and -webkit-linear-gradient");
2141 :
2142 0 : float xValue = aGradient->mBgPosX.GetPercentValue();
2143 0 : float yValue = aGradient->mBgPosY.GetPercentValue();
2144 :
2145 0 : if (yValue == 1.0f && xValue == 0.5f) {
2146 : // omit "to bottom"
2147 0 : return;
2148 : }
2149 0 : NS_ASSERTION(yValue != 0.5f || xValue != 0.5f, "invalid box position");
2150 :
2151 0 : if (!aGradient->mLegacySyntax) {
2152 : // Modern syntax explicitly includes the word "to". Old syntax does not
2153 : // (and is implicitly "from" the given position instead).
2154 0 : aString.AppendLiteral("to ");
2155 : }
2156 :
2157 0 : if (xValue == 0.0f) {
2158 0 : aString.AppendLiteral("left");
2159 0 : } else if (xValue == 1.0f) {
2160 0 : aString.AppendLiteral("right");
2161 0 : } else if (xValue != 0.5f) { // do not write "center" keyword
2162 0 : NS_NOTREACHED("invalid box position");
2163 : }
2164 :
2165 0 : if (xValue != 0.5f && yValue != 0.5f) {
2166 : // We're appending both an x-keyword and a y-keyword.
2167 : // Add a space between them here.
2168 0 : aString.AppendLiteral(" ");
2169 : }
2170 :
2171 0 : if (yValue == 0.0f) {
2172 0 : aString.AppendLiteral("top");
2173 0 : } else if (yValue == 1.0f) {
2174 0 : aString.AppendLiteral("bottom");
2175 0 : } else if (yValue != 0.5f) { // do not write "center" keyword
2176 0 : NS_NOTREACHED("invalid box position");
2177 : }
2178 :
2179 :
2180 0 : aNeedSep = true;
2181 : }
2182 :
2183 : void
2184 0 : nsComputedDOMStyle::GetCSSGradientString(const nsStyleGradient* aGradient,
2185 : nsAString& aString)
2186 : {
2187 0 : if (!aGradient->mLegacySyntax) {
2188 0 : aString.Truncate();
2189 : } else {
2190 0 : if (aGradient->mMozLegacySyntax) {
2191 0 : aString.AssignLiteral("-moz-");
2192 : } else {
2193 0 : aString.AssignLiteral("-webkit-");
2194 : }
2195 : }
2196 0 : if (aGradient->mRepeating) {
2197 0 : aString.AppendLiteral("repeating-");
2198 : }
2199 0 : bool isRadial = aGradient->mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR;
2200 0 : if (isRadial) {
2201 0 : aString.AppendLiteral("radial-gradient(");
2202 : } else {
2203 0 : aString.AppendLiteral("linear-gradient(");
2204 : }
2205 :
2206 0 : bool needSep = false;
2207 0 : nsAutoString tokenString;
2208 0 : RefPtr<nsROCSSPrimitiveValue> tmpVal = new nsROCSSPrimitiveValue;
2209 :
2210 0 : if (isRadial && !aGradient->mLegacySyntax) {
2211 0 : if (aGradient->mSize != NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE) {
2212 0 : if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_CIRCULAR) {
2213 0 : aString.AppendLiteral("circle");
2214 0 : needSep = true;
2215 : }
2216 0 : if (aGradient->mSize != NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER) {
2217 0 : if (needSep) {
2218 0 : aString.Append(' ');
2219 : }
2220 0 : AppendASCIItoUTF16(nsCSSProps::
2221 0 : ValueToKeyword(aGradient->mSize,
2222 0 : nsCSSProps::kRadialGradientSizeKTable),
2223 0 : aString);
2224 0 : needSep = true;
2225 : }
2226 : } else {
2227 0 : AppendCSSGradientLength(aGradient->mRadiusX, tmpVal, aString);
2228 0 : if (aGradient->mShape != NS_STYLE_GRADIENT_SHAPE_CIRCULAR) {
2229 0 : aString.Append(' ');
2230 0 : AppendCSSGradientLength(aGradient->mRadiusY, tmpVal, aString);
2231 : }
2232 0 : needSep = true;
2233 : }
2234 : }
2235 0 : if (aGradient->mBgPosX.GetUnit() != eStyleUnit_None) {
2236 0 : MOZ_ASSERT(aGradient->mBgPosY.GetUnit() != eStyleUnit_None);
2237 0 : if (!isRadial &&
2238 0 : !(aGradient->mLegacySyntax && aGradient->mMozLegacySyntax)) {
2239 : // linear-gradient() or -webkit-linear-gradient()
2240 0 : AppendCSSGradientToBoxPosition(aGradient, aString, needSep);
2241 0 : } else if (aGradient->mBgPosX.GetUnit() != eStyleUnit_Percent ||
2242 0 : aGradient->mBgPosX.GetPercentValue() != 0.5f ||
2243 0 : aGradient->mBgPosY.GetUnit() != eStyleUnit_Percent ||
2244 0 : aGradient->mBgPosY.GetPercentValue() != (isRadial ? 0.5f : 1.0f)) {
2245 0 : if (isRadial && !aGradient->mLegacySyntax) {
2246 0 : if (needSep) {
2247 0 : aString.Append(' ');
2248 : }
2249 0 : aString.AppendLiteral("at ");
2250 0 : needSep = false;
2251 : }
2252 0 : AppendCSSGradientLength(aGradient->mBgPosX, tmpVal, aString);
2253 0 : if (aGradient->mBgPosY.GetUnit() != eStyleUnit_None) {
2254 0 : aString.Append(' ');
2255 0 : AppendCSSGradientLength(aGradient->mBgPosY, tmpVal, aString);
2256 : }
2257 0 : needSep = true;
2258 : }
2259 : }
2260 0 : if (aGradient->mAngle.GetUnit() != eStyleUnit_None) {
2261 0 : MOZ_ASSERT(!isRadial || aGradient->mLegacySyntax);
2262 0 : if (needSep) {
2263 0 : aString.Append(' ');
2264 : }
2265 0 : nsStyleUtil::AppendAngleValue(aGradient->mAngle, aString);
2266 0 : needSep = true;
2267 : }
2268 :
2269 0 : if (isRadial && aGradient->mLegacySyntax &&
2270 0 : (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_CIRCULAR ||
2271 0 : aGradient->mSize != NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER)) {
2272 0 : MOZ_ASSERT(aGradient->mSize != NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE);
2273 0 : if (needSep) {
2274 0 : aString.AppendLiteral(", ");
2275 0 : needSep = false;
2276 : }
2277 0 : if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_CIRCULAR) {
2278 0 : aString.AppendLiteral("circle");
2279 0 : needSep = true;
2280 : }
2281 0 : if (aGradient->mSize != NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER) {
2282 0 : if (needSep) {
2283 0 : aString.Append(' ');
2284 : }
2285 0 : AppendASCIItoUTF16(nsCSSProps::
2286 0 : ValueToKeyword(aGradient->mSize,
2287 0 : nsCSSProps::kRadialGradientSizeKTable),
2288 0 : aString);
2289 : }
2290 0 : needSep = true;
2291 : }
2292 :
2293 :
2294 : // color stops
2295 0 : for (uint32_t i = 0; i < aGradient->mStops.Length(); ++i) {
2296 0 : if (needSep) {
2297 0 : aString.AppendLiteral(", ");
2298 : }
2299 :
2300 0 : const auto& stop = aGradient->mStops[i];
2301 0 : if (!stop.mIsInterpolationHint) {
2302 0 : SetToRGBAColor(tmpVal, stop.mColor);
2303 0 : tmpVal->GetCssText(tokenString);
2304 0 : aString.Append(tokenString);
2305 : }
2306 :
2307 0 : if (stop.mLocation.GetUnit() != eStyleUnit_None) {
2308 0 : if (!stop.mIsInterpolationHint) {
2309 0 : aString.Append(' ');
2310 : }
2311 0 : AppendCSSGradientLength(stop.mLocation, tmpVal, aString);
2312 : }
2313 0 : needSep = true;
2314 : }
2315 :
2316 0 : aString.Append(')');
2317 0 : }
2318 :
2319 : // -moz-image-rect(<uri>, <top>, <right>, <bottom>, <left>)
2320 : void
2321 0 : nsComputedDOMStyle::GetImageRectString(nsIURI* aURI,
2322 : const nsStyleSides& aCropRect,
2323 : nsString& aString)
2324 : {
2325 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
2326 :
2327 : // <uri>
2328 0 : RefPtr<nsROCSSPrimitiveValue> valURI = new nsROCSSPrimitiveValue;
2329 0 : valURI->SetURI(aURI);
2330 0 : valueList->AppendCSSValue(valURI.forget());
2331 :
2332 : // <top>, <right>, <bottom>, <left>
2333 0 : NS_FOR_CSS_SIDES(side) {
2334 0 : RefPtr<nsROCSSPrimitiveValue> valSide = new nsROCSSPrimitiveValue;
2335 0 : SetValueToCoord(valSide, aCropRect.Get(side), false);
2336 0 : valueList->AppendCSSValue(valSide.forget());
2337 : }
2338 :
2339 0 : nsAutoString argumentString;
2340 0 : valueList->GetCssText(argumentString);
2341 :
2342 0 : aString = NS_LITERAL_STRING("-moz-image-rect(") +
2343 0 : argumentString +
2344 0 : NS_LITERAL_STRING(")");
2345 0 : }
2346 :
2347 : void
2348 0 : nsComputedDOMStyle::SetValueToStyleImage(const nsStyleImage& aStyleImage,
2349 : nsROCSSPrimitiveValue* aValue)
2350 : {
2351 0 : switch (aStyleImage.GetType()) {
2352 : case eStyleImageType_Image:
2353 : {
2354 0 : nsCOMPtr<nsIURI> uri = aStyleImage.GetImageURI();
2355 0 : if (!uri) {
2356 0 : aValue->SetIdent(eCSSKeyword_none);
2357 0 : break;
2358 : }
2359 :
2360 0 : const UniquePtr<nsStyleSides>& cropRect = aStyleImage.GetCropRect();
2361 0 : if (cropRect) {
2362 0 : nsAutoString imageRectString;
2363 0 : GetImageRectString(uri, *cropRect, imageRectString);
2364 0 : aValue->SetString(imageRectString);
2365 : } else {
2366 0 : aValue->SetURI(uri);
2367 : }
2368 0 : break;
2369 : }
2370 : case eStyleImageType_Gradient:
2371 : {
2372 0 : nsAutoString gradientString;
2373 0 : GetCSSGradientString(aStyleImage.GetGradientData(),
2374 0 : gradientString);
2375 0 : aValue->SetString(gradientString);
2376 0 : break;
2377 : }
2378 : case eStyleImageType_Element:
2379 : {
2380 0 : nsAutoString elementId;
2381 : nsStyleUtil::AppendEscapedCSSIdent(
2382 0 : nsDependentAtomString(aStyleImage.GetElementId()),
2383 0 : elementId);
2384 0 : nsAutoString elementString = NS_LITERAL_STRING("-moz-element(#") +
2385 0 : elementId +
2386 0 : NS_LITERAL_STRING(")");
2387 0 : aValue->SetString(elementString);
2388 0 : break;
2389 : }
2390 : case eStyleImageType_Null:
2391 0 : aValue->SetIdent(eCSSKeyword_none);
2392 0 : break;
2393 : case eStyleImageType_URL:
2394 0 : SetValueToURLValue(aStyleImage.GetURLValue(), aValue);
2395 0 : break;
2396 : default:
2397 0 : NS_NOTREACHED("unexpected image type");
2398 0 : break;
2399 : }
2400 0 : }
2401 :
2402 : already_AddRefed<CSSValue>
2403 0 : nsComputedDOMStyle::DoGetImageLayerImage(const nsStyleImageLayers& aLayers)
2404 : {
2405 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
2406 :
2407 0 : for (uint32_t i = 0, i_end = aLayers.mImageCount; i < i_end; ++i) {
2408 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2409 :
2410 0 : SetValueToStyleImage(aLayers.mLayers[i].mImage, val);
2411 0 : valueList->AppendCSSValue(val.forget());
2412 : }
2413 :
2414 0 : return valueList.forget();
2415 : }
2416 :
2417 : already_AddRefed<CSSValue>
2418 0 : nsComputedDOMStyle::DoGetImageLayerPosition(const nsStyleImageLayers& aLayers)
2419 : {
2420 0 : if (aLayers.mPositionXCount != aLayers.mPositionYCount) {
2421 : // No value to return. We can't express this combination of
2422 : // values as a shorthand.
2423 0 : return nullptr;
2424 : }
2425 :
2426 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
2427 0 : for (uint32_t i = 0, i_end = aLayers.mPositionXCount; i < i_end; ++i) {
2428 0 : RefPtr<nsDOMCSSValueList> itemList = GetROCSSValueList(false);
2429 :
2430 0 : SetValueToPosition(aLayers.mLayers[i].mPosition, itemList);
2431 0 : valueList->AppendCSSValue(itemList.forget());
2432 : }
2433 :
2434 0 : return valueList.forget();
2435 : }
2436 :
2437 : already_AddRefed<CSSValue>
2438 0 : nsComputedDOMStyle::DoGetImageLayerPositionX(const nsStyleImageLayers& aLayers)
2439 : {
2440 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
2441 0 : for (uint32_t i = 0, i_end = aLayers.mPositionXCount; i < i_end; ++i) {
2442 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2443 0 : SetValueToPositionCoord(aLayers.mLayers[i].mPosition.mXPosition, val);
2444 0 : valueList->AppendCSSValue(val.forget());
2445 : }
2446 :
2447 0 : return valueList.forget();
2448 : }
2449 :
2450 : already_AddRefed<CSSValue>
2451 0 : nsComputedDOMStyle::DoGetImageLayerPositionY(const nsStyleImageLayers& aLayers)
2452 : {
2453 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
2454 0 : for (uint32_t i = 0, i_end = aLayers.mPositionYCount; i < i_end; ++i) {
2455 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2456 0 : SetValueToPositionCoord(aLayers.mLayers[i].mPosition.mYPosition, val);
2457 0 : valueList->AppendCSSValue(val.forget());
2458 : }
2459 :
2460 0 : return valueList.forget();
2461 : }
2462 :
2463 : already_AddRefed<CSSValue>
2464 0 : nsComputedDOMStyle::DoGetImageLayerRepeat(const nsStyleImageLayers& aLayers)
2465 : {
2466 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
2467 :
2468 0 : for (uint32_t i = 0, i_end = aLayers.mRepeatCount; i < i_end; ++i) {
2469 0 : RefPtr<nsDOMCSSValueList> itemList = GetROCSSValueList(false);
2470 0 : RefPtr<nsROCSSPrimitiveValue> valX = new nsROCSSPrimitiveValue;
2471 :
2472 0 : const StyleImageLayerRepeat xRepeat = aLayers.mLayers[i].mRepeat.mXRepeat;
2473 0 : const StyleImageLayerRepeat yRepeat = aLayers.mLayers[i].mRepeat.mYRepeat;
2474 :
2475 0 : bool hasContraction = true;
2476 : unsigned contraction;
2477 0 : if (xRepeat == yRepeat) {
2478 0 : contraction = uint8_t(xRepeat);
2479 0 : } else if (xRepeat == StyleImageLayerRepeat::Repeat &&
2480 : yRepeat == StyleImageLayerRepeat::NoRepeat) {
2481 0 : contraction = uint8_t(StyleImageLayerRepeat::RepeatX);
2482 0 : } else if (xRepeat == StyleImageLayerRepeat::NoRepeat &&
2483 : yRepeat == StyleImageLayerRepeat::Repeat) {
2484 0 : contraction = uint8_t(StyleImageLayerRepeat::RepeatY);
2485 : } else {
2486 0 : hasContraction = false;
2487 : }
2488 :
2489 0 : RefPtr<nsROCSSPrimitiveValue> valY;
2490 0 : if (hasContraction) {
2491 0 : valX->SetIdent(nsCSSProps::ValueToKeywordEnum(contraction,
2492 0 : nsCSSProps::kImageLayerRepeatKTable));
2493 : } else {
2494 0 : valY = new nsROCSSPrimitiveValue;
2495 :
2496 0 : valX->SetIdent(nsCSSProps::ValueToKeywordEnum(xRepeat,
2497 0 : nsCSSProps::kImageLayerRepeatKTable));
2498 0 : valY->SetIdent(nsCSSProps::ValueToKeywordEnum(yRepeat,
2499 0 : nsCSSProps::kImageLayerRepeatKTable));
2500 : }
2501 0 : itemList->AppendCSSValue(valX.forget());
2502 0 : if (valY) {
2503 0 : itemList->AppendCSSValue(valY.forget());
2504 : }
2505 0 : valueList->AppendCSSValue(itemList.forget());
2506 : }
2507 :
2508 0 : return valueList.forget();
2509 : }
2510 :
2511 : already_AddRefed<CSSValue>
2512 0 : nsComputedDOMStyle::DoGetImageLayerSize(const nsStyleImageLayers& aLayers)
2513 : {
2514 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
2515 :
2516 0 : for (uint32_t i = 0, i_end = aLayers.mSizeCount; i < i_end; ++i) {
2517 0 : const nsStyleImageLayers::Size &size = aLayers.mLayers[i].mSize;
2518 :
2519 0 : switch (size.mWidthType) {
2520 : case nsStyleImageLayers::Size::eContain:
2521 : case nsStyleImageLayers::Size::eCover: {
2522 0 : MOZ_ASSERT(size.mWidthType == size.mHeightType,
2523 : "unsynced types");
2524 0 : nsCSSKeyword keyword = size.mWidthType == nsStyleImageLayers::Size::eContain
2525 0 : ? eCSSKeyword_contain
2526 0 : : eCSSKeyword_cover;
2527 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2528 0 : val->SetIdent(keyword);
2529 0 : valueList->AppendCSSValue(val.forget());
2530 0 : break;
2531 : }
2532 : default: {
2533 0 : RefPtr<nsDOMCSSValueList> itemList = GetROCSSValueList(false);
2534 :
2535 0 : RefPtr<nsROCSSPrimitiveValue> valX = new nsROCSSPrimitiveValue;
2536 0 : RefPtr<nsROCSSPrimitiveValue> valY = new nsROCSSPrimitiveValue;
2537 :
2538 0 : if (size.mWidthType == nsStyleImageLayers::Size::eAuto) {
2539 0 : valX->SetIdent(eCSSKeyword_auto);
2540 : } else {
2541 0 : MOZ_ASSERT(size.mWidthType ==
2542 : nsStyleImageLayers::Size::eLengthPercentage,
2543 : "bad mWidthType");
2544 0 : if (!size.mWidth.mHasPercent &&
2545 : // negative values must have come from calc()
2546 0 : size.mWidth.mLength >= 0) {
2547 0 : MOZ_ASSERT(size.mWidth.mPercent == 0.0f,
2548 : "Shouldn't have mPercent");
2549 0 : valX->SetAppUnits(size.mWidth.mLength);
2550 0 : } else if (size.mWidth.mLength == 0 &&
2551 : // negative values must have come from calc()
2552 0 : size.mWidth.mPercent >= 0.0f) {
2553 0 : valX->SetPercent(size.mWidth.mPercent);
2554 : } else {
2555 0 : SetValueToCalc(&size.mWidth, valX);
2556 : }
2557 : }
2558 :
2559 0 : if (size.mHeightType == nsStyleImageLayers::Size::eAuto) {
2560 0 : valY->SetIdent(eCSSKeyword_auto);
2561 : } else {
2562 0 : MOZ_ASSERT(size.mHeightType ==
2563 : nsStyleImageLayers::Size::eLengthPercentage,
2564 : "bad mHeightType");
2565 0 : if (!size.mHeight.mHasPercent &&
2566 : // negative values must have come from calc()
2567 0 : size.mHeight.mLength >= 0) {
2568 0 : MOZ_ASSERT(size.mHeight.mPercent == 0.0f,
2569 : "Shouldn't have mPercent");
2570 0 : valY->SetAppUnits(size.mHeight.mLength);
2571 0 : } else if (size.mHeight.mLength == 0 &&
2572 : // negative values must have come from calc()
2573 0 : size.mHeight.mPercent >= 0.0f) {
2574 0 : valY->SetPercent(size.mHeight.mPercent);
2575 : } else {
2576 0 : SetValueToCalc(&size.mHeight, valY);
2577 : }
2578 : }
2579 0 : itemList->AppendCSSValue(valX.forget());
2580 0 : itemList->AppendCSSValue(valY.forget());
2581 0 : valueList->AppendCSSValue(itemList.forget());
2582 0 : break;
2583 : }
2584 : }
2585 : }
2586 :
2587 0 : return valueList.forget();
2588 : }
2589 :
2590 : already_AddRefed<CSSValue>
2591 0 : nsComputedDOMStyle::DoGetBackgroundImage()
2592 : {
2593 0 : const nsStyleImageLayers& layers = StyleBackground()->mImage;
2594 0 : return DoGetImageLayerImage(layers);
2595 : }
2596 :
2597 : already_AddRefed<CSSValue>
2598 0 : nsComputedDOMStyle::DoGetBackgroundBlendMode()
2599 : {
2600 : return GetBackgroundList(&nsStyleImageLayers::Layer::mBlendMode,
2601 : &nsStyleImageLayers::mBlendModeCount,
2602 0 : StyleBackground()->mImage,
2603 0 : nsCSSProps::kBlendModeKTable);
2604 : }
2605 :
2606 : already_AddRefed<CSSValue>
2607 0 : nsComputedDOMStyle::DoGetBackgroundOrigin()
2608 : {
2609 : return GetBackgroundList(&nsStyleImageLayers::Layer::mOrigin,
2610 : &nsStyleImageLayers::mOriginCount,
2611 0 : StyleBackground()->mImage,
2612 0 : nsCSSProps::kBackgroundOriginKTable);
2613 : }
2614 :
2615 : void
2616 0 : nsComputedDOMStyle::SetValueToPositionCoord(
2617 : const Position::Coord& aCoord,
2618 : nsROCSSPrimitiveValue* aValue)
2619 : {
2620 0 : if (!aCoord.mHasPercent) {
2621 0 : MOZ_ASSERT(aCoord.mPercent == 0.0f,
2622 : "Shouldn't have mPercent!");
2623 0 : aValue->SetAppUnits(aCoord.mLength);
2624 0 : } else if (aCoord.mLength == 0) {
2625 0 : aValue->SetPercent(aCoord.mPercent);
2626 : } else {
2627 0 : SetValueToCalc(&aCoord, aValue);
2628 : }
2629 0 : }
2630 :
2631 : void
2632 0 : nsComputedDOMStyle::SetValueToPosition(
2633 : const Position& aPosition,
2634 : nsDOMCSSValueList* aValueList)
2635 : {
2636 0 : RefPtr<nsROCSSPrimitiveValue> valX = new nsROCSSPrimitiveValue;
2637 0 : SetValueToPositionCoord(aPosition.mXPosition, valX);
2638 0 : aValueList->AppendCSSValue(valX.forget());
2639 :
2640 0 : RefPtr<nsROCSSPrimitiveValue> valY = new nsROCSSPrimitiveValue;
2641 0 : SetValueToPositionCoord(aPosition.mYPosition, valY);
2642 0 : aValueList->AppendCSSValue(valY.forget());
2643 0 : }
2644 :
2645 :
2646 : void
2647 0 : nsComputedDOMStyle::SetValueToURLValue(const css::URLValueData* aURL,
2648 : nsROCSSPrimitiveValue* aValue)
2649 : {
2650 0 : if (!aURL) {
2651 0 : aValue->SetIdent(eCSSKeyword_none);
2652 0 : return;
2653 : }
2654 :
2655 : // If we have a usable nsIURI in the URLValueData, and the url() wasn't
2656 : // a fragment-only URL, serialize the nsIURI.
2657 0 : if (!aURL->IsLocalRef()) {
2658 0 : if (nsIURI* uri = aURL->GetURI()) {
2659 0 : aValue->SetURI(uri);
2660 0 : return;
2661 : }
2662 : }
2663 :
2664 : // Otherwise, serialize the specified URL value.
2665 0 : nsAutoString source;
2666 0 : aURL->GetSourceString(source);
2667 :
2668 0 : nsAutoString url;
2669 0 : url.AppendLiteral(u"url(");
2670 0 : nsStyleUtil::AppendEscapedCSSString(source, url, '"');
2671 0 : url.Append(')');
2672 0 : aValue->SetString(url);
2673 : }
2674 :
2675 : already_AddRefed<CSSValue>
2676 0 : nsComputedDOMStyle::DoGetBackgroundPosition()
2677 : {
2678 0 : const nsStyleImageLayers& layers = StyleBackground()->mImage;
2679 0 : return DoGetImageLayerPosition(layers);
2680 : }
2681 :
2682 : already_AddRefed<CSSValue>
2683 0 : nsComputedDOMStyle::DoGetBackgroundPositionX()
2684 : {
2685 0 : const nsStyleImageLayers& layers = StyleBackground()->mImage;
2686 0 : return DoGetImageLayerPositionX(layers);
2687 : }
2688 :
2689 : already_AddRefed<CSSValue>
2690 0 : nsComputedDOMStyle::DoGetBackgroundPositionY()
2691 : {
2692 0 : const nsStyleImageLayers& layers = StyleBackground()->mImage;
2693 0 : return DoGetImageLayerPositionY(layers);
2694 : }
2695 :
2696 : already_AddRefed<CSSValue>
2697 0 : nsComputedDOMStyle::DoGetBackgroundRepeat()
2698 : {
2699 0 : const nsStyleImageLayers& layers = StyleBackground()->mImage;
2700 0 : return DoGetImageLayerRepeat(layers);
2701 : }
2702 :
2703 : already_AddRefed<CSSValue>
2704 0 : nsComputedDOMStyle::DoGetBackgroundSize()
2705 : {
2706 0 : const nsStyleImageLayers& layers = StyleBackground()->mImage;
2707 0 : return DoGetImageLayerSize(layers);
2708 : }
2709 :
2710 : already_AddRefed<CSSValue>
2711 0 : nsComputedDOMStyle::DoGetGridTemplateAreas()
2712 : {
2713 : const css::GridTemplateAreasValue* areas =
2714 0 : StylePosition()->mGridTemplateAreas;
2715 0 : if (!areas) {
2716 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2717 0 : val->SetIdent(eCSSKeyword_none);
2718 0 : return val.forget();
2719 : }
2720 :
2721 0 : MOZ_ASSERT(!areas->mTemplates.IsEmpty(),
2722 : "Unexpected empty array in GridTemplateAreasValue");
2723 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
2724 0 : for (uint32_t i = 0; i < areas->mTemplates.Length(); i++) {
2725 0 : nsAutoString str;
2726 0 : nsStyleUtil::AppendEscapedCSSString(areas->mTemplates[i], str);
2727 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2728 0 : val->SetString(str);
2729 0 : valueList->AppendCSSValue(val.forget());
2730 : }
2731 0 : return valueList.forget();
2732 : }
2733 :
2734 : void
2735 0 : nsComputedDOMStyle::AppendGridLineNames(nsString& aResult,
2736 : const nsTArray<nsString>& aLineNames)
2737 : {
2738 0 : uint32_t numLines = aLineNames.Length();
2739 0 : if (numLines == 0) {
2740 0 : return;
2741 : }
2742 0 : for (uint32_t i = 0;;) {
2743 0 : nsStyleUtil::AppendEscapedCSSIdent(aLineNames[i], aResult);
2744 0 : if (++i == numLines) {
2745 0 : break;
2746 : }
2747 0 : aResult.Append(' ');
2748 : }
2749 : }
2750 :
2751 : void
2752 0 : nsComputedDOMStyle::AppendGridLineNames(nsDOMCSSValueList* aValueList,
2753 : const nsTArray<nsString>& aLineNames,
2754 : bool aSuppressEmptyList)
2755 : {
2756 0 : if (aLineNames.IsEmpty() && aSuppressEmptyList) {
2757 0 : return;
2758 : }
2759 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2760 0 : nsAutoString lineNamesString;
2761 0 : lineNamesString.Assign('[');
2762 0 : AppendGridLineNames(lineNamesString, aLineNames);
2763 0 : lineNamesString.Append(']');
2764 0 : val->SetString(lineNamesString);
2765 0 : aValueList->AppendCSSValue(val.forget());
2766 : }
2767 :
2768 : void
2769 0 : nsComputedDOMStyle::AppendGridLineNames(nsDOMCSSValueList* aValueList,
2770 : const nsTArray<nsString>& aLineNames1,
2771 : const nsTArray<nsString>& aLineNames2)
2772 : {
2773 0 : if (aLineNames1.IsEmpty() && aLineNames2.IsEmpty()) {
2774 0 : return;
2775 : }
2776 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2777 0 : nsAutoString lineNamesString;
2778 0 : lineNamesString.Assign('[');
2779 0 : if (!aLineNames1.IsEmpty()) {
2780 0 : AppendGridLineNames(lineNamesString, aLineNames1);
2781 : }
2782 0 : if (!aLineNames2.IsEmpty()) {
2783 0 : if (!aLineNames1.IsEmpty()) {
2784 0 : lineNamesString.Append(' ');
2785 : }
2786 0 : AppendGridLineNames(lineNamesString, aLineNames2);
2787 : }
2788 0 : lineNamesString.Append(']');
2789 0 : val->SetString(lineNamesString);
2790 0 : aValueList->AppendCSSValue(val.forget());
2791 : }
2792 :
2793 : already_AddRefed<CSSValue>
2794 0 : nsComputedDOMStyle::GetGridTrackSize(const nsStyleCoord& aMinValue,
2795 : const nsStyleCoord& aMaxValue)
2796 : {
2797 0 : if (aMinValue.GetUnit() == eStyleUnit_None) {
2798 : // A fit-content() function.
2799 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2800 0 : nsAutoString argumentStr, fitContentStr;
2801 0 : fitContentStr.AppendLiteral("fit-content(");
2802 0 : MOZ_ASSERT(aMaxValue.IsCoordPercentCalcUnit(),
2803 : "unexpected unit for fit-content() argument value");
2804 0 : SetValueToCoord(val, aMaxValue, true);
2805 0 : val->GetCssText(argumentStr);
2806 0 : fitContentStr.Append(argumentStr);
2807 0 : fitContentStr.Append(char16_t(')'));
2808 0 : val->SetString(fitContentStr);
2809 0 : return val.forget();
2810 : }
2811 :
2812 0 : if (aMinValue == aMaxValue) {
2813 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2814 0 : SetValueToCoord(val, aMinValue, true,
2815 0 : nullptr, nsCSSProps::kGridTrackBreadthKTable);
2816 0 : return val.forget();
2817 : }
2818 :
2819 : // minmax(auto, <flex>) is equivalent to (and is our internal representation
2820 : // of) <flex>, and both compute to <flex>
2821 0 : if (aMinValue.GetUnit() == eStyleUnit_Auto &&
2822 0 : aMaxValue.GetUnit() == eStyleUnit_FlexFraction) {
2823 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2824 0 : SetValueToCoord(val, aMaxValue, true);
2825 0 : return val.forget();
2826 : }
2827 :
2828 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2829 0 : nsAutoString argumentStr, minmaxStr;
2830 0 : minmaxStr.AppendLiteral("minmax(");
2831 :
2832 0 : SetValueToCoord(val, aMinValue, true,
2833 0 : nullptr, nsCSSProps::kGridTrackBreadthKTable);
2834 0 : val->GetCssText(argumentStr);
2835 0 : minmaxStr.Append(argumentStr);
2836 :
2837 0 : minmaxStr.AppendLiteral(", ");
2838 :
2839 0 : SetValueToCoord(val, aMaxValue, true,
2840 0 : nullptr, nsCSSProps::kGridTrackBreadthKTable);
2841 0 : val->GetCssText(argumentStr);
2842 0 : minmaxStr.Append(argumentStr);
2843 :
2844 0 : minmaxStr.Append(char16_t(')'));
2845 0 : val->SetString(minmaxStr);
2846 0 : return val.forget();
2847 : }
2848 :
2849 : already_AddRefed<CSSValue>
2850 0 : nsComputedDOMStyle::GetGridTemplateColumnsRows(
2851 : const nsStyleGridTemplate& aTrackList,
2852 : const ComputedGridTrackInfo* aTrackInfo)
2853 : {
2854 0 : if (aTrackList.mIsSubgrid) {
2855 : // XXX TODO: add support for repeat(auto-fill) for 'subgrid' (bug 1234311)
2856 0 : NS_ASSERTION(aTrackList.mMinTrackSizingFunctions.IsEmpty() &&
2857 : aTrackList.mMaxTrackSizingFunctions.IsEmpty(),
2858 : "Unexpected sizing functions with subgrid");
2859 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
2860 :
2861 0 : RefPtr<nsROCSSPrimitiveValue> subgridKeyword = new nsROCSSPrimitiveValue;
2862 0 : subgridKeyword->SetIdent(eCSSKeyword_subgrid);
2863 0 : valueList->AppendCSSValue(subgridKeyword.forget());
2864 :
2865 0 : for (uint32_t i = 0, len = aTrackList.mLineNameLists.Length(); ; ++i) {
2866 0 : if (MOZ_UNLIKELY(aTrackList.IsRepeatAutoIndex(i))) {
2867 0 : MOZ_ASSERT(aTrackList.mIsAutoFill, "subgrid can only have 'auto-fill'");
2868 0 : MOZ_ASSERT(aTrackList.mRepeatAutoLineNameListAfter.IsEmpty(),
2869 : "mRepeatAutoLineNameListAfter isn't used for subgrid");
2870 0 : RefPtr<nsROCSSPrimitiveValue> start = new nsROCSSPrimitiveValue;
2871 0 : start->SetString(NS_LITERAL_STRING("repeat(auto-fill,"));
2872 0 : valueList->AppendCSSValue(start.forget());
2873 0 : AppendGridLineNames(valueList, aTrackList.mRepeatAutoLineNameListBefore,
2874 0 : /*aSuppressEmptyList*/ false);
2875 0 : RefPtr<nsROCSSPrimitiveValue> end = new nsROCSSPrimitiveValue;
2876 0 : end->SetString(NS_LITERAL_STRING(")"));
2877 0 : valueList->AppendCSSValue(end.forget());
2878 : }
2879 0 : if (i == len) {
2880 0 : break;
2881 : }
2882 0 : AppendGridLineNames(valueList, aTrackList.mLineNameLists[i],
2883 0 : /*aSuppressEmptyList*/ false);
2884 0 : }
2885 0 : return valueList.forget();
2886 : }
2887 :
2888 0 : uint32_t numSizes = aTrackList.mMinTrackSizingFunctions.Length();
2889 0 : MOZ_ASSERT(aTrackList.mMaxTrackSizingFunctions.Length() == numSizes,
2890 : "Different number of min and max track sizing functions");
2891 0 : if (aTrackInfo) {
2892 : DebugOnly<bool> isAutoFill =
2893 0 : aTrackList.HasRepeatAuto() && aTrackList.mIsAutoFill;
2894 : DebugOnly<bool> isAutoFit =
2895 0 : aTrackList.HasRepeatAuto() && !aTrackList.mIsAutoFill;
2896 0 : DebugOnly<uint32_t> numExplicitTracks = aTrackInfo->mNumExplicitTracks;
2897 0 : MOZ_ASSERT(numExplicitTracks == numSizes ||
2898 : (isAutoFill && numExplicitTracks >= numSizes) ||
2899 : (isAutoFit && numExplicitTracks + 1 >= numSizes),
2900 : "expected all explicit tracks (or possibly one less, if there's "
2901 : "an 'auto-fit' track, since that can collapse away)");
2902 0 : numSizes = aTrackInfo->mSizes.Length();
2903 : }
2904 :
2905 : // An empty <track-list> without repeats is represented as "none" in syntax.
2906 0 : if (numSizes == 0 && !aTrackList.HasRepeatAuto()) {
2907 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2908 0 : val->SetIdent(eCSSKeyword_none);
2909 0 : return val.forget();
2910 : }
2911 :
2912 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
2913 0 : if (aTrackInfo) {
2914 : // We've done layout on the grid and have resolved the sizes of its tracks,
2915 : // so we'll return those sizes here. The grid spec says we MAY use
2916 : // repeat(<positive-integer>, Npx) here for consecutive tracks with the same
2917 : // size, but that doesn't seem worth doing since even for repeat(auto-*)
2918 : // the resolved size might differ for the repeated tracks.
2919 0 : const nsTArray<nscoord>& trackSizes = aTrackInfo->mSizes;
2920 0 : const uint32_t numExplicitTracks = aTrackInfo->mNumExplicitTracks;
2921 0 : const uint32_t numLeadingImplicitTracks = aTrackInfo->mNumLeadingImplicitTracks;
2922 0 : MOZ_ASSERT(numSizes >= numLeadingImplicitTracks + numExplicitTracks);
2923 :
2924 : // Add any leading implicit tracks.
2925 0 : for (uint32_t i = 0; i < numLeadingImplicitTracks; ++i) {
2926 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2927 0 : val->SetAppUnits(trackSizes[i]);
2928 0 : valueList->AppendCSSValue(val.forget());
2929 : }
2930 :
2931 : // Then add any explicit tracks and removed auto-fit tracks.
2932 0 : if (numExplicitTracks || aTrackList.HasRepeatAuto()) {
2933 0 : int32_t endOfRepeat = 0; // first index after any repeat() tracks
2934 0 : int32_t offsetToLastRepeat = 0;
2935 0 : if (aTrackList.HasRepeatAuto()) {
2936 : // offsetToLastRepeat is -1 if all repeat(auto-fit) tracks are empty
2937 0 : offsetToLastRepeat = numExplicitTracks + 1 - aTrackList.mLineNameLists.Length();
2938 0 : endOfRepeat = aTrackList.mRepeatAutoIndex + offsetToLastRepeat + 1;
2939 : }
2940 :
2941 0 : uint32_t repeatIndex = 0;
2942 0 : uint32_t numRepeatTracks = aTrackInfo->mRemovedRepeatTracks.Length();
2943 : enum LinePlacement { LinesPrecede, LinesFollow, LinesBetween };
2944 : auto AppendRemovedAutoFits = [this, aTrackInfo, &valueList, aTrackList,
2945 : &repeatIndex,
2946 0 : numRepeatTracks](LinePlacement aPlacement)
2947 0 : {
2948 : // Add in removed auto-fit tracks and lines here, if necessary
2949 0 : bool atLeastOneTrackReported = false;
2950 0 : while (repeatIndex < numRepeatTracks &&
2951 0 : aTrackInfo->mRemovedRepeatTracks[repeatIndex]) {
2952 0 : if ((aPlacement == LinesPrecede) ||
2953 0 : ((aPlacement == LinesBetween) && atLeastOneTrackReported)) {
2954 : // Precede it with the lines between repeats.
2955 0 : AppendGridLineNames(valueList,
2956 : aTrackList.mRepeatAutoLineNameListAfter,
2957 0 : aTrackList.mRepeatAutoLineNameListBefore);
2958 : }
2959 :
2960 : // Removed 'auto-fit' tracks are reported as 0px.
2961 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
2962 0 : val->SetAppUnits(0);
2963 0 : valueList->AppendCSSValue(val.forget());
2964 0 : atLeastOneTrackReported = true;
2965 :
2966 0 : if (aPlacement == LinesFollow) {
2967 : // Follow it with the lines between repeats.
2968 0 : AppendGridLineNames(valueList,
2969 : aTrackList.mRepeatAutoLineNameListAfter,
2970 0 : aTrackList.mRepeatAutoLineNameListBefore);
2971 : }
2972 0 : repeatIndex++;
2973 : }
2974 0 : repeatIndex++;
2975 0 : };
2976 :
2977 0 : for (int32_t i = 0;; i++) {
2978 0 : if (aTrackList.HasRepeatAuto()) {
2979 0 : if (i == aTrackList.mRepeatAutoIndex) {
2980 0 : const nsTArray<nsString>& lineNames = aTrackList.mLineNameLists[i];
2981 0 : if (i == endOfRepeat) {
2982 : // All auto-fit tracks are empty, but we report them anyway.
2983 0 : AppendGridLineNames(valueList, lineNames,
2984 0 : aTrackList.mRepeatAutoLineNameListBefore);
2985 :
2986 0 : AppendRemovedAutoFits(LinesBetween);
2987 :
2988 0 : AppendGridLineNames(valueList,
2989 : aTrackList.mRepeatAutoLineNameListAfter,
2990 0 : aTrackList.mLineNameLists[i + 1]);
2991 : } else {
2992 0 : AppendGridLineNames(valueList, lineNames,
2993 0 : aTrackList.mRepeatAutoLineNameListBefore);
2994 0 : AppendRemovedAutoFits(LinesFollow);
2995 : }
2996 0 : } else if (i == endOfRepeat) {
2997 : // Before appending the last line, finish off any removed auto-fits.
2998 0 : AppendRemovedAutoFits(LinesPrecede);
2999 :
3000 : const nsTArray<nsString>& lineNames =
3001 0 : aTrackList.mLineNameLists[aTrackList.mRepeatAutoIndex + 1];
3002 0 : AppendGridLineNames(valueList,
3003 : aTrackList.mRepeatAutoLineNameListAfter,
3004 0 : lineNames);
3005 0 : } else if (i > aTrackList.mRepeatAutoIndex && i < endOfRepeat) {
3006 0 : AppendGridLineNames(valueList,
3007 : aTrackList.mRepeatAutoLineNameListAfter,
3008 0 : aTrackList.mRepeatAutoLineNameListBefore);
3009 0 : AppendRemovedAutoFits(LinesFollow);
3010 : } else {
3011 0 : uint32_t j = i > endOfRepeat ? i - offsetToLastRepeat : i;
3012 0 : const nsTArray<nsString>& lineNames = aTrackList.mLineNameLists[j];
3013 0 : AppendGridLineNames(valueList, lineNames);
3014 : }
3015 : } else {
3016 0 : const nsTArray<nsString>& lineNames = aTrackList.mLineNameLists[i];
3017 0 : AppendGridLineNames(valueList, lineNames);
3018 : }
3019 0 : if (uint32_t(i) == numExplicitTracks) {
3020 0 : break;
3021 : }
3022 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3023 0 : val->SetAppUnits(trackSizes[i + numLeadingImplicitTracks]);
3024 0 : valueList->AppendCSSValue(val.forget());
3025 0 : }
3026 : }
3027 :
3028 : // Add any trailing implicit tracks.
3029 0 : for (uint32_t i = numLeadingImplicitTracks + numExplicitTracks;
3030 0 : i < numSizes; ++i) {
3031 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3032 0 : val->SetAppUnits(trackSizes[i]);
3033 0 : valueList->AppendCSSValue(val.forget());
3034 : }
3035 : } else {
3036 : // We don't have a frame. So, we'll just return a serialization of
3037 : // the tracks from the style (without resolved sizes).
3038 0 : for (uint32_t i = 0;; i++) {
3039 0 : const nsTArray<nsString>& lineNames = aTrackList.mLineNameLists[i];
3040 0 : if (!lineNames.IsEmpty()) {
3041 0 : AppendGridLineNames(valueList, lineNames);
3042 : }
3043 0 : if (i == numSizes) {
3044 0 : break;
3045 : }
3046 0 : if (MOZ_UNLIKELY(aTrackList.IsRepeatAutoIndex(i))) {
3047 0 : RefPtr<nsROCSSPrimitiveValue> start = new nsROCSSPrimitiveValue;
3048 0 : start->SetString(aTrackList.mIsAutoFill ? NS_LITERAL_STRING("repeat(auto-fill,")
3049 0 : : NS_LITERAL_STRING("repeat(auto-fit,"));
3050 0 : valueList->AppendCSSValue(start.forget());
3051 0 : if (!aTrackList.mRepeatAutoLineNameListBefore.IsEmpty()) {
3052 0 : AppendGridLineNames(valueList, aTrackList.mRepeatAutoLineNameListBefore);
3053 : }
3054 :
3055 0 : valueList->AppendCSSValue(
3056 0 : GetGridTrackSize(aTrackList.mMinTrackSizingFunctions[i],
3057 0 : aTrackList.mMaxTrackSizingFunctions[i]));
3058 0 : if (!aTrackList.mRepeatAutoLineNameListAfter.IsEmpty()) {
3059 0 : AppendGridLineNames(valueList, aTrackList.mRepeatAutoLineNameListAfter);
3060 : }
3061 0 : RefPtr<nsROCSSPrimitiveValue> end = new nsROCSSPrimitiveValue;
3062 0 : end->SetString(NS_LITERAL_STRING(")"));
3063 0 : valueList->AppendCSSValue(end.forget());
3064 : } else {
3065 0 : valueList->AppendCSSValue(
3066 0 : GetGridTrackSize(aTrackList.mMinTrackSizingFunctions[i],
3067 0 : aTrackList.mMaxTrackSizingFunctions[i]));
3068 : }
3069 0 : }
3070 : }
3071 :
3072 0 : return valueList.forget();
3073 : }
3074 :
3075 : already_AddRefed<CSSValue>
3076 0 : nsComputedDOMStyle::DoGetGridAutoFlow()
3077 : {
3078 0 : nsAutoString str;
3079 0 : nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_grid_auto_flow,
3080 0 : StylePosition()->mGridAutoFlow,
3081 : NS_STYLE_GRID_AUTO_FLOW_ROW,
3082 : NS_STYLE_GRID_AUTO_FLOW_DENSE,
3083 0 : str);
3084 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3085 0 : val->SetString(str);
3086 0 : return val.forget();
3087 : }
3088 :
3089 : already_AddRefed<CSSValue>
3090 0 : nsComputedDOMStyle::DoGetGridAutoColumns()
3091 : {
3092 0 : return GetGridTrackSize(StylePosition()->mGridAutoColumnsMin,
3093 0 : StylePosition()->mGridAutoColumnsMax);
3094 : }
3095 :
3096 : already_AddRefed<CSSValue>
3097 0 : nsComputedDOMStyle::DoGetGridAutoRows()
3098 : {
3099 0 : return GetGridTrackSize(StylePosition()->mGridAutoRowsMin,
3100 0 : StylePosition()->mGridAutoRowsMax);
3101 : }
3102 :
3103 : already_AddRefed<CSSValue>
3104 0 : nsComputedDOMStyle::DoGetGridTemplateColumns()
3105 : {
3106 0 : const ComputedGridTrackInfo* info = nullptr;
3107 :
3108 : nsGridContainerFrame* gridFrame =
3109 0 : nsGridContainerFrame::GetGridFrameWithComputedInfo(
3110 0 : mContent->GetPrimaryFrame());
3111 :
3112 0 : if (gridFrame) {
3113 0 : info = gridFrame->GetComputedTemplateColumns();
3114 : }
3115 :
3116 0 : return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateColumns, info);
3117 : }
3118 :
3119 : already_AddRefed<CSSValue>
3120 0 : nsComputedDOMStyle::DoGetGridTemplateRows()
3121 : {
3122 0 : const ComputedGridTrackInfo* info = nullptr;
3123 :
3124 : nsGridContainerFrame* gridFrame =
3125 0 : nsGridContainerFrame::GetGridFrameWithComputedInfo(
3126 0 : mContent->GetPrimaryFrame());
3127 :
3128 0 : if (gridFrame) {
3129 0 : info = gridFrame->GetComputedTemplateRows();
3130 : }
3131 :
3132 0 : return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateRows, info);
3133 : }
3134 :
3135 : already_AddRefed<CSSValue>
3136 0 : nsComputedDOMStyle::GetGridLine(const nsStyleGridLine& aGridLine)
3137 : {
3138 0 : if (aGridLine.IsAuto()) {
3139 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3140 0 : val->SetIdent(eCSSKeyword_auto);
3141 0 : return val.forget();
3142 : }
3143 :
3144 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
3145 :
3146 0 : if (aGridLine.mHasSpan) {
3147 0 : RefPtr<nsROCSSPrimitiveValue> span = new nsROCSSPrimitiveValue;
3148 0 : span->SetIdent(eCSSKeyword_span);
3149 0 : valueList->AppendCSSValue(span.forget());
3150 : }
3151 :
3152 0 : if (aGridLine.mInteger != 0) {
3153 0 : RefPtr<nsROCSSPrimitiveValue> integer = new nsROCSSPrimitiveValue;
3154 0 : integer->SetNumber(aGridLine.mInteger);
3155 0 : valueList->AppendCSSValue(integer.forget());
3156 : }
3157 :
3158 0 : if (!aGridLine.mLineName.IsEmpty()) {
3159 0 : RefPtr<nsROCSSPrimitiveValue> lineName = new nsROCSSPrimitiveValue;
3160 0 : nsString escapedLineName;
3161 0 : nsStyleUtil::AppendEscapedCSSIdent(aGridLine.mLineName, escapedLineName);
3162 0 : lineName->SetString(escapedLineName);
3163 0 : valueList->AppendCSSValue(lineName.forget());
3164 : }
3165 :
3166 0 : NS_ASSERTION(valueList->Length() > 0,
3167 : "Should have appended at least one value");
3168 0 : return valueList.forget();
3169 : }
3170 :
3171 : already_AddRefed<CSSValue>
3172 0 : nsComputedDOMStyle::DoGetGridColumnStart()
3173 : {
3174 0 : return GetGridLine(StylePosition()->mGridColumnStart);
3175 : }
3176 :
3177 : already_AddRefed<CSSValue>
3178 0 : nsComputedDOMStyle::DoGetGridColumnEnd()
3179 : {
3180 0 : return GetGridLine(StylePosition()->mGridColumnEnd);
3181 : }
3182 :
3183 : already_AddRefed<CSSValue>
3184 0 : nsComputedDOMStyle::DoGetGridRowStart()
3185 : {
3186 0 : return GetGridLine(StylePosition()->mGridRowStart);
3187 : }
3188 :
3189 : already_AddRefed<CSSValue>
3190 0 : nsComputedDOMStyle::DoGetGridRowEnd()
3191 : {
3192 0 : return GetGridLine(StylePosition()->mGridRowEnd);
3193 : }
3194 :
3195 : already_AddRefed<CSSValue>
3196 0 : nsComputedDOMStyle::DoGetGridColumnGap()
3197 : {
3198 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3199 0 : SetValueToCoord(val, StylePosition()->mGridColumnGap, true);
3200 0 : return val.forget();
3201 : }
3202 :
3203 : already_AddRefed<CSSValue>
3204 0 : nsComputedDOMStyle::DoGetGridRowGap()
3205 : {
3206 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3207 0 : SetValueToCoord(val, StylePosition()->mGridRowGap, true);
3208 0 : return val.forget();
3209 : }
3210 :
3211 : already_AddRefed<CSSValue>
3212 0 : nsComputedDOMStyle::DoGetPaddingTop()
3213 : {
3214 0 : return GetPaddingWidthFor(eSideTop);
3215 : }
3216 :
3217 : already_AddRefed<CSSValue>
3218 0 : nsComputedDOMStyle::DoGetPaddingBottom()
3219 : {
3220 0 : return GetPaddingWidthFor(eSideBottom);
3221 : }
3222 :
3223 : already_AddRefed<CSSValue>
3224 0 : nsComputedDOMStyle::DoGetPaddingLeft()
3225 : {
3226 0 : return GetPaddingWidthFor(eSideLeft);
3227 : }
3228 :
3229 : already_AddRefed<CSSValue>
3230 0 : nsComputedDOMStyle::DoGetPaddingRight()
3231 : {
3232 0 : return GetPaddingWidthFor(eSideRight);
3233 : }
3234 :
3235 : already_AddRefed<CSSValue>
3236 0 : nsComputedDOMStyle::DoGetBorderCollapse()
3237 : {
3238 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3239 0 : val->SetIdent(
3240 0 : nsCSSProps::ValueToKeywordEnum(StyleTableBorder()->mBorderCollapse,
3241 0 : nsCSSProps::kBorderCollapseKTable));
3242 0 : return val.forget();
3243 : }
3244 :
3245 : already_AddRefed<CSSValue>
3246 0 : nsComputedDOMStyle::DoGetBorderSpacing()
3247 : {
3248 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
3249 :
3250 0 : RefPtr<nsROCSSPrimitiveValue> xSpacing = new nsROCSSPrimitiveValue;
3251 0 : RefPtr<nsROCSSPrimitiveValue> ySpacing = new nsROCSSPrimitiveValue;
3252 :
3253 0 : const nsStyleTableBorder *border = StyleTableBorder();
3254 0 : xSpacing->SetAppUnits(border->mBorderSpacingCol);
3255 0 : ySpacing->SetAppUnits(border->mBorderSpacingRow);
3256 :
3257 0 : valueList->AppendCSSValue(xSpacing.forget());
3258 0 : valueList->AppendCSSValue(ySpacing.forget());
3259 :
3260 0 : return valueList.forget();
3261 : }
3262 :
3263 : already_AddRefed<CSSValue>
3264 0 : nsComputedDOMStyle::DoGetCaptionSide()
3265 : {
3266 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3267 0 : val->SetIdent(
3268 0 : nsCSSProps::ValueToKeywordEnum(StyleTableBorder()->mCaptionSide,
3269 0 : nsCSSProps::kCaptionSideKTable));
3270 0 : return val.forget();
3271 : }
3272 :
3273 : already_AddRefed<CSSValue>
3274 0 : nsComputedDOMStyle::DoGetEmptyCells()
3275 : {
3276 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3277 0 : val->SetIdent(
3278 0 : nsCSSProps::ValueToKeywordEnum(StyleTableBorder()->mEmptyCells,
3279 0 : nsCSSProps::kEmptyCellsKTable));
3280 0 : return val.forget();
3281 : }
3282 :
3283 : already_AddRefed<CSSValue>
3284 0 : nsComputedDOMStyle::DoGetTableLayout()
3285 : {
3286 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3287 0 : val->SetIdent(
3288 0 : nsCSSProps::ValueToKeywordEnum(StyleTable()->mLayoutStrategy,
3289 0 : nsCSSProps::kTableLayoutKTable));
3290 0 : return val.forget();
3291 : }
3292 :
3293 : already_AddRefed<CSSValue>
3294 0 : nsComputedDOMStyle::DoGetBorderTopStyle()
3295 : {
3296 0 : return GetBorderStyleFor(eSideTop);
3297 : }
3298 :
3299 : already_AddRefed<CSSValue>
3300 0 : nsComputedDOMStyle::DoGetBorderBottomStyle()
3301 : {
3302 0 : return GetBorderStyleFor(eSideBottom);
3303 : }
3304 :
3305 : already_AddRefed<CSSValue>
3306 0 : nsComputedDOMStyle::DoGetBorderLeftStyle()
3307 : {
3308 0 : return GetBorderStyleFor(eSideLeft);
3309 : }
3310 :
3311 : already_AddRefed<CSSValue>
3312 0 : nsComputedDOMStyle::DoGetBorderRightStyle()
3313 : {
3314 0 : return GetBorderStyleFor(eSideRight);
3315 : }
3316 :
3317 : already_AddRefed<CSSValue>
3318 0 : nsComputedDOMStyle::DoGetBorderBottomColors()
3319 : {
3320 0 : return GetBorderColorsFor(eSideBottom);
3321 : }
3322 :
3323 : already_AddRefed<CSSValue>
3324 0 : nsComputedDOMStyle::DoGetBorderLeftColors()
3325 : {
3326 0 : return GetBorderColorsFor(eSideLeft);
3327 : }
3328 :
3329 : already_AddRefed<CSSValue>
3330 0 : nsComputedDOMStyle::DoGetBorderRightColors()
3331 : {
3332 0 : return GetBorderColorsFor(eSideRight);
3333 : }
3334 :
3335 :
3336 : already_AddRefed<CSSValue>
3337 0 : nsComputedDOMStyle::DoGetBorderTopColors()
3338 : {
3339 0 : return GetBorderColorsFor(eSideTop);
3340 : }
3341 :
3342 : already_AddRefed<CSSValue>
3343 0 : nsComputedDOMStyle::DoGetBorderBottomLeftRadius()
3344 : {
3345 0 : return GetEllipseRadii(StyleBorder()->mBorderRadius,
3346 0 : eCornerBottomLeft);
3347 : }
3348 :
3349 : already_AddRefed<CSSValue>
3350 0 : nsComputedDOMStyle::DoGetBorderBottomRightRadius()
3351 : {
3352 0 : return GetEllipseRadii(StyleBorder()->mBorderRadius,
3353 0 : eCornerBottomRight);
3354 : }
3355 :
3356 : already_AddRefed<CSSValue>
3357 0 : nsComputedDOMStyle::DoGetBorderTopLeftRadius()
3358 : {
3359 0 : return GetEllipseRadii(StyleBorder()->mBorderRadius,
3360 0 : eCornerTopLeft);
3361 : }
3362 :
3363 : already_AddRefed<CSSValue>
3364 0 : nsComputedDOMStyle::DoGetBorderTopRightRadius()
3365 : {
3366 0 : return GetEllipseRadii(StyleBorder()->mBorderRadius,
3367 0 : eCornerTopRight);
3368 : }
3369 :
3370 : already_AddRefed<CSSValue>
3371 0 : nsComputedDOMStyle::DoGetBorderTopWidth()
3372 : {
3373 0 : return GetBorderWidthFor(eSideTop);
3374 : }
3375 :
3376 : already_AddRefed<CSSValue>
3377 0 : nsComputedDOMStyle::DoGetBorderBottomWidth()
3378 : {
3379 0 : return GetBorderWidthFor(eSideBottom);
3380 : }
3381 :
3382 : already_AddRefed<CSSValue>
3383 0 : nsComputedDOMStyle::DoGetBorderLeftWidth()
3384 : {
3385 0 : return GetBorderWidthFor(eSideLeft);
3386 : }
3387 :
3388 : already_AddRefed<CSSValue>
3389 0 : nsComputedDOMStyle::DoGetBorderRightWidth()
3390 : {
3391 0 : return GetBorderWidthFor(eSideRight);
3392 : }
3393 :
3394 : already_AddRefed<CSSValue>
3395 0 : nsComputedDOMStyle::DoGetBorderTopColor()
3396 : {
3397 0 : return GetBorderColorFor(eSideTop);
3398 : }
3399 :
3400 : already_AddRefed<CSSValue>
3401 0 : nsComputedDOMStyle::DoGetBorderBottomColor()
3402 : {
3403 0 : return GetBorderColorFor(eSideBottom);
3404 : }
3405 :
3406 : already_AddRefed<CSSValue>
3407 0 : nsComputedDOMStyle::DoGetBorderLeftColor()
3408 : {
3409 0 : return GetBorderColorFor(eSideLeft);
3410 : }
3411 :
3412 : already_AddRefed<CSSValue>
3413 0 : nsComputedDOMStyle::DoGetBorderRightColor()
3414 : {
3415 0 : return GetBorderColorFor(eSideRight);
3416 : }
3417 :
3418 : already_AddRefed<CSSValue>
3419 0 : nsComputedDOMStyle::DoGetMarginTopWidth()
3420 : {
3421 0 : return GetMarginWidthFor(eSideTop);
3422 : }
3423 :
3424 : already_AddRefed<CSSValue>
3425 0 : nsComputedDOMStyle::DoGetMarginBottomWidth()
3426 : {
3427 0 : return GetMarginWidthFor(eSideBottom);
3428 : }
3429 :
3430 : already_AddRefed<CSSValue>
3431 0 : nsComputedDOMStyle::DoGetMarginLeftWidth()
3432 : {
3433 0 : return GetMarginWidthFor(eSideLeft);
3434 : }
3435 :
3436 : already_AddRefed<CSSValue>
3437 0 : nsComputedDOMStyle::DoGetMarginRightWidth()
3438 : {
3439 0 : return GetMarginWidthFor(eSideRight);
3440 : }
3441 :
3442 : already_AddRefed<CSSValue>
3443 0 : nsComputedDOMStyle::DoGetOrient()
3444 : {
3445 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3446 0 : val->SetIdent(
3447 0 : nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mOrient,
3448 0 : nsCSSProps::kOrientKTable));
3449 0 : return val.forget();
3450 : }
3451 :
3452 : already_AddRefed<CSSValue>
3453 0 : nsComputedDOMStyle::DoGetScrollBehavior()
3454 : {
3455 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3456 0 : val->SetIdent(
3457 0 : nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mScrollBehavior,
3458 0 : nsCSSProps::kScrollBehaviorKTable));
3459 0 : return val.forget();
3460 : }
3461 :
3462 : already_AddRefed<CSSValue>
3463 0 : nsComputedDOMStyle::DoGetScrollSnapType()
3464 : {
3465 0 : const nsStyleDisplay* display = StyleDisplay();
3466 0 : if (display->mScrollSnapTypeX != display->mScrollSnapTypeY) {
3467 : // No value to return. We can't express this combination of
3468 : // values as a shorthand.
3469 0 : return nullptr;
3470 : }
3471 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3472 0 : val->SetIdent(
3473 0 : nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mScrollSnapTypeX,
3474 0 : nsCSSProps::kScrollSnapTypeKTable));
3475 0 : return val.forget();
3476 : }
3477 :
3478 : already_AddRefed<CSSValue>
3479 0 : nsComputedDOMStyle::DoGetScrollSnapTypeX()
3480 : {
3481 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3482 0 : val->SetIdent(
3483 0 : nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mScrollSnapTypeX,
3484 0 : nsCSSProps::kScrollSnapTypeKTable));
3485 0 : return val.forget();
3486 : }
3487 :
3488 : already_AddRefed<CSSValue>
3489 0 : nsComputedDOMStyle::DoGetScrollSnapTypeY()
3490 : {
3491 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3492 0 : val->SetIdent(
3493 0 : nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mScrollSnapTypeY,
3494 0 : nsCSSProps::kScrollSnapTypeKTable));
3495 0 : return val.forget();
3496 : }
3497 :
3498 : already_AddRefed<CSSValue>
3499 0 : nsComputedDOMStyle::GetScrollSnapPoints(const nsStyleCoord& aCoord)
3500 : {
3501 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3502 0 : if (aCoord.GetUnit() == eStyleUnit_None) {
3503 0 : val->SetIdent(eCSSKeyword_none);
3504 : } else {
3505 0 : nsAutoString argumentString;
3506 0 : SetCssTextToCoord(argumentString, aCoord);
3507 0 : nsAutoString tmp;
3508 0 : tmp.AppendLiteral("repeat(");
3509 0 : tmp.Append(argumentString);
3510 0 : tmp.Append(')');
3511 0 : val->SetString(tmp);
3512 : }
3513 0 : return val.forget();
3514 : }
3515 :
3516 : already_AddRefed<CSSValue>
3517 0 : nsComputedDOMStyle::DoGetScrollSnapPointsX()
3518 : {
3519 0 : return GetScrollSnapPoints(StyleDisplay()->mScrollSnapPointsX);
3520 : }
3521 :
3522 : already_AddRefed<CSSValue>
3523 0 : nsComputedDOMStyle::DoGetScrollSnapPointsY()
3524 : {
3525 0 : return GetScrollSnapPoints(StyleDisplay()->mScrollSnapPointsY);
3526 : }
3527 :
3528 : already_AddRefed<CSSValue>
3529 0 : nsComputedDOMStyle::DoGetScrollSnapDestination()
3530 : {
3531 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
3532 0 : SetValueToPosition(StyleDisplay()->mScrollSnapDestination, valueList);
3533 0 : return valueList.forget();
3534 : }
3535 :
3536 : already_AddRefed<CSSValue>
3537 0 : nsComputedDOMStyle::DoGetScrollSnapCoordinate()
3538 : {
3539 0 : const nsStyleDisplay* sd = StyleDisplay();
3540 0 : if (sd->mScrollSnapCoordinate.IsEmpty()) {
3541 : // Having no snap coordinates is interpreted as "none"
3542 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3543 0 : val->SetIdent(eCSSKeyword_none);
3544 0 : return val.forget();
3545 : } else {
3546 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
3547 0 : for (size_t i = 0, i_end = sd->mScrollSnapCoordinate.Length(); i < i_end; ++i) {
3548 0 : RefPtr<nsDOMCSSValueList> itemList = GetROCSSValueList(false);
3549 0 : SetValueToPosition(sd->mScrollSnapCoordinate[i], itemList);
3550 0 : valueList->AppendCSSValue(itemList.forget());
3551 : }
3552 0 : return valueList.forget();
3553 : }
3554 : }
3555 :
3556 : already_AddRefed<CSSValue>
3557 0 : nsComputedDOMStyle::DoGetOutlineWidth()
3558 : {
3559 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3560 :
3561 0 : const nsStyleOutline* outline = StyleOutline();
3562 :
3563 : nscoord width;
3564 0 : if (outline->mOutlineStyle == NS_STYLE_BORDER_STYLE_NONE) {
3565 0 : NS_ASSERTION(outline->GetOutlineWidth() == 0, "unexpected width");
3566 0 : width = 0;
3567 : } else {
3568 0 : width = outline->GetOutlineWidth();
3569 : }
3570 0 : val->SetAppUnits(width);
3571 :
3572 0 : return val.forget();
3573 : }
3574 :
3575 : already_AddRefed<CSSValue>
3576 0 : nsComputedDOMStyle::DoGetOutlineStyle()
3577 : {
3578 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3579 0 : val->SetIdent(
3580 0 : nsCSSProps::ValueToKeywordEnum(StyleOutline()->mOutlineStyle,
3581 0 : nsCSSProps::kOutlineStyleKTable));
3582 0 : return val.forget();
3583 : }
3584 :
3585 : already_AddRefed<CSSValue>
3586 0 : nsComputedDOMStyle::DoGetOutlineOffset()
3587 : {
3588 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3589 0 : val->SetAppUnits(StyleOutline()->mOutlineOffset);
3590 0 : return val.forget();
3591 : }
3592 :
3593 : already_AddRefed<CSSValue>
3594 0 : nsComputedDOMStyle::DoGetOutlineRadiusBottomLeft()
3595 : {
3596 0 : return GetEllipseRadii(StyleOutline()->mOutlineRadius,
3597 0 : eCornerBottomLeft);
3598 : }
3599 :
3600 : already_AddRefed<CSSValue>
3601 0 : nsComputedDOMStyle::DoGetOutlineRadiusBottomRight()
3602 : {
3603 0 : return GetEllipseRadii(StyleOutline()->mOutlineRadius,
3604 0 : eCornerBottomRight);
3605 : }
3606 :
3607 : already_AddRefed<CSSValue>
3608 0 : nsComputedDOMStyle::DoGetOutlineRadiusTopLeft()
3609 : {
3610 0 : return GetEllipseRadii(StyleOutline()->mOutlineRadius,
3611 0 : eCornerTopLeft);
3612 : }
3613 :
3614 : already_AddRefed<CSSValue>
3615 0 : nsComputedDOMStyle::DoGetOutlineRadiusTopRight()
3616 : {
3617 0 : return GetEllipseRadii(StyleOutline()->mOutlineRadius,
3618 0 : eCornerTopRight);
3619 : }
3620 :
3621 : already_AddRefed<CSSValue>
3622 0 : nsComputedDOMStyle::DoGetOutlineColor()
3623 : {
3624 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3625 0 : SetValueFromComplexColor(val, StyleOutline()->mOutlineColor);
3626 0 : return val.forget();
3627 : }
3628 :
3629 : already_AddRefed<CSSValue>
3630 0 : nsComputedDOMStyle::GetEllipseRadii(const nsStyleCorners& aRadius,
3631 : Corner aFullCorner)
3632 : {
3633 0 : nsStyleCoord radiusX = aRadius.Get(FullToHalfCorner(aFullCorner, false));
3634 0 : nsStyleCoord radiusY = aRadius.Get(FullToHalfCorner(aFullCorner, true));
3635 :
3636 : // for compatibility, return a single value if X and Y are equal
3637 0 : if (radiusX == radiusY) {
3638 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3639 0 : SetValueToCoord(val, radiusX, true);
3640 0 : return val.forget();
3641 : }
3642 :
3643 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
3644 :
3645 0 : RefPtr<nsROCSSPrimitiveValue> valX = new nsROCSSPrimitiveValue;
3646 0 : RefPtr<nsROCSSPrimitiveValue> valY = new nsROCSSPrimitiveValue;
3647 :
3648 0 : SetValueToCoord(valX, radiusX, true);
3649 0 : SetValueToCoord(valY, radiusY, true);
3650 :
3651 0 : valueList->AppendCSSValue(valX.forget());
3652 0 : valueList->AppendCSSValue(valY.forget());
3653 :
3654 0 : return valueList.forget();
3655 : }
3656 :
3657 : already_AddRefed<CSSValue>
3658 0 : nsComputedDOMStyle::GetCSSShadowArray(nsCSSShadowArray* aArray,
3659 : const nscolor& aDefaultColor,
3660 : bool aIsBoxShadow)
3661 : {
3662 0 : if (!aArray) {
3663 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3664 0 : val->SetIdent(eCSSKeyword_none);
3665 0 : return val.forget();
3666 : }
3667 :
3668 : static nscoord nsCSSShadowItem::* const shadowValuesNoSpread[] = {
3669 : &nsCSSShadowItem::mXOffset,
3670 : &nsCSSShadowItem::mYOffset,
3671 : &nsCSSShadowItem::mRadius
3672 : };
3673 :
3674 : static nscoord nsCSSShadowItem::* const shadowValuesWithSpread[] = {
3675 : &nsCSSShadowItem::mXOffset,
3676 : &nsCSSShadowItem::mYOffset,
3677 : &nsCSSShadowItem::mRadius,
3678 : &nsCSSShadowItem::mSpread
3679 : };
3680 :
3681 : nscoord nsCSSShadowItem::* const * shadowValues;
3682 : uint32_t shadowValuesLength;
3683 0 : if (aIsBoxShadow) {
3684 0 : shadowValues = shadowValuesWithSpread;
3685 0 : shadowValuesLength = ArrayLength(shadowValuesWithSpread);
3686 : } else {
3687 0 : shadowValues = shadowValuesNoSpread;
3688 0 : shadowValuesLength = ArrayLength(shadowValuesNoSpread);
3689 : }
3690 :
3691 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
3692 :
3693 0 : for (nsCSSShadowItem *item = aArray->ShadowAt(0),
3694 0 : *item_end = item + aArray->Length();
3695 0 : item < item_end; ++item) {
3696 0 : RefPtr<nsDOMCSSValueList> itemList = GetROCSSValueList(false);
3697 :
3698 : // Color is either the specified shadow color or the foreground color
3699 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3700 : nscolor shadowColor;
3701 0 : if (item->mHasColor) {
3702 0 : shadowColor = item->mColor;
3703 : } else {
3704 0 : shadowColor = aDefaultColor;
3705 : }
3706 0 : SetToRGBAColor(val, shadowColor);
3707 0 : itemList->AppendCSSValue(val.forget());
3708 :
3709 : // Set the offsets, blur radius, and spread if available
3710 0 : for (uint32_t i = 0; i < shadowValuesLength; ++i) {
3711 0 : val = new nsROCSSPrimitiveValue;
3712 0 : val->SetAppUnits(item->*(shadowValues[i]));
3713 0 : itemList->AppendCSSValue(val.forget());
3714 : }
3715 :
3716 0 : if (item->mInset && aIsBoxShadow) {
3717 : // This is an inset box-shadow
3718 0 : val = new nsROCSSPrimitiveValue;
3719 0 : val->SetIdent(
3720 0 : nsCSSProps::ValueToKeywordEnum(
3721 : uint8_t(StyleBoxShadowType::Inset),
3722 0 : nsCSSProps::kBoxShadowTypeKTable));
3723 0 : itemList->AppendCSSValue(val.forget());
3724 : }
3725 0 : valueList->AppendCSSValue(itemList.forget());
3726 : }
3727 :
3728 0 : return valueList.forget();
3729 : }
3730 :
3731 : already_AddRefed<CSSValue>
3732 0 : nsComputedDOMStyle::DoGetBoxDecorationBreak()
3733 : {
3734 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3735 0 : val->SetIdent(
3736 0 : nsCSSProps::ValueToKeywordEnum(StyleBorder()->mBoxDecorationBreak,
3737 0 : nsCSSProps::kBoxDecorationBreakKTable));
3738 0 : return val.forget();
3739 : }
3740 :
3741 : already_AddRefed<CSSValue>
3742 0 : nsComputedDOMStyle::DoGetBoxShadow()
3743 : {
3744 0 : return GetCSSShadowArray(StyleEffects()->mBoxShadow,
3745 0 : StyleColor()->mColor,
3746 0 : true);
3747 : }
3748 :
3749 : already_AddRefed<CSSValue>
3750 0 : nsComputedDOMStyle::DoGetZIndex()
3751 : {
3752 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3753 0 : SetValueToCoord(val, StylePosition()->mZIndex, false);
3754 0 : return val.forget();
3755 : }
3756 :
3757 : already_AddRefed<CSSValue>
3758 0 : nsComputedDOMStyle::DoGetListStyleImage()
3759 : {
3760 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3761 :
3762 0 : nsCOMPtr<nsIURI> uri = StyleList()->GetListStyleImageURI();
3763 0 : if (!uri) {
3764 0 : val->SetIdent(eCSSKeyword_none);
3765 : } else {
3766 0 : val->SetURI(uri);
3767 : }
3768 :
3769 0 : return val.forget();
3770 : }
3771 :
3772 : already_AddRefed<CSSValue>
3773 0 : nsComputedDOMStyle::DoGetListStylePosition()
3774 : {
3775 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3776 0 : val->SetIdent(
3777 0 : nsCSSProps::ValueToKeywordEnum(StyleList()->mListStylePosition,
3778 0 : nsCSSProps::kListStylePositionKTable));
3779 0 : return val.forget();
3780 : }
3781 :
3782 : already_AddRefed<CSSValue>
3783 0 : nsComputedDOMStyle::DoGetListStyleType()
3784 : {
3785 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3786 0 : nsAutoString tmp;
3787 0 : AppendCounterStyle(StyleList()->mCounterStyle, tmp);
3788 0 : val->SetString(tmp);
3789 0 : return val.forget();
3790 : }
3791 :
3792 : already_AddRefed<CSSValue>
3793 0 : nsComputedDOMStyle::DoGetImageRegion()
3794 : {
3795 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3796 :
3797 0 : const nsStyleList* list = StyleList();
3798 :
3799 0 : if (list->mImageRegion.width <= 0 || list->mImageRegion.height <= 0) {
3800 0 : val->SetIdent(eCSSKeyword_auto);
3801 : } else {
3802 : // create the cssvalues for the sides, stick them in the rect object
3803 0 : nsROCSSPrimitiveValue *topVal = new nsROCSSPrimitiveValue;
3804 0 : nsROCSSPrimitiveValue *rightVal = new nsROCSSPrimitiveValue;
3805 0 : nsROCSSPrimitiveValue *bottomVal = new nsROCSSPrimitiveValue;
3806 0 : nsROCSSPrimitiveValue *leftVal = new nsROCSSPrimitiveValue;
3807 : nsDOMCSSRect * domRect = new nsDOMCSSRect(topVal, rightVal,
3808 0 : bottomVal, leftVal);
3809 0 : topVal->SetAppUnits(list->mImageRegion.y);
3810 0 : rightVal->SetAppUnits(list->mImageRegion.width + list->mImageRegion.x);
3811 0 : bottomVal->SetAppUnits(list->mImageRegion.height + list->mImageRegion.y);
3812 0 : leftVal->SetAppUnits(list->mImageRegion.x);
3813 0 : val->SetRect(domRect);
3814 : }
3815 :
3816 0 : return val.forget();
3817 : }
3818 :
3819 : already_AddRefed<CSSValue>
3820 0 : nsComputedDOMStyle::DoGetInitialLetter()
3821 : {
3822 0 : const nsStyleTextReset* textReset = StyleTextReset();
3823 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3824 0 : if (textReset->mInitialLetterSink == 0) {
3825 0 : val->SetIdent(eCSSKeyword_normal);
3826 0 : return val.forget();
3827 : } else {
3828 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
3829 0 : val->SetNumber(textReset->mInitialLetterSize);
3830 0 : valueList->AppendCSSValue(val.forget());
3831 0 : RefPtr<nsROCSSPrimitiveValue> second = new nsROCSSPrimitiveValue;
3832 0 : second->SetNumber(textReset->mInitialLetterSink);
3833 0 : valueList->AppendCSSValue(second.forget());
3834 0 : return valueList.forget();
3835 : }
3836 : }
3837 :
3838 : already_AddRefed<CSSValue>
3839 0 : nsComputedDOMStyle::DoGetLineHeight()
3840 : {
3841 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3842 :
3843 : nscoord lineHeight;
3844 0 : if (GetLineHeightCoord(lineHeight)) {
3845 0 : val->SetAppUnits(lineHeight);
3846 : } else {
3847 0 : SetValueToCoord(val, StyleText()->mLineHeight, true,
3848 0 : nullptr, nsCSSProps::kLineHeightKTable);
3849 : }
3850 :
3851 0 : return val.forget();
3852 : }
3853 :
3854 : already_AddRefed<CSSValue>
3855 0 : nsComputedDOMStyle::DoGetRubyAlign()
3856 : {
3857 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3858 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(
3859 0 : StyleText()->mRubyAlign, nsCSSProps::kRubyAlignKTable));
3860 0 : return val.forget();
3861 : }
3862 :
3863 : already_AddRefed<CSSValue>
3864 0 : nsComputedDOMStyle::DoGetRubyPosition()
3865 : {
3866 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3867 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(
3868 0 : StyleText()->mRubyPosition, nsCSSProps::kRubyPositionKTable));
3869 0 : return val.forget();
3870 : }
3871 :
3872 : already_AddRefed<CSSValue>
3873 0 : nsComputedDOMStyle::DoGetVerticalAlign()
3874 : {
3875 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3876 0 : SetValueToCoord(val, StyleDisplay()->mVerticalAlign, false,
3877 0 : nullptr, nsCSSProps::kVerticalAlignKTable);
3878 0 : return val.forget();
3879 : }
3880 :
3881 : already_AddRefed<CSSValue>
3882 0 : nsComputedDOMStyle::CreateTextAlignValue(uint8_t aAlign, bool aAlignTrue,
3883 : const KTableEntry aTable[])
3884 : {
3885 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3886 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(aAlign, aTable));
3887 0 : if (!aAlignTrue) {
3888 0 : return val.forget();
3889 : }
3890 :
3891 0 : RefPtr<nsROCSSPrimitiveValue> first = new nsROCSSPrimitiveValue;
3892 0 : first->SetIdent(eCSSKeyword_unsafe);
3893 :
3894 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
3895 0 : valueList->AppendCSSValue(first.forget());
3896 0 : valueList->AppendCSSValue(val.forget());
3897 0 : return valueList.forget();
3898 : }
3899 :
3900 : already_AddRefed<CSSValue>
3901 0 : nsComputedDOMStyle::DoGetTextAlign()
3902 : {
3903 0 : const nsStyleText* style = StyleText();
3904 0 : return CreateTextAlignValue(style->mTextAlign, style->mTextAlignTrue,
3905 0 : nsCSSProps::kTextAlignKTable);
3906 : }
3907 :
3908 : already_AddRefed<CSSValue>
3909 0 : nsComputedDOMStyle::DoGetTextAlignLast()
3910 : {
3911 0 : const nsStyleText* style = StyleText();
3912 0 : return CreateTextAlignValue(style->mTextAlignLast, style->mTextAlignLastTrue,
3913 0 : nsCSSProps::kTextAlignLastKTable);
3914 : }
3915 :
3916 : already_AddRefed<CSSValue>
3917 0 : nsComputedDOMStyle::DoGetTextCombineUpright()
3918 : {
3919 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3920 0 : uint8_t tch = StyleText()->mTextCombineUpright;
3921 :
3922 0 : if (tch <= NS_STYLE_TEXT_COMBINE_UPRIGHT_ALL) {
3923 0 : val->SetIdent(
3924 0 : nsCSSProps::ValueToKeywordEnum(tch,
3925 0 : nsCSSProps::kTextCombineUprightKTable));
3926 0 : } else if (tch <= NS_STYLE_TEXT_COMBINE_UPRIGHT_DIGITS_2) {
3927 0 : val->SetString(NS_LITERAL_STRING("digits 2"));
3928 0 : } else if (tch <= NS_STYLE_TEXT_COMBINE_UPRIGHT_DIGITS_3) {
3929 0 : val->SetString(NS_LITERAL_STRING("digits 3"));
3930 : } else {
3931 0 : val->SetString(NS_LITERAL_STRING("digits 4"));
3932 : }
3933 :
3934 0 : return val.forget();
3935 : }
3936 :
3937 : already_AddRefed<CSSValue>
3938 0 : nsComputedDOMStyle::DoGetTextDecoration()
3939 : {
3940 0 : const nsStyleTextReset* textReset = StyleTextReset();
3941 :
3942 : bool isInitialStyle =
3943 0 : textReset->mTextDecorationStyle == NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
3944 0 : StyleComplexColor color = textReset->mTextDecorationColor;
3945 :
3946 0 : if (isInitialStyle && color.IsCurrentColor()) {
3947 0 : return DoGetTextDecorationLine();
3948 : }
3949 :
3950 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
3951 :
3952 0 : valueList->AppendCSSValue(DoGetTextDecorationLine());
3953 0 : if (!isInitialStyle) {
3954 0 : valueList->AppendCSSValue(DoGetTextDecorationStyle());
3955 : }
3956 0 : if (!color.IsCurrentColor()) {
3957 0 : valueList->AppendCSSValue(DoGetTextDecorationColor());
3958 : }
3959 :
3960 0 : return valueList.forget();
3961 : }
3962 :
3963 : already_AddRefed<CSSValue>
3964 0 : nsComputedDOMStyle::DoGetTextDecorationColor()
3965 : {
3966 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3967 0 : SetValueFromComplexColor(val, StyleTextReset()->mTextDecorationColor);
3968 0 : return val.forget();
3969 : }
3970 :
3971 : already_AddRefed<CSSValue>
3972 0 : nsComputedDOMStyle::DoGetTextDecorationLine()
3973 : {
3974 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3975 :
3976 0 : int32_t intValue = StyleTextReset()->mTextDecorationLine;
3977 :
3978 0 : if (NS_STYLE_TEXT_DECORATION_LINE_NONE == intValue) {
3979 0 : val->SetIdent(eCSSKeyword_none);
3980 : } else {
3981 0 : nsAutoString decorationLineString;
3982 : // Clear the OVERRIDE_ALL bits -- we don't want these to appear in
3983 : // the computed style.
3984 0 : intValue &= ~NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL;
3985 : nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_text_decoration_line,
3986 : intValue, NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
3987 0 : NS_STYLE_TEXT_DECORATION_LINE_BLINK, decorationLineString);
3988 0 : val->SetString(decorationLineString);
3989 : }
3990 :
3991 0 : return val.forget();
3992 : }
3993 :
3994 : already_AddRefed<CSSValue>
3995 0 : nsComputedDOMStyle::DoGetTextDecorationStyle()
3996 : {
3997 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
3998 :
3999 0 : val->SetIdent(
4000 0 : nsCSSProps::ValueToKeywordEnum(StyleTextReset()->mTextDecorationStyle,
4001 0 : nsCSSProps::kTextDecorationStyleKTable));
4002 :
4003 0 : return val.forget();
4004 : }
4005 :
4006 : already_AddRefed<CSSValue>
4007 0 : nsComputedDOMStyle::DoGetTextEmphasisColor()
4008 : {
4009 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4010 0 : SetValueFromComplexColor(val, StyleText()->mTextEmphasisColor);
4011 0 : return val.forget();
4012 : }
4013 :
4014 : already_AddRefed<CSSValue>
4015 0 : nsComputedDOMStyle::DoGetTextEmphasisPosition()
4016 : {
4017 0 : auto position = StyleText()->mTextEmphasisPosition;
4018 :
4019 0 : MOZ_ASSERT(!(position & NS_STYLE_TEXT_EMPHASIS_POSITION_OVER) !=
4020 : !(position & NS_STYLE_TEXT_EMPHASIS_POSITION_UNDER));
4021 0 : RefPtr<nsROCSSPrimitiveValue> first = new nsROCSSPrimitiveValue;
4022 0 : first->SetIdent((position & NS_STYLE_TEXT_EMPHASIS_POSITION_OVER) ?
4023 0 : eCSSKeyword_over : eCSSKeyword_under);
4024 :
4025 0 : MOZ_ASSERT(!(position & NS_STYLE_TEXT_EMPHASIS_POSITION_LEFT) !=
4026 : !(position & NS_STYLE_TEXT_EMPHASIS_POSITION_RIGHT));
4027 0 : RefPtr<nsROCSSPrimitiveValue> second = new nsROCSSPrimitiveValue;
4028 0 : second->SetIdent((position & NS_STYLE_TEXT_EMPHASIS_POSITION_LEFT) ?
4029 0 : eCSSKeyword_left : eCSSKeyword_right);
4030 :
4031 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
4032 0 : valueList->AppendCSSValue(first.forget());
4033 0 : valueList->AppendCSSValue(second.forget());
4034 0 : return valueList.forget();
4035 : }
4036 :
4037 : already_AddRefed<CSSValue>
4038 0 : nsComputedDOMStyle::DoGetTextEmphasisStyle()
4039 : {
4040 0 : auto style = StyleText()->mTextEmphasisStyle;
4041 0 : if (style == NS_STYLE_TEXT_EMPHASIS_STYLE_NONE) {
4042 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4043 0 : val->SetIdent(eCSSKeyword_none);
4044 0 : return val.forget();
4045 : }
4046 0 : if (style == NS_STYLE_TEXT_EMPHASIS_STYLE_STRING) {
4047 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4048 0 : nsAutoString tmp;
4049 0 : nsStyleUtil::AppendEscapedCSSString(
4050 0 : StyleText()->mTextEmphasisStyleString, tmp);
4051 0 : val->SetString(tmp);
4052 0 : return val.forget();
4053 : }
4054 :
4055 0 : RefPtr<nsROCSSPrimitiveValue> fillVal = new nsROCSSPrimitiveValue;
4056 0 : if ((style & NS_STYLE_TEXT_EMPHASIS_STYLE_FILL_MASK) ==
4057 : NS_STYLE_TEXT_EMPHASIS_STYLE_FILLED) {
4058 0 : fillVal->SetIdent(eCSSKeyword_filled);
4059 : } else {
4060 0 : MOZ_ASSERT((style & NS_STYLE_TEXT_EMPHASIS_STYLE_FILL_MASK) ==
4061 : NS_STYLE_TEXT_EMPHASIS_STYLE_OPEN);
4062 0 : fillVal->SetIdent(eCSSKeyword_open);
4063 : }
4064 :
4065 0 : RefPtr<nsROCSSPrimitiveValue> shapeVal = new nsROCSSPrimitiveValue;
4066 0 : shapeVal->SetIdent(nsCSSProps::ValueToKeywordEnum(
4067 0 : style & NS_STYLE_TEXT_EMPHASIS_STYLE_SHAPE_MASK,
4068 0 : nsCSSProps::kTextEmphasisStyleShapeKTable));
4069 :
4070 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
4071 0 : valueList->AppendCSSValue(fillVal.forget());
4072 0 : valueList->AppendCSSValue(shapeVal.forget());
4073 0 : return valueList.forget();
4074 : }
4075 :
4076 : already_AddRefed<CSSValue>
4077 0 : nsComputedDOMStyle::DoGetTextIndent()
4078 : {
4079 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4080 0 : SetValueToCoord(val, StyleText()->mTextIndent, false);
4081 0 : return val.forget();
4082 : }
4083 :
4084 : already_AddRefed<CSSValue>
4085 0 : nsComputedDOMStyle::DoGetTextJustify()
4086 : {
4087 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4088 0 : val->SetIdent(
4089 0 : nsCSSProps::ValueToKeywordEnum(StyleText()->mTextJustify,
4090 0 : nsCSSProps::kTextJustifyKTable));
4091 0 : return val.forget();
4092 : }
4093 :
4094 : already_AddRefed<CSSValue>
4095 0 : nsComputedDOMStyle::DoGetTextOrientation()
4096 : {
4097 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4098 0 : val->SetIdent(
4099 0 : nsCSSProps::ValueToKeywordEnum(StyleVisibility()->mTextOrientation,
4100 0 : nsCSSProps::kTextOrientationKTable));
4101 0 : return val.forget();
4102 : }
4103 :
4104 : already_AddRefed<CSSValue>
4105 0 : nsComputedDOMStyle::DoGetTextOverflow()
4106 : {
4107 0 : const nsStyleTextReset *style = StyleTextReset();
4108 0 : RefPtr<nsROCSSPrimitiveValue> first = new nsROCSSPrimitiveValue;
4109 0 : const nsStyleTextOverflowSide *side = style->mTextOverflow.GetFirstValue();
4110 0 : if (side->mType == NS_STYLE_TEXT_OVERFLOW_STRING) {
4111 0 : nsAutoString str;
4112 0 : nsStyleUtil::AppendEscapedCSSString(side->mString, str);
4113 0 : first->SetString(str);
4114 : } else {
4115 0 : first->SetIdent(
4116 0 : nsCSSProps::ValueToKeywordEnum(side->mType,
4117 0 : nsCSSProps::kTextOverflowKTable));
4118 : }
4119 0 : side = style->mTextOverflow.GetSecondValue();
4120 0 : if (!side) {
4121 0 : return first.forget();
4122 : }
4123 0 : RefPtr<nsROCSSPrimitiveValue> second = new nsROCSSPrimitiveValue;
4124 0 : if (side->mType == NS_STYLE_TEXT_OVERFLOW_STRING) {
4125 0 : nsAutoString str;
4126 0 : nsStyleUtil::AppendEscapedCSSString(side->mString, str);
4127 0 : second->SetString(str);
4128 : } else {
4129 0 : second->SetIdent(
4130 0 : nsCSSProps::ValueToKeywordEnum(side->mType,
4131 0 : nsCSSProps::kTextOverflowKTable));
4132 : }
4133 :
4134 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
4135 0 : valueList->AppendCSSValue(first.forget());
4136 0 : valueList->AppendCSSValue(second.forget());
4137 0 : return valueList.forget();
4138 : }
4139 :
4140 : already_AddRefed<CSSValue>
4141 0 : nsComputedDOMStyle::DoGetTextShadow()
4142 : {
4143 0 : return GetCSSShadowArray(StyleText()->mTextShadow,
4144 0 : StyleColor()->mColor,
4145 0 : false);
4146 : }
4147 :
4148 : already_AddRefed<CSSValue>
4149 0 : nsComputedDOMStyle::DoGetTextSizeAdjust()
4150 : {
4151 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4152 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleText()->mTextSizeAdjust,
4153 0 : nsCSSProps::kTextSizeAdjustKTable));
4154 0 : return val.forget();
4155 : }
4156 :
4157 : already_AddRefed<CSSValue>
4158 0 : nsComputedDOMStyle::DoGetTextTransform()
4159 : {
4160 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4161 0 : val->SetIdent(
4162 0 : nsCSSProps::ValueToKeywordEnum(StyleText()->mTextTransform,
4163 0 : nsCSSProps::kTextTransformKTable));
4164 0 : return val.forget();
4165 : }
4166 :
4167 : already_AddRefed<CSSValue>
4168 0 : nsComputedDOMStyle::DoGetTabSize()
4169 : {
4170 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4171 0 : SetValueToCoord(val, StyleText()->mTabSize, true);
4172 0 : return val.forget();
4173 : }
4174 :
4175 : already_AddRefed<CSSValue>
4176 0 : nsComputedDOMStyle::DoGetLetterSpacing()
4177 : {
4178 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4179 0 : SetValueToCoord(val, StyleText()->mLetterSpacing, false);
4180 0 : return val.forget();
4181 : }
4182 :
4183 : already_AddRefed<CSSValue>
4184 0 : nsComputedDOMStyle::DoGetWordSpacing()
4185 : {
4186 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4187 0 : SetValueToCoord(val, StyleText()->mWordSpacing, false);
4188 0 : return val.forget();
4189 : }
4190 :
4191 : already_AddRefed<CSSValue>
4192 0 : nsComputedDOMStyle::DoGetWhiteSpace()
4193 : {
4194 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4195 0 : val->SetIdent(
4196 0 : nsCSSProps::ValueToKeywordEnum(StyleText()->mWhiteSpace,
4197 0 : nsCSSProps::kWhitespaceKTable));
4198 0 : return val.forget();
4199 : }
4200 :
4201 : already_AddRefed<CSSValue>
4202 0 : nsComputedDOMStyle::DoGetWindowDragging()
4203 : {
4204 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4205 0 : val->SetIdent(
4206 0 : nsCSSProps::ValueToKeywordEnum(StyleUIReset()->mWindowDragging,
4207 0 : nsCSSProps::kWindowDraggingKTable));
4208 0 : return val.forget();
4209 : }
4210 :
4211 : already_AddRefed<CSSValue>
4212 0 : nsComputedDOMStyle::DoGetWindowShadow()
4213 : {
4214 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4215 0 : val->SetIdent(
4216 0 : nsCSSProps::ValueToKeywordEnum(StyleUIReset()->mWindowShadow,
4217 0 : nsCSSProps::kWindowShadowKTable));
4218 0 : return val.forget();
4219 : }
4220 :
4221 : already_AddRefed<CSSValue>
4222 0 : nsComputedDOMStyle::DoGetWindowOpacity()
4223 : {
4224 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4225 0 : val->SetNumber(StyleUIReset()->mWindowOpacity);
4226 0 : return val.forget();
4227 : }
4228 :
4229 : already_AddRefed<CSSValue>
4230 0 : nsComputedDOMStyle::DoGetWindowTransform()
4231 : {
4232 0 : const nsStyleUIReset* uiReset = StyleUIReset();
4233 0 : return GetTransformValue(uiReset->mSpecifiedWindowTransform);
4234 : }
4235 :
4236 : already_AddRefed<CSSValue>
4237 0 : nsComputedDOMStyle::DoGetWindowTransformOrigin()
4238 : {
4239 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
4240 :
4241 0 : const nsStyleUIReset* uiReset = StyleUIReset();
4242 :
4243 0 : RefPtr<nsROCSSPrimitiveValue> originX = new nsROCSSPrimitiveValue;
4244 0 : SetValueToCoord(originX, uiReset->mWindowTransformOrigin[0], false,
4245 0 : &nsComputedDOMStyle::GetFrameBoundsWidthForTransform);
4246 0 : valueList->AppendCSSValue(originX.forget());
4247 :
4248 0 : RefPtr<nsROCSSPrimitiveValue> originY = new nsROCSSPrimitiveValue;
4249 0 : SetValueToCoord(originY, uiReset->mWindowTransformOrigin[1], false,
4250 0 : &nsComputedDOMStyle::GetFrameBoundsHeightForTransform);
4251 0 : valueList->AppendCSSValue(originY.forget());
4252 :
4253 0 : return valueList.forget();
4254 : }
4255 :
4256 : already_AddRefed<CSSValue>
4257 0 : nsComputedDOMStyle::DoGetWordBreak()
4258 : {
4259 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4260 0 : val->SetIdent(
4261 0 : nsCSSProps::ValueToKeywordEnum(StyleText()->mWordBreak,
4262 0 : nsCSSProps::kWordBreakKTable));
4263 0 : return val.forget();
4264 : }
4265 :
4266 : already_AddRefed<CSSValue>
4267 0 : nsComputedDOMStyle::DoGetOverflowWrap()
4268 : {
4269 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4270 0 : val->SetIdent(
4271 0 : nsCSSProps::ValueToKeywordEnum(StyleText()->mOverflowWrap,
4272 0 : nsCSSProps::kOverflowWrapKTable));
4273 0 : return val.forget();
4274 : }
4275 :
4276 : already_AddRefed<CSSValue>
4277 0 : nsComputedDOMStyle::DoGetHyphens()
4278 : {
4279 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4280 0 : val->SetIdent(
4281 0 : nsCSSProps::ValueToKeywordEnum(StyleText()->mHyphens,
4282 0 : nsCSSProps::kHyphensKTable));
4283 0 : return val.forget();
4284 : }
4285 :
4286 : already_AddRefed<CSSValue>
4287 0 : nsComputedDOMStyle::DoGetWebkitTextFillColor()
4288 : {
4289 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4290 0 : SetValueFromComplexColor(val, StyleText()->mWebkitTextFillColor);
4291 0 : return val.forget();
4292 : }
4293 :
4294 : already_AddRefed<CSSValue>
4295 0 : nsComputedDOMStyle::DoGetWebkitTextStrokeColor()
4296 : {
4297 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4298 0 : SetValueFromComplexColor(val, StyleText()->mWebkitTextStrokeColor);
4299 0 : return val.forget();
4300 : }
4301 :
4302 : already_AddRefed<CSSValue>
4303 0 : nsComputedDOMStyle::DoGetWebkitTextStrokeWidth()
4304 : {
4305 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4306 0 : val->SetAppUnits(StyleText()->mWebkitTextStrokeWidth);
4307 0 : return val.forget();
4308 : }
4309 :
4310 : already_AddRefed<CSSValue>
4311 0 : nsComputedDOMStyle::DoGetPointerEvents()
4312 : {
4313 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4314 0 : val->SetIdent(
4315 0 : nsCSSProps::ValueToKeywordEnum(StyleUserInterface()->mPointerEvents,
4316 0 : nsCSSProps::kPointerEventsKTable));
4317 0 : return val.forget();
4318 : }
4319 :
4320 : already_AddRefed<CSSValue>
4321 0 : nsComputedDOMStyle::DoGetVisibility()
4322 : {
4323 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4324 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleVisibility()->mVisible,
4325 0 : nsCSSProps::kVisibilityKTable));
4326 0 : return val.forget();
4327 : }
4328 :
4329 : already_AddRefed<CSSValue>
4330 0 : nsComputedDOMStyle::DoGetWritingMode()
4331 : {
4332 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4333 0 : val->SetIdent(
4334 0 : nsCSSProps::ValueToKeywordEnum(StyleVisibility()->mWritingMode,
4335 0 : nsCSSProps::kWritingModeKTable));
4336 0 : return val.forget();
4337 : }
4338 :
4339 : already_AddRefed<CSSValue>
4340 1 : nsComputedDOMStyle::DoGetDirection()
4341 : {
4342 2 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4343 1 : val->SetIdent(
4344 1 : nsCSSProps::ValueToKeywordEnum(StyleVisibility()->mDirection,
4345 1 : nsCSSProps::kDirectionKTable));
4346 2 : return val.forget();
4347 : }
4348 :
4349 : static_assert(NS_STYLE_UNICODE_BIDI_NORMAL == 0,
4350 : "unicode-bidi style constants not as expected");
4351 :
4352 : already_AddRefed<CSSValue>
4353 0 : nsComputedDOMStyle::DoGetUnicodeBidi()
4354 : {
4355 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4356 0 : val->SetIdent(
4357 0 : nsCSSProps::ValueToKeywordEnum(StyleTextReset()->mUnicodeBidi,
4358 0 : nsCSSProps::kUnicodeBidiKTable));
4359 0 : return val.forget();
4360 : }
4361 :
4362 : already_AddRefed<CSSValue>
4363 0 : nsComputedDOMStyle::DoGetCaretColor()
4364 : {
4365 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4366 0 : SetValueFromComplexColor(val, StyleUserInterface()->mCaretColor);
4367 0 : return val.forget();
4368 : }
4369 :
4370 : already_AddRefed<CSSValue>
4371 0 : nsComputedDOMStyle::DoGetCursor()
4372 : {
4373 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
4374 :
4375 0 : const nsStyleUserInterface *ui = StyleUserInterface();
4376 :
4377 0 : for (const nsCursorImage& item : ui->mCursorImages) {
4378 0 : RefPtr<nsDOMCSSValueList> itemList = GetROCSSValueList(false);
4379 :
4380 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4381 0 : SetValueToURLValue(item.mImage->GetImageValue(), val);
4382 0 : itemList->AppendCSSValue(val.forget());
4383 :
4384 0 : if (item.mHaveHotspot) {
4385 0 : RefPtr<nsROCSSPrimitiveValue> valX = new nsROCSSPrimitiveValue;
4386 0 : RefPtr<nsROCSSPrimitiveValue> valY = new nsROCSSPrimitiveValue;
4387 :
4388 0 : valX->SetNumber(item.mHotspotX);
4389 0 : valY->SetNumber(item.mHotspotY);
4390 :
4391 0 : itemList->AppendCSSValue(valX.forget());
4392 0 : itemList->AppendCSSValue(valY.forget());
4393 : }
4394 0 : valueList->AppendCSSValue(itemList.forget());
4395 : }
4396 :
4397 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4398 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(ui->mCursor,
4399 0 : nsCSSProps::kCursorKTable));
4400 0 : valueList->AppendCSSValue(val.forget());
4401 0 : return valueList.forget();
4402 : }
4403 :
4404 : already_AddRefed<CSSValue>
4405 0 : nsComputedDOMStyle::DoGetAppearance()
4406 : {
4407 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4408 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mAppearance,
4409 0 : nsCSSProps::kAppearanceKTable));
4410 0 : return val.forget();
4411 : }
4412 :
4413 :
4414 : already_AddRefed<CSSValue>
4415 0 : nsComputedDOMStyle::DoGetBoxAlign()
4416 : {
4417 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4418 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleXUL()->mBoxAlign,
4419 0 : nsCSSProps::kBoxAlignKTable));
4420 0 : return val.forget();
4421 : }
4422 :
4423 : already_AddRefed<CSSValue>
4424 0 : nsComputedDOMStyle::DoGetBoxDirection()
4425 : {
4426 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4427 0 : val->SetIdent(
4428 0 : nsCSSProps::ValueToKeywordEnum(StyleXUL()->mBoxDirection,
4429 0 : nsCSSProps::kBoxDirectionKTable));
4430 0 : return val.forget();
4431 : }
4432 :
4433 : already_AddRefed<CSSValue>
4434 0 : nsComputedDOMStyle::DoGetBoxFlex()
4435 : {
4436 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4437 0 : val->SetNumber(StyleXUL()->mBoxFlex);
4438 0 : return val.forget();
4439 : }
4440 :
4441 : already_AddRefed<CSSValue>
4442 0 : nsComputedDOMStyle::DoGetBoxOrdinalGroup()
4443 : {
4444 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4445 0 : val->SetNumber(StyleXUL()->mBoxOrdinal);
4446 0 : return val.forget();
4447 : }
4448 :
4449 : already_AddRefed<CSSValue>
4450 0 : nsComputedDOMStyle::DoGetBoxOrient()
4451 : {
4452 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4453 0 : val->SetIdent(
4454 0 : nsCSSProps::ValueToKeywordEnum(StyleXUL()->mBoxOrient,
4455 0 : nsCSSProps::kBoxOrientKTable));
4456 0 : return val.forget();
4457 : }
4458 :
4459 : already_AddRefed<CSSValue>
4460 0 : nsComputedDOMStyle::DoGetBoxPack()
4461 : {
4462 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4463 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleXUL()->mBoxPack,
4464 0 : nsCSSProps::kBoxPackKTable));
4465 0 : return val.forget();
4466 : }
4467 :
4468 : already_AddRefed<CSSValue>
4469 0 : nsComputedDOMStyle::DoGetBoxSizing()
4470 : {
4471 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4472 0 : val->SetIdent(
4473 0 : nsCSSProps::ValueToKeywordEnum(StylePosition()->mBoxSizing,
4474 0 : nsCSSProps::kBoxSizingKTable));
4475 0 : return val.forget();
4476 : }
4477 :
4478 : /* Border image properties */
4479 :
4480 : already_AddRefed<CSSValue>
4481 0 : nsComputedDOMStyle::DoGetBorderImageSource()
4482 : {
4483 0 : const nsStyleBorder* border = StyleBorder();
4484 :
4485 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4486 0 : const nsStyleImage& image = border->mBorderImageSource;
4487 0 : SetValueToStyleImage(image, val);
4488 :
4489 0 : return val.forget();
4490 : }
4491 :
4492 : void
4493 0 : nsComputedDOMStyle::AppendFourSideCoordValues(nsDOMCSSValueList* aList,
4494 : const nsStyleSides& aValues)
4495 : {
4496 0 : const nsStyleCoord& top = aValues.Get(eSideTop);
4497 0 : const nsStyleCoord& right = aValues.Get(eSideRight);
4498 0 : const nsStyleCoord& bottom = aValues.Get(eSideBottom);
4499 0 : const nsStyleCoord& left = aValues.Get(eSideLeft);
4500 :
4501 0 : auto appendValue = [this, aList](const nsStyleCoord& value) {
4502 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4503 0 : SetValueToCoord(val, value, true);
4504 0 : aList->AppendCSSValue(val.forget());
4505 0 : };
4506 0 : appendValue(top);
4507 0 : if (top != right || top != bottom || top != left) {
4508 0 : appendValue(right);
4509 0 : if (top != bottom || right != left) {
4510 0 : appendValue(bottom);
4511 0 : if (right != left) {
4512 0 : appendValue(left);
4513 : }
4514 : }
4515 : }
4516 0 : }
4517 :
4518 : already_AddRefed<CSSValue>
4519 0 : nsComputedDOMStyle::DoGetBorderImageSlice()
4520 : {
4521 0 : const nsStyleBorder* border = StyleBorder();
4522 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
4523 0 : AppendFourSideCoordValues(valueList, border->mBorderImageSlice);
4524 :
4525 : // Fill keyword.
4526 0 : if (NS_STYLE_BORDER_IMAGE_SLICE_FILL == border->mBorderImageFill) {
4527 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4528 0 : val->SetIdent(eCSSKeyword_fill);
4529 0 : valueList->AppendCSSValue(val.forget());
4530 : }
4531 :
4532 0 : return valueList.forget();
4533 : }
4534 :
4535 : already_AddRefed<CSSValue>
4536 0 : nsComputedDOMStyle::DoGetBorderImageWidth()
4537 : {
4538 0 : const nsStyleBorder* border = StyleBorder();
4539 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
4540 0 : AppendFourSideCoordValues(valueList, border->mBorderImageWidth);
4541 0 : return valueList.forget();
4542 : }
4543 :
4544 : already_AddRefed<CSSValue>
4545 0 : nsComputedDOMStyle::DoGetBorderImageOutset()
4546 : {
4547 0 : const nsStyleBorder* border = StyleBorder();
4548 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
4549 0 : AppendFourSideCoordValues(valueList, border->mBorderImageOutset);
4550 0 : return valueList.forget();
4551 : }
4552 :
4553 : already_AddRefed<CSSValue>
4554 0 : nsComputedDOMStyle::DoGetBorderImageRepeat()
4555 : {
4556 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
4557 :
4558 0 : const nsStyleBorder* border = StyleBorder();
4559 :
4560 : // horizontal repeat
4561 0 : RefPtr<nsROCSSPrimitiveValue> valX = new nsROCSSPrimitiveValue;
4562 0 : valX->SetIdent(
4563 0 : nsCSSProps::ValueToKeywordEnum(border->mBorderImageRepeatH,
4564 0 : nsCSSProps::kBorderImageRepeatKTable));
4565 0 : valueList->AppendCSSValue(valX.forget());
4566 :
4567 : // vertical repeat
4568 0 : RefPtr<nsROCSSPrimitiveValue> valY = new nsROCSSPrimitiveValue;
4569 0 : valY->SetIdent(
4570 0 : nsCSSProps::ValueToKeywordEnum(border->mBorderImageRepeatV,
4571 0 : nsCSSProps::kBorderImageRepeatKTable));
4572 0 : valueList->AppendCSSValue(valY.forget());
4573 0 : return valueList.forget();
4574 : }
4575 :
4576 : already_AddRefed<CSSValue>
4577 0 : nsComputedDOMStyle::DoGetFlexBasis()
4578 : {
4579 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4580 :
4581 : // XXXdholbert We could make this more automagic and resolve percentages
4582 : // if we wanted, by passing in a PercentageBaseGetter instead of nullptr
4583 : // below. Logic would go like this:
4584 : // if (i'm a flex item) {
4585 : // if (my flex container is horizontal) {
4586 : // percentageBaseGetter = &nsComputedDOMStyle::GetCBContentWidth;
4587 : // } else {
4588 : // percentageBaseGetter = &nsComputedDOMStyle::GetCBContentHeight;
4589 : // }
4590 : // }
4591 :
4592 0 : SetValueToCoord(val, StylePosition()->mFlexBasis, true,
4593 0 : nullptr, nsCSSProps::kWidthKTable);
4594 0 : return val.forget();
4595 : }
4596 :
4597 : already_AddRefed<CSSValue>
4598 0 : nsComputedDOMStyle::DoGetFlexDirection()
4599 : {
4600 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4601 0 : val->SetIdent(
4602 0 : nsCSSProps::ValueToKeywordEnum(StylePosition()->mFlexDirection,
4603 0 : nsCSSProps::kFlexDirectionKTable));
4604 0 : return val.forget();
4605 : }
4606 :
4607 : already_AddRefed<CSSValue>
4608 0 : nsComputedDOMStyle::DoGetFlexGrow()
4609 : {
4610 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4611 0 : val->SetNumber(StylePosition()->mFlexGrow);
4612 0 : return val.forget();
4613 : }
4614 :
4615 : already_AddRefed<CSSValue>
4616 0 : nsComputedDOMStyle::DoGetFlexShrink()
4617 : {
4618 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4619 0 : val->SetNumber(StylePosition()->mFlexShrink);
4620 0 : return val.forget();
4621 : }
4622 :
4623 : already_AddRefed<CSSValue>
4624 0 : nsComputedDOMStyle::DoGetFlexWrap()
4625 : {
4626 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4627 0 : val->SetIdent(
4628 0 : nsCSSProps::ValueToKeywordEnum(StylePosition()->mFlexWrap,
4629 0 : nsCSSProps::kFlexWrapKTable));
4630 0 : return val.forget();
4631 : }
4632 :
4633 : already_AddRefed<CSSValue>
4634 0 : nsComputedDOMStyle::DoGetOrder()
4635 : {
4636 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4637 0 : val->SetNumber(StylePosition()->mOrder);
4638 0 : return val.forget();
4639 : }
4640 :
4641 : already_AddRefed<CSSValue>
4642 0 : nsComputedDOMStyle::DoGetAlignContent()
4643 : {
4644 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4645 0 : nsAutoString str;
4646 0 : auto align = StylePosition()->mAlignContent;
4647 0 : nsCSSValue::AppendAlignJustifyValueToString(align & NS_STYLE_ALIGN_ALL_BITS, str);
4648 0 : auto fallback = align >> NS_STYLE_ALIGN_ALL_SHIFT;
4649 0 : if (fallback) {
4650 0 : str.Append(' ');
4651 0 : nsCSSValue::AppendAlignJustifyValueToString(fallback, str);
4652 : }
4653 0 : val->SetString(str);
4654 0 : return val.forget();
4655 : }
4656 :
4657 : already_AddRefed<CSSValue>
4658 0 : nsComputedDOMStyle::DoGetAlignItems()
4659 : {
4660 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4661 0 : nsAutoString str;
4662 0 : auto align = StylePosition()->mAlignItems;
4663 0 : nsCSSValue::AppendAlignJustifyValueToString(align, str);
4664 0 : val->SetString(str);
4665 0 : return val.forget();
4666 : }
4667 :
4668 : already_AddRefed<CSSValue>
4669 0 : nsComputedDOMStyle::DoGetAlignSelf()
4670 : {
4671 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4672 0 : nsAutoString str;
4673 0 : auto align = StylePosition()->mAlignSelf;
4674 0 : nsCSSValue::AppendAlignJustifyValueToString(align, str);
4675 0 : val->SetString(str);
4676 0 : return val.forget();
4677 : }
4678 :
4679 : already_AddRefed<CSSValue>
4680 0 : nsComputedDOMStyle::DoGetJustifyContent()
4681 : {
4682 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4683 0 : nsAutoString str;
4684 0 : auto justify = StylePosition()->mJustifyContent;
4685 0 : nsCSSValue::AppendAlignJustifyValueToString(justify & NS_STYLE_JUSTIFY_ALL_BITS, str);
4686 0 : auto fallback = justify >> NS_STYLE_JUSTIFY_ALL_SHIFT;
4687 0 : if (fallback) {
4688 0 : MOZ_ASSERT(nsCSSProps::ValueToKeywordEnum(fallback & ~NS_STYLE_JUSTIFY_FLAG_BITS,
4689 : nsCSSProps::kAlignSelfPosition)
4690 : != eCSSKeyword_UNKNOWN, "unknown fallback value");
4691 0 : str.Append(' ');
4692 0 : nsCSSValue::AppendAlignJustifyValueToString(fallback, str);
4693 : }
4694 0 : val->SetString(str);
4695 0 : return val.forget();
4696 : }
4697 :
4698 : already_AddRefed<CSSValue>
4699 0 : nsComputedDOMStyle::DoGetJustifyItems()
4700 : {
4701 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4702 0 : nsAutoString str;
4703 : auto justify =
4704 0 : StylePosition()->ComputedJustifyItems(mStyleContext->GetParentAllowServo());
4705 0 : nsCSSValue::AppendAlignJustifyValueToString(justify, str);
4706 0 : val->SetString(str);
4707 0 : return val.forget();
4708 : }
4709 :
4710 : already_AddRefed<CSSValue>
4711 0 : nsComputedDOMStyle::DoGetJustifySelf()
4712 : {
4713 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4714 0 : nsAutoString str;
4715 0 : auto justify = StylePosition()->mJustifySelf;
4716 0 : nsCSSValue::AppendAlignJustifyValueToString(justify, str);
4717 0 : val->SetString(str);
4718 0 : return val.forget();
4719 : }
4720 :
4721 : already_AddRefed<CSSValue>
4722 0 : nsComputedDOMStyle::DoGetFloatEdge()
4723 : {
4724 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4725 0 : val->SetIdent(
4726 0 : nsCSSProps::ValueToKeywordEnum(uint8_t(StyleBorder()->mFloatEdge),
4727 0 : nsCSSProps::kFloatEdgeKTable));
4728 0 : return val.forget();
4729 : }
4730 :
4731 : already_AddRefed<CSSValue>
4732 0 : nsComputedDOMStyle::DoGetForceBrokenImageIcon()
4733 : {
4734 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4735 0 : val->SetNumber(StyleUIReset()->mForceBrokenImageIcon);
4736 0 : return val.forget();
4737 : }
4738 :
4739 : already_AddRefed<CSSValue>
4740 0 : nsComputedDOMStyle::DoGetImageOrientation()
4741 : {
4742 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4743 0 : nsAutoString string;
4744 0 : nsStyleImageOrientation orientation = StyleVisibility()->mImageOrientation;
4745 :
4746 0 : if (orientation.IsFromImage()) {
4747 0 : string.AppendLiteral("from-image");
4748 : } else {
4749 0 : nsStyleUtil::AppendAngleValue(orientation.AngleAsCoord(), string);
4750 :
4751 0 : if (orientation.IsFlipped()) {
4752 0 : string.AppendLiteral(" flip");
4753 : }
4754 : }
4755 :
4756 0 : val->SetString(string);
4757 0 : return val.forget();
4758 : }
4759 :
4760 : already_AddRefed<CSSValue>
4761 0 : nsComputedDOMStyle::DoGetIMEMode()
4762 : {
4763 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4764 0 : val->SetIdent(
4765 0 : nsCSSProps::ValueToKeywordEnum(StyleUIReset()->mIMEMode,
4766 0 : nsCSSProps::kIMEModeKTable));
4767 0 : return val.forget();
4768 : }
4769 :
4770 : already_AddRefed<CSSValue>
4771 0 : nsComputedDOMStyle::DoGetUserFocus()
4772 : {
4773 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4774 0 : val->SetIdent(
4775 0 : nsCSSProps::ValueToKeywordEnum(uint8_t(StyleUserInterface()->mUserFocus),
4776 0 : nsCSSProps::kUserFocusKTable));
4777 0 : return val.forget();
4778 : }
4779 :
4780 : already_AddRefed<CSSValue>
4781 0 : nsComputedDOMStyle::DoGetUserInput()
4782 : {
4783 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4784 0 : val->SetIdent(
4785 0 : nsCSSProps::ValueToKeywordEnum(StyleUserInterface()->mUserInput,
4786 0 : nsCSSProps::kUserInputKTable));
4787 0 : return val.forget();
4788 : }
4789 :
4790 : already_AddRefed<CSSValue>
4791 0 : nsComputedDOMStyle::DoGetUserModify()
4792 : {
4793 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4794 0 : val->SetIdent(
4795 0 : nsCSSProps::ValueToKeywordEnum(StyleUserInterface()->mUserModify,
4796 0 : nsCSSProps::kUserModifyKTable));
4797 0 : return val.forget();
4798 : }
4799 :
4800 : already_AddRefed<CSSValue>
4801 0 : nsComputedDOMStyle::DoGetUserSelect()
4802 : {
4803 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4804 0 : val->SetIdent(
4805 0 : nsCSSProps::ValueToKeywordEnum(StyleUIReset()->mUserSelect,
4806 0 : nsCSSProps::kUserSelectKTable));
4807 0 : return val.forget();
4808 : }
4809 :
4810 : already_AddRefed<CSSValue>
4811 0 : nsComputedDOMStyle::DoGetDisplay()
4812 : {
4813 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4814 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mDisplay,
4815 0 : nsCSSProps::kDisplayKTable));
4816 0 : return val.forget();
4817 : }
4818 :
4819 : already_AddRefed<CSSValue>
4820 0 : nsComputedDOMStyle::DoGetContain()
4821 : {
4822 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4823 :
4824 0 : int32_t mask = StyleDisplay()->mContain;
4825 :
4826 0 : if (mask == 0) {
4827 0 : val->SetIdent(eCSSKeyword_none);
4828 0 : } else if (mask & NS_STYLE_CONTAIN_STRICT) {
4829 0 : NS_ASSERTION(mask == (NS_STYLE_CONTAIN_STRICT | NS_STYLE_CONTAIN_ALL_BITS),
4830 : "contain: strict should imply contain: layout style paint");
4831 0 : val->SetIdent(eCSSKeyword_strict);
4832 : } else {
4833 0 : nsAutoString valueStr;
4834 :
4835 : nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_contain,
4836 : mask, NS_STYLE_CONTAIN_LAYOUT,
4837 0 : NS_STYLE_CONTAIN_PAINT, valueStr);
4838 0 : val->SetString(valueStr);
4839 : }
4840 :
4841 0 : return val.forget();
4842 : }
4843 :
4844 : already_AddRefed<CSSValue>
4845 0 : nsComputedDOMStyle::DoGetPosition()
4846 : {
4847 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4848 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mPosition,
4849 0 : nsCSSProps::kPositionKTable));
4850 0 : return val.forget();
4851 : }
4852 :
4853 : already_AddRefed<CSSValue>
4854 0 : nsComputedDOMStyle::DoGetClip()
4855 : {
4856 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4857 :
4858 0 : const nsStyleEffects* effects = StyleEffects();
4859 :
4860 0 : if (effects->mClipFlags == NS_STYLE_CLIP_AUTO) {
4861 0 : val->SetIdent(eCSSKeyword_auto);
4862 : } else {
4863 : // create the cssvalues for the sides, stick them in the rect object
4864 0 : nsROCSSPrimitiveValue *topVal = new nsROCSSPrimitiveValue;
4865 0 : nsROCSSPrimitiveValue *rightVal = new nsROCSSPrimitiveValue;
4866 0 : nsROCSSPrimitiveValue *bottomVal = new nsROCSSPrimitiveValue;
4867 0 : nsROCSSPrimitiveValue *leftVal = new nsROCSSPrimitiveValue;
4868 : nsDOMCSSRect * domRect = new nsDOMCSSRect(topVal, rightVal,
4869 0 : bottomVal, leftVal);
4870 0 : if (effects->mClipFlags & NS_STYLE_CLIP_TOP_AUTO) {
4871 0 : topVal->SetIdent(eCSSKeyword_auto);
4872 : } else {
4873 0 : topVal->SetAppUnits(effects->mClip.y);
4874 : }
4875 :
4876 0 : if (effects->mClipFlags & NS_STYLE_CLIP_RIGHT_AUTO) {
4877 0 : rightVal->SetIdent(eCSSKeyword_auto);
4878 : } else {
4879 0 : rightVal->SetAppUnits(effects->mClip.width + effects->mClip.x);
4880 : }
4881 :
4882 0 : if (effects->mClipFlags & NS_STYLE_CLIP_BOTTOM_AUTO) {
4883 0 : bottomVal->SetIdent(eCSSKeyword_auto);
4884 : } else {
4885 0 : bottomVal->SetAppUnits(effects->mClip.height + effects->mClip.y);
4886 : }
4887 :
4888 0 : if (effects->mClipFlags & NS_STYLE_CLIP_LEFT_AUTO) {
4889 0 : leftVal->SetIdent(eCSSKeyword_auto);
4890 : } else {
4891 0 : leftVal->SetAppUnits(effects->mClip.x);
4892 : }
4893 0 : val->SetRect(domRect);
4894 : }
4895 :
4896 0 : return val.forget();
4897 : }
4898 :
4899 : already_AddRefed<CSSValue>
4900 0 : nsComputedDOMStyle::DoGetWillChange()
4901 : {
4902 0 : const nsCOMArray<nsIAtom>& willChange = StyleDisplay()->mWillChange;
4903 :
4904 0 : if (willChange.IsEmpty()) {
4905 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4906 0 : val->SetIdent(eCSSKeyword_auto);
4907 0 : return val.forget();
4908 : }
4909 :
4910 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
4911 0 : for (const nsIAtom* ident : willChange) {
4912 0 : RefPtr<nsROCSSPrimitiveValue> property = new nsROCSSPrimitiveValue;
4913 0 : property->SetString(nsDependentAtomString(ident));
4914 0 : valueList->AppendCSSValue(property.forget());
4915 : }
4916 :
4917 0 : return valueList.forget();
4918 : }
4919 :
4920 : already_AddRefed<CSSValue>
4921 0 : nsComputedDOMStyle::DoGetOverflow()
4922 : {
4923 0 : const nsStyleDisplay* display = StyleDisplay();
4924 :
4925 0 : if (display->mOverflowX != display->mOverflowY) {
4926 : // No value to return. We can't express this combination of
4927 : // values as a shorthand.
4928 0 : return nullptr;
4929 : }
4930 :
4931 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4932 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(display->mOverflowX,
4933 0 : nsCSSProps::kOverflowKTable));
4934 0 : return val.forget();
4935 : }
4936 :
4937 : already_AddRefed<CSSValue>
4938 0 : nsComputedDOMStyle::DoGetOverflowX()
4939 : {
4940 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4941 0 : val->SetIdent(
4942 0 : nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mOverflowX,
4943 0 : nsCSSProps::kOverflowSubKTable));
4944 0 : return val.forget();
4945 : }
4946 :
4947 : already_AddRefed<CSSValue>
4948 0 : nsComputedDOMStyle::DoGetOverflowY()
4949 : {
4950 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4951 0 : val->SetIdent(
4952 0 : nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mOverflowY,
4953 0 : nsCSSProps::kOverflowSubKTable));
4954 0 : return val.forget();
4955 : }
4956 :
4957 : already_AddRefed<CSSValue>
4958 0 : nsComputedDOMStyle::DoGetOverflowClipBox()
4959 : {
4960 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4961 0 : val->SetIdent(
4962 0 : nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mOverflowClipBox,
4963 0 : nsCSSProps::kOverflowClipBoxKTable));
4964 0 : return val.forget();
4965 : }
4966 :
4967 : already_AddRefed<CSSValue>
4968 0 : nsComputedDOMStyle::DoGetResize()
4969 : {
4970 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4971 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mResize,
4972 0 : nsCSSProps::kResizeKTable));
4973 0 : return val.forget();
4974 : }
4975 :
4976 :
4977 : already_AddRefed<CSSValue>
4978 0 : nsComputedDOMStyle::DoGetPageBreakAfter()
4979 : {
4980 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4981 :
4982 0 : const nsStyleDisplay *display = StyleDisplay();
4983 :
4984 0 : if (display->mBreakAfter) {
4985 0 : val->SetIdent(eCSSKeyword_always);
4986 : } else {
4987 0 : val->SetIdent(eCSSKeyword_auto);
4988 : }
4989 :
4990 0 : return val.forget();
4991 : }
4992 :
4993 : already_AddRefed<CSSValue>
4994 0 : nsComputedDOMStyle::DoGetPageBreakBefore()
4995 : {
4996 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
4997 :
4998 0 : const nsStyleDisplay *display = StyleDisplay();
4999 :
5000 0 : if (display->mBreakBefore) {
5001 0 : val->SetIdent(eCSSKeyword_always);
5002 : } else {
5003 0 : val->SetIdent(eCSSKeyword_auto);
5004 : }
5005 :
5006 0 : return val.forget();
5007 : }
5008 :
5009 : already_AddRefed<CSSValue>
5010 0 : nsComputedDOMStyle::DoGetPageBreakInside()
5011 : {
5012 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5013 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mBreakInside,
5014 0 : nsCSSProps::kPageBreakInsideKTable));
5015 0 : return val.forget();
5016 : }
5017 :
5018 : already_AddRefed<CSSValue>
5019 0 : nsComputedDOMStyle::DoGetTouchAction()
5020 : {
5021 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5022 :
5023 0 : int32_t intValue = StyleDisplay()->mTouchAction;
5024 :
5025 : // None and Auto and Manipulation values aren't allowed
5026 : // to be in conjunction with other values.
5027 : // But there are all checks in CSSParserImpl::ParseTouchAction
5028 0 : nsAutoString valueStr;
5029 : nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_touch_action, intValue,
5030 : NS_STYLE_TOUCH_ACTION_NONE, NS_STYLE_TOUCH_ACTION_MANIPULATION,
5031 0 : valueStr);
5032 0 : val->SetString(valueStr);
5033 0 : return val.forget();
5034 : }
5035 :
5036 : already_AddRefed<CSSValue>
5037 0 : nsComputedDOMStyle::DoGetHeight()
5038 : {
5039 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5040 :
5041 0 : bool calcHeight = false;
5042 :
5043 0 : if (mInnerFrame) {
5044 0 : calcHeight = true;
5045 :
5046 0 : const nsStyleDisplay* displayData = StyleDisplay();
5047 0 : if (displayData->mDisplay == mozilla::StyleDisplay::Inline &&
5048 0 : !(mInnerFrame->IsFrameOfType(nsIFrame::eReplaced)) &&
5049 : // An outer SVG frame should behave the same as eReplaced in this case
5050 0 : !mInnerFrame->IsSVGOuterSVGFrame()) {
5051 :
5052 0 : calcHeight = false;
5053 : }
5054 : }
5055 :
5056 0 : if (calcHeight) {
5057 0 : AssertFlushedPendingReflows();
5058 0 : nsMargin adjustedValues = GetAdjustedValuesForBoxSizing();
5059 0 : val->SetAppUnits(mInnerFrame->GetContentRect().height +
5060 0 : adjustedValues.TopBottom());
5061 : } else {
5062 0 : const nsStylePosition *positionData = StylePosition();
5063 :
5064 : nscoord minHeight =
5065 0 : StyleCoordToNSCoord(positionData->mMinHeight,
5066 0 : &nsComputedDOMStyle::GetCBContentHeight, 0, true);
5067 :
5068 : nscoord maxHeight =
5069 0 : StyleCoordToNSCoord(positionData->mMaxHeight,
5070 : &nsComputedDOMStyle::GetCBContentHeight,
5071 0 : nscoord_MAX, true);
5072 :
5073 0 : SetValueToCoord(val, positionData->mHeight, true, nullptr,
5074 0 : nsCSSProps::kWidthKTable, minHeight, maxHeight);
5075 : }
5076 :
5077 0 : return val.forget();
5078 : }
5079 :
5080 : already_AddRefed<CSSValue>
5081 0 : nsComputedDOMStyle::DoGetWidth()
5082 : {
5083 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5084 :
5085 0 : bool calcWidth = false;
5086 :
5087 0 : if (mInnerFrame) {
5088 0 : calcWidth = true;
5089 :
5090 0 : const nsStyleDisplay *displayData = StyleDisplay();
5091 0 : if (displayData->mDisplay == mozilla::StyleDisplay::Inline &&
5092 0 : !(mInnerFrame->IsFrameOfType(nsIFrame::eReplaced)) &&
5093 : // An outer SVG frame should behave the same as eReplaced in this case
5094 0 : !mInnerFrame->IsSVGOuterSVGFrame()) {
5095 :
5096 0 : calcWidth = false;
5097 : }
5098 : }
5099 :
5100 0 : if (calcWidth) {
5101 0 : AssertFlushedPendingReflows();
5102 0 : nsMargin adjustedValues = GetAdjustedValuesForBoxSizing();
5103 0 : val->SetAppUnits(mInnerFrame->GetContentRect().width +
5104 0 : adjustedValues.LeftRight());
5105 : } else {
5106 0 : const nsStylePosition *positionData = StylePosition();
5107 :
5108 : nscoord minWidth =
5109 0 : StyleCoordToNSCoord(positionData->mMinWidth,
5110 0 : &nsComputedDOMStyle::GetCBContentWidth, 0, true);
5111 :
5112 : nscoord maxWidth =
5113 0 : StyleCoordToNSCoord(positionData->mMaxWidth,
5114 : &nsComputedDOMStyle::GetCBContentWidth,
5115 0 : nscoord_MAX, true);
5116 :
5117 0 : SetValueToCoord(val, positionData->mWidth, true, nullptr,
5118 0 : nsCSSProps::kWidthKTable, minWidth, maxWidth);
5119 : }
5120 :
5121 0 : return val.forget();
5122 : }
5123 :
5124 : already_AddRefed<CSSValue>
5125 0 : nsComputedDOMStyle::DoGetMaxHeight()
5126 : {
5127 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5128 0 : SetValueToCoord(val, StylePosition()->mMaxHeight, true,
5129 0 : nullptr, nsCSSProps::kWidthKTable);
5130 0 : return val.forget();
5131 : }
5132 :
5133 : already_AddRefed<CSSValue>
5134 0 : nsComputedDOMStyle::DoGetMaxWidth()
5135 : {
5136 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5137 0 : SetValueToCoord(val, StylePosition()->mMaxWidth, true,
5138 0 : nullptr, nsCSSProps::kWidthKTable);
5139 0 : return val.forget();
5140 : }
5141 :
5142 : bool
5143 0 : nsComputedDOMStyle::ShouldHonorMinSizeAutoInAxis(PhysicalAxis aAxis)
5144 : {
5145 : // A {flex,grid} item's min-{width|height} "auto" value gets special
5146 : // treatment in getComputedStyle().
5147 : // https://drafts.csswg.org/css-flexbox-1/#valdef-min-width-auto
5148 : // https://drafts.csswg.org/css-grid/#min-size-auto
5149 : // In most cases, "min-{width|height}: auto" is mapped to "0px", unless
5150 : // we're a flex item (and the min-size is in the flex container's main
5151 : // axis), or we're a grid item, AND we also have overflow:visible.
5152 :
5153 : // Note: We only need to bother checking one "overflow" subproperty for
5154 : // "visible", because a non-"visible" value in either axis would force the
5155 : // other axis to also be non-"visible" as well.
5156 :
5157 0 : if (mOuterFrame) {
5158 0 : nsIFrame* containerFrame = mOuterFrame->GetParent();
5159 0 : if (containerFrame &&
5160 0 : StyleDisplay()->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE) {
5161 0 : if (containerFrame->IsFlexContainerFrame() &&
5162 0 : (static_cast<nsFlexContainerFrame*>(containerFrame)->IsHorizontal() ==
5163 0 : (aAxis == eAxisHorizontal))) {
5164 0 : return true;
5165 : }
5166 0 : if (containerFrame->IsGridContainerFrame()) {
5167 0 : return true;
5168 : }
5169 : }
5170 : }
5171 0 : return false;
5172 : }
5173 :
5174 : already_AddRefed<CSSValue>
5175 0 : nsComputedDOMStyle::DoGetMinHeight()
5176 : {
5177 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5178 0 : nsStyleCoord minHeight = StylePosition()->mMinHeight;
5179 :
5180 0 : if (eStyleUnit_Auto == minHeight.GetUnit() &&
5181 0 : !ShouldHonorMinSizeAutoInAxis(eAxisVertical)) {
5182 0 : minHeight.SetCoordValue(0);
5183 : }
5184 :
5185 0 : SetValueToCoord(val, minHeight, true, nullptr, nsCSSProps::kWidthKTable);
5186 0 : return val.forget();
5187 : }
5188 :
5189 : already_AddRefed<CSSValue>
5190 0 : nsComputedDOMStyle::DoGetMinWidth()
5191 : {
5192 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5193 :
5194 0 : nsStyleCoord minWidth = StylePosition()->mMinWidth;
5195 :
5196 0 : if (eStyleUnit_Auto == minWidth.GetUnit() &&
5197 0 : !ShouldHonorMinSizeAutoInAxis(eAxisHorizontal)) {
5198 0 : minWidth.SetCoordValue(0);
5199 : }
5200 :
5201 0 : SetValueToCoord(val, minWidth, true, nullptr, nsCSSProps::kWidthKTable);
5202 0 : return val.forget();
5203 : }
5204 :
5205 : already_AddRefed<CSSValue>
5206 0 : nsComputedDOMStyle::DoGetMixBlendMode()
5207 : {
5208 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5209 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleEffects()->mMixBlendMode,
5210 0 : nsCSSProps::kBlendModeKTable));
5211 0 : return val.forget();
5212 : }
5213 :
5214 : already_AddRefed<CSSValue>
5215 0 : nsComputedDOMStyle::DoGetIsolation()
5216 : {
5217 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5218 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mIsolation,
5219 0 : nsCSSProps::kIsolationKTable));
5220 0 : return val.forget();
5221 : }
5222 :
5223 : already_AddRefed<CSSValue>
5224 0 : nsComputedDOMStyle::DoGetObjectFit()
5225 : {
5226 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5227 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StylePosition()->mObjectFit,
5228 0 : nsCSSProps::kObjectFitKTable));
5229 0 : return val.forget();
5230 : }
5231 :
5232 : already_AddRefed<CSSValue>
5233 0 : nsComputedDOMStyle::DoGetObjectPosition()
5234 : {
5235 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
5236 0 : SetValueToPosition(StylePosition()->mObjectPosition, valueList);
5237 0 : return valueList.forget();
5238 : }
5239 :
5240 : already_AddRefed<CSSValue>
5241 0 : nsComputedDOMStyle::DoGetLeft()
5242 : {
5243 0 : return GetOffsetWidthFor(eSideLeft);
5244 : }
5245 :
5246 : already_AddRefed<CSSValue>
5247 0 : nsComputedDOMStyle::DoGetRight()
5248 : {
5249 0 : return GetOffsetWidthFor(eSideRight);
5250 : }
5251 :
5252 : already_AddRefed<CSSValue>
5253 0 : nsComputedDOMStyle::DoGetTop()
5254 : {
5255 0 : return GetOffsetWidthFor(eSideTop);
5256 : }
5257 :
5258 : already_AddRefed<CSSValue>
5259 0 : nsComputedDOMStyle::GetOffsetWidthFor(mozilla::Side aSide)
5260 : {
5261 0 : const nsStyleDisplay* display = StyleDisplay();
5262 :
5263 0 : AssertFlushedPendingReflows();
5264 :
5265 0 : uint8_t position = display->mPosition;
5266 0 : if (!mOuterFrame) {
5267 : // GetRelativeOffset and GetAbsoluteOffset don't handle elements
5268 : // without frames in any sensible way. GetStaticOffset, however,
5269 : // is perfect for that case.
5270 0 : position = NS_STYLE_POSITION_STATIC;
5271 : }
5272 :
5273 0 : switch (position) {
5274 : case NS_STYLE_POSITION_STATIC:
5275 0 : return GetStaticOffset(aSide);
5276 : case NS_STYLE_POSITION_RELATIVE:
5277 0 : return GetRelativeOffset(aSide);
5278 : case NS_STYLE_POSITION_STICKY:
5279 0 : return GetStickyOffset(aSide);
5280 : case NS_STYLE_POSITION_ABSOLUTE:
5281 : case NS_STYLE_POSITION_FIXED:
5282 0 : return GetAbsoluteOffset(aSide);
5283 : default:
5284 0 : NS_ERROR("Invalid position");
5285 0 : return nullptr;
5286 : }
5287 : }
5288 :
5289 : already_AddRefed<CSSValue>
5290 0 : nsComputedDOMStyle::GetAbsoluteOffset(mozilla::Side aSide)
5291 : {
5292 0 : MOZ_ASSERT(mOuterFrame, "need a frame, so we can call GetContainingBlock()");
5293 :
5294 0 : nsIFrame* container = mOuterFrame->GetContainingBlock();
5295 0 : nsMargin margin = mOuterFrame->GetUsedMargin();
5296 0 : nsMargin border = container->GetUsedBorder();
5297 0 : nsMargin scrollbarSizes(0, 0, 0, 0);
5298 0 : nsRect rect = mOuterFrame->GetRect();
5299 0 : nsRect containerRect = container->GetRect();
5300 :
5301 0 : if (container->IsViewportFrame()) {
5302 : // For absolutely positioned frames scrollbars are taken into
5303 : // account by virtue of getting a containing block that does
5304 : // _not_ include the scrollbars. For fixed positioned frames,
5305 : // the containing block is the viewport, which _does_ include
5306 : // scrollbars. We have to do some extra work.
5307 : // the first child in the default frame list is what we want
5308 0 : nsIFrame* scrollingChild = container->PrincipalChildList().FirstChild();
5309 0 : nsIScrollableFrame *scrollFrame = do_QueryFrame(scrollingChild);
5310 0 : if (scrollFrame) {
5311 0 : scrollbarSizes = scrollFrame->GetActualScrollbarSizes();
5312 : }
5313 : }
5314 :
5315 0 : nscoord offset = 0;
5316 0 : switch (aSide) {
5317 : case eSideTop:
5318 0 : offset = rect.y - margin.top - border.top - scrollbarSizes.top;
5319 :
5320 0 : break;
5321 : case eSideRight:
5322 0 : offset = containerRect.width - rect.width -
5323 0 : rect.x - margin.right - border.right - scrollbarSizes.right;
5324 :
5325 0 : break;
5326 : case eSideBottom:
5327 0 : offset = containerRect.height - rect.height -
5328 0 : rect.y - margin.bottom - border.bottom - scrollbarSizes.bottom;
5329 :
5330 0 : break;
5331 : case eSideLeft:
5332 0 : offset = rect.x - margin.left - border.left - scrollbarSizes.left;
5333 :
5334 0 : break;
5335 : default:
5336 0 : NS_ERROR("Invalid side");
5337 0 : break;
5338 : }
5339 :
5340 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5341 0 : val->SetAppUnits(offset);
5342 0 : return val.forget();
5343 : }
5344 :
5345 : static_assert(eSideTop == 0 && eSideRight == 1 &&
5346 : eSideBottom == 2 && eSideLeft == 3,
5347 : "box side constants not as expected for NS_OPPOSITE_SIDE");
5348 : #define NS_OPPOSITE_SIDE(s_) mozilla::Side(((s_) + 2) & 3)
5349 :
5350 : already_AddRefed<CSSValue>
5351 0 : nsComputedDOMStyle::GetRelativeOffset(mozilla::Side aSide)
5352 : {
5353 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5354 :
5355 0 : const nsStylePosition* positionData = StylePosition();
5356 0 : int32_t sign = 1;
5357 0 : nsStyleCoord coord = positionData->mOffset.Get(aSide);
5358 :
5359 0 : NS_ASSERTION(coord.GetUnit() == eStyleUnit_Coord ||
5360 : coord.GetUnit() == eStyleUnit_Percent ||
5361 : coord.GetUnit() == eStyleUnit_Auto ||
5362 : coord.IsCalcUnit(),
5363 : "Unexpected unit");
5364 :
5365 0 : if (coord.GetUnit() == eStyleUnit_Auto) {
5366 0 : coord = positionData->mOffset.Get(NS_OPPOSITE_SIDE(aSide));
5367 0 : sign = -1;
5368 : }
5369 : PercentageBaseGetter baseGetter;
5370 0 : if (aSide == eSideLeft || aSide == eSideRight) {
5371 0 : baseGetter = &nsComputedDOMStyle::GetCBContentWidth;
5372 : } else {
5373 0 : baseGetter = &nsComputedDOMStyle::GetCBContentHeight;
5374 : }
5375 :
5376 0 : val->SetAppUnits(sign * StyleCoordToNSCoord(coord, baseGetter, 0, false));
5377 0 : return val.forget();
5378 : }
5379 :
5380 : already_AddRefed<CSSValue>
5381 0 : nsComputedDOMStyle::GetStickyOffset(mozilla::Side aSide)
5382 : {
5383 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5384 :
5385 0 : const nsStylePosition* positionData = StylePosition();
5386 0 : nsStyleCoord coord = positionData->mOffset.Get(aSide);
5387 :
5388 0 : NS_ASSERTION(coord.GetUnit() == eStyleUnit_Coord ||
5389 : coord.GetUnit() == eStyleUnit_Percent ||
5390 : coord.GetUnit() == eStyleUnit_Auto ||
5391 : coord.IsCalcUnit(),
5392 : "Unexpected unit");
5393 :
5394 0 : if (coord.GetUnit() == eStyleUnit_Auto) {
5395 0 : val->SetIdent(eCSSKeyword_auto);
5396 0 : return val.forget();
5397 : }
5398 : PercentageBaseGetter baseGetter;
5399 0 : if (aSide == eSideLeft || aSide == eSideRight) {
5400 0 : baseGetter = &nsComputedDOMStyle::GetScrollFrameContentWidth;
5401 : } else {
5402 0 : baseGetter = &nsComputedDOMStyle::GetScrollFrameContentHeight;
5403 : }
5404 :
5405 0 : val->SetAppUnits(StyleCoordToNSCoord(coord, baseGetter, 0, false));
5406 0 : return val.forget();
5407 : }
5408 :
5409 :
5410 : already_AddRefed<CSSValue>
5411 0 : nsComputedDOMStyle::GetStaticOffset(mozilla::Side aSide)
5412 :
5413 : {
5414 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5415 0 : SetValueToCoord(val, StylePosition()->mOffset.Get(aSide), false);
5416 0 : return val.forget();
5417 : }
5418 :
5419 : already_AddRefed<CSSValue>
5420 0 : nsComputedDOMStyle::GetPaddingWidthFor(mozilla::Side aSide)
5421 : {
5422 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5423 :
5424 0 : if (!mInnerFrame) {
5425 0 : SetValueToCoord(val, StylePadding()->mPadding.Get(aSide), true);
5426 : } else {
5427 0 : AssertFlushedPendingReflows();
5428 :
5429 0 : val->SetAppUnits(mInnerFrame->GetUsedPadding().Side(aSide));
5430 : }
5431 :
5432 0 : return val.forget();
5433 : }
5434 :
5435 : bool
5436 0 : nsComputedDOMStyle::GetLineHeightCoord(nscoord& aCoord)
5437 : {
5438 0 : AssertFlushedPendingReflows();
5439 :
5440 0 : nscoord blockHeight = NS_AUTOHEIGHT;
5441 0 : if (StyleText()->mLineHeight.GetUnit() == eStyleUnit_Enumerated) {
5442 0 : if (!mInnerFrame)
5443 0 : return false;
5444 :
5445 0 : if (nsLayoutUtils::IsNonWrapperBlock(mInnerFrame)) {
5446 0 : blockHeight = mInnerFrame->GetContentRect().height;
5447 : } else {
5448 0 : GetCBContentHeight(blockHeight);
5449 : }
5450 : }
5451 :
5452 : // lie about font size inflation since we lie about font size (since
5453 : // the inflation only applies to text)
5454 0 : aCoord = ReflowInput::CalcLineHeight(mContent, mStyleContext,
5455 : blockHeight, 1.0f);
5456 :
5457 : // CalcLineHeight uses font->mFont.size, but we want to use
5458 : // font->mSize as the font size. Adjust for that. Also adjust for
5459 : // the text zoom, if any.
5460 0 : const nsStyleFont* font = StyleFont();
5461 0 : float fCoord = float(aCoord);
5462 0 : if (font->mAllowZoom) {
5463 0 : fCoord /= mPresShell->GetPresContext()->EffectiveTextZoom();
5464 : }
5465 0 : if (font->mFont.size != font->mSize) {
5466 0 : fCoord = fCoord * (float(font->mSize) / float(font->mFont.size));
5467 : }
5468 0 : aCoord = NSToCoordRound(fCoord);
5469 :
5470 0 : return true;
5471 : }
5472 :
5473 : already_AddRefed<CSSValue>
5474 0 : nsComputedDOMStyle::GetBorderColorsFor(mozilla::Side aSide)
5475 : {
5476 0 : const nsStyleBorder *border = StyleBorder();
5477 :
5478 0 : if (border->mBorderColors) {
5479 0 : nsBorderColors* borderColors = border->mBorderColors[aSide];
5480 0 : if (borderColors) {
5481 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
5482 :
5483 0 : do {
5484 0 : RefPtr<nsROCSSPrimitiveValue> primitive = new nsROCSSPrimitiveValue;
5485 :
5486 0 : SetToRGBAColor(primitive, borderColors->mColor);
5487 :
5488 0 : valueList->AppendCSSValue(primitive.forget());
5489 0 : borderColors = borderColors->mNext;
5490 0 : } while (borderColors);
5491 :
5492 0 : return valueList.forget();
5493 : }
5494 : }
5495 :
5496 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5497 0 : val->SetIdent(eCSSKeyword_none);
5498 0 : return val.forget();
5499 : }
5500 :
5501 : already_AddRefed<CSSValue>
5502 0 : nsComputedDOMStyle::GetBorderWidthFor(mozilla::Side aSide)
5503 : {
5504 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5505 :
5506 : nscoord width;
5507 0 : if (mInnerFrame) {
5508 0 : AssertFlushedPendingReflows();
5509 0 : width = mInnerFrame->GetUsedBorder().Side(aSide);
5510 : } else {
5511 0 : width = StyleBorder()->GetComputedBorderWidth(aSide);
5512 : }
5513 0 : val->SetAppUnits(width);
5514 :
5515 0 : return val.forget();
5516 : }
5517 :
5518 : already_AddRefed<CSSValue>
5519 0 : nsComputedDOMStyle::GetBorderColorFor(mozilla::Side aSide)
5520 : {
5521 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5522 0 : SetValueFromComplexColor(val, StyleBorder()->mBorderColor[aSide]);
5523 0 : return val.forget();
5524 : }
5525 :
5526 : already_AddRefed<CSSValue>
5527 0 : nsComputedDOMStyle::GetMarginWidthFor(mozilla::Side aSide)
5528 : {
5529 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5530 :
5531 0 : if (!mInnerFrame) {
5532 0 : SetValueToCoord(val, StyleMargin()->mMargin.Get(aSide), false);
5533 : } else {
5534 0 : AssertFlushedPendingReflows();
5535 :
5536 : // For tables, GetUsedMargin always returns an empty margin, so we
5537 : // should read the margin from the table wrapper frame instead.
5538 0 : val->SetAppUnits(mOuterFrame->GetUsedMargin().Side(aSide));
5539 0 : NS_ASSERTION(mOuterFrame == mInnerFrame ||
5540 : mInnerFrame->GetUsedMargin() == nsMargin(0, 0, 0, 0),
5541 : "Inner tables must have zero margins");
5542 : }
5543 :
5544 0 : return val.forget();
5545 : }
5546 :
5547 : already_AddRefed<CSSValue>
5548 0 : nsComputedDOMStyle::GetBorderStyleFor(mozilla::Side aSide)
5549 : {
5550 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5551 0 : val->SetIdent(
5552 0 : nsCSSProps::ValueToKeywordEnum(StyleBorder()->GetBorderStyle(aSide),
5553 0 : nsCSSProps::kBorderStyleKTable));
5554 0 : return val.forget();
5555 : }
5556 :
5557 : void
5558 0 : nsComputedDOMStyle::SetValueToCoord(nsROCSSPrimitiveValue* aValue,
5559 : const nsStyleCoord& aCoord,
5560 : bool aClampNegativeCalc,
5561 : PercentageBaseGetter aPercentageBaseGetter,
5562 : const KTableEntry aTable[],
5563 : nscoord aMinAppUnits,
5564 : nscoord aMaxAppUnits)
5565 : {
5566 0 : NS_PRECONDITION(aValue, "Must have a value to work with");
5567 :
5568 0 : switch (aCoord.GetUnit()) {
5569 : case eStyleUnit_Normal:
5570 0 : aValue->SetIdent(eCSSKeyword_normal);
5571 0 : break;
5572 :
5573 : case eStyleUnit_Auto:
5574 0 : aValue->SetIdent(eCSSKeyword_auto);
5575 0 : break;
5576 :
5577 : case eStyleUnit_Percent:
5578 : {
5579 : nscoord percentageBase;
5580 0 : if (aPercentageBaseGetter &&
5581 0 : (this->*aPercentageBaseGetter)(percentageBase)) {
5582 0 : nscoord val = NSCoordSaturatingMultiply(percentageBase,
5583 0 : aCoord.GetPercentValue());
5584 0 : aValue->SetAppUnits(std::max(aMinAppUnits, std::min(val, aMaxAppUnits)));
5585 : } else {
5586 0 : aValue->SetPercent(aCoord.GetPercentValue());
5587 : }
5588 : }
5589 0 : break;
5590 :
5591 : case eStyleUnit_Factor:
5592 0 : aValue->SetNumber(aCoord.GetFactorValue());
5593 0 : break;
5594 :
5595 : case eStyleUnit_Coord:
5596 : {
5597 0 : nscoord val = aCoord.GetCoordValue();
5598 0 : aValue->SetAppUnits(std::max(aMinAppUnits, std::min(val, aMaxAppUnits)));
5599 : }
5600 0 : break;
5601 :
5602 : case eStyleUnit_Integer:
5603 0 : aValue->SetNumber(aCoord.GetIntValue());
5604 0 : break;
5605 :
5606 : case eStyleUnit_Enumerated:
5607 0 : NS_ASSERTION(aTable, "Must have table to handle this case");
5608 0 : aValue->SetIdent(nsCSSProps::ValueToKeywordEnum(aCoord.GetIntValue(),
5609 0 : aTable));
5610 0 : break;
5611 :
5612 : case eStyleUnit_None:
5613 0 : aValue->SetIdent(eCSSKeyword_none);
5614 0 : break;
5615 :
5616 : case eStyleUnit_Calc:
5617 : nscoord percentageBase;
5618 0 : if (!aCoord.CalcHasPercent()) {
5619 0 : nscoord val = nsRuleNode::ComputeCoordPercentCalc(aCoord, 0);
5620 0 : if (aClampNegativeCalc && val < 0) {
5621 0 : MOZ_ASSERT(aCoord.IsCalcUnit(),
5622 : "parser should have rejected value");
5623 0 : val = 0;
5624 : }
5625 0 : aValue->SetAppUnits(std::max(aMinAppUnits, std::min(val, aMaxAppUnits)));
5626 0 : } else if (aPercentageBaseGetter &&
5627 0 : (this->*aPercentageBaseGetter)(percentageBase)) {
5628 : nscoord val =
5629 0 : nsRuleNode::ComputeCoordPercentCalc(aCoord, percentageBase);
5630 0 : if (aClampNegativeCalc && val < 0) {
5631 0 : MOZ_ASSERT(aCoord.IsCalcUnit(),
5632 : "parser should have rejected value");
5633 0 : val = 0;
5634 : }
5635 0 : aValue->SetAppUnits(std::max(aMinAppUnits, std::min(val, aMaxAppUnits)));
5636 : } else {
5637 0 : nsStyleCoord::Calc *calc = aCoord.GetCalcValue();
5638 0 : SetValueToCalc(calc, aValue);
5639 : }
5640 0 : break;
5641 :
5642 : case eStyleUnit_Degree:
5643 0 : aValue->SetDegree(aCoord.GetAngleValue());
5644 0 : break;
5645 :
5646 : case eStyleUnit_Grad:
5647 0 : aValue->SetGrad(aCoord.GetAngleValue());
5648 0 : break;
5649 :
5650 : case eStyleUnit_Radian:
5651 0 : aValue->SetRadian(aCoord.GetAngleValue());
5652 0 : break;
5653 :
5654 : case eStyleUnit_Turn:
5655 0 : aValue->SetTurn(aCoord.GetAngleValue());
5656 0 : break;
5657 :
5658 : case eStyleUnit_FlexFraction: {
5659 0 : nsAutoString tmpStr;
5660 0 : nsStyleUtil::AppendCSSNumber(aCoord.GetFlexFractionValue(), tmpStr);
5661 0 : tmpStr.AppendLiteral("fr");
5662 0 : aValue->SetString(tmpStr);
5663 0 : break;
5664 : }
5665 :
5666 : default:
5667 0 : NS_ERROR("Can't handle this unit");
5668 0 : break;
5669 : }
5670 0 : }
5671 :
5672 : nscoord
5673 0 : nsComputedDOMStyle::StyleCoordToNSCoord(const nsStyleCoord& aCoord,
5674 : PercentageBaseGetter aPercentageBaseGetter,
5675 : nscoord aDefaultValue,
5676 : bool aClampNegativeCalc)
5677 : {
5678 0 : NS_PRECONDITION(aPercentageBaseGetter, "Must have a percentage base getter");
5679 0 : if (aCoord.GetUnit() == eStyleUnit_Coord) {
5680 0 : return aCoord.GetCoordValue();
5681 : }
5682 0 : if (aCoord.GetUnit() == eStyleUnit_Percent || aCoord.IsCalcUnit()) {
5683 : nscoord percentageBase;
5684 0 : if ((this->*aPercentageBaseGetter)(percentageBase)) {
5685 : nscoord result =
5686 0 : nsRuleNode::ComputeCoordPercentCalc(aCoord, percentageBase);
5687 0 : if (aClampNegativeCalc && result < 0) {
5688 : // It's expected that we can get a negative value here with calc().
5689 : // We can also get a negative value with a percentage value if
5690 : // percentageBase is negative; this isn't expected, but can happen
5691 : // when large length values overflow.
5692 0 : NS_WARNING_ASSERTION(
5693 : percentageBase >= 0,
5694 : "percentage base value overflowed to become negative for a property "
5695 : "that disallows negative values");
5696 0 : MOZ_ASSERT(aCoord.IsCalcUnit() ||
5697 : (aCoord.HasPercent() && percentageBase < 0),
5698 : "parser should have rejected value");
5699 0 : result = 0;
5700 : }
5701 0 : return result;
5702 : }
5703 : // Fall through to returning aDefaultValue if we have no percentage base.
5704 : }
5705 :
5706 0 : return aDefaultValue;
5707 : }
5708 :
5709 : bool
5710 0 : nsComputedDOMStyle::GetCBContentWidth(nscoord& aWidth)
5711 : {
5712 0 : if (!mOuterFrame) {
5713 0 : return false;
5714 : }
5715 :
5716 0 : AssertFlushedPendingReflows();
5717 :
5718 0 : nsIFrame* container = mOuterFrame->GetContainingBlock();
5719 0 : aWidth = container->GetContentRect().width;
5720 0 : return true;
5721 : }
5722 :
5723 : bool
5724 0 : nsComputedDOMStyle::GetCBContentHeight(nscoord& aHeight)
5725 : {
5726 0 : if (!mOuterFrame) {
5727 0 : return false;
5728 : }
5729 :
5730 0 : AssertFlushedPendingReflows();
5731 :
5732 0 : nsIFrame* container = mOuterFrame->GetContainingBlock();
5733 0 : aHeight = container->GetContentRect().height;
5734 0 : return true;
5735 : }
5736 :
5737 : bool
5738 0 : nsComputedDOMStyle::GetScrollFrameContentWidth(nscoord& aWidth)
5739 : {
5740 0 : if (!mOuterFrame) {
5741 0 : return false;
5742 : }
5743 :
5744 0 : AssertFlushedPendingReflows();
5745 :
5746 : nsIScrollableFrame* scrollableFrame =
5747 0 : nsLayoutUtils::GetNearestScrollableFrame(mOuterFrame->GetParent(),
5748 : nsLayoutUtils::SCROLLABLE_SAME_DOC |
5749 0 : nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN);
5750 :
5751 0 : if (!scrollableFrame) {
5752 0 : return false;
5753 : }
5754 0 : aWidth =
5755 0 : scrollableFrame->GetScrolledFrame()->GetContentRectRelativeToSelf().width;
5756 0 : return true;
5757 : }
5758 :
5759 : bool
5760 0 : nsComputedDOMStyle::GetScrollFrameContentHeight(nscoord& aHeight)
5761 : {
5762 0 : if (!mOuterFrame) {
5763 0 : return false;
5764 : }
5765 :
5766 0 : AssertFlushedPendingReflows();
5767 :
5768 : nsIScrollableFrame* scrollableFrame =
5769 0 : nsLayoutUtils::GetNearestScrollableFrame(mOuterFrame->GetParent(),
5770 : nsLayoutUtils::SCROLLABLE_SAME_DOC |
5771 0 : nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN);
5772 :
5773 0 : if (!scrollableFrame) {
5774 0 : return false;
5775 : }
5776 0 : aHeight =
5777 0 : scrollableFrame->GetScrolledFrame()->GetContentRectRelativeToSelf().height;
5778 0 : return true;
5779 : }
5780 :
5781 : bool
5782 0 : nsComputedDOMStyle::GetFrameBorderRectWidth(nscoord& aWidth)
5783 : {
5784 0 : if (!mInnerFrame) {
5785 0 : return false;
5786 : }
5787 :
5788 0 : AssertFlushedPendingReflows();
5789 :
5790 0 : aWidth = mInnerFrame->GetSize().width;
5791 0 : return true;
5792 : }
5793 :
5794 : bool
5795 0 : nsComputedDOMStyle::GetFrameBorderRectHeight(nscoord& aHeight)
5796 : {
5797 0 : if (!mInnerFrame) {
5798 0 : return false;
5799 : }
5800 :
5801 0 : AssertFlushedPendingReflows();
5802 :
5803 0 : aHeight = mInnerFrame->GetSize().height;
5804 0 : return true;
5805 : }
5806 :
5807 : bool
5808 0 : nsComputedDOMStyle::GetFrameBoundsWidthForTransform(nscoord& aWidth)
5809 : {
5810 : // We need a frame to work with.
5811 0 : if (!mInnerFrame) {
5812 0 : return false;
5813 : }
5814 :
5815 0 : AssertFlushedPendingReflows();
5816 :
5817 0 : aWidth = nsStyleTransformMatrix::TransformReferenceBox(mInnerFrame).Width();
5818 0 : return true;
5819 : }
5820 :
5821 : bool
5822 0 : nsComputedDOMStyle::GetFrameBoundsHeightForTransform(nscoord& aHeight)
5823 : {
5824 : // We need a frame to work with.
5825 0 : if (!mInnerFrame) {
5826 0 : return false;
5827 : }
5828 :
5829 0 : AssertFlushedPendingReflows();
5830 :
5831 0 : aHeight = nsStyleTransformMatrix::TransformReferenceBox(mInnerFrame).Height();
5832 0 : return true;
5833 : }
5834 :
5835 : already_AddRefed<CSSValue>
5836 0 : nsComputedDOMStyle::GetFallbackValue(const nsStyleSVGPaint* aPaint)
5837 : {
5838 0 : RefPtr<nsROCSSPrimitiveValue> fallback = new nsROCSSPrimitiveValue;
5839 0 : if (aPaint->GetFallbackType() == eStyleSVGFallbackType_Color) {
5840 0 : SetToRGBAColor(fallback, aPaint->GetFallbackColor());
5841 : } else {
5842 0 : fallback->SetIdent(eCSSKeyword_none);
5843 : }
5844 0 : return fallback.forget();
5845 : }
5846 :
5847 : already_AddRefed<CSSValue>
5848 0 : nsComputedDOMStyle::GetSVGPaintFor(bool aFill)
5849 : {
5850 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5851 :
5852 0 : const nsStyleSVG* svg = StyleSVG();
5853 0 : const nsStyleSVGPaint* paint = aFill ? &svg->mFill : &svg->mStroke;
5854 :
5855 0 : nsAutoString paintString;
5856 :
5857 0 : switch (paint->Type()) {
5858 : case eStyleSVGPaintType_None:
5859 0 : val->SetIdent(eCSSKeyword_none);
5860 0 : break;
5861 : case eStyleSVGPaintType_Color:
5862 0 : SetToRGBAColor(val, paint->GetColor());
5863 0 : break;
5864 : case eStyleSVGPaintType_Server: {
5865 0 : SetValueToURLValue(paint->GetPaintServer(), val);
5866 0 : if (paint->GetFallbackType() != eStyleSVGFallbackType_NotSet) {
5867 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
5868 0 : RefPtr<CSSValue> fallback = GetFallbackValue(paint);
5869 0 : valueList->AppendCSSValue(val.forget());
5870 0 : valueList->AppendCSSValue(fallback.forget());
5871 0 : return valueList.forget();
5872 : }
5873 0 : break;
5874 : }
5875 : case eStyleSVGPaintType_ContextFill:
5876 : case eStyleSVGPaintType_ContextStroke: {
5877 0 : val->SetIdent(paint->Type() == eStyleSVGPaintType_ContextFill ?
5878 0 : eCSSKeyword_context_fill : eCSSKeyword_context_stroke);
5879 0 : if (paint->GetFallbackType() != eStyleSVGFallbackType_NotSet) {
5880 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
5881 0 : RefPtr<CSSValue> fallback = GetFallbackValue(paint);
5882 0 : valueList->AppendCSSValue(val.forget());
5883 0 : valueList->AppendCSSValue(fallback.forget());
5884 0 : return valueList.forget();
5885 : }
5886 0 : break;
5887 : }
5888 : }
5889 :
5890 0 : return val.forget();
5891 : }
5892 :
5893 : /* If the property is "none", hand back "none" wrapped in a value.
5894 : * Otherwise, compute the aggregate transform matrix and hands it back in a
5895 : * "matrix" wrapper.
5896 : */
5897 : already_AddRefed<CSSValue>
5898 0 : nsComputedDOMStyle::GetTransformValue(nsCSSValueSharedList* aSpecifiedTransform)
5899 : {
5900 : /* If there are no transforms, then we should construct a single-element
5901 : * entry and hand it back.
5902 : */
5903 0 : if (!aSpecifiedTransform) {
5904 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5905 :
5906 : /* Set it to "none." */
5907 0 : val->SetIdent(eCSSKeyword_none);
5908 0 : return val.forget();
5909 : }
5910 :
5911 : /* Otherwise, we need to compute the current value of the transform matrix,
5912 : * store it in a string, and hand it back to the caller.
5913 : */
5914 :
5915 : /* Use the inner frame for the reference box. If we don't have an inner
5916 : * frame we use empty dimensions to allow us to continue (and percentage
5917 : * values in the transform will simply give broken results).
5918 : * TODO: There is no good way for us to represent the case where there's no
5919 : * frame, which is problematic. The reason is that when we have percentage
5920 : * transforms, there are a total of four stored matrix entries that influence
5921 : * the transform based on the size of the element. However, this poses a
5922 : * problem, because only two of these values can be explicitly referenced
5923 : * using the named transforms. Until a real solution is found, we'll just
5924 : * use this approach.
5925 : */
5926 0 : nsStyleTransformMatrix::TransformReferenceBox refBox(mInnerFrame,
5927 0 : nsSize(0, 0));
5928 :
5929 0 : RuleNodeCacheConditions dummy;
5930 : bool dummyBool;
5931 : gfx::Matrix4x4 matrix =
5932 0 : nsStyleTransformMatrix::ReadTransforms(aSpecifiedTransform->mHead,
5933 : mStyleContext,
5934 : mStyleContext->PresContext(),
5935 : dummy,
5936 : refBox,
5937 0 : float(mozilla::AppUnitsPerCSSPixel()),
5938 0 : &dummyBool);
5939 :
5940 0 : return MatrixToCSSValue(matrix);
5941 : }
5942 :
5943 : already_AddRefed<CSSValue>
5944 0 : nsComputedDOMStyle::DoGetFill()
5945 : {
5946 0 : return GetSVGPaintFor(true);
5947 : }
5948 :
5949 : already_AddRefed<CSSValue>
5950 0 : nsComputedDOMStyle::DoGetStroke()
5951 : {
5952 0 : return GetSVGPaintFor(false);
5953 : }
5954 :
5955 : already_AddRefed<CSSValue>
5956 0 : nsComputedDOMStyle::DoGetMarkerEnd()
5957 : {
5958 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5959 0 : SetValueToURLValue(StyleSVG()->mMarkerEnd, val);
5960 :
5961 0 : return val.forget();
5962 : }
5963 :
5964 : already_AddRefed<CSSValue>
5965 0 : nsComputedDOMStyle::DoGetMarkerMid()
5966 : {
5967 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5968 0 : SetValueToURLValue(StyleSVG()->mMarkerMid, val);
5969 :
5970 0 : return val.forget();
5971 : }
5972 :
5973 : already_AddRefed<CSSValue>
5974 0 : nsComputedDOMStyle::DoGetMarkerStart()
5975 : {
5976 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5977 0 : SetValueToURLValue(StyleSVG()->mMarkerStart, val);
5978 :
5979 0 : return val.forget();
5980 : }
5981 :
5982 : already_AddRefed<CSSValue>
5983 0 : nsComputedDOMStyle::DoGetStrokeDasharray()
5984 : {
5985 0 : const nsStyleSVG* svg = StyleSVG();
5986 :
5987 0 : if (svg->mStrokeDasharray.IsEmpty()) {
5988 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
5989 0 : val->SetIdent(eCSSKeyword_none);
5990 0 : return val.forget();
5991 : }
5992 :
5993 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
5994 :
5995 0 : for (uint32_t i = 0; i < svg->mStrokeDasharray.Length(); i++) {
5996 0 : RefPtr<nsROCSSPrimitiveValue> dash = new nsROCSSPrimitiveValue;
5997 0 : SetValueToCoord(dash, svg->mStrokeDasharray[i], true);
5998 0 : valueList->AppendCSSValue(dash.forget());
5999 : }
6000 :
6001 0 : return valueList.forget();
6002 : }
6003 :
6004 : already_AddRefed<CSSValue>
6005 0 : nsComputedDOMStyle::DoGetStrokeDashoffset()
6006 : {
6007 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6008 0 : SetValueToCoord(val, StyleSVG()->mStrokeDashoffset, false);
6009 0 : return val.forget();
6010 : }
6011 :
6012 : already_AddRefed<CSSValue>
6013 0 : nsComputedDOMStyle::DoGetStrokeWidth()
6014 : {
6015 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6016 0 : SetValueToCoord(val, StyleSVG()->mStrokeWidth, true);
6017 0 : return val.forget();
6018 : }
6019 :
6020 : already_AddRefed<CSSValue>
6021 0 : nsComputedDOMStyle::DoGetVectorEffect()
6022 : {
6023 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6024 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleSVGReset()->mVectorEffect,
6025 0 : nsCSSProps::kVectorEffectKTable));
6026 0 : return val.forget();
6027 : }
6028 :
6029 : already_AddRefed<CSSValue>
6030 0 : nsComputedDOMStyle::DoGetFillOpacity()
6031 : {
6032 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6033 0 : val->SetNumber(StyleSVG()->mFillOpacity);
6034 0 : return val.forget();
6035 : }
6036 :
6037 : already_AddRefed<CSSValue>
6038 0 : nsComputedDOMStyle::DoGetFloodOpacity()
6039 : {
6040 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6041 0 : val->SetNumber(StyleSVGReset()->mFloodOpacity);
6042 0 : return val.forget();
6043 : }
6044 :
6045 : already_AddRefed<CSSValue>
6046 0 : nsComputedDOMStyle::DoGetStopOpacity()
6047 : {
6048 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6049 0 : val->SetNumber(StyleSVGReset()->mStopOpacity);
6050 0 : return val.forget();
6051 : }
6052 :
6053 : already_AddRefed<CSSValue>
6054 0 : nsComputedDOMStyle::DoGetStrokeMiterlimit()
6055 : {
6056 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6057 0 : val->SetNumber(StyleSVG()->mStrokeMiterlimit);
6058 0 : return val.forget();
6059 : }
6060 :
6061 : already_AddRefed<CSSValue>
6062 0 : nsComputedDOMStyle::DoGetStrokeOpacity()
6063 : {
6064 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6065 0 : val->SetNumber(StyleSVG()->mStrokeOpacity);
6066 0 : return val.forget();
6067 : }
6068 :
6069 : already_AddRefed<CSSValue>
6070 0 : nsComputedDOMStyle::DoGetClipRule()
6071 : {
6072 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6073 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(
6074 0 : StyleSVG()->mClipRule, nsCSSProps::kFillRuleKTable));
6075 0 : return val.forget();
6076 : }
6077 :
6078 : already_AddRefed<CSSValue>
6079 0 : nsComputedDOMStyle::DoGetFillRule()
6080 : {
6081 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6082 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(
6083 0 : StyleSVG()->mFillRule, nsCSSProps::kFillRuleKTable));
6084 0 : return val.forget();
6085 : }
6086 :
6087 : already_AddRefed<CSSValue>
6088 0 : nsComputedDOMStyle::DoGetStrokeLinecap()
6089 : {
6090 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6091 0 : val->SetIdent(
6092 0 : nsCSSProps::ValueToKeywordEnum(StyleSVG()->mStrokeLinecap,
6093 0 : nsCSSProps::kStrokeLinecapKTable));
6094 0 : return val.forget();
6095 : }
6096 :
6097 : already_AddRefed<CSSValue>
6098 0 : nsComputedDOMStyle::DoGetStrokeLinejoin()
6099 : {
6100 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6101 0 : val->SetIdent(
6102 0 : nsCSSProps::ValueToKeywordEnum(StyleSVG()->mStrokeLinejoin,
6103 0 : nsCSSProps::kStrokeLinejoinKTable));
6104 0 : return val.forget();
6105 : }
6106 :
6107 : already_AddRefed<CSSValue>
6108 0 : nsComputedDOMStyle::DoGetTextAnchor()
6109 : {
6110 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6111 0 : val->SetIdent(
6112 0 : nsCSSProps::ValueToKeywordEnum(StyleSVG()->mTextAnchor,
6113 0 : nsCSSProps::kTextAnchorKTable));
6114 0 : return val.forget();
6115 : }
6116 :
6117 : already_AddRefed<CSSValue>
6118 0 : nsComputedDOMStyle::DoGetColorInterpolation()
6119 : {
6120 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6121 0 : val->SetIdent(
6122 0 : nsCSSProps::ValueToKeywordEnum(StyleSVG()->mColorInterpolation,
6123 0 : nsCSSProps::kColorInterpolationKTable));
6124 0 : return val.forget();
6125 : }
6126 :
6127 : already_AddRefed<CSSValue>
6128 0 : nsComputedDOMStyle::DoGetColorInterpolationFilters()
6129 : {
6130 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6131 0 : val->SetIdent(
6132 0 : nsCSSProps::ValueToKeywordEnum(StyleSVG()->mColorInterpolationFilters,
6133 0 : nsCSSProps::kColorInterpolationKTable));
6134 0 : return val.forget();
6135 : }
6136 :
6137 : already_AddRefed<CSSValue>
6138 0 : nsComputedDOMStyle::DoGetDominantBaseline()
6139 : {
6140 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6141 0 : val->SetIdent(
6142 0 : nsCSSProps::ValueToKeywordEnum(StyleSVGReset()->mDominantBaseline,
6143 0 : nsCSSProps::kDominantBaselineKTable));
6144 0 : return val.forget();
6145 : }
6146 :
6147 : already_AddRefed<CSSValue>
6148 0 : nsComputedDOMStyle::DoGetImageRendering()
6149 : {
6150 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6151 0 : val->SetIdent(
6152 0 : nsCSSProps::ValueToKeywordEnum(StyleVisibility()->mImageRendering,
6153 0 : nsCSSProps::kImageRenderingKTable));
6154 0 : return val.forget();
6155 : }
6156 :
6157 : already_AddRefed<CSSValue>
6158 0 : nsComputedDOMStyle::DoGetShapeRendering()
6159 : {
6160 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6161 0 : val->SetIdent(
6162 0 : nsCSSProps::ValueToKeywordEnum(StyleSVG()->mShapeRendering,
6163 0 : nsCSSProps::kShapeRenderingKTable));
6164 0 : return val.forget();
6165 : }
6166 :
6167 : already_AddRefed<CSSValue>
6168 0 : nsComputedDOMStyle::DoGetTextRendering()
6169 : {
6170 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6171 0 : val->SetIdent(
6172 0 : nsCSSProps::ValueToKeywordEnum(StyleText()->mTextRendering,
6173 0 : nsCSSProps::kTextRenderingKTable));
6174 0 : return val.forget();
6175 : }
6176 :
6177 : already_AddRefed<CSSValue>
6178 0 : nsComputedDOMStyle::DoGetFloodColor()
6179 : {
6180 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6181 0 : SetToRGBAColor(val, StyleSVGReset()->mFloodColor);
6182 0 : return val.forget();
6183 : }
6184 :
6185 : already_AddRefed<CSSValue>
6186 0 : nsComputedDOMStyle::DoGetLightingColor()
6187 : {
6188 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6189 0 : SetToRGBAColor(val, StyleSVGReset()->mLightingColor);
6190 0 : return val.forget();
6191 : }
6192 :
6193 : already_AddRefed<CSSValue>
6194 0 : nsComputedDOMStyle::DoGetStopColor()
6195 : {
6196 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6197 0 : SetToRGBAColor(val, StyleSVGReset()->mStopColor);
6198 0 : return val.forget();
6199 : }
6200 :
6201 : void
6202 0 : nsComputedDOMStyle::BoxValuesToString(nsAString& aString,
6203 : const nsTArray<nsStyleCoord>& aBoxValues)
6204 : {
6205 0 : MOZ_ASSERT(aBoxValues.Length() == 4, "wrong number of box values");
6206 0 : nsAutoString value1, value2, value3, value4;
6207 0 : SetCssTextToCoord(value1, aBoxValues[0]);
6208 0 : SetCssTextToCoord(value2, aBoxValues[1]);
6209 0 : SetCssTextToCoord(value3, aBoxValues[2]);
6210 0 : SetCssTextToCoord(value4, aBoxValues[3]);
6211 :
6212 : // nsROCSSPrimitiveValue do not have binary comparison operators.
6213 : // Compare string results instead.
6214 0 : aString.Append(value1);
6215 0 : if (value1 != value2 || value1 != value3 || value1 != value4) {
6216 0 : aString.Append(' ');
6217 0 : aString.Append(value2);
6218 0 : if (value1 != value3 || value2 != value4) {
6219 0 : aString.Append(' ');
6220 0 : aString.Append(value3);
6221 0 : if (value2 != value4) {
6222 0 : aString.Append(' ');
6223 0 : aString.Append(value4);
6224 : }
6225 : }
6226 : }
6227 0 : }
6228 :
6229 : void
6230 0 : nsComputedDOMStyle::BasicShapeRadiiToString(nsAString& aCssText,
6231 : const nsStyleCorners& aCorners)
6232 : {
6233 0 : nsTArray<nsStyleCoord> horizontal, vertical;
6234 0 : nsAutoString horizontalString, verticalString;
6235 0 : NS_FOR_CSS_FULL_CORNERS(corner) {
6236 : horizontal.AppendElement(
6237 0 : aCorners.Get(FullToHalfCorner(corner, false)));
6238 : vertical.AppendElement(
6239 0 : aCorners.Get(FullToHalfCorner(corner, true)));
6240 : }
6241 0 : BoxValuesToString(horizontalString, horizontal);
6242 0 : BoxValuesToString(verticalString, vertical);
6243 0 : aCssText.Append(horizontalString);
6244 0 : if (horizontalString == verticalString) {
6245 0 : return;
6246 : }
6247 0 : aCssText.AppendLiteral(" / ");
6248 0 : aCssText.Append(verticalString);
6249 : }
6250 :
6251 : already_AddRefed<CSSValue>
6252 0 : nsComputedDOMStyle::CreatePrimitiveValueForBasicShape(
6253 : const StyleBasicShape* aStyleBasicShape)
6254 : {
6255 0 : MOZ_ASSERT(aStyleBasicShape, "Expect a valid basic shape pointer!");
6256 :
6257 0 : StyleBasicShapeType type = aStyleBasicShape->GetShapeType();
6258 : // Shape function name and opening parenthesis.
6259 0 : nsAutoString shapeFunctionString;
6260 0 : AppendASCIItoUTF16(nsCSSKeywords::GetStringValue(
6261 0 : aStyleBasicShape->GetShapeTypeName()),
6262 0 : shapeFunctionString);
6263 0 : shapeFunctionString.Append('(');
6264 0 : switch (type) {
6265 : case StyleBasicShapeType::Polygon: {
6266 0 : bool hasEvenOdd = aStyleBasicShape->GetFillRule() ==
6267 0 : StyleFillRule::Evenodd;
6268 0 : if (hasEvenOdd) {
6269 0 : shapeFunctionString.AppendLiteral("evenodd");
6270 : }
6271 0 : for (size_t i = 0;
6272 0 : i < aStyleBasicShape->Coordinates().Length(); i += 2) {
6273 0 : nsAutoString coordString;
6274 0 : if (i > 0 || hasEvenOdd) {
6275 0 : shapeFunctionString.AppendLiteral(", ");
6276 : }
6277 : SetCssTextToCoord(coordString,
6278 0 : aStyleBasicShape->Coordinates()[i]);
6279 0 : shapeFunctionString.Append(coordString);
6280 0 : shapeFunctionString.Append(' ');
6281 : SetCssTextToCoord(coordString,
6282 0 : aStyleBasicShape->Coordinates()[i + 1]);
6283 0 : shapeFunctionString.Append(coordString);
6284 : }
6285 0 : break;
6286 : }
6287 : case StyleBasicShapeType::Circle:
6288 : case StyleBasicShapeType::Ellipse: {
6289 0 : const nsTArray<nsStyleCoord>& radii = aStyleBasicShape->Coordinates();
6290 0 : MOZ_ASSERT(radii.Length() ==
6291 : (type == StyleBasicShapeType::Circle ? 1 : 2),
6292 : "wrong number of radii");
6293 0 : for (size_t i = 0; i < radii.Length(); ++i) {
6294 0 : nsAutoString radius;
6295 0 : RefPtr<nsROCSSPrimitiveValue> value = new nsROCSSPrimitiveValue;
6296 0 : bool clampNegativeCalc = true;
6297 0 : SetValueToCoord(value, radii[i], clampNegativeCalc, nullptr,
6298 0 : nsCSSProps::kShapeRadiusKTable);
6299 0 : value->GetCssText(radius);
6300 0 : shapeFunctionString.Append(radius);
6301 0 : shapeFunctionString.Append(' ');
6302 : }
6303 0 : shapeFunctionString.AppendLiteral("at ");
6304 :
6305 0 : RefPtr<nsDOMCSSValueList> position = GetROCSSValueList(false);
6306 0 : nsAutoString positionString;
6307 0 : SetValueToPosition(aStyleBasicShape->GetPosition(), position);
6308 0 : position->GetCssText(positionString);
6309 0 : shapeFunctionString.Append(positionString);
6310 0 : break;
6311 : }
6312 : case StyleBasicShapeType::Inset: {
6313 0 : BoxValuesToString(shapeFunctionString, aStyleBasicShape->Coordinates());
6314 0 : if (aStyleBasicShape->HasRadius()) {
6315 0 : shapeFunctionString.AppendLiteral(" round ");
6316 0 : nsAutoString radiiString;
6317 0 : BasicShapeRadiiToString(radiiString, aStyleBasicShape->GetRadius());
6318 0 : shapeFunctionString.Append(radiiString);
6319 : }
6320 0 : break;
6321 : }
6322 : default:
6323 0 : NS_NOTREACHED("unexpected type");
6324 : }
6325 0 : shapeFunctionString.Append(')');
6326 0 : RefPtr<nsROCSSPrimitiveValue> functionValue = new nsROCSSPrimitiveValue;
6327 0 : functionValue->SetString(shapeFunctionString);
6328 0 : return functionValue.forget();
6329 : }
6330 :
6331 : template<typename ReferenceBox>
6332 : already_AddRefed<CSSValue>
6333 0 : nsComputedDOMStyle::CreatePrimitiveValueForShapeSource(
6334 : const StyleBasicShape* aStyleBasicShape,
6335 : ReferenceBox aReferenceBox,
6336 : const KTableEntry aBoxKeywordTable[])
6337 : {
6338 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
6339 0 : if (aStyleBasicShape) {
6340 0 : valueList->AppendCSSValue(
6341 : CreatePrimitiveValueForBasicShape(aStyleBasicShape));
6342 : }
6343 :
6344 0 : if (aReferenceBox == ReferenceBox::NoBox) {
6345 0 : return valueList.forget();
6346 : }
6347 :
6348 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6349 0 : val->SetIdent(nsCSSProps::ValueToKeywordEnum(aReferenceBox, aBoxKeywordTable));
6350 0 : valueList->AppendCSSValue(val.forget());
6351 :
6352 0 : return valueList.forget();
6353 : }
6354 :
6355 : already_AddRefed<CSSValue>
6356 0 : nsComputedDOMStyle::GetShapeSource(
6357 : const StyleShapeSource& aShapeSource,
6358 : const KTableEntry aBoxKeywordTable[])
6359 : {
6360 0 : switch (aShapeSource.GetType()) {
6361 : case StyleShapeSourceType::Shape:
6362 0 : return CreatePrimitiveValueForShapeSource(aShapeSource.GetBasicShape(),
6363 : aShapeSource.GetReferenceBox(),
6364 0 : aBoxKeywordTable);
6365 : case StyleShapeSourceType::Box:
6366 : return CreatePrimitiveValueForShapeSource(nullptr,
6367 : aShapeSource.GetReferenceBox(),
6368 0 : aBoxKeywordTable);
6369 : case StyleShapeSourceType::URL: {
6370 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6371 0 : SetValueToURLValue(aShapeSource.GetURL(), val);
6372 0 : return val.forget();
6373 : }
6374 : case StyleShapeSourceType::None: {
6375 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6376 0 : val->SetIdent(eCSSKeyword_none);
6377 0 : return val.forget();
6378 : }
6379 : default:
6380 0 : NS_NOTREACHED("unexpected type");
6381 : }
6382 0 : return nullptr;
6383 : }
6384 :
6385 : already_AddRefed<CSSValue>
6386 0 : nsComputedDOMStyle::DoGetClipPath()
6387 : {
6388 0 : return GetShapeSource(StyleSVGReset()->mClipPath,
6389 0 : nsCSSProps::kClipPathGeometryBoxKTable);
6390 : }
6391 :
6392 : already_AddRefed<CSSValue>
6393 0 : nsComputedDOMStyle::DoGetShapeOutside()
6394 : {
6395 0 : return GetShapeSource(StyleDisplay()->mShapeOutside,
6396 0 : nsCSSProps::kShapeOutsideShapeBoxKTable);
6397 : }
6398 :
6399 : void
6400 0 : nsComputedDOMStyle::SetCssTextToCoord(nsAString& aCssText,
6401 : const nsStyleCoord& aCoord)
6402 : {
6403 0 : RefPtr<nsROCSSPrimitiveValue> value = new nsROCSSPrimitiveValue;
6404 0 : bool clampNegativeCalc = true;
6405 0 : SetValueToCoord(value, aCoord, clampNegativeCalc);
6406 0 : value->GetCssText(aCssText);
6407 0 : }
6408 :
6409 : already_AddRefed<CSSValue>
6410 0 : nsComputedDOMStyle::CreatePrimitiveValueForStyleFilter(
6411 : const nsStyleFilter& aStyleFilter)
6412 : {
6413 0 : RefPtr<nsROCSSPrimitiveValue> value = new nsROCSSPrimitiveValue;
6414 : // Handle url().
6415 0 : if (aStyleFilter.GetType() == NS_STYLE_FILTER_URL) {
6416 0 : MOZ_ASSERT(aStyleFilter.GetURL() &&
6417 : aStyleFilter.GetURL()->GetURI());
6418 0 : SetValueToURLValue(aStyleFilter.GetURL(), value);
6419 0 : return value.forget();
6420 : }
6421 :
6422 : // Filter function name and opening parenthesis.
6423 0 : nsAutoString filterFunctionString;
6424 0 : AppendASCIItoUTF16(
6425 0 : nsCSSProps::ValueToKeyword(aStyleFilter.GetType(),
6426 0 : nsCSSProps::kFilterFunctionKTable),
6427 0 : filterFunctionString);
6428 0 : filterFunctionString.Append('(');
6429 :
6430 0 : nsAutoString argumentString;
6431 0 : if (aStyleFilter.GetType() == NS_STYLE_FILTER_DROP_SHADOW) {
6432 : // Handle drop-shadow()
6433 : RefPtr<CSSValue> shadowValue =
6434 0 : GetCSSShadowArray(aStyleFilter.GetDropShadow(),
6435 0 : StyleColor()->mColor,
6436 0 : false);
6437 0 : ErrorResult dummy;
6438 0 : shadowValue->GetCssText(argumentString, dummy);
6439 : } else {
6440 : // Filter function argument.
6441 0 : SetCssTextToCoord(argumentString, aStyleFilter.GetFilterParameter());
6442 : }
6443 0 : filterFunctionString.Append(argumentString);
6444 :
6445 : // Filter function closing parenthesis.
6446 0 : filterFunctionString.Append(')');
6447 :
6448 0 : value->SetString(filterFunctionString);
6449 0 : return value.forget();
6450 : }
6451 :
6452 : already_AddRefed<CSSValue>
6453 0 : nsComputedDOMStyle::DoGetFilter()
6454 : {
6455 0 : const nsTArray<nsStyleFilter>& filters = StyleEffects()->mFilters;
6456 :
6457 0 : if (filters.IsEmpty()) {
6458 0 : RefPtr<nsROCSSPrimitiveValue> value = new nsROCSSPrimitiveValue;
6459 0 : value->SetIdent(eCSSKeyword_none);
6460 0 : return value.forget();
6461 : }
6462 :
6463 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
6464 0 : for(uint32_t i = 0; i < filters.Length(); i++) {
6465 0 : RefPtr<CSSValue> value = CreatePrimitiveValueForStyleFilter(filters[i]);
6466 0 : valueList->AppendCSSValue(value.forget());
6467 : }
6468 0 : return valueList.forget();
6469 : }
6470 :
6471 : already_AddRefed<CSSValue>
6472 0 : nsComputedDOMStyle::DoGetMask()
6473 : {
6474 0 : const nsStyleSVGReset* svg = StyleSVGReset();
6475 0 : const nsStyleImageLayers::Layer& firstLayer = svg->mMask.mLayers[0];
6476 :
6477 : // Mask is now a shorthand, but it used to be a longhand, so that we
6478 : // need to support computed style for the cases where it used to be
6479 : // a longhand.
6480 0 : if (svg->mMask.mImageCount > 1 ||
6481 0 : firstLayer.mClip != StyleGeometryBox::BorderBox ||
6482 0 : firstLayer.mOrigin != StyleGeometryBox::BorderBox ||
6483 0 : firstLayer.mComposite != NS_STYLE_MASK_COMPOSITE_ADD ||
6484 0 : firstLayer.mMaskMode != NS_STYLE_MASK_MODE_MATCH_SOURCE ||
6485 0 : !nsStyleImageLayers::IsInitialPositionForLayerType(
6486 0 : firstLayer.mPosition, nsStyleImageLayers::LayerType::Mask) ||
6487 0 : !firstLayer.mRepeat.IsInitialValue() ||
6488 0 : !firstLayer.mSize.IsInitialValue() ||
6489 0 : !(firstLayer.mImage.GetType() == eStyleImageType_Null ||
6490 0 : firstLayer.mImage.GetType() == eStyleImageType_Image ||
6491 0 : firstLayer.mImage.GetType() == eStyleImageType_URL)) {
6492 0 : return nullptr;
6493 : }
6494 :
6495 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6496 :
6497 0 : SetValueToURLValue(firstLayer.mImage.GetURLValue(), val);
6498 :
6499 0 : return val.forget();
6500 : }
6501 :
6502 : #ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
6503 : already_AddRefed<CSSValue>
6504 0 : nsComputedDOMStyle::DoGetMaskClip()
6505 : {
6506 : return GetBackgroundList(&nsStyleImageLayers::Layer::mClip,
6507 : &nsStyleImageLayers::mClipCount,
6508 0 : StyleSVGReset()->mMask,
6509 0 : nsCSSProps::kMaskClipKTable);
6510 : }
6511 :
6512 : already_AddRefed<CSSValue>
6513 0 : nsComputedDOMStyle::DoGetMaskComposite()
6514 : {
6515 : return GetBackgroundList(&nsStyleImageLayers::Layer::mComposite,
6516 : &nsStyleImageLayers::mCompositeCount,
6517 0 : StyleSVGReset()->mMask,
6518 0 : nsCSSProps::kImageLayerCompositeKTable);
6519 : }
6520 :
6521 : already_AddRefed<CSSValue>
6522 0 : nsComputedDOMStyle::DoGetMaskImage()
6523 : {
6524 0 : const nsStyleImageLayers& layers = StyleSVGReset()->mMask;
6525 0 : return DoGetImageLayerImage(layers);
6526 : }
6527 :
6528 : already_AddRefed<CSSValue>
6529 0 : nsComputedDOMStyle::DoGetMaskMode()
6530 : {
6531 : return GetBackgroundList(&nsStyleImageLayers::Layer::mMaskMode,
6532 : &nsStyleImageLayers::mMaskModeCount,
6533 0 : StyleSVGReset()->mMask,
6534 0 : nsCSSProps::kImageLayerModeKTable);
6535 : }
6536 :
6537 : already_AddRefed<CSSValue>
6538 0 : nsComputedDOMStyle::DoGetMaskOrigin()
6539 : {
6540 : return GetBackgroundList(&nsStyleImageLayers::Layer::mOrigin,
6541 : &nsStyleImageLayers::mOriginCount,
6542 0 : StyleSVGReset()->mMask,
6543 0 : nsCSSProps::kMaskOriginKTable);
6544 : }
6545 :
6546 : already_AddRefed<CSSValue>
6547 0 : nsComputedDOMStyle::DoGetMaskPosition()
6548 : {
6549 0 : const nsStyleImageLayers& layers = StyleSVGReset()->mMask;
6550 0 : return DoGetImageLayerPosition(layers);
6551 : }
6552 :
6553 : already_AddRefed<CSSValue>
6554 0 : nsComputedDOMStyle::DoGetMaskPositionX()
6555 : {
6556 0 : const nsStyleImageLayers& layers = StyleSVGReset()->mMask;
6557 0 : return DoGetImageLayerPositionX(layers);
6558 : }
6559 :
6560 : already_AddRefed<CSSValue>
6561 0 : nsComputedDOMStyle::DoGetMaskPositionY()
6562 : {
6563 0 : const nsStyleImageLayers& layers = StyleSVGReset()->mMask;
6564 0 : return DoGetImageLayerPositionY(layers);
6565 : }
6566 :
6567 : already_AddRefed<CSSValue>
6568 0 : nsComputedDOMStyle::DoGetMaskRepeat()
6569 : {
6570 0 : const nsStyleImageLayers& layers = StyleSVGReset()->mMask;
6571 0 : return DoGetImageLayerRepeat(layers);
6572 : }
6573 :
6574 : already_AddRefed<CSSValue>
6575 0 : nsComputedDOMStyle::DoGetMaskSize()
6576 : {
6577 0 : const nsStyleImageLayers& layers = StyleSVGReset()->mMask;
6578 0 : return DoGetImageLayerSize(layers);
6579 : }
6580 : #endif
6581 :
6582 : already_AddRefed<CSSValue>
6583 0 : nsComputedDOMStyle::DoGetMaskType()
6584 : {
6585 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6586 0 : val->SetIdent(
6587 0 : nsCSSProps::ValueToKeywordEnum(StyleSVGReset()->mMaskType,
6588 0 : nsCSSProps::kMaskTypeKTable));
6589 0 : return val.forget();
6590 : }
6591 :
6592 : already_AddRefed<CSSValue>
6593 0 : nsComputedDOMStyle::DoGetContextProperties()
6594 : {
6595 0 : const nsTArray<nsCOMPtr<nsIAtom>>& contextProps = StyleSVG()->mContextProps;
6596 :
6597 0 : if (contextProps.IsEmpty()) {
6598 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6599 0 : val->SetIdent(eCSSKeyword_none);
6600 0 : return val.forget();
6601 : }
6602 :
6603 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
6604 0 : for (const nsIAtom* ident : contextProps) {
6605 0 : RefPtr<nsROCSSPrimitiveValue> property = new nsROCSSPrimitiveValue;
6606 0 : property->SetString(nsDependentAtomString(ident));
6607 0 : valueList->AppendCSSValue(property.forget());
6608 : }
6609 :
6610 0 : return valueList.forget();
6611 : }
6612 :
6613 : already_AddRefed<CSSValue>
6614 0 : nsComputedDOMStyle::DoGetPaintOrder()
6615 : {
6616 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6617 0 : nsAutoString string;
6618 0 : uint8_t paintOrder = StyleSVG()->mPaintOrder;
6619 0 : nsStyleUtil::AppendPaintOrderValue(paintOrder, string);
6620 0 : val->SetString(string);
6621 0 : return val.forget();
6622 : }
6623 :
6624 : already_AddRefed<CSSValue>
6625 0 : nsComputedDOMStyle::DoGetTransitionDelay()
6626 : {
6627 0 : const nsStyleDisplay* display = StyleDisplay();
6628 :
6629 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
6630 :
6631 0 : MOZ_ASSERT(display->mTransitionDelayCount > 0,
6632 : "first item must be explicit");
6633 0 : uint32_t i = 0;
6634 0 : do {
6635 0 : const StyleTransition *transition = &display->mTransitions[i];
6636 0 : RefPtr<nsROCSSPrimitiveValue> delay = new nsROCSSPrimitiveValue;
6637 0 : delay->SetTime((float)transition->GetDelay() / (float)PR_MSEC_PER_SEC);
6638 0 : valueList->AppendCSSValue(delay.forget());
6639 0 : } while (++i < display->mTransitionDelayCount);
6640 :
6641 0 : return valueList.forget();
6642 : }
6643 :
6644 : already_AddRefed<CSSValue>
6645 0 : nsComputedDOMStyle::DoGetTransitionDuration()
6646 : {
6647 0 : const nsStyleDisplay* display = StyleDisplay();
6648 :
6649 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
6650 :
6651 0 : MOZ_ASSERT(display->mTransitionDurationCount > 0,
6652 : "first item must be explicit");
6653 0 : uint32_t i = 0;
6654 0 : do {
6655 0 : const StyleTransition *transition = &display->mTransitions[i];
6656 0 : RefPtr<nsROCSSPrimitiveValue> duration = new nsROCSSPrimitiveValue;
6657 :
6658 0 : duration->SetTime((float)transition->GetDuration() / (float)PR_MSEC_PER_SEC);
6659 0 : valueList->AppendCSSValue(duration.forget());
6660 0 : } while (++i < display->mTransitionDurationCount);
6661 :
6662 0 : return valueList.forget();
6663 : }
6664 :
6665 : already_AddRefed<CSSValue>
6666 0 : nsComputedDOMStyle::DoGetTransitionProperty()
6667 : {
6668 0 : const nsStyleDisplay* display = StyleDisplay();
6669 :
6670 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
6671 :
6672 0 : MOZ_ASSERT(display->mTransitionPropertyCount > 0,
6673 : "first item must be explicit");
6674 0 : uint32_t i = 0;
6675 0 : do {
6676 0 : const StyleTransition *transition = &display->mTransitions[i];
6677 0 : RefPtr<nsROCSSPrimitiveValue> property = new nsROCSSPrimitiveValue;
6678 0 : nsCSSPropertyID cssprop = transition->GetProperty();
6679 0 : if (cssprop == eCSSPropertyExtra_all_properties)
6680 0 : property->SetIdent(eCSSKeyword_all);
6681 0 : else if (cssprop == eCSSPropertyExtra_no_properties)
6682 0 : property->SetIdent(eCSSKeyword_none);
6683 0 : else if (cssprop == eCSSProperty_UNKNOWN ||
6684 : cssprop == eCSSPropertyExtra_variable)
6685 : {
6686 0 : nsAutoString escaped;
6687 : nsStyleUtil::AppendEscapedCSSIdent(
6688 0 : nsDependentAtomString(transition->GetUnknownProperty()), escaped);
6689 0 : property->SetString(escaped); // really want SetIdent
6690 : }
6691 : else
6692 0 : property->SetString(nsCSSProps::GetStringValue(cssprop));
6693 :
6694 0 : valueList->AppendCSSValue(property.forget());
6695 0 : } while (++i < display->mTransitionPropertyCount);
6696 :
6697 0 : return valueList.forget();
6698 : }
6699 :
6700 : void
6701 0 : nsComputedDOMStyle::AppendTimingFunction(nsDOMCSSValueList *aValueList,
6702 : const nsTimingFunction& aTimingFunction)
6703 : {
6704 0 : RefPtr<nsROCSSPrimitiveValue> timingFunction = new nsROCSSPrimitiveValue;
6705 :
6706 0 : nsAutoString tmp;
6707 0 : switch (aTimingFunction.mType) {
6708 : case nsTimingFunction::Type::CubicBezier:
6709 0 : nsStyleUtil::AppendCubicBezierTimingFunction(aTimingFunction.mFunc.mX1,
6710 0 : aTimingFunction.mFunc.mY1,
6711 0 : aTimingFunction.mFunc.mX2,
6712 0 : aTimingFunction.mFunc.mY2,
6713 0 : tmp);
6714 0 : break;
6715 : case nsTimingFunction::Type::StepStart:
6716 : case nsTimingFunction::Type::StepEnd:
6717 0 : nsStyleUtil::AppendStepsTimingFunction(aTimingFunction.mType,
6718 0 : aTimingFunction.mStepsOrFrames,
6719 0 : tmp);
6720 0 : break;
6721 : case nsTimingFunction::Type::Frames:
6722 0 : nsStyleUtil::AppendFramesTimingFunction(aTimingFunction.mStepsOrFrames,
6723 0 : tmp);
6724 0 : break;
6725 : default:
6726 0 : nsStyleUtil::AppendCubicBezierKeywordTimingFunction(aTimingFunction.mType,
6727 0 : tmp);
6728 0 : break;
6729 : }
6730 0 : timingFunction->SetString(tmp);
6731 0 : aValueList->AppendCSSValue(timingFunction.forget());
6732 0 : }
6733 :
6734 : already_AddRefed<CSSValue>
6735 0 : nsComputedDOMStyle::DoGetTransitionTimingFunction()
6736 : {
6737 0 : const nsStyleDisplay* display = StyleDisplay();
6738 :
6739 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
6740 :
6741 0 : MOZ_ASSERT(display->mTransitionTimingFunctionCount > 0,
6742 : "first item must be explicit");
6743 0 : uint32_t i = 0;
6744 0 : do {
6745 0 : AppendTimingFunction(valueList,
6746 0 : display->mTransitions[i].GetTimingFunction());
6747 0 : } while (++i < display->mTransitionTimingFunctionCount);
6748 :
6749 0 : return valueList.forget();
6750 : }
6751 :
6752 : already_AddRefed<CSSValue>
6753 0 : nsComputedDOMStyle::DoGetAnimationName()
6754 : {
6755 0 : const nsStyleDisplay* display = StyleDisplay();
6756 :
6757 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
6758 :
6759 0 : MOZ_ASSERT(display->mAnimationNameCount > 0,
6760 : "first item must be explicit");
6761 0 : uint32_t i = 0;
6762 0 : do {
6763 0 : const StyleAnimation *animation = &display->mAnimations[i];
6764 0 : RefPtr<nsROCSSPrimitiveValue> property = new nsROCSSPrimitiveValue;
6765 :
6766 0 : const nsString& name = animation->GetName();
6767 0 : if (name.IsEmpty()) {
6768 0 : property->SetIdent(eCSSKeyword_none);
6769 : } else {
6770 0 : nsAutoString escaped;
6771 0 : nsStyleUtil::AppendEscapedCSSIdent(animation->GetName(), escaped);
6772 0 : property->SetString(escaped); // really want SetIdent
6773 : }
6774 0 : valueList->AppendCSSValue(property.forget());
6775 0 : } while (++i < display->mAnimationNameCount);
6776 :
6777 0 : return valueList.forget();
6778 : }
6779 :
6780 : already_AddRefed<CSSValue>
6781 0 : nsComputedDOMStyle::DoGetAnimationDelay()
6782 : {
6783 0 : const nsStyleDisplay* display = StyleDisplay();
6784 :
6785 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
6786 :
6787 0 : MOZ_ASSERT(display->mAnimationDelayCount > 0,
6788 : "first item must be explicit");
6789 0 : uint32_t i = 0;
6790 0 : do {
6791 0 : const StyleAnimation *animation = &display->mAnimations[i];
6792 0 : RefPtr<nsROCSSPrimitiveValue> delay = new nsROCSSPrimitiveValue;
6793 0 : delay->SetTime((float)animation->GetDelay() / (float)PR_MSEC_PER_SEC);
6794 0 : valueList->AppendCSSValue(delay.forget());
6795 0 : } while (++i < display->mAnimationDelayCount);
6796 :
6797 0 : return valueList.forget();
6798 : }
6799 :
6800 : already_AddRefed<CSSValue>
6801 0 : nsComputedDOMStyle::DoGetAnimationDuration()
6802 : {
6803 0 : const nsStyleDisplay* display = StyleDisplay();
6804 :
6805 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
6806 :
6807 0 : MOZ_ASSERT(display->mAnimationDurationCount > 0,
6808 : "first item must be explicit");
6809 0 : uint32_t i = 0;
6810 0 : do {
6811 0 : const StyleAnimation *animation = &display->mAnimations[i];
6812 0 : RefPtr<nsROCSSPrimitiveValue> duration = new nsROCSSPrimitiveValue;
6813 :
6814 0 : duration->SetTime((float)animation->GetDuration() / (float)PR_MSEC_PER_SEC);
6815 0 : valueList->AppendCSSValue(duration.forget());
6816 0 : } while (++i < display->mAnimationDurationCount);
6817 :
6818 0 : return valueList.forget();
6819 : }
6820 :
6821 : already_AddRefed<CSSValue>
6822 0 : nsComputedDOMStyle::DoGetAnimationTimingFunction()
6823 : {
6824 0 : const nsStyleDisplay* display = StyleDisplay();
6825 :
6826 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
6827 :
6828 0 : MOZ_ASSERT(display->mAnimationTimingFunctionCount > 0,
6829 : "first item must be explicit");
6830 0 : uint32_t i = 0;
6831 0 : do {
6832 0 : AppendTimingFunction(valueList,
6833 0 : display->mAnimations[i].GetTimingFunction());
6834 0 : } while (++i < display->mAnimationTimingFunctionCount);
6835 :
6836 0 : return valueList.forget();
6837 : }
6838 :
6839 : already_AddRefed<CSSValue>
6840 0 : nsComputedDOMStyle::DoGetAnimationDirection()
6841 : {
6842 0 : const nsStyleDisplay* display = StyleDisplay();
6843 :
6844 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
6845 :
6846 0 : MOZ_ASSERT(display->mAnimationDirectionCount > 0,
6847 : "first item must be explicit");
6848 0 : uint32_t i = 0;
6849 0 : do {
6850 0 : const StyleAnimation *animation = &display->mAnimations[i];
6851 0 : RefPtr<nsROCSSPrimitiveValue> direction = new nsROCSSPrimitiveValue;
6852 0 : direction->SetIdent(
6853 0 : nsCSSProps::ValueToKeywordEnum(
6854 0 : static_cast<int32_t>(animation->GetDirection()),
6855 0 : nsCSSProps::kAnimationDirectionKTable));
6856 :
6857 0 : valueList->AppendCSSValue(direction.forget());
6858 0 : } while (++i < display->mAnimationDirectionCount);
6859 :
6860 0 : return valueList.forget();
6861 : }
6862 :
6863 : already_AddRefed<CSSValue>
6864 0 : nsComputedDOMStyle::DoGetAnimationFillMode()
6865 : {
6866 0 : const nsStyleDisplay* display = StyleDisplay();
6867 :
6868 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
6869 :
6870 0 : MOZ_ASSERT(display->mAnimationFillModeCount > 0,
6871 : "first item must be explicit");
6872 0 : uint32_t i = 0;
6873 0 : do {
6874 0 : const StyleAnimation *animation = &display->mAnimations[i];
6875 0 : RefPtr<nsROCSSPrimitiveValue> fillMode = new nsROCSSPrimitiveValue;
6876 0 : fillMode->SetIdent(
6877 0 : nsCSSProps::ValueToKeywordEnum(
6878 0 : static_cast<int32_t>(animation->GetFillMode()),
6879 0 : nsCSSProps::kAnimationFillModeKTable));
6880 :
6881 0 : valueList->AppendCSSValue(fillMode.forget());
6882 0 : } while (++i < display->mAnimationFillModeCount);
6883 :
6884 0 : return valueList.forget();
6885 : }
6886 :
6887 : already_AddRefed<CSSValue>
6888 0 : nsComputedDOMStyle::DoGetAnimationIterationCount()
6889 : {
6890 0 : const nsStyleDisplay* display = StyleDisplay();
6891 :
6892 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
6893 :
6894 0 : MOZ_ASSERT(display->mAnimationIterationCountCount > 0,
6895 : "first item must be explicit");
6896 0 : uint32_t i = 0;
6897 0 : do {
6898 0 : const StyleAnimation *animation = &display->mAnimations[i];
6899 0 : RefPtr<nsROCSSPrimitiveValue> iterationCount = new nsROCSSPrimitiveValue;
6900 :
6901 0 : float f = animation->GetIterationCount();
6902 : /* Need a nasty hack here to work around an optimizer bug in gcc
6903 : 4.2 on Mac, which somehow gets confused when directly comparing
6904 : a float to the return value of NS_IEEEPositiveInfinity when
6905 : building 32-bit builds. */
6906 : #ifdef XP_MACOSX
6907 : volatile
6908 : #endif
6909 0 : float inf = NS_IEEEPositiveInfinity();
6910 0 : if (f == inf) {
6911 0 : iterationCount->SetIdent(eCSSKeyword_infinite);
6912 : } else {
6913 0 : iterationCount->SetNumber(f);
6914 : }
6915 0 : valueList->AppendCSSValue(iterationCount.forget());
6916 0 : } while (++i < display->mAnimationIterationCountCount);
6917 :
6918 0 : return valueList.forget();
6919 : }
6920 :
6921 : already_AddRefed<CSSValue>
6922 0 : nsComputedDOMStyle::DoGetAnimationPlayState()
6923 : {
6924 0 : const nsStyleDisplay* display = StyleDisplay();
6925 :
6926 0 : RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(true);
6927 :
6928 0 : MOZ_ASSERT(display->mAnimationPlayStateCount > 0,
6929 : "first item must be explicit");
6930 0 : uint32_t i = 0;
6931 0 : do {
6932 0 : const StyleAnimation *animation = &display->mAnimations[i];
6933 0 : RefPtr<nsROCSSPrimitiveValue> playState = new nsROCSSPrimitiveValue;
6934 0 : playState->SetIdent(
6935 0 : nsCSSProps::ValueToKeywordEnum(animation->GetPlayState(),
6936 0 : nsCSSProps::kAnimationPlayStateKTable));
6937 0 : valueList->AppendCSSValue(playState.forget());
6938 0 : } while (++i < display->mAnimationPlayStateCount);
6939 :
6940 0 : return valueList.forget();
6941 : }
6942 :
6943 : static void
6944 0 : MarkComputedStyleMapDirty(const char* aPref, void* aData)
6945 : {
6946 0 : static_cast<nsComputedStyleMap*>(aData)->MarkDirty();
6947 0 : }
6948 :
6949 : already_AddRefed<CSSValue>
6950 0 : nsComputedDOMStyle::DoGetCustomProperty(const nsAString& aPropertyName)
6951 : {
6952 0 : MOZ_ASSERT(nsCSSProps::IsCustomPropertyName(aPropertyName));
6953 :
6954 0 : nsString variableValue;
6955 : const nsAString& name = Substring(aPropertyName,
6956 0 : CSS_CUSTOM_NAME_PREFIX_LENGTH);
6957 0 : bool present = mStyleContext->IsServo()
6958 0 : ? Servo_GetCustomPropertyValue(mStyleContext->ComputedValues(),
6959 : &name, &variableValue)
6960 0 : : StyleVariables()->mVariables.Get(name, variableValue);
6961 0 : if (!present) {
6962 0 : return nullptr;
6963 : }
6964 :
6965 0 : RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
6966 0 : val->SetString(variableValue);
6967 :
6968 0 : return val.forget();
6969 : }
6970 :
6971 : void
6972 0 : nsComputedDOMStyle::ParentChainChanged(nsIContent* aContent)
6973 : {
6974 0 : NS_ASSERTION(mContent == aContent, "didn't we register mContent?");
6975 0 : NS_ASSERTION(mResolvedStyleContext,
6976 : "should have only registered an observer when "
6977 : "mResolvedStyleContext is true");
6978 :
6979 0 : ClearStyleContext();
6980 0 : }
6981 :
6982 : /* static */ nsComputedStyleMap*
6983 7 : nsComputedDOMStyle::GetComputedStyleMap()
6984 : {
6985 : static nsComputedStyleMap map = {
6986 : {
6987 : #define COMPUTED_STYLE_PROP(prop_, method_) \
6988 : { eCSSProperty_##prop_, &nsComputedDOMStyle::DoGet##method_ },
6989 : #include "nsComputedDOMStylePropertyList.h"
6990 : #undef COMPUTED_STYLE_PROP
6991 : }
6992 : };
6993 7 : return ↦
6994 : }
6995 :
6996 : /* static */ void
6997 3 : nsComputedDOMStyle::RegisterPrefChangeCallbacks()
6998 : {
6999 : // Note that this will register callbacks for all properties with prefs, not
7000 : // just those that are implemented on computed style objects, as it's not
7001 : // easy to grab specific property data from nsCSSPropList.h based on the
7002 : // entries iterated in nsComputedDOMStylePropertyList.h.
7003 3 : nsComputedStyleMap* data = GetComputedStyleMap();
7004 : #define REGISTER_CALLBACK(pref_) \
7005 : if (pref_[0]) { \
7006 : Preferences::RegisterCallback(MarkComputedStyleMapDirty, pref_, data); \
7007 : }
7008 : #define CSS_PROP(prop_, id_, method_, flags_, pref_, parsevariant_, \
7009 : kwtable_, stylestruct_, stylestructoffset_, animtype_) \
7010 : REGISTER_CALLBACK(pref_)
7011 : #define CSS_PROP_LIST_INCLUDE_LOGICAL
7012 : #include "nsCSSPropList.h"
7013 : #undef CSS_PROP_LIST_INCLUDE_LOGICAL
7014 : #undef CSS_PROP
7015 : #undef REGISTER_CALLBACK
7016 3 : }
7017 :
7018 : /* static */ void
7019 0 : nsComputedDOMStyle::UnregisterPrefChangeCallbacks()
7020 : {
7021 0 : nsComputedStyleMap* data = GetComputedStyleMap();
7022 : #define UNREGISTER_CALLBACK(pref_) \
7023 : if (pref_[0]) { \
7024 : Preferences::UnregisterCallback(MarkComputedStyleMapDirty, pref_, data); \
7025 : }
7026 : #define CSS_PROP(prop_, id_, method_, flags_, pref_, parsevariant_, \
7027 : kwtable_, stylestruct_, stylestructoffset_, animtype_) \
7028 : UNREGISTER_CALLBACK(pref_)
7029 : #define CSS_PROP_LIST_INCLUDE_LOGICAL
7030 : #include "nsCSSPropList.h"
7031 : #undef CSS_PROP_LIST_INCLUDE_LOGICAL
7032 : #undef CSS_PROP
7033 : #undef UNREGISTER_CALLBACK
7034 0 : }
|