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/. */
7 /* Some inline functions declared in cbindgen.toml */
9 #ifndef mozilla_ServoStyleConstsInlines_h
10 #define mozilla_ServoStyleConstsInlines_h
12 #include "mozilla/ServoStyleConsts.h"
13 #include "mozilla/AspectRatio.h"
14 #include "mozilla/EndianUtils.h"
15 #include "mozilla/URLExtraData.h"
16 #include "mozilla/dom/WorkerCommon.h"
17 #include "nsGkAtoms.h"
18 #include "MainThreadUtils.h"
19 #include "nsNetUtil.h"
20 #include <type_traits>
23 // TODO(emilio): there are quite a few other implementations scattered around
24 // that should move here.
28 // We need to explicitly instantiate these so that the clang plugin can see that
29 // they're trivially copyable...
31 // https://github.com/eqrion/cbindgen/issues/402 tracks doing something like
32 // this automatically from cbindgen.
33 template struct StyleStrong
<ComputedStyle
>;
34 template struct StyleStrong
<StyleLockedCssRules
>;
35 template struct StyleStrong
<StyleAnimationValue
>;
36 template struct StyleStrong
<StyleLockedDeclarationBlock
>;
37 template struct StyleStrong
<StyleStylesheetContents
>;
38 template struct StyleStrong
<StyleLockedKeyframe
>;
39 template struct StyleStrong
<StyleLayerBlockRule
>;
40 template struct StyleStrong
<StyleLayerStatementRule
>;
41 template struct StyleStrong
<StyleLockedMediaList
>;
42 template struct StyleStrong
<StyleLockedStyleRule
>;
43 template struct StyleStrong
<StyleLockedImportRule
>;
44 template struct StyleStrong
<StyleLockedKeyframesRule
>;
45 template struct StyleStrong
<StyleMediaRule
>;
46 template struct StyleStrong
<StyleDocumentRule
>;
47 template struct StyleStrong
<StyleNamespaceRule
>;
48 template struct StyleStrong
<StyleLockedPageRule
>;
49 template struct StyleStrong
<StylePropertyRule
>;
50 template struct StyleStrong
<StyleSupportsRule
>;
51 template struct StyleStrong
<StyleFontFeatureValuesRule
>;
52 template struct StyleStrong
<StyleFontPaletteValuesRule
>;
53 template struct StyleStrong
<StyleLockedFontFaceRule
>;
54 template struct StyleStrong
<StyleLockedCounterStyleRule
>;
55 template struct StyleStrong
<StyleContainerRule
>;
56 template struct StyleStrong
<StyleScopeRule
>;
57 template struct StyleStrong
<StyleStartingStyleRule
>;
60 inline void StyleOwnedSlice
<T
>::Clear() {
64 for (size_t i
: IntegerRange(len
)) {
73 inline void StyleOwnedSlice
<T
>::CopyFrom(const StyleOwnedSlice
& aOther
) {
79 ptr
= (T
*)malloc(len
* sizeof(T
));
81 for (const T
& elem
: aOther
.AsSpan()) {
82 new (ptr
+ i
++) T(elem
);
88 inline void StyleOwnedSlice
<T
>::SwapElements(StyleOwnedSlice
& aOther
) {
89 std::swap(ptr
, aOther
.ptr
);
90 std::swap(len
, aOther
.len
);
94 inline StyleOwnedSlice
<T
>::StyleOwnedSlice(const StyleOwnedSlice
& aOther
)
100 inline StyleOwnedSlice
<T
>::StyleOwnedSlice(StyleOwnedSlice
&& aOther
)
101 : StyleOwnedSlice() {
102 SwapElements(aOther
);
105 template <typename T
>
106 inline StyleOwnedSlice
<T
>::StyleOwnedSlice(Vector
<T
>&& aVector
)
107 : StyleOwnedSlice() {
108 if (!aVector
.length()) {
112 // We could handle this if Vector provided the relevant APIs, see bug 1610702.
113 MOZ_DIAGNOSTIC_ASSERT(aVector
.length() == aVector
.capacity(),
114 "Shouldn't over-allocate");
115 len
= aVector
.length();
116 ptr
= aVector
.extractRawBuffer();
118 "How did extractRawBuffer return null if we're not using inline "
122 template <typename T
>
123 inline StyleOwnedSlice
<T
>& StyleOwnedSlice
<T
>::operator=(
124 const StyleOwnedSlice
& aOther
) {
129 template <typename T
>
130 inline StyleOwnedSlice
<T
>& StyleOwnedSlice
<T
>::operator=(
131 StyleOwnedSlice
&& aOther
) {
133 SwapElements(aOther
);
137 template <typename T
>
138 inline StyleOwnedSlice
<T
>::~StyleOwnedSlice() {
142 // This code is basically a C++ port of the Arc::clone() implementation in
143 // servo/components/servo_arc/lib.rs.
144 static constexpr const size_t kStaticRefcount
=
145 std::numeric_limits
<size_t>::max();
146 static constexpr const size_t kMaxRefcount
=
147 std::numeric_limits
<intptr_t>::max();
149 template <typename T
>
150 inline void StyleArcInner
<T
>::IncrementRef() {
151 if (count
.load(std::memory_order_relaxed
) != kStaticRefcount
) {
152 auto old_size
= count
.fetch_add(1, std::memory_order_relaxed
);
153 if (MOZ_UNLIKELY(old_size
> kMaxRefcount
)) {
159 // This is a C++ port-ish of Arc::drop().
160 template <typename T
>
161 inline bool StyleArcInner
<T
>::DecrementRef() {
162 if (count
.load(std::memory_order_relaxed
) == kStaticRefcount
) {
165 if (count
.fetch_sub(1, std::memory_order_release
) != 1) {
169 // TSan doesn't understand std::atomic_thread_fence, so in order
170 // to avoid a false positive for every time a refcounted object
171 // is deleted, we replace the fence with an atomic operation.
172 count
.load(std::memory_order_acquire
);
174 std::atomic_thread_fence(std::memory_order_acquire
);
176 MOZ_LOG_DTOR(this, "ServoArc", 8);
180 template <typename H
, typename T
>
181 inline bool StyleHeaderSlice
<H
, T
>::operator==(
182 const StyleHeaderSlice
& aOther
) const {
183 return header
== aOther
.header
&& AsSpan() == aOther
.AsSpan();
186 template <typename H
, typename T
>
187 inline bool StyleHeaderSlice
<H
, T
>::operator!=(
188 const StyleHeaderSlice
& aOther
) const {
189 return !(*this == aOther
);
192 template <typename H
, typename T
>
193 inline StyleHeaderSlice
<H
, T
>::~StyleHeaderSlice() {
194 for (T
& elem
: Span(data
, len
)) {
199 template <typename H
, typename T
>
200 inline Span
<const T
> StyleHeaderSlice
<H
, T
>::AsSpan() const {
201 // Explicitly specify template argument here to avoid instantiating Span<T>
202 // first and then implicitly converting to Span<const T>
203 return Span
<const T
>{data
, len
};
206 static constexpr const uint64_t kArcSliceCanary
= 0xf3f3f3f3f3f3f3f3;
208 #define ASSERT_CANARY \
209 MOZ_DIAGNOSTIC_ASSERT(_0.p->data.header == kArcSliceCanary, "Uh?");
211 template <typename T
>
212 inline StyleArcSlice
<T
>::StyleArcSlice()
213 : _0(reinterpret_cast<decltype(_0
.p
)>(Servo_StyleArcSlice_EmptyPtr())) {
217 template <typename T
>
218 inline StyleArcSlice
<T
>::StyleArcSlice(
219 const StyleForgottenArcSlicePtr
<T
>& aPtr
) {
220 // See the forget() implementation to see why reinterpret_cast() is ok.
221 _0
.p
= reinterpret_cast<decltype(_0
.p
)>(aPtr
._0
);
225 template <typename T
>
226 inline size_t StyleArcSlice
<T
>::Length() const {
231 template <typename T
>
232 inline bool StyleArcSlice
<T
>::IsEmpty() const {
234 return _0
->IsEmpty();
237 template <typename T
>
238 inline Span
<const T
> StyleArcSlice
<T
>::AsSpan() const {
245 template <typename T
>
246 inline StyleArc
<T
>::StyleArc(const StyleArc
& aOther
) : p(aOther
.p
) {
250 template <typename T
>
251 inline void StyleArc
<T
>::Release() {
252 if (MOZ_LIKELY(!p
->DecrementRef())) {
259 template <typename T
>
260 inline StyleArc
<T
>& StyleArc
<T
>::operator=(const StyleArc
& aOther
) {
269 template <typename T
>
270 inline StyleArc
<T
>& StyleArc
<T
>::operator=(StyleArc
&& aOther
) {
271 std::swap(p
, aOther
.p
);
275 template <typename T
>
276 inline StyleArc
<T
>::~StyleArc() {
280 inline bool StyleAtom::IsStatic() const { return !!(_0
& 1); }
282 inline nsAtom
* StyleAtom::AsAtom() const {
284 return const_cast<nsStaticAtom
*>(&detail::gGkAtoms
.mAtoms
[_0
>> 1]);
286 return reinterpret_cast<nsAtom
*>(_0
);
289 inline void StyleAtom::AddRef() {
295 inline void StyleAtom::Release() {
301 inline StyleAtom::StyleAtom(already_AddRefed
<nsAtom
> aAtom
) {
302 nsAtom
* atom
= aAtom
.take();
303 if (atom
->IsStatic()) {
304 size_t index
= atom
->AsStatic() - &detail::gGkAtoms
.mAtoms
[0];
305 _0
= (index
<< 1) | 1;
307 _0
= reinterpret_cast<uintptr_t>(atom
);
309 MOZ_ASSERT(IsStatic() == atom
->IsStatic());
310 MOZ_ASSERT(AsAtom() == atom
);
313 inline StyleAtom::StyleAtom(nsStaticAtom
* aAtom
)
314 : StyleAtom(do_AddRef(static_cast<nsAtom
*>(aAtom
))) {}
316 inline StyleAtom::StyleAtom(const StyleAtom
& aOther
) : _0(aOther
._0
) {
320 inline StyleAtom
& StyleAtom::operator=(const StyleAtom
& aOther
) {
321 if (MOZ_LIKELY(this != &aOther
)) {
329 inline StyleAtom::~StyleAtom() { Release(); }
331 inline nsAtom
* StyleCustomIdent::AsAtom() const { return _0
.AsAtom(); }
333 inline nsDependentCSubstring
StyleOwnedStr::AsString() const {
334 Span
<const uint8_t> s
= _0
.AsSpan();
335 return nsDependentCSubstring(reinterpret_cast<const char*>(s
.Elements()),
339 template <typename T
>
340 inline Span
<const T
> StyleGenericTransform
<T
>::Operations() const {
344 template <typename T
>
345 inline bool StyleGenericTransform
<T
>::IsNone() const {
346 return Operations().IsEmpty();
349 inline StyleAngle
StyleAngle::Zero() { return {0.0f
}; }
351 inline float StyleAngle::ToDegrees() const { return _0
; }
353 inline double StyleAngle::ToRadians() const {
354 return double(ToDegrees()) * M_PI
/ 180.0;
357 inline bool StyleUrlExtraData::IsShared() const { return !!(_0
& 1); }
359 inline StyleUrlExtraData::~StyleUrlExtraData() {
361 reinterpret_cast<URLExtraData
*>(_0
)->Release();
365 inline const URLExtraData
& StyleUrlExtraData::get() const {
367 return *URLExtraData::sShared
[_0
>> 1];
369 return *reinterpret_cast<const URLExtraData
*>(_0
);
372 inline nsDependentCSubstring
StyleCssUrl::SpecifiedSerialization() const {
373 return _0
->serialization
.AsString();
376 inline const URLExtraData
& StyleCssUrl::ExtraData() const {
377 return _0
->extra_data
.get();
380 inline StyleLoadData
& StyleCssUrl::LoadData() const {
381 if (MOZ_LIKELY(_0
->load_data
.tag
== StyleLoadDataSource::Tag::Owned
)) {
382 MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread() ||
383 dom::IsCurrentThreadRunningWorker());
384 return const_cast<StyleLoadData
&>(_0
->load_data
.owned
._0
);
386 MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread(),
387 "Lazy load datas should come from user-agent sheets, "
388 "which don't make sense on workers");
389 return const_cast<StyleLoadData
&>(*Servo_LoadData_GetLazy(&_0
->load_data
));
392 inline nsIURI
* StyleCssUrl::GetURI() const {
393 auto& loadData
= LoadData();
394 if (!(loadData
.flags
& StyleLoadDataFlags::TRIED_TO_RESOLVE_URI
)) {
395 loadData
.flags
|= StyleLoadDataFlags::TRIED_TO_RESOLVE_URI
;
396 nsDependentCSubstring serialization
= SpecifiedSerialization();
397 // https://drafts.csswg.org/css-values-4/#url-empty:
399 // If the value of the url() is the empty string (like url("") or
400 // url()), the url must resolve to an invalid resource (similar to what
401 // the url about:invalid does).
403 if (!serialization
.IsEmpty()) {
404 RefPtr
<nsIURI
> resolved
;
405 NS_NewURI(getter_AddRefs(resolved
), serialization
, nullptr,
406 ExtraData().BaseURI());
407 loadData
.resolved_uri
= resolved
.forget().take();
410 return loadData
.resolved_uri
;
413 inline nsDependentCSubstring
StyleComputedUrl::SpecifiedSerialization() const {
414 return _0
.SpecifiedSerialization();
416 inline const URLExtraData
& StyleComputedUrl::ExtraData() const {
417 return _0
.ExtraData();
419 inline StyleLoadData
& StyleComputedUrl::LoadData() const {
420 return _0
.LoadData();
422 inline StyleCorsMode
StyleComputedUrl::CorsMode() const {
423 return _0
._0
->cors_mode
;
425 inline nsIURI
* StyleComputedUrl::GetURI() const { return _0
.GetURI(); }
427 inline bool StyleComputedUrl::IsLocalRef() const {
428 return Servo_CssUrl_IsLocalRef(&_0
);
431 inline bool StyleComputedUrl::HasRef() const {
435 if (nsIURI
* uri
= GetURI()) {
437 return NS_SUCCEEDED(uri
->GetHasRef(&hasRef
)) && hasRef
;
442 inline bool StyleComputedImageUrl::IsImageResolved() const {
443 return bool(LoadData().flags
& StyleLoadDataFlags::TRIED_TO_RESOLVE_IMAGE
);
446 inline imgRequestProxy
* StyleComputedImageUrl::GetImage() const {
447 MOZ_ASSERT(IsImageResolved());
448 return LoadData().resolved_image
;
452 inline bool StyleGradient::Repeating() const {
454 return bool(AsLinear().flags
& StyleGradientFlags::REPEATING
);
457 return bool(AsRadial().flags
& StyleGradientFlags::REPEATING
);
459 return bool(AsConic().flags
& StyleGradientFlags::REPEATING
);
463 bool StyleGradient::IsOpaque() const;
466 inline const StyleColorInterpolationMethod
&
467 StyleGradient::ColorInterpolationMethod() const {
469 return AsLinear().color_interpolation_method
;
472 return AsRadial().color_interpolation_method
;
474 return AsConic().color_interpolation_method
;
477 template <typename Integer
>
478 inline StyleGenericGridLine
<Integer
>::StyleGenericGridLine()
479 : ident
{StyleAtom(nsGkAtoms::_empty
)}, line_num(0), is_span(false) {}
482 inline nsAtom
* StyleGridLine::LineName() const {
483 return ident
.AsAtom();
487 inline bool StyleGridLine::IsAuto() const {
488 return LineName()->IsEmpty() && line_num
== 0 && !is_span
;
491 using LengthPercentage
= StyleLengthPercentage
;
492 using LengthPercentageOrAuto
= StyleLengthPercentageOrAuto
;
493 using NonNegativeLengthPercentage
= StyleNonNegativeLengthPercentage
;
494 using NonNegativeLengthPercentageOrAuto
=
495 StyleNonNegativeLengthPercentageOrAuto
;
496 using NonNegativeLengthPercentageOrNormal
=
497 StyleNonNegativeLengthPercentageOrNormal
;
498 using Length
= StyleLength
;
499 using LengthOrAuto
= StyleLengthOrAuto
;
500 using NonNegativeLength
= StyleNonNegativeLength
;
501 using NonNegativeLengthOrAuto
= StyleNonNegativeLengthOrAuto
;
502 using BorderRadius
= StyleBorderRadius
;
504 bool StyleCSSPixelLength::IsZero() const { return _0
== 0.0f
; }
506 void StyleCSSPixelLength::ScaleBy(float aScale
) { _0
*= aScale
; }
508 StyleCSSPixelLength
StyleCSSPixelLength::ScaledBy(float aScale
) const {
509 return FromPixels(ToCSSPixels() * aScale
);
513 static inline nscoord
DefaultPercentLengthToAppUnits(float aPixelLength
) {
514 return NSToCoordTruncClamped(aPixelLength
);
517 static inline nscoord
DefaultLengthToAppUnits(float aPixelLength
) {
518 // We want to round lengths rounding 0.5 away from zero, instead of the
519 // default behavior of NSToCoordRound{,WithClamp} which do floor(x + 0.5).
520 float length
= aPixelLength
* float(mozilla::AppUnitsPerCSSPixel());
521 if (length
>= float(nscoord_MAX
)) {
524 if (length
<= float(nscoord_MIN
)) {
527 return NSToIntRound(length
);
529 } // namespace detail
531 nscoord
StyleCSSPixelLength::ToAppUnits() const {
533 // Avoid the expensive FP math below.
536 return detail::DefaultLengthToAppUnits(_0
);
539 bool LengthPercentage::IsLength() const { return Tag() == TAG_LENGTH
; }
541 StyleLengthPercentageUnion::StyleLengthPercentageUnion() {
542 length
= {TAG_LENGTH
, {0.0f
}};
543 MOZ_ASSERT(IsLength());
546 static_assert(sizeof(LengthPercentage
) == sizeof(uint64_t), "");
548 Length
& LengthPercentage::AsLength() {
549 MOZ_ASSERT(IsLength());
550 return length
.length
;
553 const Length
& LengthPercentage::AsLength() const {
554 return const_cast<LengthPercentage
*>(this)->AsLength();
557 bool LengthPercentage::IsPercentage() const { return Tag() == TAG_PERCENTAGE
; }
559 StylePercentage
& LengthPercentage::AsPercentage() {
560 MOZ_ASSERT(IsPercentage());
561 return percentage
.percentage
;
564 const StylePercentage
& LengthPercentage::AsPercentage() const {
565 return const_cast<LengthPercentage
*>(this)->AsPercentage();
568 bool LengthPercentage::IsCalc() const { return Tag() == TAG_CALC
; }
570 StyleCalcLengthPercentage
& LengthPercentage::AsCalc() {
571 MOZ_ASSERT(IsCalc());
572 // NOTE: in 32-bits, the pointer is not swapped, and goes along with the tag.
576 return *reinterpret_cast<StyleCalcLengthPercentage
*>(
577 NativeEndian::swapFromLittleEndian(calc
.ptr
));
581 const StyleCalcLengthPercentage
& LengthPercentage::AsCalc() const {
582 return const_cast<LengthPercentage
*>(this)->AsCalc();
585 StyleLengthPercentageUnion::StyleLengthPercentageUnion(const Self
& aOther
) {
586 if (aOther
.IsLength()) {
587 length
= {TAG_LENGTH
, aOther
.AsLength()};
588 } else if (aOther
.IsPercentage()) {
589 percentage
= {TAG_PERCENTAGE
, aOther
.AsPercentage()};
591 MOZ_ASSERT(aOther
.IsCalc());
592 auto* ptr
= new StyleCalcLengthPercentage(aOther
.AsCalc());
593 // NOTE: in 32-bits, the pointer is not swapped, and goes along with the
600 NativeEndian::swapToLittleEndian(reinterpret_cast<uintptr_t>(ptr
)),
604 MOZ_ASSERT(Tag() == aOther
.Tag());
607 StyleLengthPercentageUnion::~StyleLengthPercentageUnion() {
613 LengthPercentage
& LengthPercentage::operator=(const LengthPercentage
& aOther
) {
614 if (this != &aOther
) {
615 this->~LengthPercentage();
616 new (this) LengthPercentage(aOther
);
621 bool LengthPercentage::operator==(const LengthPercentage
& aOther
) const {
622 if (Tag() != aOther
.Tag()) {
626 return AsLength() == aOther
.AsLength();
628 if (IsPercentage()) {
629 return AsPercentage() == aOther
.AsPercentage();
631 return AsCalc() == aOther
.AsCalc();
634 bool LengthPercentage::operator!=(const LengthPercentage
& aOther
) const {
635 return !(*this == aOther
);
638 LengthPercentage
LengthPercentage::Zero() { return {}; }
640 LengthPercentage
LengthPercentage::FromPixels(CSSCoord aCoord
) {
642 MOZ_ASSERT(l
.IsLength());
643 l
.length
.length
= {aCoord
};
647 LengthPercentage
LengthPercentage::FromAppUnits(nscoord aCoord
) {
648 return FromPixels(CSSPixel::FromAppUnits(aCoord
));
651 LengthPercentage
LengthPercentage::FromPercentage(float aPercentage
) {
653 l
.percentage
= {TAG_PERCENTAGE
, {aPercentage
}};
657 bool LengthPercentage::HasPercent() const { return IsPercentage() || IsCalc(); }
659 bool LengthPercentage::ConvertsToLength() const { return IsLength(); }
661 nscoord
LengthPercentage::ToLength() const {
662 MOZ_ASSERT(ConvertsToLength());
663 return AsLength().ToAppUnits();
666 CSSCoord
LengthPercentage::ToLengthInCSSPixels() const {
667 MOZ_ASSERT(ConvertsToLength());
668 return AsLength().ToCSSPixels();
671 bool LengthPercentage::ConvertsToPercentage() const { return IsPercentage(); }
673 float LengthPercentage::ToPercentage() const {
674 MOZ_ASSERT(ConvertsToPercentage());
675 return AsPercentage()._0
;
678 bool LengthPercentage::HasLengthAndPercentage() const {
682 MOZ_ASSERT(!ConvertsToLength() && !ConvertsToPercentage(),
683 "Should've been simplified earlier");
687 bool LengthPercentage::IsDefinitelyZero() const {
689 return AsLength().IsZero();
691 if (IsPercentage()) {
692 return AsPercentage()._0
== 0.0f
;
694 // calc() should've been simplified to a percentage.
698 CSSCoord
StyleCalcLengthPercentage::ResolveToCSSPixels(CSSCoord aBasis
) const {
699 return Servo_ResolveCalcLengthPercentage(this, aBasis
);
702 nscoord
StyleCalcLengthPercentage::Resolve(nscoord aBasis
) const {
703 return detail::DefaultLengthToAppUnits(
704 ResolveToCSSPixels(CSSPixel::FromAppUnits(aBasis
)));
708 void StyleCalcNode::ScaleLengthsBy(float);
710 CSSCoord
LengthPercentage::ResolveToCSSPixels(CSSCoord aPercentageBasis
) const {
712 return AsLength().ToCSSPixels();
714 if (IsPercentage()) {
715 return AsPercentage()._0
* aPercentageBasis
;
717 return AsCalc().ResolveToCSSPixels(aPercentageBasis
);
720 template <typename T
>
721 CSSCoord
LengthPercentage::ResolveToCSSPixelsWith(T aPercentageGetter
) const {
722 static_assert(std::is_same_v
<decltype(aPercentageGetter()), CSSCoord
>);
723 if (ConvertsToLength()) {
724 return ToLengthInCSSPixels();
726 return ResolveToCSSPixels(aPercentageGetter());
729 template <typename T
, typename PercentRounder
>
730 nscoord
LengthPercentage::Resolve(T aPercentageGetter
,
731 PercentRounder aPercentRounder
) const {
732 static_assert(std::is_same_v
<decltype(aPercentageGetter()), nscoord
>);
733 static_assert(std::is_same_v
<decltype(aPercentRounder(1.0f
)), nscoord
>);
734 if (ConvertsToLength()) {
737 if (IsPercentage() && AsPercentage()._0
== 0.0f
) {
740 nscoord basis
= aPercentageGetter();
741 if (IsPercentage()) {
742 return aPercentRounder(basis
* AsPercentage()._0
);
744 return AsCalc().Resolve(basis
);
747 nscoord
LengthPercentage::Resolve(nscoord aPercentageBasis
) const {
748 return Resolve([=] { return aPercentageBasis
; },
749 detail::DefaultPercentLengthToAppUnits
);
752 template <typename T
>
753 nscoord
LengthPercentage::Resolve(T aPercentageGetter
) const {
754 return Resolve(aPercentageGetter
, detail::DefaultPercentLengthToAppUnits
);
757 template <typename PercentRounder
>
758 nscoord
LengthPercentage::Resolve(nscoord aPercentageBasis
,
759 PercentRounder aPercentRounder
) const {
760 return Resolve([aPercentageBasis
] { return aPercentageBasis
; },
764 void LengthPercentage::ScaleLengthsBy(float aScale
) {
766 AsLength().ScaleBy(aScale
);
769 AsCalc().node
.ScaleLengthsBy(aScale
);
773 #define IMPL_LENGTHPERCENTAGE_FORWARDS(ty_) \
775 inline bool ty_::HasPercent() const { \
776 return IsLengthPercentage() && AsLengthPercentage().HasPercent(); \
779 inline bool ty_::ConvertsToLength() const { \
780 return IsLengthPercentage() && AsLengthPercentage().ConvertsToLength(); \
783 inline bool ty_::HasLengthAndPercentage() const { \
784 return IsLengthPercentage() && \
785 AsLengthPercentage().HasLengthAndPercentage(); \
788 inline nscoord ty_::ToLength() const { \
789 MOZ_ASSERT(ConvertsToLength()); \
790 return AsLengthPercentage().ToLength(); \
793 inline bool ty_::ConvertsToPercentage() const { \
794 return IsLengthPercentage() && \
795 AsLengthPercentage().ConvertsToPercentage(); \
798 inline float ty_::ToPercentage() const { \
799 MOZ_ASSERT(ConvertsToPercentage()); \
800 return AsLengthPercentage().ToPercentage(); \
803 IMPL_LENGTHPERCENTAGE_FORWARDS(LengthPercentageOrAuto
)
804 IMPL_LENGTHPERCENTAGE_FORWARDS(StyleSize
)
805 IMPL_LENGTHPERCENTAGE_FORWARDS(StyleMaxSize
)
808 inline bool LengthOrAuto::IsLength() const {
809 return IsLengthPercentage();
813 inline const Length
& LengthOrAuto::AsLength() const {
814 return AsLengthPercentage();
818 inline nscoord
LengthOrAuto::ToLength() const {
819 return AsLength().ToAppUnits();
823 inline bool StyleFlexBasis::IsAuto() const {
824 return IsSize() && AsSize().IsAuto();
828 inline bool StyleSize::BehavesLikeInitialValueOnBlockAxis() const {
829 return IsAuto() || !IsLengthPercentage();
833 inline bool StyleMaxSize::BehavesLikeInitialValueOnBlockAxis() const {
834 return IsNone() || !IsLengthPercentage();
838 inline bool StyleBackgroundSize::IsInitialValue() const {
839 return IsExplicitSize() && explicit_size
.width
.IsAuto() &&
840 explicit_size
.height
.IsAuto();
843 template <typename T
>
844 const T
& StyleRect
<T
>::Get(mozilla::Side aSide
) const {
845 static_assert(sizeof(StyleRect
<T
>) == sizeof(T
) * 4, "");
846 static_assert(alignof(StyleRect
<T
>) == alignof(T
), "");
847 return reinterpret_cast<const T
*>(this)[aSide
];
850 template <typename T
>
851 T
& StyleRect
<T
>::Get(mozilla::Side aSide
) {
852 return const_cast<T
&>(static_cast<const StyleRect
&>(*this).Get(aSide
));
855 template <typename T
>
856 template <typename Predicate
>
857 bool StyleRect
<T
>::All(Predicate aPredicate
) const {
858 return aPredicate(_0
) && aPredicate(_1
) && aPredicate(_2
) && aPredicate(_3
);
861 template <typename T
>
862 template <typename Predicate
>
863 bool StyleRect
<T
>::Any(Predicate aPredicate
) const {
864 return aPredicate(_0
) || aPredicate(_1
) || aPredicate(_2
) || aPredicate(_3
);
868 inline const LengthPercentage
& BorderRadius::Get(HalfCorner aCorner
) const {
869 static_assert(sizeof(BorderRadius
) == sizeof(LengthPercentage
) * 8, "");
870 static_assert(alignof(BorderRadius
) == alignof(LengthPercentage
), "");
871 const auto* self
= reinterpret_cast<const LengthPercentage
*>(this);
872 return self
[aCorner
];
876 inline bool StyleTrackBreadth::HasPercent() const {
877 return IsBreadth() && AsBreadth().HasPercent();
880 // Implemented in nsStyleStructs.cpp
882 bool StyleTransform::HasPercent() const;
885 inline bool StyleTransformOrigin::HasPercent() const {
886 // NOTE(emilio): `depth` is just a `<length>` so doesn't have a percentage at
888 return horizontal
.HasPercent() || vertical
.HasPercent();
892 inline Maybe
<size_t> StyleGridTemplateComponent::RepeatAutoIndex() const {
893 if (!IsTrackList()) {
896 const auto& list
= *AsTrackList();
897 return list
.auto_repeat_index
< list
.values
.Length()
898 ? Some(list
.auto_repeat_index
)
903 inline bool StyleGridTemplateComponent::HasRepeatAuto() const {
904 return RepeatAutoIndex().isSome();
908 inline Span
<const StyleGenericTrackListValue
<LengthPercentage
, StyleInteger
>>
909 StyleGridTemplateComponent::TrackListValues() const {
911 return AsTrackList()->values
.AsSpan();
917 inline const StyleGenericTrackRepeat
<LengthPercentage
, StyleInteger
>*
918 StyleGridTemplateComponent::GetRepeatAutoValue() const {
919 auto index
= RepeatAutoIndex();
923 return &TrackListValues()[*index
].AsTrackRepeat();
926 constexpr const auto kPaintOrderShift
= StylePAINT_ORDER_SHIFT
;
927 constexpr const auto kPaintOrderMask
= StylePAINT_ORDER_MASK
;
930 inline nsRect StyleGenericClipRect
<LengthOrAuto
>::ToLayoutRect(
931 nscoord aAutoSize
) const {
932 nscoord x
= left
.IsLength() ? left
.ToLength() : 0;
933 nscoord y
= top
.IsLength() ? top
.ToLength() : 0;
934 nscoord width
= right
.IsLength() ? right
.ToLength() - x
: aAutoSize
;
935 nscoord height
= bottom
.IsLength() ? bottom
.ToLength() - y
: aAutoSize
;
936 return nsRect(x
, y
, width
, height
);
939 using RestyleHint
= StyleRestyleHint
;
941 inline RestyleHint
RestyleHint::RestyleSubtree() {
942 return RESTYLE_SELF
| RESTYLE_DESCENDANTS
;
945 inline RestyleHint
RestyleHint::RecascadeSubtree() {
946 return RECASCADE_SELF
| RECASCADE_DESCENDANTS
;
949 inline RestyleHint
RestyleHint::ForAnimations() {
950 return RESTYLE_CSS_TRANSITIONS
| RESTYLE_CSS_ANIMATIONS
| RESTYLE_SMIL
;
953 inline bool RestyleHint::DefinitelyRecascadesAllSubtree() const {
954 if (!(*this & (RECASCADE_DESCENDANTS
| RESTYLE_DESCENDANTS
))) {
957 return bool(*this & (RESTYLE_SELF
| RECASCADE_SELF
));
961 ImageResolution
StyleImage::GetResolution(const ComputedStyle
&) const;
964 inline const StyleImage
& StyleImage::FinalImage() const {
968 const auto& set
= *AsImageSet();
969 auto items
= set
.items
.AsSpan();
970 if (MOZ_LIKELY(set
.selected_index
< items
.Length())) {
971 return items
[set
.selected_index
].image
.FinalImage();
973 static auto sNone
= StyleImage::None();
978 inline bool StyleImage::IsImageRequestType() const {
979 const auto& finalImage
= FinalImage();
980 return finalImage
.IsUrl();
984 inline const StyleComputedImageUrl
* StyleImage::GetImageRequestURLValue()
986 const auto& finalImage
= FinalImage();
987 if (finalImage
.IsUrl()) {
988 return &finalImage
.AsUrl();
994 inline imgRequestProxy
* StyleImage::GetImageRequest() const {
995 const auto* url
= GetImageRequestURLValue();
996 return url
? url
->GetImage() : nullptr;
1000 inline bool StyleImage::IsResolved() const {
1001 const auto* url
= GetImageRequestURLValue();
1002 return !url
|| url
->IsImageResolved();
1006 bool StyleImage::IsOpaque() const;
1008 bool StyleImage::IsSizeAvailable() const;
1010 bool StyleImage::IsComplete() const;
1012 void StyleImage::ResolveImage(dom::Document
&, const StyleImage
*);
1015 inline AspectRatio StyleRatio
<StyleNonNegativeNumber
>::ToLayoutRatio(
1016 UseBoxSizing aUseBoxSizing
) const {
1017 // 0/1, 1/0, and 0/0 are all degenerate ratios (which behave as auto), and we
1018 // always return 0.0f.
1019 // https://drafts.csswg.org/css-values-4/#degenerate-ratio
1020 return AspectRatio::FromSize(_0
, _1
, aUseBoxSizing
);
1024 inline AspectRatio
StyleAspectRatio::ToLayoutRatio() const {
1025 return HasRatio() ? ratio
.AsRatio().ToLayoutRatio(auto_
? UseBoxSizing::No
1026 : UseBoxSizing::Yes
)
1030 inline void StyleFontWeight::ToString(nsACString
& aString
) const {
1031 Servo_FontWeight_ToCss(this, &aString
);
1034 inline void StyleFontStretch::ToString(nsACString
& aString
) const {
1035 Servo_FontStretch_ToCss(this, &aString
);
1038 inline void StyleFontStyle::ToString(nsACString
& aString
) const {
1039 Servo_FontStyle_ToCss(this, &aString
);
1042 inline bool StyleFontWeight::IsBold() const { return *this >= BOLD_THRESHOLD
; }
1044 inline bool StyleFontStyle::IsItalic() const { return *this == ITALIC
; }
1046 inline bool StyleFontStyle::IsOblique() const {
1047 return !IsItalic() && !IsNormal();
1050 inline float StyleFontStyle::ObliqueAngle() const {
1051 MOZ_ASSERT(IsOblique());
1055 inline float StyleFontStyle::SlantAngle() const {
1056 return IsNormal() ? 0 : IsItalic() ? DEFAULT_OBLIQUE_DEGREES
: ObliqueAngle();
1059 using FontStretch
= StyleFontStretch
;
1060 using FontSlantStyle
= StyleFontStyle
;
1061 using FontWeight
= StyleFontWeight
;
1064 inline double StyleComputedTimingFunction::At(double aPortion
,
1065 bool aBeforeFlag
) const {
1066 return Servo_EasingFunctionAt(
1068 aBeforeFlag
? StyleEasingBeforeFlag::Set
: StyleEasingBeforeFlag::Unset
);
1072 inline void StyleComputedTimingFunction::AppendToString(
1073 nsACString
& aOut
) const {
1074 return Servo_SerializeEasing(this, &aOut
);
1078 inline double StyleComputedTimingFunction::GetPortion(
1079 const Maybe
<StyleComputedTimingFunction
>& aFn
, double aPortion
,
1081 return aFn
? aFn
->At(aPortion
, aBeforeFlag
) : aPortion
;
1086 inline LengthPercentageOrAuto
LengthPercentageOrAuto::Zero() {
1087 return LengthPercentage(LengthPercentage::Zero());
1091 inline StyleViewTimelineInset::StyleGenericViewTimelineInset()
1092 : start(LengthPercentageOrAuto::Auto()),
1093 end(LengthPercentageOrAuto::Auto()) {}
1095 inline StyleDisplayOutside
StyleDisplay::Outside() const {
1096 return StyleDisplayOutside((_0
& OUTSIDE_MASK
) >> OUTSIDE_SHIFT
);
1099 inline StyleDisplayInside
StyleDisplay::Inside() const {
1100 return StyleDisplayInside(_0
& INSIDE_MASK
);
1103 inline bool StyleDisplay::IsListItem() const { return _0
& LIST_ITEM_MASK
; }
1105 inline bool StyleDisplay::IsInternalTable() const {
1106 return Outside() == StyleDisplayOutside::InternalTable
;
1109 inline bool StyleDisplay::IsInternalTableExceptCell() const {
1110 return IsInternalTable() && *this != TableCell
;
1113 inline bool StyleDisplay::IsInternalRuby() const {
1114 return Outside() == StyleDisplayOutside::InternalRuby
;
1117 inline bool StyleDisplay::IsRuby() const {
1118 return Inside() == StyleDisplayInside::Ruby
|| IsInternalRuby();
1121 inline bool StyleDisplay::IsInlineFlow() const {
1122 return Outside() == StyleDisplayOutside::Inline
&&
1123 Inside() == StyleDisplayInside::Flow
;
1126 inline bool StyleDisplay::IsInlineInside() const {
1127 return IsInlineFlow() || IsRuby();
1130 inline bool StyleDisplay::IsInlineOutside() const {
1131 return Outside() == StyleDisplayOutside::Inline
|| IsInternalRuby();
1134 inline float StyleZoom::Zoom(float aValue
) const {
1138 return ToFloat() * aValue
;
1141 inline float StyleZoom::Unzoom(float aValue
) const {
1145 return aValue
/ ToFloat();
1148 inline nscoord
StyleZoom::ZoomCoord(nscoord aValue
) const {
1152 return NSToCoordRoundWithClamp(Zoom(float(aValue
)));
1155 inline nscoord
StyleZoom::UnzoomCoord(nscoord aValue
) const {
1159 return NSToCoordRoundWithClamp(Unzoom(float(aValue
)));
1162 inline nsSize
StyleZoom::Zoom(const nsSize
& aValue
) const {
1166 return nsSize(ZoomCoord(aValue
.Width()), ZoomCoord(aValue
.Height()));
1169 inline nsSize
StyleZoom::Unzoom(const nsSize
& aValue
) const {
1173 return nsSize(UnzoomCoord(aValue
.Width()), UnzoomCoord(aValue
.Height()));
1176 inline nsPoint
StyleZoom::Zoom(const nsPoint
& aValue
) const {
1180 return nsPoint(ZoomCoord(aValue
.X()), ZoomCoord(aValue
.Y()));
1183 inline nsPoint
StyleZoom::Unzoom(const nsPoint
& aValue
) const {
1187 return nsPoint(UnzoomCoord(aValue
.X()), UnzoomCoord(aValue
.Y()));
1190 inline nsRect
StyleZoom::Zoom(const nsRect
& aValue
) const {
1194 return nsRect(ZoomCoord(aValue
.X()), ZoomCoord(aValue
.Y()),
1195 ZoomCoord(aValue
.Width()), ZoomCoord(aValue
.Height()));
1198 inline nsRect
StyleZoom::Unzoom(const nsRect
& aValue
) const {
1202 return nsRect(UnzoomCoord(aValue
.X()), UnzoomCoord(aValue
.Y()),
1203 UnzoomCoord(aValue
.Width()), UnzoomCoord(aValue
.Height()));
1207 inline gfx::Point StyleCoordinatePair
<StyleCSSFloat
>::ToGfxPoint(
1208 const CSSSize
* aBasis
) const {
1209 return gfx::Point(x
, y
);
1213 inline gfx::Point StyleCoordinatePair
<LengthPercentage
>::ToGfxPoint(
1214 const CSSSize
* aBasis
) const {
1216 return gfx::Point(x
.ResolveToCSSPixels(aBasis
->Width()),
1217 y
.ResolveToCSSPixels(aBasis
->Height()));
1220 } // namespace mozilla