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