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 /*
8 * structs that contain the data provided by nsStyleContext, the
9 * internal API for computed style data for an element
10 */
11
12 #ifndef nsStyleStruct_h___
13 #define nsStyleStruct_h___
14
15 #include "mozilla/ArenaObjectID.h"
16 #include "mozilla/Attributes.h"
17 #include "mozilla/CSSVariableValues.h"
18 #include "mozilla/Maybe.h"
19 #include "mozilla/SheetType.h"
20 #include "mozilla/StaticPtr.h"
21 #include "mozilla/StyleComplexColor.h"
22 #include "mozilla/StyleStructContext.h"
23 #include "mozilla/UniquePtr.h"
24 #include "nsColor.h"
25 #include "nsCoord.h"
26 #include "nsMargin.h"
27 #include "nsFont.h"
28 #include "nsStyleCoord.h"
29 #include "nsStyleConsts.h"
30 #include "nsChangeHint.h"
31 #include "nsPresContext.h"
32 #include "nsCOMPtr.h"
33 #include "nsCOMArray.h"
34 #include "nsTArray.h"
35 #include "nsCSSValue.h"
36 #include "imgRequestProxy.h"
37 #include "Orientation.h"
38 #include "CounterStyleManager.h"
39 #include <cstddef> // offsetof()
40 #include <utility>
41 #include "X11UndefineNone.h"
42
43 class nsIFrame;
44 class nsIURI;
45 class nsStyleContext;
46 class nsTextFrame;
47 class imgIContainer;
48 struct nsStyleVisibility;
49 namespace mozilla {
50 namespace dom {
51 class ImageTracker;
52 } // namespace dom
53 } // namespace mozilla
54
55 // Includes nsStyleStructID.
56 #include "nsStyleStructFwd.h"
57
58 // Bits for each struct.
59 // NS_STYLE_INHERIT_BIT defined in nsStyleStructFwd.h
60 #define NS_STYLE_INHERIT_MASK 0x000ffffff
61
62 // Bits for inherited structs.
63 #define NS_STYLE_INHERITED_STRUCT_MASK \
64 ((nsStyleStructID_size_t(1) << nsStyleStructID_Inherited_Count) - 1)
65 // Bits for reset structs.
66 #define NS_STYLE_RESET_STRUCT_MASK \
67 (((nsStyleStructID_size_t(1) << nsStyleStructID_Reset_Count) - 1) \
68 << nsStyleStructID_Inherited_Count)
69
70 // Additional bits for nsStyleContext's mBits:
71 // See nsStyleContext::HasTextDecorationLines
72 #define NS_STYLE_HAS_TEXT_DECORATION_LINES 0x001000000
73 // See nsStyleContext::HasPseudoElementData.
74 #define NS_STYLE_HAS_PSEUDO_ELEMENT_DATA 0x002000000
75 // See nsStyleContext::RelevantLinkIsVisited
76 #define NS_STYLE_RELEVANT_LINK_VISITED 0x004000000
77 // See nsStyleContext::IsStyleIfVisited
78 #define NS_STYLE_IS_STYLE_IF_VISITED 0x008000000
79 // See nsStyleContext::HasChildThatUsesGrandancestorStyle
80 #define NS_STYLE_CHILD_USES_GRANDANCESTOR_STYLE 0x010000000
81 // See nsStyleContext::IsShared
82 #define NS_STYLE_IS_SHARED 0x020000000
83 // See nsStyleContext::AssertStructsNotUsedElsewhere
84 // (This bit is currently only used in #ifdef DEBUG code.)
85 #define NS_STYLE_IS_GOING_AWAY 0x040000000
86 // See nsStyleContext::ShouldSuppressLineBreak
87 #define NS_STYLE_SUPPRESS_LINEBREAK 0x080000000
88 // See nsStyleContext::IsInDisplayNoneSubtree
89 #define NS_STYLE_IN_DISPLAY_NONE_SUBTREE 0x100000000
90 // See nsStyleContext::FindChildWithRules
91 #define NS_STYLE_INELIGIBLE_FOR_SHARING 0x200000000
92 // See nsStyleContext::HasChildThatUsesResetStyle
93 #define NS_STYLE_HAS_CHILD_THAT_USES_RESET_STYLE 0x400000000
94 // See nsStyleContext::IsTextCombined
95 #define NS_STYLE_IS_TEXT_COMBINED 0x800000000
96 // See nsStyleContext::GetPseudoEnum
97 #define NS_STYLE_CONTEXT_TYPE_SHIFT 36
98
99 // Additional bits for nsRuleNode's mDependentBits:
100 #define NS_RULE_NODE_IS_ANIMATION_RULE 0x01000000
101 // Free bit 0x02000000
102 #define NS_RULE_NODE_USED_DIRECTLY 0x04000000
103 #define NS_RULE_NODE_IS_IMPORTANT 0x08000000
104 #define NS_RULE_NODE_LEVEL_MASK 0xf0000000
105 #define NS_RULE_NODE_LEVEL_SHIFT 28
106
107 // Additional bits for nsRuleNode's mNoneBits:
108 #define NS_RULE_NODE_HAS_ANIMATION_DATA 0x80000000
109
110 static_assert(int(mozilla::SheetType::Count) - 1 <=
111 (NS_RULE_NODE_LEVEL_MASK >> NS_RULE_NODE_LEVEL_SHIFT),
112 "NS_RULE_NODE_LEVEL_MASK cannot fit SheetType");
113
114 static_assert(NS_STYLE_INHERIT_MASK == (1 << nsStyleStructID_Length) - 1,
115 "NS_STYLE_INHERIT_MASK is not correct");
116
117 static_assert((NS_RULE_NODE_IS_ANIMATION_RULE & NS_STYLE_INHERIT_MASK) == 0,
118 "NS_RULE_NODE_IS_ANIMATION_RULE must not overlap the style struct bits.");
119
120 namespace mozilla {
121
122 struct Position {
123 using Coord = nsStyleCoord::CalcValue;
124
125 Coord mXPosition, mYPosition;
126
127 // Initialize nothing
PositionPosition128 Position() {}
129
130 // Sets both mXPosition and mYPosition to the given percent value for the
131 // initial property-value (e.g. 0.0f for "0% 0%", or 0.5f for "50% 50%")
132 void SetInitialPercentValues(float aPercentVal);
133
134 // Sets both mXPosition and mYPosition to 0 (app units) for the
135 // initial property-value as a length with no percentage component.
136 void SetInitialZeroValues();
137
138 // True if the effective background image position described by this depends
139 // on the size of the corresponding frame.
DependsOnPositioningAreaSizePosition140 bool DependsOnPositioningAreaSize() const {
141 return mXPosition.mPercent != 0.0f || mYPosition.mPercent != 0.0f;
142 }
143
144 bool operator==(const Position& aOther) const {
145 return mXPosition == aOther.mXPosition &&
146 mYPosition == aOther.mYPosition;
147 }
148 bool operator!=(const Position& aOther) const {
149 return !(*this == aOther);
150 }
151 };
152
153 } // namespace mozilla
154
155 // The lifetime of these objects is managed by the presshell's arena.
156 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleFont
157 {
158 nsStyleFont(const nsFont& aFont, StyleStructContext aContext);
159 nsStyleFont(const nsStyleFont& aStyleFont);
160 explicit nsStyleFont(StyleStructContext aContext);
~nsStyleFontnsStyleFont161 ~nsStyleFont() {
162 MOZ_COUNT_DTOR(nsStyleFont);
163 }
FinishStylensStyleFont164 void FinishStyle(nsPresContext* aPresContext) {}
165
166 nsChangeHint CalcDifference(const nsStyleFont& aNewData) const;
MaxDifferencensStyleFont167 static nsChangeHint MaxDifference() {
168 return NS_STYLE_HINT_REFLOW |
169 nsChangeHint_NeutralChange;
170 }
DifferenceAlwaysHandledForDescendantsnsStyleFont171 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
172 // CalcDifference never returns the reflow hints that are sometimes
173 // handled for descendants as hints not handled for descendants.
174 return nsChangeHint_NeedReflow |
175 nsChangeHint_ReflowChangesSizeOrPosition |
176 nsChangeHint_ClearAncestorIntrinsics;
177 }
178
179 /**
180 * Return aSize multiplied by the current text zoom factor (in aPresContext).
181 * aSize is allowed to be negative, but the caller is expected to deal with
182 * negative results. The result is clamped to nscoord_MIN .. nscoord_MAX.
183 */
184 static nscoord ZoomText(StyleStructContext aContext, nscoord aSize);
185 /**
186 * Return aSize divided by the current text zoom factor (in aPresContext).
187 * aSize is allowed to be negative, but the caller is expected to deal with
188 * negative results. The result is clamped to nscoord_MIN .. nscoord_MAX.
189 */
190 static nscoord UnZoomText(nsPresContext* aPresContext, nscoord aSize);
191 static already_AddRefed<nsIAtom> GetLanguage(StyleStructContext aPresContext);
192
newnsStyleFont193 void* operator new(size_t sz, nsStyleFont* aSelf) { return aSelf; }
newnsStyleFont194 void* operator new(size_t sz, nsPresContext* aContext) {
195 return aContext->PresShell()->
196 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleFont, sz);
197 }
198 void Destroy(nsPresContext* aContext);
199
200 void EnableZoom(nsPresContext* aContext, bool aEnable);
201
202 nsFont mFont; // [inherited]
203 nscoord mSize; // [inherited] Our "computed size". Can be different
204 // from mFont.size which is our "actual size" and is
205 // enforced to be >= the user's preferred min-size.
206 // mFont.size should be used for display purposes
207 // while mSize is the value to return in
208 // getComputedStyle() for example.
209 uint8_t mGenericID; // [inherited] generic CSS font family, if any;
210 // value is a kGenericFont_* constant, see nsFont.h.
211
212 // MathML scriptlevel support
213 int8_t mScriptLevel; // [inherited]
214 // MathML mathvariant support
215 uint8_t mMathVariant; // [inherited]
216 // MathML displaystyle support
217 uint8_t mMathDisplay; // [inherited]
218
219 // allow different min font-size for certain cases
220 uint8_t mMinFontSizeRatio; // [inherited] percent * 100
221
222 // was mLanguage set based on a lang attribute in the document?
223 bool mExplicitLanguage; // [inherited]
224
225 // should calls to ZoomText() and UnZoomText() be made to the font
226 // size on this nsStyleFont?
227 bool mAllowZoom; // [inherited]
228
229 // The value mSize would have had if scriptminsize had never been applied
230 nscoord mScriptUnconstrainedSize;
231 nscoord mScriptMinSize; // [inherited] length
232 float mScriptSizeMultiplier; // [inherited]
233 nsCOMPtr<nsIAtom> mLanguage; // [inherited]
234 };
235
236 struct nsStyleGradientStop
237 {
238 nsStyleCoord mLocation; // percent, coord, calc, none
239 nscolor mColor;
240 bool mIsInterpolationHint;
241
242 // Use ==/!= on nsStyleGradient instead of on the gradient stop.
243 bool operator==(const nsStyleGradientStop&) const = delete;
244 bool operator!=(const nsStyleGradientStop&) const = delete;
245 };
246
247 class nsStyleGradient final
248 {
249 public:
250 nsStyleGradient();
251 uint8_t mShape; // NS_STYLE_GRADIENT_SHAPE_*
252 uint8_t mSize; // NS_STYLE_GRADIENT_SIZE_*;
253 // not used (must be FARTHEST_CORNER) for linear shape
254 bool mRepeating;
255 bool mLegacySyntax;
256
257 nsStyleCoord mBgPosX; // percent, coord, calc, none
258 nsStyleCoord mBgPosY; // percent, coord, calc, none
259 nsStyleCoord mAngle; // none, angle
260
261 nsStyleCoord mRadiusX; // percent, coord, calc, none
262 nsStyleCoord mRadiusY; // percent, coord, calc, none
263
264 // stops are in the order specified in the stylesheet
265 nsTArray<nsStyleGradientStop> mStops;
266
267 bool operator==(const nsStyleGradient& aOther) const;
268 bool operator!=(const nsStyleGradient& aOther) const {
269 return !(*this == aOther);
270 }
271
272 bool IsOpaque();
273 bool HasCalc();
274 uint32_t Hash(PLDHashNumber aHash);
275
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsStyleGradient)276 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsStyleGradient)
277
278 private:
279 // Private destructor, to discourage deletion outside of Release():
280 ~nsStyleGradient() {}
281
282 nsStyleGradient(const nsStyleGradient& aOther) = delete;
283 nsStyleGradient& operator=(const nsStyleGradient& aOther) = delete;
284 };
285
286 /**
287 * A wrapper for an imgRequestProxy that supports off-main-thread creation
288 * and equality comparison.
289 *
290 * An nsStyleImageRequest can be created in two ways:
291 *
292 * 1. Using the constructor that takes an imgRequestProxy. This must
293 * be called from the main thread. The nsStyleImageRequest is
294 * immediately considered "resolved", and the get() method that
295 * returns the imgRequestProxy can be called.
296 *
297 * 2. Using the constructor that takes the URL, base URI, referrer
298 * and principal that can be used to inititiate an image load and
299 * produce an imgRequestProxy later. This can be called from
300 * any thread. The nsStyleImageRequest is not considered "resolved"
301 * at this point, and the Resolve() method must be called later
302 * to initiate the image load and make calls to get() valid.
303 *
304 * Calls to TrackImage(), UntrackImage(), LockImage(), UnlockImage() and
305 * RequestDiscard() are made to the imgRequestProxy and ImageTracker as
306 * appropriate, according to the mode flags passed in to the constructor.
307 *
308 * The main thread constructor takes a pointer to the css::ImageValue that
309 * is the specified url() value, while the off-main-thread constructor
310 * creates a new css::ImageValue to represent the url() information passed
311 * to the constructor. This ImageValue is held on to for the comparisons done
312 * in DefinitelyEquals(), so that we don't need to call into the non-OMT-safe
313 * Equals() on the nsIURI objects returned from imgRequestProxy::GetURI().
314 */
315 class nsStyleImageRequest
316 {
317 public:
318 // Flags describing whether the imgRequestProxy must be tracked in the
319 // ImageTracker, whether LockImage/UnlockImage calls will be made
320 // when obtaining and releasing the imgRequestProxy, and whether
321 // RequestDiscard will be called on release.
322 enum class Mode : uint8_t {
323 // The imgRequestProxy will be added to the ImageTracker when resolved
324 // Without this flag, the nsStyleImageRequest itself will call LockImage/
325 // UnlockImage on the imgRequestProxy, rather than leaving locking to the
326 // ImageTracker to manage.
327 //
328 // This flag is currently used by all nsStyleImageRequests except
329 // those for list-style-image and cursor.
330 Track = 0x1,
331
332 // The imgRequestProxy will have its RequestDiscard method called when
333 // the nsStyleImageRequest is going away.
334 //
335 // This is currently used only for cursor images.
336 Discard = 0x2,
337 };
338
339 // Must be called from the main thread.
340 //
341 // aImageTracker must be non-null iff aModeFlags contains Track.
342 nsStyleImageRequest(Mode aModeFlags,
343 imgRequestProxy* aRequestProxy,
344 mozilla::css::ImageValue* aImageValue,
345 mozilla::dom::ImageTracker* aImageTracker);
346
347 // Can be called from any thread, but Resolve() must be called later
348 // on the main thread before get() can be used.
349 nsStyleImageRequest(
350 Mode aModeFlags,
351 nsStringBuffer* aURLBuffer,
352 already_AddRefed<mozilla::PtrHolder<nsIURI>> aBaseURI,
353 already_AddRefed<mozilla::PtrHolder<nsIURI>> aReferrer,
354 already_AddRefed<mozilla::PtrHolder<nsIPrincipal>> aPrincipal);
355
356 bool Resolve(nsPresContext* aPresContext);
IsResolved()357 bool IsResolved() const { return mResolved; }
358
get()359 imgRequestProxy* get() {
360 MOZ_ASSERT(IsResolved(), "Resolve() must be called first");
361 MOZ_ASSERT(NS_IsMainThread());
362 return mRequestProxy.get();
363 }
get()364 const imgRequestProxy* get() const {
365 return const_cast<nsStyleImageRequest*>(this)->get();
366 }
367
368 // Returns whether the ImageValue objects in the two nsStyleImageRequests
369 // return true from URLValueData::DefinitelyEqualURIs.
370 bool DefinitelyEquals(const nsStyleImageRequest& aOther) const;
371
372 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsStyleImageRequest);
373
374 private:
375 ~nsStyleImageRequest();
376 nsStyleImageRequest& operator=(const nsStyleImageRequest& aOther) = delete;
377
378 void MaybeTrackAndLock();
379
380 RefPtr<imgRequestProxy> mRequestProxy;
381 RefPtr<mozilla::css::ImageValue> mImageValue;
382 RefPtr<mozilla::dom::ImageTracker> mImageTracker;
383
384 Mode mModeFlags;
385 bool mResolved;
386 };
387
388 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsStyleImageRequest::Mode)
389
390 enum nsStyleImageType {
391 eStyleImageType_Null,
392 eStyleImageType_Image,
393 eStyleImageType_Gradient,
394 eStyleImageType_Element
395 };
396
397 struct CachedBorderImageData
398 {
399 // Caller are expected to ensure that the value of aSVGViewportSize is
400 // different from the cached one since the method won't do the check.
401 void SetCachedSVGViewportSize(const mozilla::Maybe<nsSize>& aSVGViewportSize);
402 const mozilla::Maybe<nsSize>& GetCachedSVGViewportSize();
403 void PurgeCachedImages();
404 void SetSubImage(uint8_t aIndex, imgIContainer* aSubImage);
405 imgIContainer* GetSubImage(uint8_t aIndex);
406
407 private:
408 // If this is a SVG border-image, we save the size of the SVG viewport that
409 // we used when rasterizing any cached border-image subimages. (The viewport
410 // size matters for percent-valued sizes & positions in inner SVG doc).
411 mozilla::Maybe<nsSize> mCachedSVGViewportSize;
412 nsCOMArray<imgIContainer> mSubImages;
413 };
414
415 /**
416 * Represents a paintable image of one of the following types.
417 * (1) A real image loaded from an external source.
418 * (2) A CSS linear or radial gradient.
419 * (3) An element within a document, or an <img>, <video>, or <canvas> element
420 * not in a document.
421 * (*) Optionally a crop rect can be set to paint a partial (rectangular)
422 * region of an image. (Currently, this feature is only supported with an
423 * image of type (1)).
424 */
425 struct nsStyleImage
426 {
427 nsStyleImage();
428 ~nsStyleImage();
429 nsStyleImage(const nsStyleImage& aOther);
430 nsStyleImage& operator=(const nsStyleImage& aOther);
431
432 void SetNull();
433 void SetImageRequest(already_AddRefed<nsStyleImageRequest> aImage);
434 void SetGradientData(nsStyleGradient* aGradient);
435 void SetElementId(const char16_t* aElementId);
436 void SetCropRect(mozilla::UniquePtr<nsStyleSides> aCropRect);
437
ResolveImagensStyleImage438 void ResolveImage(nsPresContext* aContext) {
439 MOZ_ASSERT(mType != eStyleImageType_Image || mImage);
440 if (mType == eStyleImageType_Image && !mImage->IsResolved()) {
441 mImage->Resolve(aContext);
442 }
443 }
444
GetTypensStyleImage445 nsStyleImageType GetType() const {
446 return mType;
447 }
GetImageRequestnsStyleImage448 nsStyleImageRequest* GetImageRequest() const {
449 MOZ_ASSERT(mType == eStyleImageType_Image, "Data is not an image!");
450 MOZ_ASSERT(mImage);
451 return mImage;
452 }
GetImageDatansStyleImage453 imgRequestProxy* GetImageData() const {
454 return GetImageRequest()->get();
455 }
GetGradientDatansStyleImage456 nsStyleGradient* GetGradientData() const {
457 NS_ASSERTION(mType == eStyleImageType_Gradient, "Data is not a gradient!");
458 return mGradient;
459 }
GetElementIdnsStyleImage460 const char16_t* GetElementId() const {
461 NS_ASSERTION(mType == eStyleImageType_Element, "Data is not an element!");
462 return mElementId;
463 }
GetCropRectnsStyleImage464 const mozilla::UniquePtr<nsStyleSides>& GetCropRect() const {
465 NS_ASSERTION(mType == eStyleImageType_Image,
466 "Only image data can have a crop rect");
467 return mCropRect;
468 }
469
470 /**
471 * Compute the actual crop rect in pixels, using the source image bounds.
472 * The computation involves converting percentage unit to pixel unit and
473 * clamping each side value to fit in the source image bounds.
474 * @param aActualCropRect the computed actual crop rect.
475 * @param aIsEntireImage true iff |aActualCropRect| is identical to the
476 * source image bounds.
477 * @return true iff |aActualCropRect| holds a meaningful value.
478 */
479 bool ComputeActualCropRect(nsIntRect& aActualCropRect,
480 bool* aIsEntireImage = nullptr) const;
481
482 /**
483 * Starts the decoding of a image.
484 */
485 nsresult StartDecoding() const;
486 /**
487 * @return true if the item is definitely opaque --- i.e., paints every
488 * pixel within its bounds opaquely, and the bounds contains at least a pixel.
489 */
490 bool IsOpaque() const;
491 /**
492 * @return true if this image is fully loaded, and its size is calculated;
493 * always returns true if |mType| is |eStyleImageType_Gradient| or
494 * |eStyleImageType_Element|.
495 */
496 bool IsComplete() const;
497 /**
498 * @return true if this image is loaded without error;
499 * always returns true if |mType| is |eStyleImageType_Gradient| or
500 * |eStyleImageType_Element|.
501 */
502 bool IsLoaded() const;
503 /**
504 * @return true if it is 100% confident that this image contains no pixel
505 * to draw.
506 */
IsEmptynsStyleImage507 bool IsEmpty() const {
508 // There are some other cases when the image will be empty, for example
509 // when the crop rect is empty. However, checking the emptiness of crop
510 // rect is non-trivial since each side value can be specified with
511 // percentage unit, which can not be evaluated until the source image size
512 // is available. Therefore, we currently postpone the evaluation of crop
513 // rect until the actual rendering time --- alternatively until GetOpaqueRegion()
514 // is called.
515 return mType == eStyleImageType_Null;
516 }
517
518 bool operator==(const nsStyleImage& aOther) const;
519 bool operator!=(const nsStyleImage& aOther) const {
520 return !(*this == aOther);
521 }
522
ImageDataEqualsnsStyleImage523 bool ImageDataEquals(const nsStyleImage& aOther) const
524 {
525 return GetType() == eStyleImageType_Image &&
526 aOther.GetType() == eStyleImageType_Image &&
527 GetImageData() == aOther.GetImageData();
528 }
529
530 // These methods are used for the caller to caches the sub images created
531 // during a border-image paint operation
532 inline void SetSubImage(uint8_t aIndex, imgIContainer* aSubImage) const;
533 inline imgIContainer* GetSubImage(uint8_t aIndex) const;
534 void PurgeCacheForViewportChange(
535 const mozilla::Maybe<nsSize>& aSVGViewportSize,
536 const bool aHasIntrinsicRatio) const;
537
538 private:
539 void DoCopy(const nsStyleImage& aOther);
540 void EnsureCachedBIData() const;
541
542 // This variable keeps some cache data for border image and is lazily
543 // allocated since it is only used in border image case.
544 mozilla::UniquePtr<CachedBorderImageData> mCachedBIData;
545
546 nsStyleImageType mType;
547 union {
548 nsStyleImageRequest* mImage;
549 nsStyleGradient* mGradient;
550 char16_t* mElementId;
551 };
552
553 // This is _currently_ used only in conjunction with eStyleImageType_Image.
554 mozilla::UniquePtr<nsStyleSides> mCropRect;
555 };
556
557 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColor
558 {
559 explicit nsStyleColor(StyleStructContext aContext);
560 nsStyleColor(const nsStyleColor& aOther);
~nsStyleColornsStyleColor561 ~nsStyleColor() {
562 MOZ_COUNT_DTOR(nsStyleColor);
563 }
FinishStylensStyleColor564 void FinishStyle(nsPresContext* aPresContext) {}
565
CalcComplexColornsStyleColor566 nscolor CalcComplexColor(const mozilla::StyleComplexColor& aColor) const {
567 return mozilla::LinearBlendColors(aColor.mColor, mColor,
568 aColor.mForegroundRatio);
569 }
570
571 nsChangeHint CalcDifference(const nsStyleColor& aNewData) const;
MaxDifferencensStyleColor572 static nsChangeHint MaxDifference() {
573 return nsChangeHint_RepaintFrame;
574 }
DifferenceAlwaysHandledForDescendantsnsStyleColor575 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
576 // CalcDifference never returns the reflow hints that are sometimes
577 // handled for descendants at all.
578 return nsChangeHint(0);
579 }
580
newnsStyleColor581 void* operator new(size_t sz, nsStyleColor* aSelf) { return aSelf; }
newnsStyleColor582 void* operator new(size_t sz, nsPresContext* aContext) {
583 return aContext->PresShell()->
584 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleColor, sz);
585 }
DestroynsStyleColor586 void Destroy(nsPresContext* aContext) {
587 this->~nsStyleColor();
588 aContext->PresShell()->
589 FreeByObjectID(mozilla::eArenaObjectID_nsStyleColor, this);
590 }
591
592 // Don't add ANY members to this struct! We can achieve caching in the rule
593 // tree (rather than the style tree) by letting color stay by itself! -dwh
594 nscolor mColor; // [inherited]
595 };
596
597 /**
598 * An array of objects, similar to AutoTArray<T,1> but which is memmovable. It
599 * always has length >= 1.
600 */
601 template<typename T>
602 class nsStyleAutoArray
603 {
604 public:
605 // This constructor places a single element in mFirstElement.
606 enum WithSingleInitialElement { WITH_SINGLE_INITIAL_ELEMENT };
nsStyleAutoArray(WithSingleInitialElement)607 explicit nsStyleAutoArray(WithSingleInitialElement) {}
nsStyleAutoArray(const nsStyleAutoArray & aOther)608 nsStyleAutoArray(const nsStyleAutoArray& aOther) { *this = aOther; }
609 nsStyleAutoArray& operator=(const nsStyleAutoArray& aOther) {
610 mFirstElement = aOther.mFirstElement;
611 mOtherElements = aOther.mOtherElements;
612 return *this;
613 }
614
615 bool operator==(const nsStyleAutoArray& aOther) const {
616 return Length() == aOther.Length() &&
617 mFirstElement == aOther.mFirstElement &&
618 mOtherElements == aOther.mOtherElements;
619 }
620 bool operator!=(const nsStyleAutoArray& aOther) const {
621 return !(*this == aOther);
622 }
623
Length()624 size_t Length() const {
625 return mOtherElements.Length() + 1;
626 }
627 const T& operator[](size_t aIndex) const {
628 return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1];
629 }
630 T& operator[](size_t aIndex) {
631 return aIndex == 0 ? mFirstElement : mOtherElements[aIndex - 1];
632 }
633
EnsureLengthAtLeast(size_t aMinLen)634 void EnsureLengthAtLeast(size_t aMinLen) {
635 if (aMinLen > 0) {
636 mOtherElements.EnsureLengthAtLeast(aMinLen - 1);
637 }
638 }
639
SetLengthNonZero(size_t aNewLen)640 void SetLengthNonZero(size_t aNewLen) {
641 MOZ_ASSERT(aNewLen > 0);
642 mOtherElements.SetLength(aNewLen - 1);
643 }
644
TruncateLengthNonZero(size_t aNewLen)645 void TruncateLengthNonZero(size_t aNewLen) {
646 MOZ_ASSERT(aNewLen > 0);
647 MOZ_ASSERT(aNewLen <= Length());
648 mOtherElements.TruncateLength(aNewLen - 1);
649 }
650
651 private:
652 T mFirstElement;
653 nsTArray<T> mOtherElements;
654 };
655
656 struct nsStyleImageLayers {
657 // Indices into kBackgroundLayerTable and kMaskLayerTable
658 enum {
659 shorthand = 0,
660 color,
661 image,
662 repeat,
663 positionX,
664 positionY,
665 clip,
666 origin,
667 size,
668 attachment,
669 maskMode,
670 composite
671 };
672
673 enum class LayerType : uint8_t {
674 Background = 0,
675 Mask
676 };
677
678 explicit nsStyleImageLayers(LayerType aType);
679 nsStyleImageLayers(const nsStyleImageLayers &aSource);
~nsStyleImageLayersnsStyleImageLayers680 ~nsStyleImageLayers() {
681 MOZ_COUNT_DTOR(nsStyleImageLayers);
682 }
683
684 static bool IsInitialPositionForLayerType(mozilla::Position aPosition, LayerType aType);
685
686 struct Size;
687 friend struct Size;
688 struct Size {
689 struct Dimension : public nsStyleCoord::CalcValue {
ResolveLengthPercentagensStyleImageLayers::Size::Dimension690 nscoord ResolveLengthPercentage(nscoord aAvailable) const {
691 double d = double(mPercent) * double(aAvailable) + double(mLength);
692 if (d < 0.0) {
693 return 0;
694 }
695 return NSToCoordRoundWithClamp(float(d));
696 }
697 };
698 Dimension mWidth, mHeight;
699
IsInitialValuensStyleImageLayers::Size700 bool IsInitialValue() const {
701 return mWidthType == eAuto && mHeightType == eAuto;
702 }
703
ResolveWidthLengthPercentagensStyleImageLayers::Size704 nscoord ResolveWidthLengthPercentage(const nsSize& aBgPositioningArea) const {
705 MOZ_ASSERT(mWidthType == eLengthPercentage,
706 "resolving non-length/percent dimension!");
707 return mWidth.ResolveLengthPercentage(aBgPositioningArea.width);
708 }
709
ResolveHeightLengthPercentagensStyleImageLayers::Size710 nscoord ResolveHeightLengthPercentage(const nsSize& aBgPositioningArea) const {
711 MOZ_ASSERT(mHeightType == eLengthPercentage,
712 "resolving non-length/percent dimension!");
713 return mHeight.ResolveLengthPercentage(aBgPositioningArea.height);
714 }
715
716 // Except for eLengthPercentage, Dimension types which might change
717 // how a layer is painted when the corresponding frame's dimensions
718 // change *must* precede all dimension types which are agnostic to
719 // frame size; see DependsOnDependsOnPositioningAreaSizeSize.
720 enum DimensionType {
721 // If one of mWidth and mHeight is eContain or eCover, then both are.
722 // NOTE: eContain and eCover *must* be equal to NS_STYLE_BG_SIZE_CONTAIN
723 // and NS_STYLE_BG_SIZE_COVER (in kBackgroundSizeKTable).
724 eContain, eCover,
725
726 eAuto,
727 eLengthPercentage,
728 eDimensionType_COUNT
729 };
730 uint8_t mWidthType, mHeightType;
731
732 // True if the effective image size described by this depends on the size of
733 // the corresponding frame, when aImage (which must not have null type) is
734 // the background image.
735 bool DependsOnPositioningAreaSize(const nsStyleImage& aImage) const;
736
737 // Initialize nothing
SizensStyleImageLayers::Size738 Size() {}
739
740 // Initialize to initial values
741 void SetInitialValues();
742
743 bool operator==(const Size& aOther) const;
744 bool operator!=(const Size& aOther) const {
745 return !(*this == aOther);
746 }
747 };
748
749 struct Repeat;
750 friend struct Repeat;
751 struct Repeat {
752 uint8_t mXRepeat, mYRepeat;
753
754 // Initialize nothing
RepeatnsStyleImageLayers::Repeat755 Repeat() {}
756
IsInitialValuensStyleImageLayers::Repeat757 bool IsInitialValue() const {
758 return mXRepeat == NS_STYLE_IMAGELAYER_REPEAT_REPEAT &&
759 mYRepeat == NS_STYLE_IMAGELAYER_REPEAT_REPEAT;
760 }
761
DependsOnPositioningAreaSizensStyleImageLayers::Repeat762 bool DependsOnPositioningAreaSize() const {
763 return mXRepeat == NS_STYLE_IMAGELAYER_REPEAT_SPACE ||
764 mYRepeat == NS_STYLE_IMAGELAYER_REPEAT_SPACE;
765 }
766
767 // Initialize to initial values
SetInitialValuesnsStyleImageLayers::Repeat768 void SetInitialValues() {
769 mXRepeat = NS_STYLE_IMAGELAYER_REPEAT_REPEAT;
770 mYRepeat = NS_STYLE_IMAGELAYER_REPEAT_REPEAT;
771 }
772
773 bool operator==(const Repeat& aOther) const {
774 return mXRepeat == aOther.mXRepeat &&
775 mYRepeat == aOther.mYRepeat;
776 }
777 bool operator!=(const Repeat& aOther) const {
778 return !(*this == aOther);
779 }
780 };
781
782 struct Layer;
783 friend struct Layer;
784 struct Layer {
785 nsStyleImage mImage; // [reset]
786 RefPtr<mozilla::css::URLValueData> mSourceURI; // [reset]
787 // mask-only property
788 // This property is used for mask layer only.
789 // For a background layer, it should always
790 // be the initial value, which is nullptr.
791 // Store mask-image URI so that we can resolve
792 // SVG mask path later. (Might be a URLValue
793 // or an ImageValue.)
794 mozilla::Position mPosition; // [reset]
795 Size mSize; // [reset]
796 uint8_t mClip; // [reset] See nsStyleConsts.h
797 MOZ_INIT_OUTSIDE_CTOR
798 uint8_t mOrigin; // [reset] See nsStyleConsts.h
799 uint8_t mAttachment; // [reset] See nsStyleConsts.h
800 // background-only property
801 // This property is used for background layer
802 // only. For a mask layer, it should always
803 // be the initial value, which is
804 // NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL.
805 uint8_t mBlendMode; // [reset] See nsStyleConsts.h
806 // background-only property
807 // This property is used for background layer
808 // only. For a mask layer, it should always
809 // be the initial value, which is
810 // NS_STYLE_BLEND_NORMAL.
811 uint8_t mComposite; // [reset] See nsStyleConsts.h
812 // mask-only property
813 // This property is used for mask layer only.
814 // For a background layer, it should always
815 // be the initial value, which is
816 // NS_STYLE_COMPOSITE_MODE_ADD.
817 uint8_t mMaskMode; // [reset] See nsStyleConsts.h
818 // mask-only property
819 // This property is used for mask layer only.
820 // For a background layer, it should always
821 // be the initial value, which is
822 // NS_STYLE_MASK_MODE_MATCH_SOURCE.
823 Repeat mRepeat; // [reset] See nsStyleConsts.h
824
825 // This constructor does not initialize mRepeat or mOrigin and Initialize()
826 // must be called to do that.
827 Layer();
828 ~Layer();
829
830 // Initialize mRepeat and mOrigin by specified layer type
831 void Initialize(LayerType aType);
832
ResolveImagensStyleImageLayers::Layer833 void ResolveImage(nsPresContext* aContext) {
834 if (mImage.GetType() == eStyleImageType_Image) {
835 mImage.ResolveImage(aContext);
836 }
837 }
838
839 // True if the rendering of this layer might change when the size
840 // of the background positioning area changes. This is true for any
841 // non-solid-color background whose position or size depends on
842 // the size of the positioning area. It's also true for SVG images
843 // whose root <svg> node has a viewBox.
844 bool RenderingMightDependOnPositioningAreaSizeChange() const;
845
846 // Compute the change hint required by changes in just this layer.
847 nsChangeHint CalcDifference(const Layer& aNewLayer) const;
848
849 // An equality operator that compares the images using URL-equality
850 // rather than pointer-equality.
851 bool operator==(const Layer& aOther) const;
852 bool operator!=(const Layer& aOther) const {
853 return !(*this == aOther);
854 }
855 };
856
857 // The (positive) number of computed values of each property, since
858 // the lengths of the lists are independent.
859 uint32_t mAttachmentCount,
860 mClipCount,
861 mOriginCount,
862 mRepeatCount,
863 mPositionXCount,
864 mPositionYCount,
865 mImageCount,
866 mSizeCount,
867 mMaskModeCount,
868 mBlendModeCount,
869 mCompositeCount;
870
871 // Layers are stored in an array, matching the top-to-bottom order in
872 // which they are specified in CSS. The number of layers to be used
873 // should come from the background-image property. We create
874 // additional |Layer| objects for *any* property, not just
875 // background-image. This means that the bottommost layer that
876 // callers in layout care about (which is also the one whose
877 // background-clip applies to the background-color) may not be last
878 // layer. In layers below the bottom layer, properties will be
879 // uninitialized unless their count, above, indicates that they are
880 // present.
881 nsStyleAutoArray<Layer> mLayers;
882
BottomLayernsStyleImageLayers883 const Layer& BottomLayer() const { return mLayers[mImageCount - 1]; }
884
ResolveImagesnsStyleImageLayers885 void ResolveImages(nsPresContext* aContext) {
886 for (uint32_t i = 0; i < mImageCount; ++i) {
887 mLayers[i].ResolveImage(aContext);
888 }
889 }
890
891 nsChangeHint CalcDifference(const nsStyleImageLayers& aNewLayers,
892 nsStyleImageLayers::LayerType aType) const;
893
894 bool HasLayerWithImage() const;
895 nsStyleImageLayers& operator=(const nsStyleImageLayers& aOther);
896
897 static const nsCSSPropertyID kBackgroundLayerTable[];
898 static const nsCSSPropertyID kMaskLayerTable[];
899
900 #define NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(var_, layers_) \
901 for (uint32_t var_ = (layers_).mImageCount; var_-- != 0; )
902 #define NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT_WITH_RANGE(var_, layers_, start_, count_) \
903 NS_ASSERTION((int32_t)(start_) >= 0 && (uint32_t)(start_) < (layers_).mImageCount, "Invalid layer start!"); \
904 NS_ASSERTION((count_) > 0 && (count_) <= (start_) + 1, "Invalid layer range!"); \
905 for (uint32_t var_ = (start_) + 1; var_-- != (uint32_t)((start_) + 1 - (count_)); )
906 };
907
908 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBackground {
909 explicit nsStyleBackground(StyleStructContext aContext);
910 nsStyleBackground(const nsStyleBackground& aOther);
911 ~nsStyleBackground();
912
913 // Resolves and tracks the images in mImage. Only called with a Servo-backed
914 // style system, where those images must be resolved later than the OMT
915 // nsStyleBackground constructor call.
916 void FinishStyle(nsPresContext* aPresContext);
917
newnsStyleBackground918 void* operator new(size_t sz, nsStyleBackground* aSelf) { return aSelf; }
newnsStyleBackground919 void* operator new(size_t sz, nsPresContext* aContext) {
920 return aContext->PresShell()->
921 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleBackground, sz);
922 }
923 void Destroy(nsPresContext* aContext);
924
925 nsChangeHint CalcDifference(const nsStyleBackground& aNewData) const;
MaxDifferencensStyleBackground926 static nsChangeHint MaxDifference() {
927 return nsChangeHint_UpdateEffects |
928 nsChangeHint_RepaintFrame |
929 nsChangeHint_UpdateBackgroundPosition |
930 nsChangeHint_NeutralChange;
931 }
DifferenceAlwaysHandledForDescendantsnsStyleBackground932 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
933 // CalcDifference never returns the reflow hints that are sometimes
934 // handled for descendants at all.
935 return nsChangeHint(0);
936 }
937
938 // True if this background is completely transparent.
939 bool IsTransparent() const;
940
941 // We have to take slower codepaths for fixed background attachment,
942 // but we don't want to do that when there's no image.
943 // Not inline because it uses an nsCOMPtr<imgIRequest>
944 // FIXME: Should be in nsStyleStructInlines.h.
945 bool HasFixedBackground(nsIFrame* aFrame) const;
946
947 // Checks to see if this has a non-empty image with "local" attachment.
948 // This is defined in nsStyleStructInlines.h.
949 inline bool HasLocalBackground() const;
950
BottomLayernsStyleBackground951 const nsStyleImageLayers::Layer& BottomLayer() const { return mImage.BottomLayer(); }
952
953 nsStyleImageLayers mImage;
954 nscolor mBackgroundColor; // [reset]
955 };
956
957 #define NS_SPACING_MARGIN 0
958 #define NS_SPACING_PADDING 1
959 #define NS_SPACING_BORDER 2
960
961
962 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleMargin
963 {
964 explicit nsStyleMargin(StyleStructContext aContext);
965 nsStyleMargin(const nsStyleMargin& aMargin);
~nsStyleMarginnsStyleMargin966 ~nsStyleMargin() {
967 MOZ_COUNT_DTOR(nsStyleMargin);
968 }
FinishStylensStyleMargin969 void FinishStyle(nsPresContext* aPresContext) {}
970
newnsStyleMargin971 void* operator new(size_t sz, nsStyleMargin* aSelf) { return aSelf; }
newnsStyleMargin972 void* operator new(size_t sz, nsPresContext* aContext) {
973 return aContext->PresShell()->
974 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleMargin, sz);
975 }
976 void Destroy(nsPresContext* aContext);
977
978 nsChangeHint CalcDifference(const nsStyleMargin& aNewData) const;
MaxDifferencensStyleMargin979 static nsChangeHint MaxDifference() {
980 return nsChangeHint_NeedReflow |
981 nsChangeHint_ReflowChangesSizeOrPosition |
982 nsChangeHint_ClearAncestorIntrinsics;
983 }
DifferenceAlwaysHandledForDescendantsnsStyleMargin984 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
985 // CalcDifference can return all of the reflow hints sometimes not
986 // handled for descendants as hints not handled for descendants.
987 return nsChangeHint(0);
988 }
989
GetMarginnsStyleMargin990 bool GetMargin(nsMargin& aMargin) const
991 {
992 if (!mMargin.ConvertsToLength()) {
993 return false;
994 }
995
996 NS_FOR_CSS_SIDES(side) {
997 aMargin.Side(side) = mMargin.ToLength(side);
998 }
999 return true;
1000 }
1001
1002 // Return true if either the start or end side in the axis is 'auto'.
1003 // (defined in WritingModes.h since we need the full WritingMode type)
1004 inline bool HasBlockAxisAuto(mozilla::WritingMode aWM) const;
1005 inline bool HasInlineAxisAuto(mozilla::WritingMode aWM) const;
1006
1007 nsStyleSides mMargin; // [reset] coord, percent, calc, auto
1008 };
1009
1010 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePadding
1011 {
1012 explicit nsStylePadding(StyleStructContext aContext);
1013 nsStylePadding(const nsStylePadding& aPadding);
~nsStylePaddingnsStylePadding1014 ~nsStylePadding() {
1015 MOZ_COUNT_DTOR(nsStylePadding);
1016 }
FinishStylensStylePadding1017 void FinishStyle(nsPresContext* aPresContext) {}
1018
newnsStylePadding1019 void* operator new(size_t sz, nsStylePadding* aSelf) { return aSelf; }
newnsStylePadding1020 void* operator new(size_t sz, nsPresContext* aContext) {
1021 return aContext->PresShell()->
1022 AllocateByObjectID(mozilla::eArenaObjectID_nsStylePadding, sz);
1023 }
1024 void Destroy(nsPresContext* aContext);
1025
1026 nsChangeHint CalcDifference(const nsStylePadding& aNewData) const;
MaxDifferencensStylePadding1027 static nsChangeHint MaxDifference() {
1028 return NS_STYLE_HINT_REFLOW & ~nsChangeHint_ClearDescendantIntrinsics;
1029 }
DifferenceAlwaysHandledForDescendantsnsStylePadding1030 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
1031 // CalcDifference can return nsChangeHint_ClearAncestorIntrinsics as
1032 // a hint not handled for descendants. We could (and perhaps
1033 // should) return nsChangeHint_NeedReflow and
1034 // nsChangeHint_ReflowChangesSizeOrPosition as always handled for
1035 // descendants, but since they're always returned in conjunction
1036 // with nsChangeHint_ClearAncestorIntrinsics (which is not), it
1037 // won't ever lead to any optimization in
1038 // nsStyleContext::CalcStyleDifference.
1039 return nsChangeHint(0);
1040 }
1041
1042 nsStyleSides mPadding; // [reset] coord, percent, calc
1043
IsWidthDependentnsStylePadding1044 bool IsWidthDependent() const {
1045 return !mPadding.ConvertsToLength();
1046 }
1047
GetPaddingnsStylePadding1048 bool GetPadding(nsMargin& aPadding) const
1049 {
1050 if (!mPadding.ConvertsToLength()) {
1051 return false;
1052 }
1053
1054 NS_FOR_CSS_SIDES(side) {
1055 // Clamp negative calc() to 0.
1056 aPadding.Side(side) = std::max(mPadding.ToLength(side), 0);
1057 }
1058 return true;
1059 }
1060 };
1061
1062 struct nsBorderColors
1063 {
1064 nsBorderColors* mNext;
1065 nscolor mColor;
1066
nsBorderColorsnsBorderColors1067 nsBorderColors() : mNext(nullptr), mColor(NS_RGB(0,0,0)) {}
nsBorderColorsnsBorderColors1068 explicit nsBorderColors(const nscolor& aColor) : mNext(nullptr), mColor(aColor) {}
1069 ~nsBorderColors();
1070
ClonensBorderColors1071 nsBorderColors* Clone() const { return Clone(true); }
1072
EqualnsBorderColors1073 static bool Equal(const nsBorderColors* c1,
1074 const nsBorderColors* c2) {
1075 if (c1 == c2) {
1076 return true;
1077 }
1078 while (c1 && c2) {
1079 if (c1->mColor != c2->mColor) {
1080 return false;
1081 }
1082 c1 = c1->mNext;
1083 c2 = c2->mNext;
1084 }
1085 // both should be nullptr if these are equal, otherwise one
1086 // has more colors than another
1087 return !c1 && !c2;
1088 }
1089
1090 private:
1091 nsBorderColors* Clone(bool aDeep) const;
1092 };
1093
1094 struct nsCSSShadowItem
1095 {
1096 nscoord mXOffset;
1097 nscoord mYOffset;
1098 nscoord mRadius;
1099 nscoord mSpread;
1100
1101 nscolor mColor;
1102 bool mHasColor; // Whether mColor should be used
1103 bool mInset;
1104
nsCSSShadowItemnsCSSShadowItem1105 nsCSSShadowItem() : mHasColor(false) {
1106 MOZ_COUNT_CTOR(nsCSSShadowItem);
1107 }
~nsCSSShadowItemnsCSSShadowItem1108 ~nsCSSShadowItem() {
1109 MOZ_COUNT_DTOR(nsCSSShadowItem);
1110 }
1111
1112 bool operator==(const nsCSSShadowItem& aOther) const {
1113 return (mXOffset == aOther.mXOffset &&
1114 mYOffset == aOther.mYOffset &&
1115 mRadius == aOther.mRadius &&
1116 mHasColor == aOther.mHasColor &&
1117 mSpread == aOther.mSpread &&
1118 mInset == aOther.mInset &&
1119 (!mHasColor || mColor == aOther.mColor));
1120 }
1121 bool operator!=(const nsCSSShadowItem& aOther) const {
1122 return !(*this == aOther);
1123 }
1124 };
1125
1126 class nsCSSShadowArray final
1127 {
1128 public:
new(size_t aBaseSize,uint32_t aArrayLen)1129 void* operator new(size_t aBaseSize, uint32_t aArrayLen) {
1130 // We can allocate both this nsCSSShadowArray and the
1131 // actual array in one allocation. The amount of memory to
1132 // allocate is equal to the class's size + the number of bytes for all
1133 // but the first array item (because aBaseSize includes one
1134 // item, see the private declarations)
1135 return ::operator new(aBaseSize +
1136 (aArrayLen - 1) * sizeof(nsCSSShadowItem));
1137 }
1138
nsCSSShadowArray(uint32_t aArrayLen)1139 explicit nsCSSShadowArray(uint32_t aArrayLen) :
1140 mLength(aArrayLen)
1141 {
1142 MOZ_COUNT_CTOR(nsCSSShadowArray);
1143 for (uint32_t i = 1; i < mLength; ++i) {
1144 // Make sure we call the constructors of each nsCSSShadowItem
1145 // (the first one is called for us because we declared it under private)
1146 new (&mArray[i]) nsCSSShadowItem();
1147 }
1148 }
1149
1150 private:
1151 // Private destructor, to discourage deletion outside of Release():
~nsCSSShadowArray()1152 ~nsCSSShadowArray() {
1153 MOZ_COUNT_DTOR(nsCSSShadowArray);
1154 for (uint32_t i = 1; i < mLength; ++i) {
1155 mArray[i].~nsCSSShadowItem();
1156 }
1157 }
1158
1159 public:
Length()1160 uint32_t Length() const { return mLength; }
ShadowAt(uint32_t i)1161 nsCSSShadowItem* ShadowAt(uint32_t i) {
1162 MOZ_ASSERT(i < mLength, "Accessing too high an index in the text shadow array!");
1163 return &mArray[i];
1164 }
ShadowAt(uint32_t i)1165 const nsCSSShadowItem* ShadowAt(uint32_t i) const {
1166 MOZ_ASSERT(i < mLength, "Accessing too high an index in the text shadow array!");
1167 return &mArray[i];
1168 }
1169
HasShadowWithInset(bool aInset)1170 bool HasShadowWithInset(bool aInset) {
1171 for (uint32_t i = 0; i < mLength; ++i) {
1172 if (mArray[i].mInset == aInset) {
1173 return true;
1174 }
1175 }
1176 return false;
1177 }
1178
1179 bool operator==(const nsCSSShadowArray& aOther) const {
1180 if (mLength != aOther.Length()) {
1181 return false;
1182 }
1183
1184 for (uint32_t i = 0; i < mLength; ++i) {
1185 if (ShadowAt(i) != aOther.ShadowAt(i)) {
1186 return false;
1187 }
1188 }
1189
1190 return true;
1191 }
1192
1193 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsCSSShadowArray)
1194
1195 private:
1196 uint32_t mLength;
1197 nsCSSShadowItem mArray[1]; // This MUST be the last item
1198 };
1199
1200 // Border widths are rounded to the nearest-below integer number of pixels,
1201 // but values between zero and one device pixels are always rounded up to
1202 // one device pixel.
1203 #define NS_ROUND_BORDER_TO_PIXELS(l,tpp) \
1204 ((l) == 0) ? 0 : std::max((tpp), (l) / (tpp) * (tpp))
1205 // Outline offset is rounded to the nearest integer number of pixels, but values
1206 // between zero and one device pixels are always rounded up to one device pixel.
1207 // Note that the offset can be negative.
1208 #define NS_ROUND_OFFSET_TO_PIXELS(l,tpp) \
1209 (((l) == 0) ? 0 : \
1210 ((l) > 0) ? std::max( (tpp), ((l) + ((tpp) / 2)) / (tpp) * (tpp)) : \
1211 std::min(-(tpp), ((l) - ((tpp) / 2)) / (tpp) * (tpp)))
1212
1213 // Returns if the given border style type is visible or not
IsVisibleBorderStyle(uint8_t aStyle)1214 static bool IsVisibleBorderStyle(uint8_t aStyle)
1215 {
1216 return (aStyle != NS_STYLE_BORDER_STYLE_NONE &&
1217 aStyle != NS_STYLE_BORDER_STYLE_HIDDEN);
1218 }
1219
1220 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder
1221 {
1222 explicit nsStyleBorder(StyleStructContext aContext);
1223 nsStyleBorder(const nsStyleBorder& aBorder);
1224 ~nsStyleBorder();
1225
1226 // Resolves and tracks mBorderImageSource. Only called with a Servo-backed
1227 // style system, where those images must be resolved later than the OMT
1228 // nsStyleBorder constructor call.
1229 void FinishStyle(nsPresContext* aPresContext);
1230
newnsStyleBorder1231 void* operator new(size_t sz, nsStyleBorder* aSelf) { return aSelf; }
newnsStyleBorder1232 void* operator new(size_t sz, nsPresContext* aContext) {
1233 return aContext->PresShell()->
1234 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleBorder, sz);
1235 }
1236 void Destroy(nsPresContext* aContext);
1237
1238 nsChangeHint CalcDifference(const nsStyleBorder& aNewData) const;
MaxDifferencensStyleBorder1239 static nsChangeHint MaxDifference() {
1240 return NS_STYLE_HINT_REFLOW |
1241 nsChangeHint_UpdateOverflow |
1242 nsChangeHint_BorderStyleNoneChange |
1243 nsChangeHint_NeutralChange;
1244 }
DifferenceAlwaysHandledForDescendantsnsStyleBorder1245 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
1246 // CalcDifference never returns the reflow hints that are sometimes
1247 // handled for descendants as hints not handled for descendants.
1248 return nsChangeHint_NeedReflow |
1249 nsChangeHint_ReflowChangesSizeOrPosition |
1250 nsChangeHint_ClearAncestorIntrinsics;
1251 }
1252
EnsureBorderColorsnsStyleBorder1253 void EnsureBorderColors() {
1254 if (!mBorderColors) {
1255 mBorderColors = new nsBorderColors*[4];
1256 if (mBorderColors) {
1257 for (int32_t i = 0; i < 4; i++) {
1258 mBorderColors[i] = nullptr;
1259 }
1260 }
1261 }
1262 }
1263
ClearBorderColorsnsStyleBorder1264 void ClearBorderColors(mozilla::css::Side aSide) {
1265 if (mBorderColors && mBorderColors[aSide]) {
1266 delete mBorderColors[aSide];
1267 mBorderColors[aSide] = nullptr;
1268 }
1269 }
1270
1271 // Return whether aStyle is a visible style. Invisible styles cause
1272 // the relevant computed border width to be 0.
1273 // Note that this does *not* consider the effects of 'border-image':
1274 // if border-style is none, but there is a loaded border image,
1275 // HasVisibleStyle will be false even though there *is* a border.
HasVisibleStylensStyleBorder1276 bool HasVisibleStyle(mozilla::css::Side aSide) const
1277 {
1278 return IsVisibleBorderStyle(mBorderStyle[aSide]);
1279 }
1280
1281 // aBorderWidth is in twips
SetBorderWidthnsStyleBorder1282 void SetBorderWidth(mozilla::css::Side aSide, nscoord aBorderWidth)
1283 {
1284 nscoord roundedWidth =
1285 NS_ROUND_BORDER_TO_PIXELS(aBorderWidth, mTwipsPerPixel);
1286 mBorder.Side(aSide) = roundedWidth;
1287 if (HasVisibleStyle(aSide)) {
1288 mComputedBorder.Side(aSide) = roundedWidth;
1289 }
1290 }
1291
1292 // Get the computed border (plus rounding). This does consider the
1293 // effects of 'border-style: none', but does not consider
1294 // 'border-image'.
GetComputedBordernsStyleBorder1295 const nsMargin& GetComputedBorder() const
1296 {
1297 return mComputedBorder;
1298 }
1299
HasBordernsStyleBorder1300 bool HasBorder() const
1301 {
1302 return mComputedBorder != nsMargin(0,0,0,0) || !mBorderImageSource.IsEmpty();
1303 }
1304
1305 // Get the actual border width for a particular side, in appunits. Note that
1306 // this is zero if and only if there is no border to be painted for this
1307 // side. That is, this value takes into account the border style and the
1308 // value is rounded to the nearest device pixel by NS_ROUND_BORDER_TO_PIXELS.
GetComputedBorderWidthnsStyleBorder1309 nscoord GetComputedBorderWidth(mozilla::css::Side aSide) const
1310 {
1311 return GetComputedBorder().Side(aSide);
1312 }
1313
GetBorderStylensStyleBorder1314 uint8_t GetBorderStyle(mozilla::css::Side aSide) const
1315 {
1316 NS_ASSERTION(aSide <= NS_SIDE_LEFT, "bad side");
1317 return mBorderStyle[aSide];
1318 }
1319
SetBorderStylensStyleBorder1320 void SetBorderStyle(mozilla::css::Side aSide, uint8_t aStyle)
1321 {
1322 NS_ASSERTION(aSide <= NS_SIDE_LEFT, "bad side");
1323 mBorderStyle[aSide] = aStyle;
1324 mComputedBorder.Side(aSide) =
1325 (HasVisibleStyle(aSide) ? mBorder.Side(aSide) : 0);
1326 }
1327
IsBorderImageLoadednsStyleBorder1328 inline bool IsBorderImageLoaded() const
1329 {
1330 return mBorderImageSource.IsLoaded();
1331 }
1332
ResolveImagensStyleBorder1333 void ResolveImage(nsPresContext* aContext)
1334 {
1335 if (mBorderImageSource.GetType() == eStyleImageType_Image) {
1336 mBorderImageSource.ResolveImage(aContext);
1337 }
1338 }
1339
1340 nsMargin GetImageOutset() const;
1341
GetCompositeColorsnsStyleBorder1342 void GetCompositeColors(int32_t aIndex, nsBorderColors** aColors) const
1343 {
1344 if (!mBorderColors) {
1345 *aColors = nullptr;
1346 } else {
1347 *aColors = mBorderColors[aIndex];
1348 }
1349 }
1350
AppendBorderColornsStyleBorder1351 void AppendBorderColor(int32_t aIndex, nscolor aColor)
1352 {
1353 NS_ASSERTION(aIndex >= 0 && aIndex <= 3, "bad side for composite border color");
1354 nsBorderColors* colorEntry = new nsBorderColors(aColor);
1355 if (!mBorderColors[aIndex]) {
1356 mBorderColors[aIndex] = colorEntry;
1357 } else {
1358 nsBorderColors* last = mBorderColors[aIndex];
1359 while (last->mNext) {
1360 last = last->mNext;
1361 }
1362 last->mNext = colorEntry;
1363 }
1364 }
1365
GetBorderImageRequestnsStyleBorder1366 imgIRequest* GetBorderImageRequest() const
1367 {
1368 if (mBorderImageSource.GetType() == eStyleImageType_Image) {
1369 return mBorderImageSource.GetImageData();
1370 }
1371 return nullptr;
1372 }
1373
1374 public:
1375 nsBorderColors** mBorderColors; // [reset] composite (stripe) colors
1376 nsStyleCorners mBorderRadius; // [reset] coord, percent
1377 nsStyleImage mBorderImageSource; // [reset]
1378 nsStyleSides mBorderImageSlice; // [reset] factor, percent
1379 nsStyleSides mBorderImageWidth; // [reset] length, factor, percent, auto
1380 nsStyleSides mBorderImageOutset; // [reset] length, factor
1381
1382 uint8_t mBorderImageFill; // [reset]
1383 uint8_t mBorderImageRepeatH; // [reset] see nsStyleConsts.h
1384 uint8_t mBorderImageRepeatV; // [reset]
1385 mozilla::StyleFloatEdge mFloatEdge; // [reset]
1386 mozilla::StyleBoxDecorationBreak mBoxDecorationBreak; // [reset]
1387
1388 protected:
1389 uint8_t mBorderStyle[4]; // [reset] See nsStyleConsts.h
1390
1391 public:
1392 // [reset] the colors to use for a simple border.
1393 // not used for -moz-border-colors
1394 union {
1395 struct {
1396 mozilla::StyleComplexColor mBorderTopColor;
1397 mozilla::StyleComplexColor mBorderRightColor;
1398 mozilla::StyleComplexColor mBorderBottomColor;
1399 mozilla::StyleComplexColor mBorderLeftColor;
1400 };
1401 mozilla::StyleComplexColor mBorderColor[4];
1402 };
1403
1404 protected:
1405 // mComputedBorder holds the CSS2.1 computed border-width values.
1406 // In particular, these widths take into account the border-style
1407 // for the relevant side, and the values are rounded to the nearest
1408 // device pixel (which is not part of the definition of computed
1409 // values). The presence or absence of a border-image does not
1410 // affect border-width values.
1411 nsMargin mComputedBorder;
1412
1413 // mBorder holds the nscoord values for the border widths as they
1414 // would be if all the border-style values were visible (not hidden
1415 // or none). This member exists so that when we create structs
1416 // using the copy constructor during style resolution the new
1417 // structs will know what the specified values of the border were in
1418 // case they have more specific rules setting the border style.
1419 //
1420 // Note that this isn't quite the CSS specified value, since this
1421 // has had the enumerated border widths converted to lengths, and
1422 // all lengths converted to twips. But it's not quite the computed
1423 // value either. The values are rounded to the nearest device pixel.
1424 nsMargin mBorder;
1425
1426 private:
1427 nscoord mTwipsPerPixel;
1428
1429 nsStyleBorder& operator=(const nsStyleBorder& aOther) = delete;
1430 };
1431
1432 #define ASSERT_BORDER_COLOR_FIELD(side_) \
1433 static_assert(offsetof(nsStyleBorder, mBorder##side_##Color) == \
1434 offsetof(nsStyleBorder, mBorderColor) + \
1435 size_t(mozilla::eSide##side_) * \
1436 sizeof(mozilla::StyleComplexColor), \
1437 "mBorder" #side_ "Color must be at same offset " \
1438 "as mBorderColor[mozilla::eSide" #side_ "]")
1439 ASSERT_BORDER_COLOR_FIELD(Top);
1440 ASSERT_BORDER_COLOR_FIELD(Right);
1441 ASSERT_BORDER_COLOR_FIELD(Bottom);
1442 ASSERT_BORDER_COLOR_FIELD(Left);
1443 #undef ASSERT_BORDER_COLOR_FIELD
1444
1445
1446 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleOutline
1447 {
1448 explicit nsStyleOutline(StyleStructContext aContext);
1449 nsStyleOutline(const nsStyleOutline& aOutline);
~nsStyleOutlinensStyleOutline1450 ~nsStyleOutline() {
1451 MOZ_COUNT_DTOR(nsStyleOutline);
1452 }
FinishStylensStyleOutline1453 void FinishStyle(nsPresContext* aPresContext) {}
1454
newnsStyleOutline1455 void* operator new(size_t sz, nsStyleOutline* aSelf) { return aSelf; }
newnsStyleOutline1456 void* operator new(size_t sz, nsPresContext* aContext) {
1457 return aContext->PresShell()->
1458 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleOutline, sz);
1459 }
DestroynsStyleOutline1460 void Destroy(nsPresContext* aContext) {
1461 this->~nsStyleOutline();
1462 aContext->PresShell()->
1463 FreeByObjectID(mozilla::eArenaObjectID_nsStyleOutline, this);
1464 }
1465
1466 void RecalcData();
1467 nsChangeHint CalcDifference(const nsStyleOutline& aNewData) const;
MaxDifferencensStyleOutline1468 static nsChangeHint MaxDifference() {
1469 return nsChangeHint_UpdateOverflow |
1470 nsChangeHint_SchedulePaint |
1471 nsChangeHint_RepaintFrame |
1472 nsChangeHint_NeutralChange;
1473 }
DifferenceAlwaysHandledForDescendantsnsStyleOutline1474 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
1475 // CalcDifference never returns the reflow hints that are sometimes
1476 // handled for descendants at all.
1477 return nsChangeHint(0);
1478 }
1479
1480 nsStyleCorners mOutlineRadius; // [reset] coord, percent, calc
1481
1482 // This is the specified value of outline-width, but with length values
1483 // computed to absolute. mActualOutlineWidth stores the outline-width
1484 // value used by layout. (We must store mOutlineWidth for the same
1485 // style struct resolution reasons that we do nsStyleBorder::mBorder;
1486 // see that field's comment.)
1487 nsStyleCoord mOutlineWidth; // [reset] coord, enum (see nsStyleConsts.h)
1488 nscoord mOutlineOffset; // [reset]
1489 mozilla::StyleComplexColor mOutlineColor; // [reset]
1490 uint8_t mOutlineStyle; // [reset] See nsStyleConsts.h
1491
GetOutlineWidthnsStyleOutline1492 nscoord GetOutlineWidth() const
1493 {
1494 return mActualOutlineWidth;
1495 }
1496
1497 protected:
1498 // The actual value of outline-width is the computed value (an absolute
1499 // length, forced to zero when outline-style is none) rounded to device
1500 // pixels. This is the value used by layout.
1501 nscoord mActualOutlineWidth;
1502 nscoord mTwipsPerPixel;
1503 };
1504
1505
1506 /**
1507 * An object that allows sharing of arrays that store 'quotes' property
1508 * values. This is particularly important for inheritance, where we want
1509 * to share the same 'quotes' value with a parent style context.
1510 */
1511 class nsStyleQuoteValues
1512 {
1513 public:
1514 typedef nsTArray<std::pair<nsString, nsString>> QuotePairArray;
1515 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsStyleQuoteValues);
1516 QuotePairArray mQuotePairs;
1517
1518 private:
~nsStyleQuoteValues()1519 ~nsStyleQuoteValues() {}
1520 };
1521
1522 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleList
1523 {
1524 explicit nsStyleList(StyleStructContext aContext);
1525 nsStyleList(const nsStyleList& aStyleList);
1526 ~nsStyleList();
1527
1528 void FinishStyle(nsPresContext* aPresContext);
1529
newnsStyleList1530 void* operator new(size_t sz, nsStyleList* aSelf) { return aSelf; }
newnsStyleList1531 void* operator new(size_t sz, nsPresContext* aContext) {
1532 return aContext->PresShell()->
1533 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleList, sz);
1534 }
DestroynsStyleList1535 void Destroy(nsPresContext* aContext) {
1536 this->~nsStyleList();
1537 aContext->PresShell()->
1538 FreeByObjectID(mozilla::eArenaObjectID_nsStyleList, this);
1539 }
1540
1541 nsChangeHint CalcDifference(const nsStyleList& aNewData) const;
MaxDifferencensStyleList1542 static nsChangeHint MaxDifference() {
1543 return nsChangeHint_ReconstructFrame |
1544 NS_STYLE_HINT_REFLOW;
1545 }
DifferenceAlwaysHandledForDescendantsnsStyleList1546 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
1547 // CalcDifference never returns the reflow hints that are sometimes
1548 // handled for descendants as hints not handled for descendants.
1549 return nsChangeHint_NeedReflow |
1550 nsChangeHint_ReflowChangesSizeOrPosition |
1551 nsChangeHint_ClearAncestorIntrinsics;
1552 }
1553
ShutdownnsStyleList1554 static void Shutdown() {
1555 sInitialQuotes = nullptr;
1556 sNoneQuotes = nullptr;
1557 }
1558
GetListStyleImagensStyleList1559 imgRequestProxy* GetListStyleImage() const
1560 {
1561 return mListStyleImage ? mListStyleImage->get() : nullptr;
1562 }
1563
GetListStyleTypensStyleList1564 void GetListStyleType(nsSubstring& aType) const { mCounterStyle->GetStyleName(aType); }
GetCounterStylensStyleList1565 mozilla::CounterStyle* GetCounterStyle() const
1566 {
1567 return mCounterStyle.get();
1568 }
SetCounterStylensStyleList1569 void SetCounterStyle(mozilla::CounterStyle* aStyle)
1570 {
1571 // NB: This function is called off-main-thread during parallel restyle, but
1572 // only with builtin styles that use dummy refcounting.
1573 MOZ_ASSERT(NS_IsMainThread() || !aStyle->IsDependentStyle());
1574 mCounterStyle = aStyle;
1575 }
SetListStyleTypensStyleList1576 void SetListStyleType(const nsSubstring& aType,
1577 nsPresContext* aPresContext)
1578 {
1579 SetCounterStyle(aPresContext->CounterStyleManager()->BuildCounterStyle(aType));
1580 }
1581
1582 const nsStyleQuoteValues::QuotePairArray& GetQuotePairs() const;
1583
1584 void SetQuotesInherit(const nsStyleList* aOther);
1585 void SetQuotesInitial();
1586 void SetQuotesNone();
1587 void SetQuotes(nsStyleQuoteValues::QuotePairArray&& aValues);
1588
1589 uint8_t mListStylePosition; // [inherited]
1590 RefPtr<nsStyleImageRequest> mListStyleImage; // [inherited]
1591 private:
1592 RefPtr<mozilla::CounterStyle> mCounterStyle; // [inherited]
1593 RefPtr<nsStyleQuoteValues> mQuotes; // [inherited]
1594 nsStyleList& operator=(const nsStyleList& aOther) = delete;
1595 public:
1596 nsRect mImageRegion; // [inherited] the rect to use within an image
1597
1598 private:
1599 // nsStyleQuoteValues objects representing two common values, for sharing.
1600 static mozilla::StaticRefPtr<nsStyleQuoteValues> sInitialQuotes;
1601 static mozilla::StaticRefPtr<nsStyleQuoteValues> sNoneQuotes;
1602 };
1603
1604 struct nsStyleGridLine
1605 {
1606 // http://dev.w3.org/csswg/css-grid/#typedef-grid-line
1607 // XXXmats we could optimize memory size here
1608 bool mHasSpan;
1609 int32_t mInteger; // 0 means not provided
1610 nsString mLineName; // Empty string means not provided.
1611
1612 // These are the limits that we choose to clamp grid line numbers to.
1613 // http://dev.w3.org/csswg/css-grid/#overlarge-grids
1614 // mInteger is clamped to this range:
1615 static const int32_t kMinLine = -10000;
1616 static const int32_t kMaxLine = 10000;
1617
nsStyleGridLinensStyleGridLine1618 nsStyleGridLine()
1619 : mHasSpan(false)
1620 , mInteger(0)
1621 // mLineName get its default constructor, the empty string
1622 {
1623 }
1624
nsStyleGridLinensStyleGridLine1625 nsStyleGridLine(const nsStyleGridLine& aOther)
1626 {
1627 (*this) = aOther;
1628 }
1629
1630 void operator=(const nsStyleGridLine& aOther)
1631 {
1632 mHasSpan = aOther.mHasSpan;
1633 mInteger = aOther.mInteger;
1634 mLineName = aOther.mLineName;
1635 }
1636
1637 bool operator!=(const nsStyleGridLine& aOther) const
1638 {
1639 return mHasSpan != aOther.mHasSpan ||
1640 mInteger != aOther.mInteger ||
1641 mLineName != aOther.mLineName;
1642 }
1643
SetToIntegernsStyleGridLine1644 void SetToInteger(uint32_t value)
1645 {
1646 mHasSpan = false;
1647 mInteger = value;
1648 mLineName.Truncate();
1649 }
1650
SetAutonsStyleGridLine1651 void SetAuto()
1652 {
1653 mHasSpan = false;
1654 mInteger = 0;
1655 mLineName.Truncate();
1656 }
1657
IsAutonsStyleGridLine1658 bool IsAuto() const
1659 {
1660 bool haveInitialValues = mInteger == 0 && mLineName.IsEmpty();
1661 MOZ_ASSERT(!(haveInitialValues && mHasSpan),
1662 "should not have 'span' when other components are "
1663 "at their initial values");
1664 return haveInitialValues;
1665 }
1666 };
1667
1668 // Computed value of the grid-template-columns or grid-template-rows property
1669 // (but *not* grid-template-areas.)
1670 // http://dev.w3.org/csswg/css-grid/#track-sizing
1671 //
1672 // This represents either:
1673 // * none:
1674 // mIsSubgrid is false, all three arrays are empty
1675 // * <track-list>:
1676 // mIsSubgrid is false,
1677 // mMinTrackSizingFunctions and mMaxTrackSizingFunctions
1678 // are of identical non-zero size,
1679 // and mLineNameLists is one element longer than that.
1680 // (Delimiting N columns requires N+1 lines:
1681 // one before each track, plus one at the very end.)
1682 //
1683 // An omitted <line-names> is still represented in mLineNameLists,
1684 // as an empty sub-array.
1685 //
1686 // A <track-size> specified as a single <track-breadth> is represented
1687 // as identical min and max sizing functions.
1688 // A 'fit-content(size)' <track-size> is represented as eStyleUnit_None
1689 // in the min sizing function and 'size' in the max sizing function.
1690 //
1691 // The units for nsStyleCoord are:
1692 // * eStyleUnit_Percent represents a <percentage>
1693 // * eStyleUnit_FlexFraction represents a <flex> flexible fraction
1694 // * eStyleUnit_Coord represents a <length>
1695 // * eStyleUnit_Enumerated represents min-content or max-content
1696 // * subgrid <line-name-list>?:
1697 // mIsSubgrid is true,
1698 // mLineNameLists may or may not be empty,
1699 // mMinTrackSizingFunctions and mMaxTrackSizingFunctions are empty.
1700 //
1701 // If mRepeatAutoIndex != -1 then that index is an <auto-repeat> and
1702 // mIsAutoFill == true means it's an 'auto-fill', otherwise 'auto-fit'.
1703 // mRepeatAutoLineNameListBefore is the list of line names before the track
1704 // size, mRepeatAutoLineNameListAfter the names after. (They are empty
1705 // when there is no <auto-repeat> track, i.e. when mRepeatAutoIndex == -1).
1706 // When mIsSubgrid is true, mRepeatAutoLineNameListBefore contains the line
1707 // names and mRepeatAutoLineNameListAfter is empty.
1708 struct nsStyleGridTemplate
1709 {
1710 nsTArray<nsTArray<nsString>> mLineNameLists;
1711 nsTArray<nsStyleCoord> mMinTrackSizingFunctions;
1712 nsTArray<nsStyleCoord> mMaxTrackSizingFunctions;
1713 nsTArray<nsString> mRepeatAutoLineNameListBefore;
1714 nsTArray<nsString> mRepeatAutoLineNameListAfter;
1715 int16_t mRepeatAutoIndex; // -1 or the track index for an auto-fill/fit track
1716 bool mIsAutoFill : 1;
1717 bool mIsSubgrid : 1;
1718
nsStyleGridTemplatensStyleGridTemplate1719 nsStyleGridTemplate()
1720 : mRepeatAutoIndex(-1)
1721 , mIsAutoFill(false)
1722 , mIsSubgrid(false)
1723 {
1724 }
1725
1726 inline bool operator!=(const nsStyleGridTemplate& aOther) const {
1727 return
1728 mIsSubgrid != aOther.mIsSubgrid ||
1729 mLineNameLists != aOther.mLineNameLists ||
1730 mMinTrackSizingFunctions != aOther.mMinTrackSizingFunctions ||
1731 mMaxTrackSizingFunctions != aOther.mMaxTrackSizingFunctions ||
1732 mIsAutoFill != aOther.mIsAutoFill ||
1733 mRepeatAutoIndex != aOther.mRepeatAutoIndex ||
1734 mRepeatAutoLineNameListBefore != aOther.mRepeatAutoLineNameListBefore ||
1735 mRepeatAutoLineNameListAfter != aOther.mRepeatAutoLineNameListAfter;
1736 }
1737
HasRepeatAutonsStyleGridTemplate1738 bool HasRepeatAuto() const {
1739 return mRepeatAutoIndex != -1;
1740 }
1741
IsRepeatAutoIndexnsStyleGridTemplate1742 bool IsRepeatAutoIndex(uint32_t aIndex) const {
1743 MOZ_ASSERT(aIndex < uint32_t(2*nsStyleGridLine::kMaxLine));
1744 return int32_t(aIndex) == mRepeatAutoIndex;
1745 }
1746 };
1747
1748 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition
1749 {
1750 explicit nsStylePosition(StyleStructContext aContext);
1751 nsStylePosition(const nsStylePosition& aOther);
1752 ~nsStylePosition();
FinishStylensStylePosition1753 void FinishStyle(nsPresContext* aPresContext) {}
1754
newnsStylePosition1755 void* operator new(size_t sz, nsStylePosition* aSelf) { return aSelf; }
newnsStylePosition1756 void* operator new(size_t sz, nsPresContext* aContext) {
1757 return aContext->PresShell()->
1758 AllocateByObjectID(mozilla::eArenaObjectID_nsStylePosition, sz);
1759 }
DestroynsStylePosition1760 void Destroy(nsPresContext* aContext) {
1761 this->~nsStylePosition();
1762 aContext->PresShell()->
1763 FreeByObjectID(mozilla::eArenaObjectID_nsStylePosition, this);
1764 }
1765
1766 nsChangeHint CalcDifference(const nsStylePosition& aNewData,
1767 const nsStyleVisibility* aOldStyleVisibility) const;
MaxDifferencensStylePosition1768 static nsChangeHint MaxDifference() {
1769 return NS_STYLE_HINT_REFLOW |
1770 nsChangeHint_NeutralChange |
1771 nsChangeHint_RecomputePosition |
1772 nsChangeHint_UpdateParentOverflow |
1773 nsChangeHint_UpdateComputedBSize;
1774 }
DifferenceAlwaysHandledForDescendantsnsStylePosition1775 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
1776 // CalcDifference can return all of the reflow hints that are
1777 // sometimes handled for descendants as hints not handled for
1778 // descendants.
1779 return nsChangeHint(0);
1780 }
1781
1782 /**
1783 * Return the used value for 'align-self' given our parent StyleContext
1784 * aParent (or null for the root).
1785 */
1786 uint8_t UsedAlignSelf(nsStyleContext* aParent) const;
1787
1788 /**
1789 * Return the computed value for 'justify-items' given our parent StyleContext
1790 * aParent (or null for the root).
1791 */
1792 uint8_t ComputedJustifyItems(nsStyleContext* aParent) const;
1793
1794 /**
1795 * Return the used value for 'justify-self' given our parent StyleContext
1796 * aParent (or null for the root).
1797 */
1798 uint8_t UsedJustifySelf(nsStyleContext* aParent) const;
1799
1800 mozilla::Position mObjectPosition; // [reset]
1801 nsStyleSides mOffset; // [reset] coord, percent, calc, auto
1802 nsStyleCoord mWidth; // [reset] coord, percent, enum, calc, auto
1803 nsStyleCoord mMinWidth; // [reset] coord, percent, enum, calc
1804 nsStyleCoord mMaxWidth; // [reset] coord, percent, enum, calc, none
1805 nsStyleCoord mHeight; // [reset] coord, percent, calc, auto
1806 nsStyleCoord mMinHeight; // [reset] coord, percent, calc
1807 nsStyleCoord mMaxHeight; // [reset] coord, percent, calc, none
1808 nsStyleCoord mFlexBasis; // [reset] coord, percent, enum, calc, auto
1809 nsStyleCoord mGridAutoColumnsMin; // [reset] coord, percent, enum, calc, flex
1810 nsStyleCoord mGridAutoColumnsMax; // [reset] coord, percent, enum, calc, flex
1811 nsStyleCoord mGridAutoRowsMin; // [reset] coord, percent, enum, calc, flex
1812 nsStyleCoord mGridAutoRowsMax; // [reset] coord, percent, enum, calc, flex
1813 uint8_t mGridAutoFlow; // [reset] enumerated. See nsStyleConsts.h
1814 mozilla::StyleBoxSizing mBoxSizing; // [reset] see nsStyleConsts.h
1815
1816 uint16_t mAlignContent; // [reset] fallback value in the high byte
1817 uint8_t mAlignItems; // [reset] see nsStyleConsts.h
1818 uint8_t mAlignSelf; // [reset] see nsStyleConsts.h
1819 uint16_t mJustifyContent; // [reset] fallback value in the high byte
1820 private:
1821 friend class nsRuleNode;
1822
1823 // mJustifyItems should only be read via ComputedJustifyItems(), which
1824 // lazily resolves its "auto" value. nsRuleNode needs direct access so
1825 // it can set mJustifyItems' value when populating this struct.
1826 uint8_t mJustifyItems; // [reset] see nsStyleConsts.h
1827 public:
1828 uint8_t mJustifySelf; // [reset] see nsStyleConsts.h
1829 uint8_t mFlexDirection; // [reset] see nsStyleConsts.h
1830 uint8_t mFlexWrap; // [reset] see nsStyleConsts.h
1831 uint8_t mObjectFit; // [reset] see nsStyleConsts.h
1832 int32_t mOrder; // [reset] integer
1833 float mFlexGrow; // [reset] float
1834 float mFlexShrink; // [reset] float
1835 nsStyleCoord mZIndex; // [reset] integer, auto
1836 nsStyleGridTemplate mGridTemplateColumns;
1837 nsStyleGridTemplate mGridTemplateRows;
1838
1839 // nullptr for 'none'
1840 RefPtr<mozilla::css::GridTemplateAreasValue> mGridTemplateAreas;
1841
1842 nsStyleGridLine mGridColumnStart;
1843 nsStyleGridLine mGridColumnEnd;
1844 nsStyleGridLine mGridRowStart;
1845 nsStyleGridLine mGridRowEnd;
1846 nsStyleCoord mGridColumnGap; // [reset] coord, percent, calc
1847 nsStyleCoord mGridRowGap; // [reset] coord, percent, calc
1848
1849 // FIXME: Logical-coordinate equivalents to these WidthDepends... and
1850 // HeightDepends... methods have been introduced (see below); we probably
1851 // want to work towards removing the physical methods, and using the logical
1852 // ones in all cases.
1853
WidthDependsOnContainernsStylePosition1854 bool WidthDependsOnContainer() const
1855 {
1856 return mWidth.GetUnit() == eStyleUnit_Auto ||
1857 WidthCoordDependsOnContainer(mWidth);
1858 }
1859
1860 // NOTE: For a flex item, "min-width:auto" is supposed to behave like
1861 // "min-content", which does depend on the container, so you might think we'd
1862 // need a special case for "flex item && min-width:auto" here. However,
1863 // we don't actually need that special-case code, because flex items are
1864 // explicitly supposed to *ignore* their min-width (i.e. behave like it's 0)
1865 // until the flex container explicitly considers it. So -- since the flex
1866 // container doesn't rely on this method, we don't need to worry about
1867 // special behavior for flex items' "min-width:auto" values here.
MinWidthDependsOnContainernsStylePosition1868 bool MinWidthDependsOnContainer() const
1869 { return WidthCoordDependsOnContainer(mMinWidth); }
MaxWidthDependsOnContainernsStylePosition1870 bool MaxWidthDependsOnContainer() const
1871 { return WidthCoordDependsOnContainer(mMaxWidth); }
1872
1873 // Note that these functions count 'auto' as depending on the
1874 // container since that's the case for absolutely positioned elements.
1875 // However, some callers do not care about this case and should check
1876 // for it, since it is the most common case.
1877 // FIXME: We should probably change the assumption to be the other way
1878 // around.
1879 // Consider this as part of moving to the logical-coordinate APIs.
HeightDependsOnContainernsStylePosition1880 bool HeightDependsOnContainer() const
1881 {
1882 return mHeight.GetUnit() == eStyleUnit_Auto || // CSS 2.1, 10.6.4, item (5)
1883 HeightCoordDependsOnContainer(mHeight);
1884 }
1885
1886 // NOTE: The comment above MinWidthDependsOnContainer about flex items
1887 // applies here, too.
MinHeightDependsOnContainernsStylePosition1888 bool MinHeightDependsOnContainer() const
1889 { return HeightCoordDependsOnContainer(mMinHeight); }
MaxHeightDependsOnContainernsStylePosition1890 bool MaxHeightDependsOnContainer() const
1891 { return HeightCoordDependsOnContainer(mMaxHeight); }
1892
OffsetHasPercentnsStylePosition1893 bool OffsetHasPercent(mozilla::css::Side aSide) const
1894 {
1895 return mOffset.Get(aSide).HasPercent();
1896 }
1897
1898 // Logical-coordinate accessors for width and height properties,
1899 // given a WritingMode value. The definitions of these methods are
1900 // found in WritingModes.h (after the WritingMode class is fully
1901 // declared).
1902 inline nsStyleCoord& ISize(mozilla::WritingMode aWM);
1903 inline nsStyleCoord& MinISize(mozilla::WritingMode aWM);
1904 inline nsStyleCoord& MaxISize(mozilla::WritingMode aWM);
1905 inline nsStyleCoord& BSize(mozilla::WritingMode aWM);
1906 inline nsStyleCoord& MinBSize(mozilla::WritingMode aWM);
1907 inline nsStyleCoord& MaxBSize(mozilla::WritingMode aWM);
1908 inline const nsStyleCoord& ISize(mozilla::WritingMode aWM) const;
1909 inline const nsStyleCoord& MinISize(mozilla::WritingMode aWM) const;
1910 inline const nsStyleCoord& MaxISize(mozilla::WritingMode aWM) const;
1911 inline const nsStyleCoord& BSize(mozilla::WritingMode aWM) const;
1912 inline const nsStyleCoord& MinBSize(mozilla::WritingMode aWM) const;
1913 inline const nsStyleCoord& MaxBSize(mozilla::WritingMode aWM) const;
1914 inline bool ISizeDependsOnContainer(mozilla::WritingMode aWM) const;
1915 inline bool MinISizeDependsOnContainer(mozilla::WritingMode aWM) const;
1916 inline bool MaxISizeDependsOnContainer(mozilla::WritingMode aWM) const;
1917 inline bool BSizeDependsOnContainer(mozilla::WritingMode aWM) const;
1918 inline bool MinBSizeDependsOnContainer(mozilla::WritingMode aWM) const;
1919 inline bool MaxBSizeDependsOnContainer(mozilla::WritingMode aWM) const;
1920
1921 private:
1922 static bool WidthCoordDependsOnContainer(const nsStyleCoord &aCoord);
HeightCoordDependsOnContainernsStylePosition1923 static bool HeightCoordDependsOnContainer(const nsStyleCoord &aCoord)
1924 { return aCoord.HasPercent(); }
1925 };
1926
1927 struct nsStyleTextOverflowSide
1928 {
nsStyleTextOverflowSidensStyleTextOverflowSide1929 nsStyleTextOverflowSide() : mType(NS_STYLE_TEXT_OVERFLOW_CLIP) {}
1930
1931 bool operator==(const nsStyleTextOverflowSide& aOther) const {
1932 return mType == aOther.mType &&
1933 (mType != NS_STYLE_TEXT_OVERFLOW_STRING ||
1934 mString == aOther.mString);
1935 }
1936 bool operator!=(const nsStyleTextOverflowSide& aOther) const {
1937 return !(*this == aOther);
1938 }
1939
1940 nsString mString;
1941 uint8_t mType;
1942 };
1943
1944 struct nsStyleTextOverflow
1945 {
nsStyleTextOverflownsStyleTextOverflow1946 nsStyleTextOverflow() : mLogicalDirections(true) {}
1947 bool operator==(const nsStyleTextOverflow& aOther) const {
1948 return mLeft == aOther.mLeft && mRight == aOther.mRight;
1949 }
1950 bool operator!=(const nsStyleTextOverflow& aOther) const {
1951 return !(*this == aOther);
1952 }
1953
1954 // Returns the value to apply on the left side.
GetLeftnsStyleTextOverflow1955 const nsStyleTextOverflowSide& GetLeft(uint8_t aDirection) const {
1956 NS_ASSERTION(aDirection == NS_STYLE_DIRECTION_LTR ||
1957 aDirection == NS_STYLE_DIRECTION_RTL, "bad direction");
1958 return !mLogicalDirections || aDirection == NS_STYLE_DIRECTION_LTR ?
1959 mLeft : mRight;
1960 }
1961
1962 // Returns the value to apply on the right side.
GetRightnsStyleTextOverflow1963 const nsStyleTextOverflowSide& GetRight(uint8_t aDirection) const {
1964 NS_ASSERTION(aDirection == NS_STYLE_DIRECTION_LTR ||
1965 aDirection == NS_STYLE_DIRECTION_RTL, "bad direction");
1966 return !mLogicalDirections || aDirection == NS_STYLE_DIRECTION_LTR ?
1967 mRight : mLeft;
1968 }
1969
1970 // Returns the first value that was specified.
GetFirstValuensStyleTextOverflow1971 const nsStyleTextOverflowSide* GetFirstValue() const {
1972 return mLogicalDirections ? &mRight : &mLeft;
1973 }
1974
1975 // Returns the second value, or null if there was only one value specified.
GetSecondValuensStyleTextOverflow1976 const nsStyleTextOverflowSide* GetSecondValue() const {
1977 return mLogicalDirections ? nullptr : &mRight;
1978 }
1979
1980 nsStyleTextOverflowSide mLeft; // start side when mLogicalDirections is true
1981 nsStyleTextOverflowSide mRight; // end side when mLogicalDirections is true
1982 bool mLogicalDirections; // true when only one value was specified
1983 };
1984
1985 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTextReset
1986 {
1987 explicit nsStyleTextReset(StyleStructContext aContext);
1988 nsStyleTextReset(const nsStyleTextReset& aOther);
1989 ~nsStyleTextReset();
FinishStylensStyleTextReset1990 void FinishStyle(nsPresContext* aPresContext) {}
1991
newnsStyleTextReset1992 void* operator new(size_t sz, nsStyleTextReset* aSelf) { return aSelf; }
newnsStyleTextReset1993 void* operator new(size_t sz, nsPresContext* aContext) {
1994 return aContext->PresShell()->
1995 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTextReset, sz);
1996 }
DestroynsStyleTextReset1997 void Destroy(nsPresContext* aContext) {
1998 this->~nsStyleTextReset();
1999 aContext->PresShell()->
2000 FreeByObjectID(mozilla::eArenaObjectID_nsStyleTextReset, this);
2001 }
2002
2003 // Note the difference between this and
2004 // nsStyleContext::HasTextDecorationLines.
HasTextDecorationLinesnsStyleTextReset2005 bool HasTextDecorationLines() const {
2006 return mTextDecorationLine != NS_STYLE_TEXT_DECORATION_LINE_NONE &&
2007 mTextDecorationLine != NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL;
2008 }
2009
2010 nsChangeHint CalcDifference(const nsStyleTextReset& aNewData) const;
MaxDifferencensStyleTextReset2011 static nsChangeHint MaxDifference() {
2012 return nsChangeHint(
2013 NS_STYLE_HINT_REFLOW |
2014 nsChangeHint_UpdateSubtreeOverflow);
2015 }
DifferenceAlwaysHandledForDescendantsnsStyleTextReset2016 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
2017 // CalcDifference never returns the reflow hints that are sometimes
2018 // handled for descendants as hints not handled for descendants.
2019 return nsChangeHint_NeedReflow |
2020 nsChangeHint_ReflowChangesSizeOrPosition |
2021 nsChangeHint_ClearAncestorIntrinsics;
2022 }
2023
2024 nsStyleTextOverflow mTextOverflow; // [reset] enum, string
2025
2026 uint8_t mTextDecorationLine; // [reset] see nsStyleConsts.h
2027 uint8_t mTextDecorationStyle; // [reset] see nsStyleConsts.h
2028 uint8_t mUnicodeBidi; // [reset] see nsStyleConsts.h
2029 nscoord mInitialLetterSink; // [reset] 0 means normal
2030 float mInitialLetterSize; // [reset] 0.0f means normal
2031 mozilla::StyleComplexColor mTextDecorationColor; // [reset]
2032 };
2033
2034 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleText
2035 {
2036 explicit nsStyleText(StyleStructContext aContext);
2037 nsStyleText(const nsStyleText& aOther);
2038 ~nsStyleText();
FinishStylensStyleText2039 void FinishStyle(nsPresContext* aPresContext) {}
2040
newnsStyleText2041 void* operator new(size_t sz, nsStyleText* aSelf) { return aSelf; }
newnsStyleText2042 void* operator new(size_t sz, nsPresContext* aContext) {
2043 return aContext->PresShell()->
2044 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleText, sz);
2045 }
DestroynsStyleText2046 void Destroy(nsPresContext* aContext) {
2047 this->~nsStyleText();
2048 aContext->PresShell()->
2049 FreeByObjectID(mozilla::eArenaObjectID_nsStyleText, this);
2050 }
2051
2052 nsChangeHint CalcDifference(const nsStyleText& aNewData) const;
MaxDifferencensStyleText2053 static nsChangeHint MaxDifference() {
2054 return nsChangeHint_ReconstructFrame |
2055 NS_STYLE_HINT_REFLOW |
2056 nsChangeHint_UpdateSubtreeOverflow |
2057 nsChangeHint_NeutralChange;
2058 }
DifferenceAlwaysHandledForDescendantsnsStyleText2059 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
2060 // CalcDifference never returns the reflow hints that are sometimes
2061 // handled for descendants as hints not handled for descendants.
2062 return nsChangeHint_NeedReflow |
2063 nsChangeHint_ReflowChangesSizeOrPosition |
2064 nsChangeHint_ClearAncestorIntrinsics;
2065 }
2066
2067 uint8_t mTextAlign; // [inherited] see nsStyleConsts.h
2068 uint8_t mTextAlignLast; // [inherited] see nsStyleConsts.h
2069 bool mTextAlignTrue : 1; // [inherited] see nsStyleConsts.h
2070 bool mTextAlignLastTrue : 1; // [inherited] see nsStyleConsts.h
2071 uint8_t mTextTransform; // [inherited] see nsStyleConsts.h
2072 uint8_t mWhiteSpace; // [inherited] see nsStyleConsts.h
2073 uint8_t mWordBreak; // [inherited] see nsStyleConsts.h
2074 uint8_t mOverflowWrap; // [inherited] see nsStyleConsts.h
2075 uint8_t mHyphens; // [inherited] see nsStyleConsts.h
2076 uint8_t mRubyAlign; // [inherited] see nsStyleConsts.h
2077 uint8_t mRubyPosition; // [inherited] see nsStyleConsts.h
2078 uint8_t mTextSizeAdjust; // [inherited] see nsStyleConsts.h
2079 uint8_t mTextCombineUpright; // [inherited] see nsStyleConsts.h
2080 uint8_t mControlCharacterVisibility; // [inherited] see nsStyleConsts.h
2081 uint8_t mTextEmphasisPosition; // [inherited] see nsStyleConsts.h
2082 uint8_t mTextEmphasisStyle; // [inherited] see nsStyleConsts.h
2083 uint8_t mTextRendering; // [inherited] see nsStyleConsts.h
2084 int32_t mTabSize; // [inherited] see nsStyleConsts.h
2085 mozilla::StyleComplexColor mTextEmphasisColor; // [inherited]
2086 mozilla::StyleComplexColor mWebkitTextFillColor; // [inherited]
2087 mozilla::StyleComplexColor mWebkitTextStrokeColor; // [inherited]
2088
2089 nsStyleCoord mWordSpacing; // [inherited] coord, percent, calc
2090 nsStyleCoord mLetterSpacing; // [inherited] coord, normal
2091 nsStyleCoord mLineHeight; // [inherited] coord, factor, normal
2092 nsStyleCoord mTextIndent; // [inherited] coord, percent, calc
2093 nsStyleCoord mWebkitTextStrokeWidth; // [inherited] coord
2094
2095 RefPtr<nsCSSShadowArray> mTextShadow; // [inherited] nullptr in case of a zero-length
2096
2097 nsString mTextEmphasisStyleString; // [inherited]
2098
WhiteSpaceIsSignificantnsStyleText2099 bool WhiteSpaceIsSignificant() const {
2100 return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
2101 mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
2102 mWhiteSpace == NS_STYLE_WHITESPACE_PRE_SPACE;
2103 }
2104
NewlineIsSignificantStylensStyleText2105 bool NewlineIsSignificantStyle() const {
2106 return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
2107 mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
2108 mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE;
2109 }
2110
WhiteSpaceOrNewlineIsSignificantnsStyleText2111 bool WhiteSpaceOrNewlineIsSignificant() const {
2112 return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
2113 mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
2114 mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE ||
2115 mWhiteSpace == NS_STYLE_WHITESPACE_PRE_SPACE;
2116 }
2117
TabIsSignificantnsStyleText2118 bool TabIsSignificant() const {
2119 return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
2120 mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP;
2121 }
2122
WhiteSpaceCanWrapStylensStyleText2123 bool WhiteSpaceCanWrapStyle() const {
2124 return mWhiteSpace == NS_STYLE_WHITESPACE_NORMAL ||
2125 mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
2126 mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE;
2127 }
2128
WordCanWrapStylensStyleText2129 bool WordCanWrapStyle() const {
2130 return WhiteSpaceCanWrapStyle() &&
2131 mOverflowWrap == NS_STYLE_OVERFLOWWRAP_BREAK_WORD;
2132 }
2133
HasTextEmphasisnsStyleText2134 bool HasTextEmphasis() const {
2135 return !mTextEmphasisStyleString.IsEmpty();
2136 }
2137
HasWebkitTextStrokensStyleText2138 bool HasWebkitTextStroke() const {
2139 return mWebkitTextStrokeWidth.GetCoordValue() > 0;
2140 }
2141
2142 // These are defined in nsStyleStructInlines.h.
2143 inline bool HasTextShadow() const;
2144 inline nsCSSShadowArray* GetTextShadow() const;
2145
2146 // The aContextFrame argument on each of these is the frame this
2147 // style struct is for. If the frame is for SVG text or inside ruby,
2148 // the return value will be massaged to be something that makes sense
2149 // for those cases.
2150 inline bool NewlineIsSignificant(const nsTextFrame* aContextFrame) const;
2151 inline bool WhiteSpaceCanWrap(const nsIFrame* aContextFrame) const;
2152 inline bool WordCanWrap(const nsIFrame* aContextFrame) const;
2153
2154 mozilla::LogicalSide TextEmphasisSide(mozilla::WritingMode aWM) const;
2155 };
2156
2157 struct nsStyleImageOrientation
2158 {
CreateAsAngleAndFlipnsStyleImageOrientation2159 static nsStyleImageOrientation CreateAsAngleAndFlip(double aRadians,
2160 bool aFlip) {
2161 uint8_t orientation(0);
2162
2163 // Compute the final angle value, rounding to the closest quarter turn.
2164 double roundedAngle = fmod(aRadians, 2 * M_PI);
2165 if (roundedAngle < 0.25 * M_PI) { orientation = ANGLE_0; }
2166 else if (roundedAngle < 0.75 * M_PI) { orientation = ANGLE_90; }
2167 else if (roundedAngle < 1.25 * M_PI) { orientation = ANGLE_180;}
2168 else if (roundedAngle < 1.75 * M_PI) { orientation = ANGLE_270;}
2169 else { orientation = ANGLE_0; }
2170
2171 // Add a bit for 'flip' if needed.
2172 if (aFlip) {
2173 orientation |= FLIP_MASK;
2174 }
2175
2176 return nsStyleImageOrientation(orientation);
2177 }
2178
CreateAsFlipnsStyleImageOrientation2179 static nsStyleImageOrientation CreateAsFlip() {
2180 return nsStyleImageOrientation(FLIP_MASK);
2181 }
2182
CreateAsFromImagensStyleImageOrientation2183 static nsStyleImageOrientation CreateAsFromImage() {
2184 return nsStyleImageOrientation(FROM_IMAGE_MASK);
2185 }
2186
2187 // The default constructor yields 0 degrees of rotation and no flip.
nsStyleImageOrientationnsStyleImageOrientation2188 nsStyleImageOrientation() : mOrientation(0) { }
2189
IsDefaultnsStyleImageOrientation2190 bool IsDefault() const { return mOrientation == 0; }
IsFlippednsStyleImageOrientation2191 bool IsFlipped() const { return mOrientation & FLIP_MASK; }
IsFromImagensStyleImageOrientation2192 bool IsFromImage() const { return mOrientation & FROM_IMAGE_MASK; }
SwapsWidthAndHeightnsStyleImageOrientation2193 bool SwapsWidthAndHeight() const {
2194 uint8_t angle = mOrientation & ORIENTATION_MASK;
2195 return (angle == ANGLE_90) || (angle == ANGLE_270);
2196 }
2197
AnglensStyleImageOrientation2198 mozilla::image::Angle Angle() const {
2199 switch (mOrientation & ORIENTATION_MASK) {
2200 case ANGLE_0: return mozilla::image::Angle::D0;
2201 case ANGLE_90: return mozilla::image::Angle::D90;
2202 case ANGLE_180: return mozilla::image::Angle::D180;
2203 case ANGLE_270: return mozilla::image::Angle::D270;
2204 default:
2205 NS_NOTREACHED("Unexpected angle");
2206 return mozilla::image::Angle::D0;
2207 }
2208 }
2209
AngleAsCoordnsStyleImageOrientation2210 nsStyleCoord AngleAsCoord() const {
2211 switch (mOrientation & ORIENTATION_MASK) {
2212 case ANGLE_0: return nsStyleCoord(0.0f, eStyleUnit_Degree);
2213 case ANGLE_90: return nsStyleCoord(90.0f, eStyleUnit_Degree);
2214 case ANGLE_180: return nsStyleCoord(180.0f, eStyleUnit_Degree);
2215 case ANGLE_270: return nsStyleCoord(270.0f, eStyleUnit_Degree);
2216 default:
2217 NS_NOTREACHED("Unexpected angle");
2218 return nsStyleCoord();
2219 }
2220 }
2221
2222 bool operator==(const nsStyleImageOrientation& aOther) const {
2223 return aOther.mOrientation == mOrientation;
2224 }
2225
2226 bool operator!=(const nsStyleImageOrientation& aOther) const {
2227 return !(*this == aOther);
2228 }
2229
2230 protected:
2231 enum Bits {
2232 ORIENTATION_MASK = 0x1 | 0x2, // The bottom two bits are the angle.
2233 FLIP_MASK = 0x4, // Whether the image should be flipped.
2234 FROM_IMAGE_MASK = 0x8, // Whether the image's inherent orientation
2235 }; // should be used.
2236
2237 enum Angles {
2238 ANGLE_0 = 0,
2239 ANGLE_90 = 1,
2240 ANGLE_180 = 2,
2241 ANGLE_270 = 3,
2242 };
2243
nsStyleImageOrientationnsStyleImageOrientation2244 explicit nsStyleImageOrientation(uint8_t aOrientation)
2245 : mOrientation(aOrientation)
2246 { }
2247
2248 uint8_t mOrientation;
2249 };
2250
2251 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleVisibility
2252 {
2253 explicit nsStyleVisibility(StyleStructContext aContext);
2254 nsStyleVisibility(const nsStyleVisibility& aVisibility);
~nsStyleVisibilitynsStyleVisibility2255 ~nsStyleVisibility() {
2256 MOZ_COUNT_DTOR(nsStyleVisibility);
2257 }
FinishStylensStyleVisibility2258 void FinishStyle(nsPresContext* aPresContext) {}
2259
newnsStyleVisibility2260 void* operator new(size_t sz, nsStyleVisibility* aSelf) { return aSelf; }
newnsStyleVisibility2261 void* operator new(size_t sz, nsPresContext* aContext) {
2262 return aContext->PresShell()->
2263 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleVisibility, sz);
2264 }
DestroynsStyleVisibility2265 void Destroy(nsPresContext* aContext) {
2266 this->~nsStyleVisibility();
2267 aContext->PresShell()->
2268 FreeByObjectID(mozilla::eArenaObjectID_nsStyleVisibility, this);
2269 }
2270
2271 nsChangeHint CalcDifference(const nsStyleVisibility& aNewData) const;
MaxDifferencensStyleVisibility2272 static nsChangeHint MaxDifference() {
2273 return nsChangeHint_ReconstructFrame |
2274 NS_STYLE_HINT_REFLOW |
2275 nsChangeHint_NeutralChange;
2276 }
DifferenceAlwaysHandledForDescendantsnsStyleVisibility2277 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
2278 // CalcDifference never returns the reflow hints that are sometimes
2279 // handled for descendants as hints not handled for descendants.
2280 return nsChangeHint_NeedReflow |
2281 nsChangeHint_ReflowChangesSizeOrPosition |
2282 nsChangeHint_ClearAncestorIntrinsics;
2283 }
2284
2285 nsStyleImageOrientation mImageOrientation; // [inherited]
2286 uint8_t mDirection; // [inherited] see nsStyleConsts.h NS_STYLE_DIRECTION_*
2287 uint8_t mVisible; // [inherited]
2288 uint8_t mImageRendering; // [inherited] see nsStyleConsts.h
2289 uint8_t mWritingMode; // [inherited] see nsStyleConsts.h
2290 uint8_t mTextOrientation; // [inherited] see nsStyleConsts.h
2291 uint8_t mColorAdjust; // [inherited] see nsStyleConsts.h
2292
IsVisiblensStyleVisibility2293 bool IsVisible() const {
2294 return (mVisible == NS_STYLE_VISIBILITY_VISIBLE);
2295 }
2296
IsVisibleOrCollapsednsStyleVisibility2297 bool IsVisibleOrCollapsed() const {
2298 return ((mVisible == NS_STYLE_VISIBILITY_VISIBLE) ||
2299 (mVisible == NS_STYLE_VISIBILITY_COLLAPSE));
2300 }
2301 };
2302
2303 struct nsTimingFunction
2304 {
2305
2306 enum class Type {
2307 Ease, // ease
2308 Linear, // linear
2309 EaseIn, // ease-in
2310 EaseOut, // ease-out
2311 EaseInOut, // ease-in-out
2312 StepStart, // step-start and steps(..., start)
2313 StepEnd, // step-end, steps(..., end) and steps(...)
2314 CubicBezier, // cubic-bezier()
2315 };
2316
2317 // Whether the timing function type is represented by a spline,
2318 // and thus will have mFunc filled in.
IsSplineTypensTimingFunction2319 static bool IsSplineType(Type aType)
2320 {
2321 return aType != Type::StepStart && aType != Type::StepEnd;
2322 }
2323
2324 explicit nsTimingFunction(int32_t aTimingFunctionType
2325 = NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE)
2326 {
2327 AssignFromKeyword(aTimingFunctionType);
2328 }
2329
nsTimingFunctionnsTimingFunction2330 nsTimingFunction(float x1, float y1, float x2, float y2)
2331 : mType(Type::CubicBezier)
2332 {
2333 mFunc.mX1 = x1;
2334 mFunc.mY1 = y1;
2335 mFunc.mX2 = x2;
2336 mFunc.mY2 = y2;
2337 }
2338
2339 enum class Keyword { Implicit, Explicit };
2340
nsTimingFunctionnsTimingFunction2341 nsTimingFunction(Type aType, uint32_t aSteps)
2342 : mType(aType)
2343 {
2344 MOZ_ASSERT(mType == Type::StepStart || mType == Type::StepEnd,
2345 "wrong type");
2346 mSteps = aSteps;
2347 }
2348
nsTimingFunctionnsTimingFunction2349 nsTimingFunction(const nsTimingFunction& aOther)
2350 {
2351 *this = aOther;
2352 }
2353
2354 Type mType;
2355 union {
2356 struct {
2357 float mX1;
2358 float mY1;
2359 float mX2;
2360 float mY2;
2361 } mFunc;
2362 struct {
2363 uint32_t mSteps;
2364 };
2365 };
2366
2367 nsTimingFunction&
2368 operator=(const nsTimingFunction& aOther)
2369 {
2370 if (&aOther == this) {
2371 return *this;
2372 }
2373
2374 mType = aOther.mType;
2375
2376 if (HasSpline()) {
2377 mFunc.mX1 = aOther.mFunc.mX1;
2378 mFunc.mY1 = aOther.mFunc.mY1;
2379 mFunc.mX2 = aOther.mFunc.mX2;
2380 mFunc.mY2 = aOther.mFunc.mY2;
2381 } else {
2382 mSteps = aOther.mSteps;
2383 }
2384
2385 return *this;
2386 }
2387
2388 bool operator==(const nsTimingFunction& aOther) const
2389 {
2390 if (mType != aOther.mType) {
2391 return false;
2392 }
2393 if (HasSpline()) {
2394 return mFunc.mX1 == aOther.mFunc.mX1 && mFunc.mY1 == aOther.mFunc.mY1 &&
2395 mFunc.mX2 == aOther.mFunc.mX2 && mFunc.mY2 == aOther.mFunc.mY2;
2396 }
2397 return mSteps == aOther.mSteps;
2398 }
2399
2400 bool operator!=(const nsTimingFunction& aOther) const
2401 {
2402 return !(*this == aOther);
2403 }
2404
HasSplinensTimingFunction2405 bool HasSpline() const { return IsSplineType(mType); }
2406
2407 private:
2408 void AssignFromKeyword(int32_t aTimingFunctionType);
2409 };
2410
2411 namespace mozilla {
2412
2413 struct StyleTransition
2414 {
StyleTransitionStyleTransition2415 StyleTransition() { /* leaves uninitialized; see also SetInitialValues */ }
2416 explicit StyleTransition(const StyleTransition& aCopy);
2417
2418 void SetInitialValues();
2419
2420 // Delay and Duration are in milliseconds
2421
GetTimingFunctionStyleTransition2422 const nsTimingFunction& GetTimingFunction() const { return mTimingFunction; }
GetDelayStyleTransition2423 float GetDelay() const { return mDelay; }
GetDurationStyleTransition2424 float GetDuration() const { return mDuration; }
GetPropertyStyleTransition2425 nsCSSPropertyID GetProperty() const { return mProperty; }
GetUnknownPropertyStyleTransition2426 nsIAtom* GetUnknownProperty() const { return mUnknownProperty; }
2427
GetCombinedDurationStyleTransition2428 float GetCombinedDuration() const {
2429 // http://dev.w3.org/csswg/css-transitions/#combined-duration
2430 return std::max(mDuration, 0.0f) + mDelay;
2431 }
2432
SetTimingFunctionStyleTransition2433 void SetTimingFunction(const nsTimingFunction& aTimingFunction)
2434 { mTimingFunction = aTimingFunction; }
SetDelayStyleTransition2435 void SetDelay(float aDelay) { mDelay = aDelay; }
SetDurationStyleTransition2436 void SetDuration(float aDuration) { mDuration = aDuration; }
SetPropertyStyleTransition2437 void SetProperty(nsCSSPropertyID aProperty)
2438 {
2439 NS_ASSERTION(aProperty != eCSSProperty_UNKNOWN &&
2440 aProperty != eCSSPropertyExtra_variable,
2441 "invalid property");
2442 mProperty = aProperty;
2443 }
2444 void SetUnknownProperty(nsCSSPropertyID aProperty,
2445 const nsAString& aPropertyString);
CopyPropertyFromStyleTransition2446 void CopyPropertyFrom(const StyleTransition& aOther)
2447 {
2448 mProperty = aOther.mProperty;
2449 mUnknownProperty = aOther.mUnknownProperty;
2450 }
2451
TimingFunctionSlotStyleTransition2452 nsTimingFunction& TimingFunctionSlot() { return mTimingFunction; }
2453
2454 bool operator==(const StyleTransition& aOther) const;
2455 bool operator!=(const StyleTransition& aOther) const
2456 { return !(*this == aOther); }
2457
2458 private:
2459 nsTimingFunction mTimingFunction;
2460 float mDuration;
2461 float mDelay;
2462 nsCSSPropertyID mProperty;
2463 nsCOMPtr<nsIAtom> mUnknownProperty; // used when mProperty is
2464 // eCSSProperty_UNKNOWN or
2465 // eCSSPropertyExtra_variable
2466 };
2467
2468 struct StyleAnimation
2469 {
StyleAnimationStyleAnimation2470 StyleAnimation() { /* leaves uninitialized; see also SetInitialValues */ }
2471 explicit StyleAnimation(const StyleAnimation& aCopy);
2472
2473 void SetInitialValues();
2474
2475 // Delay and Duration are in milliseconds
2476
GetTimingFunctionStyleAnimation2477 const nsTimingFunction& GetTimingFunction() const { return mTimingFunction; }
GetDelayStyleAnimation2478 float GetDelay() const { return mDelay; }
GetDurationStyleAnimation2479 float GetDuration() const { return mDuration; }
GetNameStyleAnimation2480 const nsString& GetName() const { return mName; }
GetDirectionStyleAnimation2481 dom::PlaybackDirection GetDirection() const { return mDirection; }
GetFillModeStyleAnimation2482 dom::FillMode GetFillMode() const { return mFillMode; }
GetPlayStateStyleAnimation2483 uint8_t GetPlayState() const { return mPlayState; }
GetIterationCountStyleAnimation2484 float GetIterationCount() const { return mIterationCount; }
2485
SetTimingFunctionStyleAnimation2486 void SetTimingFunction(const nsTimingFunction& aTimingFunction)
2487 { mTimingFunction = aTimingFunction; }
SetDelayStyleAnimation2488 void SetDelay(float aDelay) { mDelay = aDelay; }
SetDurationStyleAnimation2489 void SetDuration(float aDuration) { mDuration = aDuration; }
SetNameStyleAnimation2490 void SetName(const nsSubstring& aName) { mName = aName; }
SetDirectionStyleAnimation2491 void SetDirection(dom::PlaybackDirection aDirection) { mDirection = aDirection; }
SetFillModeStyleAnimation2492 void SetFillMode(dom::FillMode aFillMode) { mFillMode = aFillMode; }
SetPlayStateStyleAnimation2493 void SetPlayState(uint8_t aPlayState) { mPlayState = aPlayState; }
SetIterationCountStyleAnimation2494 void SetIterationCount(float aIterationCount)
2495 { mIterationCount = aIterationCount; }
2496
TimingFunctionSlotStyleAnimation2497 nsTimingFunction& TimingFunctionSlot() { return mTimingFunction; }
2498
2499 bool operator==(const StyleAnimation& aOther) const;
2500 bool operator!=(const StyleAnimation& aOther) const
2501 { return !(*this == aOther); }
2502
2503 private:
2504 nsTimingFunction mTimingFunction;
2505 float mDuration;
2506 float mDelay;
2507 nsString mName; // empty string for 'none'
2508 dom::PlaybackDirection mDirection;
2509 dom::FillMode mFillMode;
2510 uint8_t mPlayState;
2511 float mIterationCount; // mozilla::PositiveInfinity<float>() means infinite
2512 };
2513
2514 class StyleBasicShape final
2515 {
2516 public:
StyleBasicShape(StyleBasicShapeType type)2517 explicit StyleBasicShape(StyleBasicShapeType type)
2518 : mType(type),
2519 mFillRule(StyleFillRule::Nonzero)
2520 {
2521 mPosition.SetInitialPercentValues(0.5f);
2522 }
2523
GetShapeType()2524 StyleBasicShapeType GetShapeType() const { return mType; }
2525 nsCSSKeyword GetShapeTypeName() const;
2526
GetFillRule()2527 StyleFillRule GetFillRule() const { return mFillRule; }
SetFillRule(StyleFillRule aFillRule)2528 void SetFillRule(StyleFillRule aFillRule)
2529 {
2530 MOZ_ASSERT(mType == StyleBasicShapeType::Polygon, "expected polygon");
2531 mFillRule = aFillRule;
2532 }
2533
GetPosition()2534 Position& GetPosition() {
2535 MOZ_ASSERT(mType == StyleBasicShapeType::Circle ||
2536 mType == StyleBasicShapeType::Ellipse,
2537 "expected circle or ellipse");
2538 return mPosition;
2539 }
GetPosition()2540 const Position& GetPosition() const {
2541 MOZ_ASSERT(mType == StyleBasicShapeType::Circle ||
2542 mType == StyleBasicShapeType::Ellipse,
2543 "expected circle or ellipse");
2544 return mPosition;
2545 }
2546
HasRadius()2547 bool HasRadius() const {
2548 MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
2549 nsStyleCoord zero;
2550 zero.SetCoordValue(0);
2551 NS_FOR_CSS_HALF_CORNERS(corner) {
2552 if (mRadius.Get(corner) != zero) {
2553 return true;
2554 }
2555 }
2556 return false;
2557 }
GetRadius()2558 nsStyleCorners& GetRadius() {
2559 MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
2560 return mRadius;
2561 }
GetRadius()2562 const nsStyleCorners& GetRadius() const {
2563 MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
2564 return mRadius;
2565 }
2566
2567 // mCoordinates has coordinates for polygon or radii for
2568 // ellipse and circle.
Coordinates()2569 nsTArray<nsStyleCoord>& Coordinates()
2570 {
2571 return mCoordinates;
2572 }
2573
Coordinates()2574 const nsTArray<nsStyleCoord>& Coordinates() const
2575 {
2576 return mCoordinates;
2577 }
2578
2579 bool operator==(const StyleBasicShape& aOther) const
2580 {
2581 return mType == aOther.mType &&
2582 mFillRule == aOther.mFillRule &&
2583 mCoordinates == aOther.mCoordinates &&
2584 mPosition == aOther.mPosition &&
2585 mRadius == aOther.mRadius;
2586 }
2587 bool operator!=(const StyleBasicShape& aOther) const {
2588 return !(*this == aOther);
2589 }
2590
2591 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StyleBasicShape);
2592
2593 private:
~StyleBasicShape()2594 ~StyleBasicShape() {}
2595
2596 StyleBasicShapeType mType;
2597 StyleFillRule mFillRule;
2598
2599 // mCoordinates has coordinates for polygon or radii for
2600 // ellipse and circle.
2601 // (top, right, bottom, left) for inset
2602 nsTArray<nsStyleCoord> mCoordinates;
2603 // position of center for ellipse or circle
2604 Position mPosition;
2605 // corner radii for inset (0 if not set)
2606 nsStyleCorners mRadius;
2607 };
2608
2609 template<typename ReferenceBox>
2610 struct StyleShapeSource
2611 {
StyleShapeSourceStyleShapeSource2612 StyleShapeSource()
2613 : mURL(nullptr)
2614 {}
2615
StyleShapeSourceStyleShapeSource2616 StyleShapeSource(const StyleShapeSource& aSource)
2617 : StyleShapeSource()
2618 {
2619 if (aSource.mType == StyleShapeSourceType::URL) {
2620 SetURL(aSource.mURL);
2621 } else if (aSource.mType == StyleShapeSourceType::Shape) {
2622 SetBasicShape(aSource.mBasicShape, aSource.mReferenceBox);
2623 } else if (aSource.mType == StyleShapeSourceType::Box) {
2624 SetReferenceBox(aSource.mReferenceBox);
2625 }
2626 }
2627
~StyleShapeSourceStyleShapeSource2628 ~StyleShapeSource()
2629 {
2630 ReleaseRef();
2631 }
2632
2633 StyleShapeSource& operator=(const StyleShapeSource& aOther)
2634 {
2635 if (this == &aOther) {
2636 return *this;
2637 }
2638
2639 if (aOther.mType == StyleShapeSourceType::URL) {
2640 SetURL(aOther.mURL);
2641 } else if (aOther.mType == StyleShapeSourceType::Shape) {
2642 SetBasicShape(aOther.mBasicShape, aOther.mReferenceBox);
2643 } else if (aOther.mType == StyleShapeSourceType::Box) {
2644 SetReferenceBox(aOther.mReferenceBox);
2645 } else {
2646 ReleaseRef();
2647 mReferenceBox = ReferenceBox::NoBox;
2648 mType = StyleShapeSourceType::None;
2649 }
2650 return *this;
2651 }
2652
2653 bool operator==(const StyleShapeSource& aOther) const
2654 {
2655 if (mType != aOther.mType) {
2656 return false;
2657 }
2658
2659 if (mType == StyleShapeSourceType::URL) {
2660 return mURL->Equals(*aOther.mURL);
2661 } else if (mType == StyleShapeSourceType::Shape) {
2662 return *mBasicShape == *aOther.mBasicShape &&
2663 mReferenceBox == aOther.mReferenceBox;
2664 } else if (mType == StyleShapeSourceType::Box) {
2665 return mReferenceBox == aOther.mReferenceBox;
2666 }
2667
2668 return true;
2669 }
2670
2671 bool operator!=(const StyleShapeSource& aOther) const
2672 {
2673 return !(*this == aOther);
2674 }
2675
GetTypeStyleShapeSource2676 StyleShapeSourceType GetType() const
2677 {
2678 return mType;
2679 }
2680
GetURLStyleShapeSource2681 css::URLValue* GetURL() const
2682 {
2683 MOZ_ASSERT(mType == StyleShapeSourceType::URL, "Wrong shape source type!");
2684 return mURL;
2685 }
2686
SetURLStyleShapeSource2687 bool SetURL(css::URLValue* aValue)
2688 {
2689 MOZ_ASSERT(aValue);
2690 ReleaseRef();
2691 mURL = aValue;
2692 mURL->AddRef();
2693 mType = StyleShapeSourceType::URL;
2694 return true;
2695 }
2696
GetBasicShapeStyleShapeSource2697 StyleBasicShape* GetBasicShape() const
2698 {
2699 MOZ_ASSERT(mType == StyleShapeSourceType::Shape, "Wrong shape source type!");
2700 return mBasicShape;
2701 }
2702
SetBasicShapeStyleShapeSource2703 void SetBasicShape(StyleBasicShape* aBasicShape,
2704 ReferenceBox aReferenceBox)
2705 {
2706 NS_ASSERTION(aBasicShape, "expected pointer");
2707 ReleaseRef();
2708 mBasicShape = aBasicShape;
2709 mBasicShape->AddRef();
2710 mReferenceBox = aReferenceBox;
2711 mType = StyleShapeSourceType::Shape;
2712 }
2713
GetReferenceBoxStyleShapeSource2714 ReferenceBox GetReferenceBox() const
2715 {
2716 MOZ_ASSERT(mType == StyleShapeSourceType::Box ||
2717 mType == StyleShapeSourceType::Shape,
2718 "Wrong shape source type!");
2719 return mReferenceBox;
2720 }
2721
SetReferenceBoxStyleShapeSource2722 void SetReferenceBox(ReferenceBox aReferenceBox)
2723 {
2724 ReleaseRef();
2725 mReferenceBox = aReferenceBox;
2726 mType = StyleShapeSourceType::Box;
2727 }
2728
2729 private:
ReleaseRefStyleShapeSource2730 void ReleaseRef()
2731 {
2732 if (mType == StyleShapeSourceType::Shape) {
2733 NS_ASSERTION(mBasicShape, "expected pointer");
2734 mBasicShape->Release();
2735 } else if (mType == StyleShapeSourceType::URL) {
2736 NS_ASSERTION(mURL, "expected pointer");
2737 mURL->Release();
2738 }
2739 // Both mBasicShape and mURL are pointers in a union. Nulling one of them
2740 // nulls both of them.
2741 mURL = nullptr;
2742 }
2743
2744 void* operator new(size_t) = delete;
2745
2746 union {
2747 StyleBasicShape* mBasicShape;
2748 css::URLValue* mURL;
2749 };
2750 StyleShapeSourceType mType = StyleShapeSourceType::None;
2751 ReferenceBox mReferenceBox = ReferenceBox::NoBox;
2752 };
2753
2754 using StyleClipPath = StyleShapeSource<StyleClipPathGeometryBox>;
2755 using StyleShapeOutside = StyleShapeSource<StyleShapeOutsideShapeBox>;
2756
2757 } // namespace mozilla
2758
2759 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay
2760 {
2761 explicit nsStyleDisplay(StyleStructContext aContext);
2762 nsStyleDisplay(const nsStyleDisplay& aOther);
~nsStyleDisplaynsStyleDisplay2763 ~nsStyleDisplay() {
2764 MOZ_COUNT_DTOR(nsStyleDisplay);
2765 }
FinishStylensStyleDisplay2766 void FinishStyle(nsPresContext* aPresContext) {}
2767
newnsStyleDisplay2768 void* operator new(size_t sz, nsStyleDisplay* aSelf) { return aSelf; }
newnsStyleDisplay2769 void* operator new(size_t sz, nsPresContext* aContext) {
2770 return aContext->PresShell()->
2771 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleDisplay, sz);
2772 }
DestroynsStyleDisplay2773 void Destroy(nsPresContext* aContext) {
2774 this->~nsStyleDisplay();
2775 aContext->PresShell()->
2776 FreeByObjectID(mozilla::eArenaObjectID_nsStyleDisplay, this);
2777 }
2778
2779 nsChangeHint CalcDifference(const nsStyleDisplay& aNewData) const;
MaxDifferencensStyleDisplay2780 static nsChangeHint MaxDifference() {
2781 // All the parts of FRAMECHANGE are present in CalcDifference.
2782 return nsChangeHint(nsChangeHint_ReconstructFrame |
2783 NS_STYLE_HINT_REFLOW |
2784 nsChangeHint_UpdateTransformLayer |
2785 nsChangeHint_UpdateOverflow |
2786 nsChangeHint_UpdatePostTransformOverflow |
2787 nsChangeHint_UpdateContainingBlock |
2788 nsChangeHint_AddOrRemoveTransform |
2789 nsChangeHint_NeutralChange);
2790 }
DifferenceAlwaysHandledForDescendantsnsStyleDisplay2791 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
2792 // CalcDifference can return all of the reflow hints that are
2793 // sometimes handled for descendants as hints not handled for
2794 // descendants.
2795 return nsChangeHint(0);
2796 }
2797
2798 // We guarantee that if mBinding is non-null, so are mBinding->GetURI() and
2799 // mBinding->mOriginPrincipal.
2800 RefPtr<mozilla::css::URLValue> mBinding; // [reset]
2801 mozilla::StyleDisplay mDisplay; // [reset] see nsStyleConsts.h SyleDisplay
2802 mozilla::StyleDisplay mOriginalDisplay; // [reset] saved mDisplay for
2803 // position:absolute/fixed
2804 // and float:left/right;
2805 // otherwise equal to
2806 // mDisplay
2807 uint8_t mContain; // [reset] see nsStyleConsts.h NS_STYLE_CONTAIN_*
2808 uint8_t mAppearance; // [reset]
2809 uint8_t mPosition; // [reset] see nsStyleConsts.h
2810
2811 // [reset] See StyleFloat in nsStyleConsts.h.
2812 mozilla::StyleFloat mFloat;
2813 // [reset] Save mFloat for position:absolute/fixed; otherwise equal to mFloat.
2814 mozilla::StyleFloat mOriginalFloat;
2815
2816 mozilla::StyleClear mBreakType; // [reset]
2817 uint8_t mBreakInside; // [reset] NS_STYLE_PAGE_BREAK_AUTO/AVOID
2818 bool mBreakBefore; // [reset]
2819 bool mBreakAfter; // [reset]
2820 uint8_t mOverflowX; // [reset] see nsStyleConsts.h
2821 uint8_t mOverflowY; // [reset] see nsStyleConsts.h
2822 uint8_t mOverflowClipBox; // [reset] see nsStyleConsts.h
2823 uint8_t mResize; // [reset] see nsStyleConsts.h
2824 mozilla::StyleOrient mOrient; // [reset] see nsStyleConsts.h
2825 uint8_t mIsolation; // [reset] see nsStyleConsts.h
2826 uint8_t mTopLayer; // [reset] see nsStyleConsts.h
2827 uint8_t mWillChangeBitField; // [reset] see nsStyleConsts.h. Stores a
2828 // bitfield representation of the properties
2829 // that are frequently queried. This should
2830 // match mWillChange. Also tracks if any of the
2831 // properties in the will-change list require
2832 // a stacking context.
2833 nsTArray<nsString> mWillChange;
2834
2835 uint8_t mTouchAction; // [reset] see nsStyleConsts.h
2836 uint8_t mScrollBehavior; // [reset] see nsStyleConsts.h NS_STYLE_SCROLL_BEHAVIOR_*
2837 uint8_t mScrollSnapTypeX; // [reset] see nsStyleConsts.h NS_STYLE_SCROLL_SNAP_TYPE_*
2838 uint8_t mScrollSnapTypeY; // [reset] see nsStyleConsts.h NS_STYLE_SCROLL_SNAP_TYPE_*
2839 nsStyleCoord mScrollSnapPointsX; // [reset]
2840 nsStyleCoord mScrollSnapPointsY; // [reset]
2841 mozilla::Position mScrollSnapDestination; // [reset]
2842 nsTArray<mozilla::Position> mScrollSnapCoordinate; // [reset]
2843
2844 // mSpecifiedTransform is the list of transform functions as
2845 // specified, or null to indicate there is no transform. (inherit or
2846 // initial are replaced by an actual list of transform functions, or
2847 // null, as appropriate.)
2848 uint8_t mBackfaceVisibility;
2849 uint8_t mTransformStyle;
2850 uint8_t mTransformBox; // [reset] see nsStyleConsts.h
2851 RefPtr<nsCSSValueSharedList> mSpecifiedTransform; // [reset]
2852 nsStyleCoord mTransformOrigin[3]; // [reset] percent, coord, calc, 3rd param is coord, calc only
2853 nsStyleCoord mChildPerspective; // [reset] none, coord
2854 nsStyleCoord mPerspectiveOrigin[2]; // [reset] percent, coord, calc
2855
2856 nsStyleCoord mVerticalAlign; // [reset] coord, percent, calc, enum (see nsStyleConsts.h)
2857
2858 nsStyleAutoArray<mozilla::StyleTransition> mTransitions; // [reset]
2859
2860 // The number of elements in mTransitions that are not from repeating
2861 // a list due to another property being longer.
2862 uint32_t mTransitionTimingFunctionCount,
2863 mTransitionDurationCount,
2864 mTransitionDelayCount,
2865 mTransitionPropertyCount;
2866
2867 nsStyleAutoArray<mozilla::StyleAnimation> mAnimations; // [reset]
2868
2869 // The number of elements in mAnimations that are not from repeating
2870 // a list due to another property being longer.
2871 uint32_t mAnimationTimingFunctionCount,
2872 mAnimationDurationCount,
2873 mAnimationDelayCount,
2874 mAnimationNameCount,
2875 mAnimationDirectionCount,
2876 mAnimationFillModeCount,
2877 mAnimationPlayStateCount,
2878 mAnimationIterationCountCount;
2879
2880 mozilla::StyleShapeOutside mShapeOutside; // [reset]
2881
IsBlockInsideStylensStyleDisplay2882 bool IsBlockInsideStyle() const {
2883 return mozilla::StyleDisplay::Block == mDisplay ||
2884 mozilla::StyleDisplay::ListItem == mDisplay ||
2885 mozilla::StyleDisplay::InlineBlock == mDisplay ||
2886 mozilla::StyleDisplay::TableCaption == mDisplay;
2887 // Should TABLE_CELL be included here? They have
2888 // block frames nested inside of them.
2889 // (But please audit all callers before changing.)
2890 }
2891
IsBlockOutsideStylensStyleDisplay2892 bool IsBlockOutsideStyle() const {
2893 return mozilla::StyleDisplay::Block == mDisplay ||
2894 mozilla::StyleDisplay::Flex == mDisplay ||
2895 mozilla::StyleDisplay::WebkitBox == mDisplay ||
2896 mozilla::StyleDisplay::Grid == mDisplay ||
2897 mozilla::StyleDisplay::ListItem == mDisplay ||
2898 mozilla::StyleDisplay::Table == mDisplay;
2899 }
2900
IsDisplayTypeInlineOutsidensStyleDisplay2901 static bool IsDisplayTypeInlineOutside(mozilla::StyleDisplay aDisplay) {
2902 return mozilla::StyleDisplay::Inline == aDisplay ||
2903 mozilla::StyleDisplay::InlineBlock == aDisplay ||
2904 mozilla::StyleDisplay::InlineTable == aDisplay ||
2905 mozilla::StyleDisplay::InlineBox == aDisplay ||
2906 mozilla::StyleDisplay::InlineFlex == aDisplay ||
2907 mozilla::StyleDisplay::WebkitInlineBox == aDisplay ||
2908 mozilla::StyleDisplay::InlineGrid == aDisplay ||
2909 mozilla::StyleDisplay::InlineXulGrid == aDisplay ||
2910 mozilla::StyleDisplay::InlineStack == aDisplay ||
2911 mozilla::StyleDisplay::Ruby == aDisplay ||
2912 mozilla::StyleDisplay::RubyBase == aDisplay ||
2913 mozilla::StyleDisplay::RubyBaseContainer == aDisplay ||
2914 mozilla::StyleDisplay::RubyText == aDisplay ||
2915 mozilla::StyleDisplay::RubyTextContainer == aDisplay ||
2916 mozilla::StyleDisplay::Contents == aDisplay;
2917 }
2918
IsInlineOutsideStylensStyleDisplay2919 bool IsInlineOutsideStyle() const {
2920 return IsDisplayTypeInlineOutside(mDisplay);
2921 }
2922
IsOriginalDisplayInlineOutsideStylensStyleDisplay2923 bool IsOriginalDisplayInlineOutsideStyle() const {
2924 return IsDisplayTypeInlineOutside(mOriginalDisplay);
2925 }
2926
IsInnerTableStylensStyleDisplay2927 bool IsInnerTableStyle() const {
2928 return mozilla::StyleDisplay::TableCaption == mDisplay ||
2929 mozilla::StyleDisplay::TableCell == mDisplay ||
2930 mozilla::StyleDisplay::TableRow == mDisplay ||
2931 mozilla::StyleDisplay::TableRowGroup == mDisplay ||
2932 mozilla::StyleDisplay::TableHeaderGroup == mDisplay ||
2933 mozilla::StyleDisplay::TableFooterGroup == mDisplay ||
2934 mozilla::StyleDisplay::TableColumn == mDisplay ||
2935 mozilla::StyleDisplay::TableColumnGroup == mDisplay;
2936 }
2937
IsFloatingStylensStyleDisplay2938 bool IsFloatingStyle() const {
2939 return mozilla::StyleFloat::None != mFloat;
2940 }
2941
IsAbsolutelyPositionedStylensStyleDisplay2942 bool IsAbsolutelyPositionedStyle() const {
2943 return NS_STYLE_POSITION_ABSOLUTE == mPosition ||
2944 NS_STYLE_POSITION_FIXED == mPosition;
2945 }
2946
IsRelativelyPositionedStylensStyleDisplay2947 bool IsRelativelyPositionedStyle() const {
2948 return NS_STYLE_POSITION_RELATIVE == mPosition ||
2949 NS_STYLE_POSITION_STICKY == mPosition;
2950 }
IsPositionForcingStackingContextnsStyleDisplay2951 bool IsPositionForcingStackingContext() const {
2952 return NS_STYLE_POSITION_STICKY == mPosition ||
2953 NS_STYLE_POSITION_FIXED == mPosition;
2954 }
2955
IsRubyDisplayTypensStyleDisplay2956 static bool IsRubyDisplayType(mozilla::StyleDisplay aDisplay) {
2957 return mozilla::StyleDisplay::Ruby == aDisplay ||
2958 mozilla::StyleDisplay::RubyBase == aDisplay ||
2959 mozilla::StyleDisplay::RubyBaseContainer == aDisplay ||
2960 mozilla::StyleDisplay::RubyText == aDisplay ||
2961 mozilla::StyleDisplay::RubyTextContainer == aDisplay;
2962 }
2963
IsRubyDisplayTypensStyleDisplay2964 bool IsRubyDisplayType() const {
2965 return IsRubyDisplayType(mDisplay);
2966 }
2967
IsOutOfFlowStylensStyleDisplay2968 bool IsOutOfFlowStyle() const {
2969 return (IsAbsolutelyPositionedStyle() || IsFloatingStyle());
2970 }
2971
IsScrollableOverflownsStyleDisplay2972 bool IsScrollableOverflow() const {
2973 // mOverflowX and mOverflowY always match when one of them is
2974 // NS_STYLE_OVERFLOW_VISIBLE or NS_STYLE_OVERFLOW_CLIP.
2975 return mOverflowX != NS_STYLE_OVERFLOW_VISIBLE &&
2976 mOverflowX != NS_STYLE_OVERFLOW_CLIP;
2977 }
2978
IsContainPaintnsStyleDisplay2979 bool IsContainPaint() const {
2980 return NS_STYLE_CONTAIN_PAINT & mContain;
2981 }
2982
2983 /* Returns whether the element has the -moz-transform property
2984 * or a related property. */
HasTransformStylensStyleDisplay2985 bool HasTransformStyle() const {
2986 return mSpecifiedTransform != nullptr ||
2987 mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D ||
2988 (mWillChangeBitField & NS_STYLE_WILL_CHANGE_TRANSFORM);
2989 }
2990
HasPerspectiveStylensStyleDisplay2991 bool HasPerspectiveStyle() const {
2992 return mChildPerspective.GetUnit() == eStyleUnit_Coord;
2993 }
2994
BackfaceIsHiddennsStyleDisplay2995 bool BackfaceIsHidden() const {
2996 return mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN;
2997 }
2998
2999 // These are defined in nsStyleStructInlines.h.
3000
3001 // The aContextFrame argument on each of these is the frame this
3002 // style struct is for. If the frame is for SVG text, the return
3003 // value will be massaged to be something that makes sense for
3004 // SVG text.
3005 inline bool IsBlockInside(const nsIFrame* aContextFrame) const;
3006 inline bool IsBlockOutside(const nsIFrame* aContextFrame) const;
3007 inline bool IsInlineOutside(const nsIFrame* aContextFrame) const;
3008 inline bool IsOriginalDisplayInlineOutside(const nsIFrame* aContextFrame) const;
3009 inline mozilla::StyleDisplay GetDisplay(const nsIFrame* aContextFrame) const;
3010 inline bool IsFloating(const nsIFrame* aContextFrame) const;
3011 inline bool IsRelativelyPositioned(const nsIFrame* aContextFrame) const;
3012 inline bool IsAbsolutelyPositioned(const nsIFrame* aContextFrame) const;
3013
3014 // These methods are defined in nsStyleStructInlines.h.
3015
3016 /**
3017 * Returns whether the element is a containing block for its
3018 * absolutely positioned descendants.
3019 * aContextFrame is the frame for which this is the nsStyleDisplay.
3020 */
3021 inline bool IsAbsPosContainingBlock(const nsIFrame* aContextFrame) const;
3022
3023 /**
3024 * The same as IsAbsPosContainingBlock, except skipping the tests that
3025 * are based on the frame rather than the style context (thus
3026 * potentially returning a false positive).
3027 */
3028 template<class StyleContextLike>
3029 inline bool IsAbsPosContainingBlockForAppropriateFrame(
3030 StyleContextLike* aStyleContext) const;
3031
3032 /**
3033 * Returns true when the element has the transform property
3034 * or a related property, and supports CSS transforms.
3035 * aContextFrame is the frame for which this is the nsStyleDisplay.
3036 */
3037 inline bool HasTransform(const nsIFrame* aContextFrame) const;
3038
3039 /**
3040 * Returns true when the element is a containing block for its fixed-pos
3041 * descendants.
3042 * aContextFrame is the frame for which this is the nsStyleDisplay.
3043 */
3044 inline bool IsFixedPosContainingBlock(const nsIFrame* aContextFrame) const;
3045
3046 /**
3047 * The same as IsFixedPosContainingBlock, except skipping the tests that
3048 * are based on the frame rather than the style context (thus
3049 * potentially returning a false positive).
3050 */
3051 template<class StyleContextLike>
3052 inline bool IsFixedPosContainingBlockForAppropriateFrame(
3053 StyleContextLike* aStyleContext) const;
3054
3055 private:
3056 // Helpers for above functions, which do some but not all of the tests
3057 // for them (since transform must be tested separately for each).
3058 template<class StyleContextLike>
3059 inline bool HasAbsPosContainingBlockStyleInternal(
3060 StyleContextLike* aStyleContext) const;
3061 template<class StyleContextLike>
3062 inline bool HasFixedPosContainingBlockStyleInternal(
3063 StyleContextLike* aStyleContext) const;
3064
3065 public:
3066 // Return the 'float' and 'clear' properties, with inline-{start,end} values
3067 // resolved to {left,right} according to the given writing mode. These are
3068 // defined in WritingModes.h.
3069 inline mozilla::StyleFloat PhysicalFloats(mozilla::WritingMode aWM) const;
3070 inline mozilla::StyleClear PhysicalBreakType(mozilla::WritingMode aWM) const;
3071 };
3072
3073 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTable
3074 {
3075 explicit nsStyleTable(StyleStructContext aContext);
3076 nsStyleTable(const nsStyleTable& aOther);
3077 ~nsStyleTable();
FinishStylensStyleTable3078 void FinishStyle(nsPresContext* aPresContext) {}
3079
newnsStyleTable3080 void* operator new(size_t sz, nsStyleTable* aSelf) { return aSelf; }
newnsStyleTable3081 void* operator new(size_t sz, nsPresContext* aContext) {
3082 return aContext->PresShell()->
3083 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTable, sz);
3084 }
DestroynsStyleTable3085 void Destroy(nsPresContext* aContext) {
3086 this->~nsStyleTable();
3087 aContext->PresShell()->
3088 FreeByObjectID(mozilla::eArenaObjectID_nsStyleTable, this);
3089 }
3090
3091 nsChangeHint CalcDifference(const nsStyleTable& aNewData) const;
MaxDifferencensStyleTable3092 static nsChangeHint MaxDifference() {
3093 return nsChangeHint_ReconstructFrame;
3094 }
DifferenceAlwaysHandledForDescendantsnsStyleTable3095 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3096 // CalcDifference never returns the reflow hints that are sometimes
3097 // handled for descendants as hints not handled for descendants.
3098 return nsChangeHint(0);
3099 }
3100
3101 uint8_t mLayoutStrategy;// [reset] see nsStyleConsts.h NS_STYLE_TABLE_LAYOUT_*
3102 int32_t mSpan; // [reset] the number of columns spanned by a colgroup or col
3103 };
3104
3105 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTableBorder
3106 {
3107 explicit nsStyleTableBorder(StyleStructContext aContext);
3108 nsStyleTableBorder(const nsStyleTableBorder& aOther);
3109 ~nsStyleTableBorder();
FinishStylensStyleTableBorder3110 void FinishStyle(nsPresContext* aPresContext) {}
3111
newnsStyleTableBorder3112 void* operator new(size_t sz, nsStyleTableBorder* aSelf) { return aSelf; }
newnsStyleTableBorder3113 void* operator new(size_t sz, nsPresContext* aContext) {
3114 return aContext->PresShell()->
3115 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTableBorder, sz);
3116 }
DestroynsStyleTableBorder3117 void Destroy(nsPresContext* aContext) {
3118 this->~nsStyleTableBorder();
3119 aContext->PresShell()->
3120 FreeByObjectID(mozilla::eArenaObjectID_nsStyleTableBorder, this);
3121 }
3122
3123 nsChangeHint CalcDifference(const nsStyleTableBorder& aNewData) const;
MaxDifferencensStyleTableBorder3124 static nsChangeHint MaxDifference() {
3125 return nsChangeHint_ReconstructFrame |
3126 NS_STYLE_HINT_REFLOW;
3127 }
DifferenceAlwaysHandledForDescendantsnsStyleTableBorder3128 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3129 // CalcDifference never returns the reflow hints that are sometimes
3130 // handled for descendants as hints not handled for descendants.
3131 return nsChangeHint_NeedReflow |
3132 nsChangeHint_ReflowChangesSizeOrPosition |
3133 nsChangeHint_ClearAncestorIntrinsics;
3134 }
3135
3136 nscoord mBorderSpacingCol;// [inherited]
3137 nscoord mBorderSpacingRow;// [inherited]
3138 uint8_t mBorderCollapse;// [inherited]
3139 uint8_t mCaptionSide; // [inherited]
3140 uint8_t mEmptyCells; // [inherited]
3141 };
3142
3143 enum nsStyleContentType {
3144 eStyleContentType_String = 1,
3145 eStyleContentType_Image = 10,
3146 eStyleContentType_Attr = 20,
3147 eStyleContentType_Counter = 30,
3148 eStyleContentType_Counters = 31,
3149 eStyleContentType_OpenQuote = 40,
3150 eStyleContentType_CloseQuote = 41,
3151 eStyleContentType_NoOpenQuote = 42,
3152 eStyleContentType_NoCloseQuote = 43,
3153 eStyleContentType_AltContent = 50,
3154 eStyleContentType_Uninitialized
3155 };
3156
3157 struct nsStyleContentData
3158 {
3159 nsStyleContentType mType;
3160 union {
3161 char16_t *mString;
3162 imgRequestProxy *mImage;
3163 nsCSSValue::Array* mCounters;
3164 } mContent;
3165 #ifdef DEBUG
3166 bool mImageTracked;
3167 #endif
3168
nsStyleContentDatansStyleContentData3169 nsStyleContentData()
3170 : mType(eStyleContentType_Uninitialized)
3171 #ifdef DEBUG
3172 , mImageTracked(false)
3173 #endif
3174 {
3175 MOZ_COUNT_CTOR(nsStyleContentData);
3176 mContent.mString = nullptr;
3177 }
3178 nsStyleContentData(const nsStyleContentData&);
3179
3180 ~nsStyleContentData();
3181 nsStyleContentData& operator=(const nsStyleContentData& aOther);
3182 bool operator==(const nsStyleContentData& aOther) const;
3183
3184 bool operator!=(const nsStyleContentData& aOther) const {
3185 return !(*this == aOther);
3186 }
3187
3188 void TrackImage(mozilla::dom::ImageTracker* aImageTracker);
3189 void UntrackImage(mozilla::dom::ImageTracker* aImageTracker);
3190
SetImagensStyleContentData3191 void SetImage(imgRequestProxy* aRequest)
3192 {
3193 MOZ_ASSERT(!mImageTracked,
3194 "Setting a new image without untracking the old one!");
3195 MOZ_ASSERT(mType == eStyleContentType_Image, "Wrong type!");
3196 NS_IF_ADDREF(mContent.mImage = aRequest);
3197 }
3198 };
3199
3200 struct nsStyleCounterData
3201 {
3202 nsString mCounter;
3203 int32_t mValue;
3204
3205 bool operator==(const nsStyleCounterData& aOther) const {
3206 return mValue == aOther.mValue && mCounter == aOther.mCounter;
3207 }
3208
3209 bool operator!=(const nsStyleCounterData& aOther) const {
3210 return !(*this == aOther);
3211 }
3212 };
3213
3214 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleContent
3215 {
3216 explicit nsStyleContent(StyleStructContext aContext);
3217 nsStyleContent(const nsStyleContent& aContent);
3218 ~nsStyleContent();
FinishStylensStyleContent3219 void FinishStyle(nsPresContext* aPresContext) {}
3220
newnsStyleContent3221 void* operator new(size_t sz, nsStyleContent* aSelf) { return aSelf; }
newnsStyleContent3222 void* operator new(size_t sz, nsPresContext* aContext) {
3223 return aContext->PresShell()->
3224 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleContent, sz);
3225 }
3226 void Destroy(nsPresContext* aContext);
3227
3228 nsChangeHint CalcDifference(const nsStyleContent& aNewData) const;
MaxDifferencensStyleContent3229 static nsChangeHint MaxDifference() {
3230 return nsChangeHint_ReconstructFrame |
3231 NS_STYLE_HINT_REFLOW;
3232 }
DifferenceAlwaysHandledForDescendantsnsStyleContent3233 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3234 // CalcDifference never returns the reflow hints that are sometimes
3235 // handled for descendants as hints not handled for descendants.
3236 return nsChangeHint_NeedReflow |
3237 nsChangeHint_ReflowChangesSizeOrPosition |
3238 nsChangeHint_ClearAncestorIntrinsics;
3239 }
3240
ContentCountnsStyleContent3241 uint32_t ContentCount() const { return mContents.Length(); } // [reset]
3242
ContentAtnsStyleContent3243 const nsStyleContentData& ContentAt(uint32_t aIndex) const {
3244 return mContents[aIndex];
3245 }
3246
ContentAtnsStyleContent3247 nsStyleContentData& ContentAt(uint32_t aIndex) { return mContents[aIndex]; }
3248
AllocateContentsnsStyleContent3249 void AllocateContents(uint32_t aCount) {
3250 // We need to run the destructors of the elements of mContents, so we
3251 // delete and reallocate even if aCount == mContentCount. (If
3252 // nsStyleContentData had its members private and managed their
3253 // ownership on setting, we wouldn't need this, but that seems
3254 // unnecessary at this point.)
3255 mContents.Clear();
3256 mContents.SetLength(aCount);
3257 }
3258
CounterIncrementCountnsStyleContent3259 uint32_t CounterIncrementCount() const { return mIncrements.Length(); } // [reset]
CounterIncrementAtnsStyleContent3260 const nsStyleCounterData& CounterIncrementAt(uint32_t aIndex) const {
3261 return mIncrements[aIndex];
3262 }
3263
AllocateCounterIncrementsnsStyleContent3264 void AllocateCounterIncrements(uint32_t aCount) {
3265 mIncrements.Clear();
3266 mIncrements.SetLength(aCount);
3267 }
3268
SetCounterIncrementAtnsStyleContent3269 void SetCounterIncrementAt(uint32_t aIndex, const nsString& aCounter, int32_t aIncrement) {
3270 mIncrements[aIndex].mCounter = aCounter;
3271 mIncrements[aIndex].mValue = aIncrement;
3272 }
3273
CounterResetCountnsStyleContent3274 uint32_t CounterResetCount() const { return mResets.Length(); } // [reset]
CounterResetAtnsStyleContent3275 const nsStyleCounterData& CounterResetAt(uint32_t aIndex) const {
3276 return mResets[aIndex];
3277 }
3278
AllocateCounterResetsnsStyleContent3279 void AllocateCounterResets(uint32_t aCount) {
3280 mResets.Clear();
3281 mResets.SetLength(aCount);
3282 }
3283
SetCounterResetAtnsStyleContent3284 void SetCounterResetAt(uint32_t aIndex, const nsString& aCounter, int32_t aValue) {
3285 mResets[aIndex].mCounter = aCounter;
3286 mResets[aIndex].mValue = aValue;
3287 }
3288
3289 protected:
3290 nsTArray<nsStyleContentData> mContents;
3291 nsTArray<nsStyleCounterData> mIncrements;
3292 nsTArray<nsStyleCounterData> mResets;
3293 };
3294
3295 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUIReset
3296 {
3297 explicit nsStyleUIReset(StyleStructContext aContext);
3298 nsStyleUIReset(const nsStyleUIReset& aOther);
3299 ~nsStyleUIReset();
FinishStylensStyleUIReset3300 void FinishStyle(nsPresContext* aPresContext) {}
3301
newnsStyleUIReset3302 void* operator new(size_t sz, nsStyleUIReset* aSelf) { return aSelf; }
newnsStyleUIReset3303 void* operator new(size_t sz, nsPresContext* aContext) {
3304 return aContext->PresShell()->
3305 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleUIReset, sz);
3306 }
DestroynsStyleUIReset3307 void Destroy(nsPresContext* aContext) {
3308 this->~nsStyleUIReset();
3309 aContext->PresShell()->
3310 FreeByObjectID(mozilla::eArenaObjectID_nsStyleUIReset, this);
3311 }
3312
3313 nsChangeHint CalcDifference(const nsStyleUIReset& aNewData) const;
MaxDifferencensStyleUIReset3314 static nsChangeHint MaxDifference() {
3315 return nsChangeHint_ReconstructFrame |
3316 NS_STYLE_HINT_REFLOW;
3317 }
DifferenceAlwaysHandledForDescendantsnsStyleUIReset3318 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3319 // CalcDifference never returns the reflow hints that are sometimes
3320 // handled for descendants as hints not handled for descendants.
3321 return nsChangeHint_NeedReflow |
3322 nsChangeHint_ReflowChangesSizeOrPosition |
3323 nsChangeHint_ClearAncestorIntrinsics;
3324 }
3325
3326 mozilla::StyleUserSelect mUserSelect; // [reset](selection-style)
3327 uint8_t mForceBrokenImageIcon; // [reset] (0 if not forcing, otherwise forcing)
3328 uint8_t mIMEMode; // [reset]
3329 mozilla::StyleWindowDragging mWindowDragging; // [reset]
3330 uint8_t mWindowShadow; // [reset]
3331 };
3332
3333 struct nsCursorImage
3334 {
3335 bool mHaveHotspot;
3336 float mHotspotX, mHotspotY;
3337
3338 nsCursorImage();
3339 nsCursorImage(const nsCursorImage& aOther);
3340 ~nsCursorImage();
3341
3342 nsCursorImage& operator=(const nsCursorImage& aOther);
3343
3344 bool operator==(const nsCursorImage& aOther) const;
3345 bool operator!=(const nsCursorImage& aOther) const
3346 {
3347 return !(*this == aOther);
3348 }
3349
SetImagensCursorImage3350 void SetImage(imgIRequest *aImage) {
3351 if (mImage) {
3352 mImage->UnlockImage();
3353 mImage->RequestDiscard();
3354 }
3355 mImage = aImage;
3356 if (mImage) {
3357 mImage->LockImage();
3358 }
3359 }
GetImagensCursorImage3360 imgIRequest* GetImage() const {
3361 return mImage;
3362 }
3363
3364 private:
3365 nsCOMPtr<imgIRequest> mImage;
3366 };
3367
3368 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUserInterface
3369 {
3370 explicit nsStyleUserInterface(StyleStructContext aContext);
3371 nsStyleUserInterface(const nsStyleUserInterface& aOther);
3372 ~nsStyleUserInterface();
FinishStylensStyleUserInterface3373 void FinishStyle(nsPresContext* aPresContext) {}
3374
newnsStyleUserInterface3375 void* operator new(size_t sz, nsStyleUserInterface* aSelf) { return aSelf; }
newnsStyleUserInterface3376 void* operator new(size_t sz, nsPresContext* aContext) {
3377 return aContext->PresShell()->
3378 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleUserInterface, sz);
3379 }
DestroynsStyleUserInterface3380 void Destroy(nsPresContext* aContext) {
3381 this->~nsStyleUserInterface();
3382 aContext->PresShell()->
3383 FreeByObjectID(mozilla::eArenaObjectID_nsStyleUserInterface, this);
3384 }
3385
3386 nsChangeHint CalcDifference(const nsStyleUserInterface& aNewData) const;
MaxDifferencensStyleUserInterface3387 static nsChangeHint MaxDifference() {
3388 return nsChangeHint_ReconstructFrame |
3389 nsChangeHint_NeedReflow |
3390 nsChangeHint_NeedDirtyReflow |
3391 NS_STYLE_HINT_VISUAL |
3392 nsChangeHint_UpdateCursor |
3393 nsChangeHint_NeutralChange;
3394 }
DifferenceAlwaysHandledForDescendantsnsStyleUserInterface3395 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3396 // CalcDifference never returns the reflow hints that are sometimes
3397 // handled for descendants as hints not handled for descendants.
3398 return nsChangeHint_NeedReflow;
3399 }
3400
3401 mozilla::StyleUserInput mUserInput; // [inherited]
3402 mozilla::StyleUserModify mUserModify; // [inherited] (modify-content)
3403 mozilla::StyleUserFocus mUserFocus; // [inherited] (auto-select)
3404 uint8_t mPointerEvents; // [inherited] see nsStyleConsts.h
3405
3406 uint8_t mCursor; // [inherited] See nsStyleConsts.h
3407 nsTArray<nsCursorImage> mCursorImages; // [inherited] images and coords
3408
3409 inline uint8_t GetEffectivePointerEvents(nsIFrame* aFrame) const;
3410 };
3411
3412 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleXUL
3413 {
3414 explicit nsStyleXUL(StyleStructContext aContext);
3415 nsStyleXUL(const nsStyleXUL& aSource);
3416 ~nsStyleXUL();
FinishStylensStyleXUL3417 void FinishStyle(nsPresContext* aPresContext) {}
3418
newnsStyleXUL3419 void* operator new(size_t sz, nsStyleXUL* aSelf) { return aSelf; }
newnsStyleXUL3420 void* operator new(size_t sz, nsPresContext* aContext) {
3421 return aContext->PresShell()->
3422 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleXUL, sz);
3423 }
DestroynsStyleXUL3424 void Destroy(nsPresContext* aContext) {
3425 this->~nsStyleXUL();
3426 aContext->PresShell()->
3427 FreeByObjectID(mozilla::eArenaObjectID_nsStyleXUL, this);
3428 }
3429
3430 nsChangeHint CalcDifference(const nsStyleXUL& aNewData) const;
MaxDifferencensStyleXUL3431 static nsChangeHint MaxDifference() {
3432 return nsChangeHint_ReconstructFrame |
3433 NS_STYLE_HINT_REFLOW;
3434 }
DifferenceAlwaysHandledForDescendantsnsStyleXUL3435 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3436 // CalcDifference never returns the reflow hints that are sometimes
3437 // handled for descendants as hints not handled for descendants.
3438 return nsChangeHint_NeedReflow |
3439 nsChangeHint_ReflowChangesSizeOrPosition |
3440 nsChangeHint_ClearAncestorIntrinsics;
3441 }
3442
3443 float mBoxFlex; // [reset] see nsStyleConsts.h
3444 uint32_t mBoxOrdinal; // [reset] see nsStyleConsts.h
3445 mozilla::StyleBoxAlign mBoxAlign; // [reset]
3446 mozilla::StyleBoxDirection mBoxDirection; // [reset]
3447 mozilla::StyleBoxOrient mBoxOrient; // [reset]
3448 mozilla::StyleBoxPack mBoxPack; // [reset]
3449 bool mStretchStack; // [reset] see nsStyleConsts.h
3450 };
3451
3452 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColumn
3453 {
3454 explicit nsStyleColumn(StyleStructContext aContext);
3455 nsStyleColumn(const nsStyleColumn& aSource);
3456 ~nsStyleColumn();
FinishStylensStyleColumn3457 void FinishStyle(nsPresContext* aPresContext) {}
3458
newnsStyleColumn3459 void* operator new(size_t sz, nsStyleColumn* aSelf) { return aSelf; }
newnsStyleColumn3460 void* operator new(size_t sz, nsPresContext* aContext) {
3461 return aContext->PresShell()->
3462 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleColumn, sz);
3463 }
DestroynsStyleColumn3464 void Destroy(nsPresContext* aContext) {
3465 this->~nsStyleColumn();
3466 aContext->PresShell()->
3467 FreeByObjectID(mozilla::eArenaObjectID_nsStyleColumn, this);
3468 }
3469
3470 nsChangeHint CalcDifference(const nsStyleColumn& aNewData) const;
MaxDifferencensStyleColumn3471 static nsChangeHint MaxDifference() {
3472 return nsChangeHint_ReconstructFrame |
3473 NS_STYLE_HINT_REFLOW |
3474 nsChangeHint_NeutralChange;
3475 }
DifferenceAlwaysHandledForDescendantsnsStyleColumn3476 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3477 // CalcDifference never returns the reflow hints that are sometimes
3478 // handled for descendants as hints not handled for descendants.
3479 return nsChangeHint_NeedReflow |
3480 nsChangeHint_ReflowChangesSizeOrPosition |
3481 nsChangeHint_ClearAncestorIntrinsics;
3482 }
3483
3484 /**
3485 * This is the maximum number of columns we can process. It's used in both
3486 * nsColumnSetFrame and nsRuleNode.
3487 */
3488 static const uint32_t kMaxColumnCount = 1000;
3489
3490 uint32_t mColumnCount; // [reset] see nsStyleConsts.h
3491 nsStyleCoord mColumnWidth; // [reset] coord, auto
3492 nsStyleCoord mColumnGap; // [reset] coord, normal
3493
3494 mozilla::StyleComplexColor mColumnRuleColor; // [reset]
3495 uint8_t mColumnRuleStyle; // [reset]
3496 uint8_t mColumnFill; // [reset] see nsStyleConsts.h
3497
SetColumnRuleWidthnsStyleColumn3498 void SetColumnRuleWidth(nscoord aWidth) {
3499 mColumnRuleWidth = NS_ROUND_BORDER_TO_PIXELS(aWidth, mTwipsPerPixel);
3500 }
3501
GetComputedColumnRuleWidthnsStyleColumn3502 nscoord GetComputedColumnRuleWidth() const {
3503 return (IsVisibleBorderStyle(mColumnRuleStyle) ? mColumnRuleWidth : 0);
3504 }
3505
3506 protected:
3507 nscoord mColumnRuleWidth; // [reset] coord
3508 nscoord mTwipsPerPixel;
3509 };
3510
3511 enum nsStyleSVGPaintType {
3512 eStyleSVGPaintType_None = 1,
3513 eStyleSVGPaintType_Color,
3514 eStyleSVGPaintType_Server,
3515 eStyleSVGPaintType_ContextFill,
3516 eStyleSVGPaintType_ContextStroke
3517 };
3518
3519 enum nsStyleSVGOpacitySource : uint8_t {
3520 eStyleSVGOpacitySource_Normal,
3521 eStyleSVGOpacitySource_ContextFillOpacity,
3522 eStyleSVGOpacitySource_ContextStrokeOpacity
3523 };
3524
3525 class nsStyleSVGPaint
3526 {
3527 public:
3528 explicit nsStyleSVGPaint(nsStyleSVGPaintType aType = nsStyleSVGPaintType(0));
3529 nsStyleSVGPaint(const nsStyleSVGPaint& aSource);
3530 ~nsStyleSVGPaint();
3531
3532 nsStyleSVGPaint& operator=(const nsStyleSVGPaint& aOther);
3533
Type()3534 nsStyleSVGPaintType Type() const { return mType; }
3535
3536 void SetNone();
3537 void SetColor(nscolor aColor);
3538 void SetPaintServer(mozilla::css::URLValue* aPaintServer,
3539 nscolor aFallbackColor);
3540 void SetContextValue(nsStyleSVGPaintType aType,
3541 nscolor aFallbackColor);
3542
GetColor()3543 nscolor GetColor() const {
3544 MOZ_ASSERT(mType == eStyleSVGPaintType_Color);
3545 return mPaint.mColor;
3546 }
3547
GetPaintServer()3548 mozilla::css::URLValue* GetPaintServer() const {
3549 MOZ_ASSERT(mType == eStyleSVGPaintType_Server);
3550 return mPaint.mPaintServer;
3551 }
3552
GetFallbackColor()3553 nscolor GetFallbackColor() const {
3554 MOZ_ASSERT(mType == eStyleSVGPaintType_Server ||
3555 mType == eStyleSVGPaintType_ContextFill ||
3556 mType == eStyleSVGPaintType_ContextStroke);
3557 return mFallbackColor;
3558 }
3559
3560 bool operator==(const nsStyleSVGPaint& aOther) const;
3561 bool operator!=(const nsStyleSVGPaint& aOther) const {
3562 return !(*this == aOther);
3563 }
3564
3565 private:
3566 void Reset();
3567 void Assign(const nsStyleSVGPaint& aOther);
3568
3569 union {
3570 nscolor mColor;
3571 mozilla::css::URLValue* mPaintServer;
3572 } mPaint;
3573 nsStyleSVGPaintType mType;
3574 nscolor mFallbackColor;
3575 };
3576
3577 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVG
3578 {
3579 explicit nsStyleSVG(StyleStructContext aContext);
3580 nsStyleSVG(const nsStyleSVG& aSource);
3581 ~nsStyleSVG();
FinishStylensStyleSVG3582 void FinishStyle(nsPresContext* aPresContext) {}
3583
newnsStyleSVG3584 void* operator new(size_t sz, nsStyleSVG* aSelf) { return aSelf; }
newnsStyleSVG3585 void* operator new(size_t sz, nsPresContext* aContext) {
3586 return aContext->PresShell()->
3587 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleSVG, sz);
3588 }
DestroynsStyleSVG3589 void Destroy(nsPresContext* aContext) {
3590 this->~nsStyleSVG();
3591 aContext->PresShell()->
3592 FreeByObjectID(mozilla::eArenaObjectID_nsStyleSVG, this);
3593 }
3594
3595 nsChangeHint CalcDifference(const nsStyleSVG& aNewData) const;
MaxDifferencensStyleSVG3596 static nsChangeHint MaxDifference() {
3597 return nsChangeHint_UpdateEffects |
3598 nsChangeHint_NeedReflow |
3599 nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
3600 nsChangeHint_RepaintFrame;
3601 }
DifferenceAlwaysHandledForDescendantsnsStyleSVG3602 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3603 // CalcDifference never returns nsChangeHint_NeedReflow as a hint
3604 // not handled for descendants, and never returns
3605 // nsChangeHint_ClearAncestorIntrinsics at all.
3606 return nsChangeHint_NeedReflow;
3607 }
3608
3609 nsStyleSVGPaint mFill; // [inherited]
3610 nsStyleSVGPaint mStroke; // [inherited]
3611 RefPtr<mozilla::css::URLValue> mMarkerEnd; // [inherited]
3612 RefPtr<mozilla::css::URLValue> mMarkerMid; // [inherited]
3613 RefPtr<mozilla::css::URLValue> mMarkerStart; // [inherited]
3614 nsTArray<nsStyleCoord> mStrokeDasharray; // [inherited] coord, percent, factor
3615
3616 nsStyleCoord mStrokeDashoffset; // [inherited] coord, percent, factor
3617 nsStyleCoord mStrokeWidth; // [inherited] coord, percent, factor
3618
3619 float mFillOpacity; // [inherited]
3620 float mStrokeMiterlimit; // [inherited]
3621 float mStrokeOpacity; // [inherited]
3622
3623 mozilla::StyleFillRule mClipRule; // [inherited]
3624 uint8_t mColorInterpolation; // [inherited] see nsStyleConsts.h
3625 uint8_t mColorInterpolationFilters; // [inherited] see nsStyleConsts.h
3626 mozilla::StyleFillRule mFillRule; // [inherited] see nsStyleConsts.h
3627 uint8_t mPaintOrder; // [inherited] see nsStyleConsts.h
3628 uint8_t mShapeRendering; // [inherited] see nsStyleConsts.h
3629 uint8_t mStrokeLinecap; // [inherited] see nsStyleConsts.h
3630 uint8_t mStrokeLinejoin; // [inherited] see nsStyleConsts.h
3631 uint8_t mTextAnchor; // [inherited] see nsStyleConsts.h
3632
FillOpacitySourcensStyleSVG3633 nsStyleSVGOpacitySource FillOpacitySource() const {
3634 uint8_t value = (mContextFlags & FILL_OPACITY_SOURCE_MASK) >>
3635 FILL_OPACITY_SOURCE_SHIFT;
3636 return nsStyleSVGOpacitySource(value);
3637 }
StrokeOpacitySourcensStyleSVG3638 nsStyleSVGOpacitySource StrokeOpacitySource() const {
3639 uint8_t value = (mContextFlags & STROKE_OPACITY_SOURCE_MASK) >>
3640 STROKE_OPACITY_SOURCE_SHIFT;
3641 return nsStyleSVGOpacitySource(value);
3642 }
StrokeDasharrayFromObjectnsStyleSVG3643 bool StrokeDasharrayFromObject() const {
3644 return mContextFlags & STROKE_DASHARRAY_CONTEXT;
3645 }
StrokeDashoffsetFromObjectnsStyleSVG3646 bool StrokeDashoffsetFromObject() const {
3647 return mContextFlags & STROKE_DASHOFFSET_CONTEXT;
3648 }
StrokeWidthFromObjectnsStyleSVG3649 bool StrokeWidthFromObject() const {
3650 return mContextFlags & STROKE_WIDTH_CONTEXT;
3651 }
3652
SetFillOpacitySourcensStyleSVG3653 void SetFillOpacitySource(nsStyleSVGOpacitySource aValue) {
3654 mContextFlags = (mContextFlags & ~FILL_OPACITY_SOURCE_MASK) |
3655 (aValue << FILL_OPACITY_SOURCE_SHIFT);
3656 }
SetStrokeOpacitySourcensStyleSVG3657 void SetStrokeOpacitySource(nsStyleSVGOpacitySource aValue) {
3658 mContextFlags = (mContextFlags & ~STROKE_OPACITY_SOURCE_MASK) |
3659 (aValue << STROKE_OPACITY_SOURCE_SHIFT);
3660 }
SetStrokeDasharrayFromObjectnsStyleSVG3661 void SetStrokeDasharrayFromObject(bool aValue) {
3662 mContextFlags = (mContextFlags & ~STROKE_DASHARRAY_CONTEXT) |
3663 (aValue ? STROKE_DASHARRAY_CONTEXT : 0);
3664 }
SetStrokeDashoffsetFromObjectnsStyleSVG3665 void SetStrokeDashoffsetFromObject(bool aValue) {
3666 mContextFlags = (mContextFlags & ~STROKE_DASHOFFSET_CONTEXT) |
3667 (aValue ? STROKE_DASHOFFSET_CONTEXT : 0);
3668 }
SetStrokeWidthFromObjectnsStyleSVG3669 void SetStrokeWidthFromObject(bool aValue) {
3670 mContextFlags = (mContextFlags & ~STROKE_WIDTH_CONTEXT) |
3671 (aValue ? STROKE_WIDTH_CONTEXT : 0);
3672 }
3673
HasMarkernsStyleSVG3674 bool HasMarker() const {
3675 return mMarkerStart || mMarkerMid || mMarkerEnd;
3676 }
3677
3678 /**
3679 * Returns true if the stroke is not "none" and the stroke-opacity is greater
3680 * than zero. This ignores stroke-widths as that depends on the context.
3681 */
HasStrokensStyleSVG3682 bool HasStroke() const {
3683 return mStroke.Type() != eStyleSVGPaintType_None && mStrokeOpacity > 0;
3684 }
3685
3686 /**
3687 * Returns true if the fill is not "none" and the fill-opacity is greater
3688 * than zero.
3689 */
HasFillnsStyleSVG3690 bool HasFill() const {
3691 return mFill.Type() != eStyleSVGPaintType_None && mFillOpacity > 0;
3692 }
3693
3694 private:
3695 // Flags to represent the use of context-fill and context-stroke
3696 // for fill-opacity or stroke-opacity, and context-value for stroke-dasharray,
3697 // stroke-dashoffset and stroke-width.
3698 enum {
3699 FILL_OPACITY_SOURCE_MASK = 0x03, // fill-opacity: context-{fill,stroke}
3700 STROKE_OPACITY_SOURCE_MASK = 0x0C, // stroke-opacity: context-{fill,stroke}
3701 STROKE_DASHARRAY_CONTEXT = 0x10, // stroke-dasharray: context-value
3702 STROKE_DASHOFFSET_CONTEXT = 0x20, // stroke-dashoffset: context-value
3703 STROKE_WIDTH_CONTEXT = 0x40, // stroke-width: context-value
3704 FILL_OPACITY_SOURCE_SHIFT = 0,
3705 STROKE_OPACITY_SOURCE_SHIFT = 2,
3706 };
3707
3708 uint8_t mContextFlags; // [inherited]
3709 };
3710
3711 struct nsStyleFilter
3712 {
3713 nsStyleFilter();
3714 nsStyleFilter(const nsStyleFilter& aSource);
3715 ~nsStyleFilter();
FinishStylensStyleFilter3716 void FinishStyle(nsPresContext* aPresContext) {}
3717
3718 nsStyleFilter& operator=(const nsStyleFilter& aOther);
3719
3720 bool operator==(const nsStyleFilter& aOther) const;
3721 bool operator!=(const nsStyleFilter& aOther) const {
3722 return !(*this == aOther);
3723 }
3724
GetTypensStyleFilter3725 uint32_t GetType() const {
3726 return mType;
3727 }
3728
GetFilterParameternsStyleFilter3729 const nsStyleCoord& GetFilterParameter() const {
3730 NS_ASSERTION(mType != NS_STYLE_FILTER_DROP_SHADOW &&
3731 mType != NS_STYLE_FILTER_URL &&
3732 mType != NS_STYLE_FILTER_NONE, "wrong filter type");
3733 return mFilterParameter;
3734 }
3735 void SetFilterParameter(const nsStyleCoord& aFilterParameter,
3736 int32_t aType);
3737
GetURLnsStyleFilter3738 mozilla::css::URLValue* GetURL() const {
3739 MOZ_ASSERT(mType == NS_STYLE_FILTER_URL, "wrong filter type");
3740 return mURL;
3741 }
3742
3743 bool SetURL(mozilla::css::URLValue* aValue);
3744
GetDropShadownsStyleFilter3745 nsCSSShadowArray* GetDropShadow() const {
3746 NS_ASSERTION(mType == NS_STYLE_FILTER_DROP_SHADOW, "wrong filter type");
3747 return mDropShadow;
3748 }
3749 void SetDropShadow(nsCSSShadowArray* aDropShadow);
3750
3751 private:
3752 void ReleaseRef();
3753
3754 uint32_t mType; // see NS_STYLE_FILTER_* constants in nsStyleConsts.h
3755 nsStyleCoord mFilterParameter; // coord, percent, factor, angle
3756 union {
3757 mozilla::css::URLValue* mURL;
3758 nsCSSShadowArray* mDropShadow;
3759 };
3760 };
3761
3762 template<>
3763 struct nsTArray_CopyChooser<nsStyleFilter>
3764 {
3765 typedef nsTArray_CopyWithConstructors<nsStyleFilter> Type;
3766 };
3767
3768 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVGReset
3769 {
3770 explicit nsStyleSVGReset(StyleStructContext aContext);
3771 nsStyleSVGReset(const nsStyleSVGReset& aSource);
3772 ~nsStyleSVGReset();
3773
3774 // Resolves and tracks the images in mMask. Only called with a Servo-backed
3775 // style system, where those images must be resolved later than the OMT
3776 // nsStyleSVGReset constructor call.
3777 void FinishStyle(nsPresContext* aPresContext);
3778
3779 void* operator new(size_t sz, nsStyleSVGReset* aSelf) { return aSelf; }
3780 void* operator new(size_t sz, nsPresContext* aContext) {
3781 return aContext->PresShell()->
3782 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, sz);
3783 }
3784 void Destroy(nsPresContext* aContext);
3785
3786 nsChangeHint CalcDifference(const nsStyleSVGReset& aNewData) const;
3787 static nsChangeHint MaxDifference() {
3788 return nsChangeHint_UpdateEffects |
3789 nsChangeHint_UpdateOverflow |
3790 nsChangeHint_NeutralChange |
3791 nsChangeHint_RepaintFrame |
3792 nsChangeHint_UpdateBackgroundPosition |
3793 NS_STYLE_HINT_REFLOW;
3794 }
3795 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3796 // CalcDifference never returns the reflow hints that are sometimes
3797 // handled for descendants as hints not handled for descendants.
3798 return nsChangeHint_NeedReflow |
3799 nsChangeHint_ReflowChangesSizeOrPosition |
3800 nsChangeHint_ClearAncestorIntrinsics;
3801 }
3802
3803 bool HasClipPath() const {
3804 return mClipPath.GetType() != mozilla::StyleShapeSourceType::None;
3805 }
3806
3807 bool HasNonScalingStroke() const {
3808 return mVectorEffect == NS_STYLE_VECTOR_EFFECT_NON_SCALING_STROKE;
3809 }
3810
3811 nsStyleImageLayers mMask;
3812 mozilla::StyleClipPath mClipPath; // [reset]
3813 nscolor mStopColor; // [reset]
3814 nscolor mFloodColor; // [reset]
3815 nscolor mLightingColor; // [reset]
3816
3817 float mStopOpacity; // [reset]
3818 float mFloodOpacity; // [reset]
3819
3820 uint8_t mDominantBaseline; // [reset] see nsStyleConsts.h
3821 uint8_t mVectorEffect; // [reset] see nsStyleConsts.h
3822 uint8_t mMaskType; // [reset] see nsStyleConsts.h
3823 };
3824
3825 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleVariables
3826 {
3827 explicit nsStyleVariables(StyleStructContext aContext);
3828 nsStyleVariables(const nsStyleVariables& aSource);
3829 ~nsStyleVariables();
3830 void FinishStyle(nsPresContext* aPresContext) {}
3831
3832 void* operator new(size_t sz, nsStyleVariables* aSelf) { return aSelf; }
3833 void* operator new(size_t sz, nsPresContext* aContext) {
3834 return aContext->PresShell()->
3835 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleVariables, sz);
3836 }
3837 void Destroy(nsPresContext* aContext) {
3838 this->~nsStyleVariables();
3839 aContext->PresShell()->
3840 FreeByObjectID(mozilla::eArenaObjectID_nsStyleVariables, this);
3841 }
3842
3843 nsChangeHint CalcDifference(const nsStyleVariables& aNewData) const;
3844 static nsChangeHint MaxDifference() {
3845 return nsChangeHint(0);
3846 }
3847 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3848 // CalcDifference never returns nsChangeHint_NeedReflow or
3849 // nsChangeHint_ClearAncestorIntrinsics at all.
3850 return nsChangeHint(0);
3851 }
3852
3853 mozilla::CSSVariableValues mVariables;
3854 };
3855
3856 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleEffects
3857 {
3858 explicit nsStyleEffects(StyleStructContext aContext);
3859 nsStyleEffects(const nsStyleEffects& aSource);
3860 ~nsStyleEffects();
3861 void FinishStyle(nsPresContext* aPresContext) {}
3862
3863 void* operator new(size_t sz, nsStyleEffects* aSelf) { return aSelf; }
3864 void* operator new(size_t sz, nsPresContext* aContext) {
3865 return aContext->PresShell()->
3866 AllocateByObjectID(mozilla::eArenaObjectID_nsStyleEffects, sz);
3867 }
3868 void Destroy(nsPresContext* aContext) {
3869 this->~nsStyleEffects();
3870 aContext->PresShell()->
3871 FreeByObjectID(mozilla::eArenaObjectID_nsStyleEffects, this);
3872 }
3873
3874 nsChangeHint CalcDifference(const nsStyleEffects& aNewData) const;
3875 static nsChangeHint MaxDifference() {
3876 return nsChangeHint_AllReflowHints |
3877 nsChangeHint_UpdateOverflow |
3878 nsChangeHint_SchedulePaint |
3879 nsChangeHint_RepaintFrame |
3880 nsChangeHint_UpdateOpacityLayer |
3881 nsChangeHint_UpdateUsesOpacity |
3882 nsChangeHint_UpdateContainingBlock |
3883 nsChangeHint_UpdateEffects |
3884 nsChangeHint_NeutralChange;
3885 }
3886 static nsChangeHint DifferenceAlwaysHandledForDescendants() {
3887 // CalcDifference never returns the reflow hints that are sometimes
3888 // handled for descendants as hints not handled for descendants.
3889 return nsChangeHint_NeedReflow |
3890 nsChangeHint_ReflowChangesSizeOrPosition |
3891 nsChangeHint_ClearAncestorIntrinsics;
3892 }
3893
3894 bool HasFilters() const {
3895 return !mFilters.IsEmpty();
3896 }
3897
3898 nsTArray<nsStyleFilter> mFilters; // [reset]
3899 RefPtr<nsCSSShadowArray> mBoxShadow; // [reset] nullptr for 'none'
3900 nsRect mClip; // [reset] offsets from UL border edge
3901 float mOpacity; // [reset]
3902 uint8_t mClipFlags; // [reset] see nsStyleConsts.h
3903 uint8_t mMixBlendMode; // [reset] see nsStyleConsts.h
3904 };
3905
3906 #define STATIC_ASSERT_TYPE_LAYOUTS_MATCH(T1, T2) \
3907 static_assert(sizeof(T1) == sizeof(T2), \
3908 "Size mismatch between " #T1 " and " #T2); \
3909 static_assert(alignof(T1) == alignof(T2), \
3910 "Align mismatch between " #T1 " and " #T2); \
3911
3912 #define STATIC_ASSERT_FIELD_OFFSET_MATCHES(T1, T2, field) \
3913 static_assert(offsetof(T1, field) == offsetof(T2, field), \
3914 "Field offset mismatch of " #field " between " #T1 " and " #T2); \
3915
3916 /**
3917 * These *_Simple types are used to map Gecko types to layout-equivalent but
3918 * simpler Rust types, to aid Rust binding generation.
3919 *
3920 * If something in this types or the assertions below needs to change, ask
3921 * bholley, heycam or emilio before!
3922 *
3923 * <div rustbindgen="true" replaces="nsPoint">
3924 */
3925 struct nsPoint_Simple {
3926 nscoord x, y;
3927 };
3928
3929 STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsPoint, nsPoint_Simple);
3930 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsPoint, nsPoint_Simple, x);
3931 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsPoint, nsPoint_Simple, y);
3932
3933 /**
3934 * <div rustbindgen="true" replaces="nsMargin">
3935 */
3936 struct nsMargin_Simple {
3937 nscoord top, right, bottom, left;
3938 };
3939
3940 STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsMargin, nsMargin_Simple);
3941 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsMargin, nsMargin_Simple, top);
3942 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsMargin, nsMargin_Simple, right);
3943 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsMargin, nsMargin_Simple, bottom);
3944 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsMargin, nsMargin_Simple, left);
3945
3946 /**
3947 * <div rustbindgen="true" replaces="nsRect">
3948 */
3949 struct nsRect_Simple {
3950 nscoord x, y, width, height;
3951 };
3952
3953 STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsRect, nsRect_Simple);
3954 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsRect, nsRect_Simple, x);
3955 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsRect, nsRect_Simple, y);
3956 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsRect, nsRect_Simple, width);
3957 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsRect, nsRect_Simple, height);
3958
3959 /**
3960 * <div rustbindgen="true" replaces="nsSize">
3961 */
3962 struct nsSize_Simple {
3963 nscoord width, height;
3964 };
3965
3966 STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsSize, nsSize_Simple);
3967 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsSize, nsSize_Simple, width);
3968 STATIC_ASSERT_FIELD_OFFSET_MATCHES(nsSize, nsSize_Simple, height);
3969
3970 /**
3971 * <div rustbindgen="true" replaces="UniquePtr">
3972 *
3973 * TODO(Emilio): This is a workaround and we should be able to get rid of this
3974 * one.
3975 */
3976 template<typename T, typename Deleter = mozilla::DefaultDelete<T>>
3977 struct UniquePtr_Simple {
3978 T* mPtr;
3979 };
3980
3981 STATIC_ASSERT_TYPE_LAYOUTS_MATCH(mozilla::UniquePtr<int>, UniquePtr_Simple<int>);
3982
3983 /**
3984 * <div rustbindgen replaces="nsTArray"></div>
3985 */
3986 template<typename T>
3987 class nsTArray_Simple {
3988 T* mBuffer;
3989 public:
3990 // The existence of a destructor here prevents bindgen from deriving the Clone
3991 // trait via a simple memory copy.
3992 ~nsTArray_Simple() {};
3993 };
3994
3995 STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsTArray<nsStyleImageLayers::Layer>,
3996 nsTArray_Simple<nsStyleImageLayers::Layer>);
3997 STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsTArray<mozilla::StyleTransition>,
3998 nsTArray_Simple<mozilla::StyleTransition>);
3999 STATIC_ASSERT_TYPE_LAYOUTS_MATCH(nsTArray<mozilla::StyleAnimation>,
4000 nsTArray_Simple<mozilla::StyleAnimation>);
4001
4002 #endif /* nsStyleStruct_h___ */
4003