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