Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /*
7 * structs that contain the data provided by nsStyleContext, the
8 * internal API for computed style data for an element
9 */
11 #ifndef nsStyleStruct_h___
12 #define nsStyleStruct_h___
14 #include "mozilla/Attributes.h"
15 #include "mozilla/CSSVariableValues.h"
16 #include "nsColor.h"
17 #include "nsCoord.h"
18 #include "nsMargin.h"
19 #include "nsRect.h"
20 #include "nsFont.h"
21 #include "nsStyleCoord.h"
22 #include "nsStyleConsts.h"
23 #include "nsChangeHint.h"
24 #include "nsPresContext.h"
25 #include "nsCOMPtr.h"
26 #include "nsCOMArray.h"
27 #include "nsTArray.h"
28 #include "nsIAtom.h"
29 #include "nsCSSValue.h"
30 #include "imgRequestProxy.h"
31 #include "Orientation.h"
32 #include <algorithm>
34 class nsIFrame;
35 class nsIURI;
36 class imgIContainer;
38 // Includes nsStyleStructID.
39 #include "nsStyleStructFwd.h"
41 // Bits for each struct.
42 // NS_STYLE_INHERIT_BIT defined in nsStyleStructFwd.h
43 #define NS_STYLE_INHERIT_MASK 0x000ffffff
45 // Additional bits for nsStyleContext's mBits:
46 // See nsStyleContext::HasTextDecorationLines
47 #define NS_STYLE_HAS_TEXT_DECORATION_LINES 0x001000000
48 // See nsStyleContext::HasPseudoElementData.
49 #define NS_STYLE_HAS_PSEUDO_ELEMENT_DATA 0x002000000
50 // See nsStyleContext::RelevantLinkIsVisited
51 #define NS_STYLE_RELEVANT_LINK_VISITED 0x004000000
52 // See nsStyleContext::IsStyleIfVisited
53 #define NS_STYLE_IS_STYLE_IF_VISITED 0x008000000
54 // See nsStyleContext::GetPseudoEnum
55 #define NS_STYLE_CONTEXT_TYPE_MASK 0x1f0000000
56 #define NS_STYLE_CONTEXT_TYPE_SHIFT 28
58 // Additional bits for nsRuleNode's mDependentBits:
59 #define NS_RULE_NODE_GC_MARK 0x02000000
60 #define NS_RULE_NODE_USED_DIRECTLY 0x04000000
61 #define NS_RULE_NODE_IS_IMPORTANT 0x08000000
62 #define NS_RULE_NODE_LEVEL_MASK 0xf0000000
63 #define NS_RULE_NODE_LEVEL_SHIFT 28
65 // The lifetime of these objects is managed by the presshell's arena.
67 struct nsStyleFont {
68 nsStyleFont(const nsFont& aFont, nsPresContext *aPresContext);
69 nsStyleFont(const nsStyleFont& aStyleFont);
70 nsStyleFont(nsPresContext *aPresContext);
71 private:
72 void Init(nsPresContext *aPresContext);
73 public:
74 ~nsStyleFont(void) {
75 MOZ_COUNT_DTOR(nsStyleFont);
76 }
78 nsChangeHint CalcDifference(const nsStyleFont& aOther) const;
79 static nsChangeHint MaxDifference() {
80 return NS_STYLE_HINT_REFLOW;
81 }
82 static nsChangeHint MaxDifferenceNeverInherited() {
83 // CalcDifference never returns nsChangeHint_NeedReflow or
84 // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
85 return NS_CombineHint(nsChangeHint_NeedReflow,
86 nsChangeHint_ClearAncestorIntrinsics);
87 }
88 static nsChangeHint CalcFontDifference(const nsFont& aFont1, const nsFont& aFont2);
90 static nscoord ZoomText(nsPresContext* aPresContext, nscoord aSize);
91 static nscoord UnZoomText(nsPresContext* aPresContext, nscoord aSize);
93 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW;
94 void Destroy(nsPresContext* aContext);
96 void EnableZoom(nsPresContext* aContext, bool aEnable);
98 nsFont mFont; // [inherited]
99 nscoord mSize; // [inherited] Our "computed size". Can be different
100 // from mFont.size which is our "actual size" and is
101 // enforced to be >= the user's preferred min-size.
102 // mFont.size should be used for display purposes
103 // while mSize is the value to return in
104 // getComputedStyle() for example.
105 uint8_t mGenericID; // [inherited] generic CSS font family, if any;
106 // value is a kGenericFont_* constant, see nsFont.h.
108 // MathML scriptlevel support
109 int8_t mScriptLevel; // [inherited]
110 // MathML mathvariant support
111 uint8_t mMathVariant; // [inherited]
112 // MathML displaystyle support
113 uint8_t mMathDisplay; // [inherited]
115 // was mLanguage set based on a lang attribute in the document?
116 bool mExplicitLanguage; // [inherited]
118 // should calls to ZoomText() and UnZoomText() be made to the font
119 // size on this nsStyleFont?
120 bool mAllowZoom; // [inherited]
122 // The value mSize would have had if scriptminsize had never been applied
123 nscoord mScriptUnconstrainedSize;
124 nscoord mScriptMinSize; // [inherited] length
125 float mScriptSizeMultiplier; // [inherited]
126 nsCOMPtr<nsIAtom> mLanguage; // [inherited]
127 };
129 struct nsStyleGradientStop {
130 nsStyleCoord mLocation; // percent, coord, calc, none
131 nscolor mColor;
132 };
134 class nsStyleGradient MOZ_FINAL {
135 public:
136 nsStyleGradient();
137 uint8_t mShape; // NS_STYLE_GRADIENT_SHAPE_*
138 uint8_t mSize; // NS_STYLE_GRADIENT_SIZE_*;
139 // not used (must be FARTHEST_CORNER) for linear shape
140 bool mRepeating;
141 bool mLegacySyntax;
143 nsStyleCoord mBgPosX; // percent, coord, calc, none
144 nsStyleCoord mBgPosY; // percent, coord, calc, none
145 nsStyleCoord mAngle; // none, angle
147 nsStyleCoord mRadiusX; // percent, coord, calc, none
148 nsStyleCoord mRadiusY; // percent, coord, calc, none
150 // stops are in the order specified in the stylesheet
151 nsTArray<nsStyleGradientStop> mStops;
153 bool operator==(const nsStyleGradient& aOther) const;
154 bool operator!=(const nsStyleGradient& aOther) const {
155 return !(*this == aOther);
156 }
158 bool IsOpaque();
159 bool HasCalc();
160 uint32_t Hash(PLDHashNumber aHash);
162 NS_INLINE_DECL_REFCOUNTING(nsStyleGradient)
164 private:
165 // Private destructor, to discourage deletion outside of Release():
166 ~nsStyleGradient() {}
168 nsStyleGradient(const nsStyleGradient& aOther) MOZ_DELETE;
169 nsStyleGradient& operator=(const nsStyleGradient& aOther) MOZ_DELETE;
170 };
172 enum nsStyleImageType {
173 eStyleImageType_Null,
174 eStyleImageType_Image,
175 eStyleImageType_Gradient,
176 eStyleImageType_Element
177 };
179 /**
180 * Represents a paintable image of one of the following types.
181 * (1) A real image loaded from an external source.
182 * (2) A CSS linear or radial gradient.
183 * (3) An element within a document, or an <img>, <video>, or <canvas> element
184 * not in a document.
185 * (*) Optionally a crop rect can be set to paint a partial (rectangular)
186 * region of an image. (Currently, this feature is only supported with an
187 * image of type (1)).
188 */
189 struct nsStyleImage {
190 nsStyleImage();
191 ~nsStyleImage();
192 nsStyleImage(const nsStyleImage& aOther);
193 nsStyleImage& operator=(const nsStyleImage& aOther);
195 void SetNull();
196 void SetImageData(imgIRequest* aImage);
197 void TrackImage(nsPresContext* aContext);
198 void UntrackImage(nsPresContext* aContext);
199 void SetGradientData(nsStyleGradient* aGradient);
200 void SetElementId(const char16_t* aElementId);
201 void SetCropRect(nsStyleSides* aCropRect);
203 nsStyleImageType GetType() const {
204 return mType;
205 }
206 imgIRequest* GetImageData() const {
207 NS_ABORT_IF_FALSE(mType == eStyleImageType_Image, "Data is not an image!");
208 NS_ABORT_IF_FALSE(mImageTracked,
209 "Should be tracking any image we're going to use!");
210 return mImage;
211 }
212 nsStyleGradient* GetGradientData() const {
213 NS_ASSERTION(mType == eStyleImageType_Gradient, "Data is not a gradient!");
214 return mGradient;
215 }
216 const char16_t* GetElementId() const {
217 NS_ASSERTION(mType == eStyleImageType_Element, "Data is not an element!");
218 return mElementId;
219 }
220 nsStyleSides* GetCropRect() const {
221 NS_ASSERTION(mType == eStyleImageType_Image,
222 "Only image data can have a crop rect");
223 return mCropRect;
224 }
226 /**
227 * Compute the actual crop rect in pixels, using the source image bounds.
228 * The computation involves converting percentage unit to pixel unit and
229 * clamping each side value to fit in the source image bounds.
230 * @param aActualCropRect the computed actual crop rect.
231 * @param aIsEntireImage true iff |aActualCropRect| is identical to the
232 * source image bounds.
233 * @return true iff |aActualCropRect| holds a meaningful value.
234 */
235 bool ComputeActualCropRect(nsIntRect& aActualCropRect,
236 bool* aIsEntireImage = nullptr) const;
238 /**
239 * Starts the decoding of a image.
240 */
241 nsresult StartDecoding() const;
242 /**
243 * @return true if the item is definitely opaque --- i.e., paints every
244 * pixel within its bounds opaquely, and the bounds contains at least a pixel.
245 */
246 bool IsOpaque() const;
247 /**
248 * @return true if this image is fully loaded, and its size is calculated;
249 * always returns true if |mType| is |eStyleImageType_Gradient| or
250 * |eStyleImageType_Element|.
251 */
252 bool IsComplete() const;
253 /**
254 * @return true if this image is loaded without error;
255 * always returns true if |mType| is |eStyleImageType_Gradient| or
256 * |eStyleImageType_Element|.
257 */
258 bool IsLoaded() const;
259 /**
260 * @return true if it is 100% confident that this image contains no pixel
261 * to draw.
262 */
263 bool IsEmpty() const {
264 // There are some other cases when the image will be empty, for example
265 // when the crop rect is empty. However, checking the emptiness of crop
266 // rect is non-trivial since each side value can be specified with
267 // percentage unit, which can not be evaluated until the source image size
268 // is available. Therefore, we currently postpone the evaluation of crop
269 // rect until the actual rendering time --- alternatively until GetOpaqueRegion()
270 // is called.
271 return mType == eStyleImageType_Null;
272 }
274 bool operator==(const nsStyleImage& aOther) const;
275 bool operator!=(const nsStyleImage& aOther) const {
276 return !(*this == aOther);
277 }
279 bool ImageDataEquals(const nsStyleImage& aOther) const
280 {
281 return GetType() == eStyleImageType_Image &&
282 aOther.GetType() == eStyleImageType_Image &&
283 GetImageData() == aOther.GetImageData();
284 }
286 // These methods are used for the caller to caches the sub images created
287 // during a border-image paint operation
288 inline void SetSubImage(uint8_t aIndex, imgIContainer* aSubImage) const;
289 inline imgIContainer* GetSubImage(uint8_t aIndex) const;
291 private:
292 void DoCopy(const nsStyleImage& aOther);
294 // Cache for border-image painting.
295 nsCOMArray<imgIContainer> mSubImages;
297 nsStyleImageType mType;
298 union {
299 imgIRequest* mImage;
300 nsStyleGradient* mGradient;
301 char16_t* mElementId;
302 };
303 // This is _currently_ used only in conjunction with eStyleImageType_Image.
304 nsAutoPtr<nsStyleSides> mCropRect;
305 #ifdef DEBUG
306 bool mImageTracked;
307 #endif
308 };
310 struct nsStyleColor {
311 nsStyleColor(nsPresContext* aPresContext);
312 nsStyleColor(const nsStyleColor& aOther);
313 ~nsStyleColor(void) {
314 MOZ_COUNT_DTOR(nsStyleColor);
315 }
317 nsChangeHint CalcDifference(const nsStyleColor& aOther) const;
318 static nsChangeHint MaxDifference() {
319 return NS_STYLE_HINT_VISUAL;
320 }
321 static nsChangeHint MaxDifferenceNeverInherited() {
322 // CalcDifference never returns nsChangeHint_NeedReflow or
323 // nsChangeHint_ClearAncestorIntrinsics at all.
324 return nsChangeHint(0);
325 }
327 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
328 return aContext->AllocateFromShell(sz);
329 }
330 void Destroy(nsPresContext* aContext) {
331 this->~nsStyleColor();
332 aContext->FreeToShell(sizeof(nsStyleColor), this);
333 }
335 // Don't add ANY members to this struct! We can achieve caching in the rule
336 // tree (rather than the style tree) by letting color stay by itself! -dwh
337 nscolor mColor; // [inherited]
338 };
340 struct nsStyleBackground {
341 nsStyleBackground();
342 nsStyleBackground(const nsStyleBackground& aOther);
343 ~nsStyleBackground();
345 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
346 return aContext->AllocateFromShell(sz);
347 }
348 void Destroy(nsPresContext* aContext);
350 nsChangeHint CalcDifference(const nsStyleBackground& aOther) const;
351 static nsChangeHint MaxDifference() {
352 return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL);
353 }
354 static nsChangeHint MaxDifferenceNeverInherited() {
355 // CalcDifference never returns nsChangeHint_NeedReflow or
356 // nsChangeHint_ClearAncestorIntrinsics at all.
357 return nsChangeHint(0);
358 }
360 struct Position;
361 friend struct Position;
362 struct Position {
363 typedef nsStyleCoord::Calc PositionCoord;
364 PositionCoord mXPosition, mYPosition;
366 // Initialize nothing
367 Position() {}
369 // Initialize to initial values
370 void SetInitialValues();
372 // True if the effective background image position described by this depends
373 // on the size of the corresponding frame.
374 bool DependsOnPositioningAreaSize() const {
375 return mXPosition.mPercent != 0.0f || mYPosition.mPercent != 0.0f;
376 }
378 bool operator==(const Position& aOther) const {
379 return mXPosition == aOther.mXPosition &&
380 mYPosition == aOther.mYPosition;
381 }
382 bool operator!=(const Position& aOther) const {
383 return !(*this == aOther);
384 }
385 };
387 struct Size;
388 friend struct Size;
389 struct Size {
390 struct Dimension : public nsStyleCoord::Calc {
391 nscoord ResolveLengthPercentage(nscoord aAvailable) const {
392 double d = double(mPercent) * double(aAvailable) + double(mLength);
393 if (d < 0.0)
394 return 0;
395 return NSToCoordRoundWithClamp(float(d));
396 }
397 };
398 Dimension mWidth, mHeight;
400 nscoord ResolveWidthLengthPercentage(const nsSize& aBgPositioningArea) const {
401 NS_ABORT_IF_FALSE(mWidthType == eLengthPercentage,
402 "resolving non-length/percent dimension!");
403 return mWidth.ResolveLengthPercentage(aBgPositioningArea.width);
404 }
406 nscoord ResolveHeightLengthPercentage(const nsSize& aBgPositioningArea) const {
407 NS_ABORT_IF_FALSE(mHeightType == eLengthPercentage,
408 "resolving non-length/percent dimension!");
409 return mHeight.ResolveLengthPercentage(aBgPositioningArea.height);
410 }
412 // Except for eLengthPercentage, Dimension types which might change
413 // how a layer is painted when the corresponding frame's dimensions
414 // change *must* precede all dimension types which are agnostic to
415 // frame size; see DependsOnDependsOnPositioningAreaSizeSize.
416 enum DimensionType {
417 // If one of mWidth and mHeight is eContain or eCover, then both are.
418 // Also, these two values must equal the corresponding values in
419 // kBackgroundSizeKTable.
420 eContain, eCover,
422 eAuto,
423 eLengthPercentage,
424 eDimensionType_COUNT
425 };
426 uint8_t mWidthType, mHeightType;
428 // True if the effective image size described by this depends on the size of
429 // the corresponding frame, when aImage (which must not have null type) is
430 // the background image.
431 bool DependsOnPositioningAreaSize(const nsStyleImage& aImage) const;
433 // Initialize nothing
434 Size() {}
436 // Initialize to initial values
437 void SetInitialValues();
439 bool operator==(const Size& aOther) const;
440 bool operator!=(const Size& aOther) const {
441 return !(*this == aOther);
442 }
443 };
445 struct Repeat;
446 friend struct Repeat;
447 struct Repeat {
448 uint8_t mXRepeat, mYRepeat;
450 // Initialize nothing
451 Repeat() {}
453 // Initialize to initial values
454 void SetInitialValues();
456 bool operator==(const Repeat& aOther) const {
457 return mXRepeat == aOther.mXRepeat &&
458 mYRepeat == aOther.mYRepeat;
459 }
460 bool operator!=(const Repeat& aOther) const {
461 return !(*this == aOther);
462 }
463 };
465 struct Layer;
466 friend struct Layer;
467 struct Layer {
468 uint8_t mAttachment; // [reset] See nsStyleConsts.h
469 uint8_t mClip; // [reset] See nsStyleConsts.h
470 uint8_t mOrigin; // [reset] See nsStyleConsts.h
471 uint8_t mBlendMode; // [reset] See nsStyleConsts.h
472 Repeat mRepeat; // [reset] See nsStyleConsts.h
473 Position mPosition; // [reset]
474 nsStyleImage mImage; // [reset]
475 Size mSize; // [reset]
477 // Initializes only mImage
478 Layer();
479 ~Layer();
481 // Register/unregister images with the document. We do this only
482 // after the dust has settled in ComputeBackgroundData.
483 void TrackImages(nsPresContext* aContext) {
484 if (mImage.GetType() == eStyleImageType_Image)
485 mImage.TrackImage(aContext);
486 }
487 void UntrackImages(nsPresContext* aContext) {
488 if (mImage.GetType() == eStyleImageType_Image)
489 mImage.UntrackImage(aContext);
490 }
492 void SetInitialValues();
494 // True if the rendering of this layer might change when the size
495 // of the background positioning area changes. This is true for any
496 // non-solid-color background whose position or size depends on
497 // the size of the positioning area. It's also true for SVG images
498 // whose root <svg> node has a viewBox.
499 bool RenderingMightDependOnPositioningAreaSizeChange() const;
501 // An equality operator that compares the images using URL-equality
502 // rather than pointer-equality.
503 bool operator==(const Layer& aOther) const;
504 bool operator!=(const Layer& aOther) const {
505 return !(*this == aOther);
506 }
507 };
509 // The (positive) number of computed values of each property, since
510 // the lengths of the lists are independent.
511 uint32_t mAttachmentCount,
512 mClipCount,
513 mOriginCount,
514 mRepeatCount,
515 mPositionCount,
516 mImageCount,
517 mSizeCount,
518 mBlendModeCount;
519 // Layers are stored in an array, matching the top-to-bottom order in
520 // which they are specified in CSS. The number of layers to be used
521 // should come from the background-image property. We create
522 // additional |Layer| objects for *any* property, not just
523 // background-image. This means that the bottommost layer that
524 // callers in layout care about (which is also the one whose
525 // background-clip applies to the background-color) may not be last
526 // layer. In layers below the bottom layer, properties will be
527 // uninitialized unless their count, above, indicates that they are
528 // present.
529 nsAutoTArray<Layer, 1> mLayers;
531 const Layer& BottomLayer() const { return mLayers[mImageCount - 1]; }
533 #define NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(var_, stylebg_) \
534 for (uint32_t var_ = (stylebg_) ? (stylebg_)->mImageCount : 1; var_-- != 0; )
535 #define NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT_WITH_RANGE(var_, stylebg_, start_, count_) \
536 NS_ASSERTION((int32_t)(start_) >= 0 && (uint32_t)(start_) < ((stylebg_) ? (stylebg_)->mImageCount : 1), "Invalid layer start!"); \
537 NS_ASSERTION((count_) > 0 && (count_) <= (start_) + 1, "Invalid layer range!"); \
538 for (uint32_t var_ = (start_) + 1; var_-- != (uint32_t)((start_) + 1 - (count_)); )
540 nscolor mBackgroundColor; // [reset]
542 // FIXME: This (now background-break in css3-background) should
543 // probably move into a different struct so that everything in
544 // nsStyleBackground is set by the background shorthand.
545 uint8_t mBackgroundInlinePolicy; // [reset] See nsStyleConsts.h
547 // True if this background is completely transparent.
548 bool IsTransparent() const;
550 // We have to take slower codepaths for fixed background attachment,
551 // but we don't want to do that when there's no image.
552 // Not inline because it uses an nsCOMPtr<imgIRequest>
553 // FIXME: Should be in nsStyleStructInlines.h.
554 bool HasFixedBackground() const;
555 };
557 // See https://bugzilla.mozilla.org/show_bug.cgi?id=271586#c43 for why
558 // this is hard to replace with 'currentColor'.
559 #define BORDER_COLOR_FOREGROUND 0x20
560 #define OUTLINE_COLOR_INITIAL 0x80
561 // FOREGROUND | INITIAL(OUTLINE)
562 #define BORDER_COLOR_SPECIAL 0xA0
563 #define BORDER_STYLE_MASK 0x1F
565 #define NS_SPACING_MARGIN 0
566 #define NS_SPACING_PADDING 1
567 #define NS_SPACING_BORDER 2
570 struct nsStyleMargin {
571 nsStyleMargin(void);
572 nsStyleMargin(const nsStyleMargin& aMargin);
573 ~nsStyleMargin(void) {
574 MOZ_COUNT_DTOR(nsStyleMargin);
575 }
577 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW;
578 void Destroy(nsPresContext* aContext);
580 void RecalcData();
581 nsChangeHint CalcDifference(const nsStyleMargin& aOther) const;
582 static nsChangeHint MaxDifference() {
583 return NS_SubtractHint(NS_STYLE_HINT_REFLOW,
584 NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics,
585 nsChangeHint_NeedDirtyReflow));
586 }
587 static nsChangeHint MaxDifferenceNeverInherited() {
588 // CalcDifference can return both nsChangeHint_ClearAncestorIntrinsics and
589 // nsChangeHint_NeedReflow as inherited hints.
590 return nsChangeHint(0);
591 }
593 nsStyleSides mMargin; // [reset] coord, percent, calc, auto
595 bool IsWidthDependent() const { return !mHasCachedMargin; }
596 bool GetMargin(nsMargin& aMargin) const
597 {
598 if (mHasCachedMargin) {
599 aMargin = mCachedMargin;
600 return true;
601 }
602 return false;
603 }
605 protected:
606 bool mHasCachedMargin;
607 nsMargin mCachedMargin;
608 };
611 struct nsStylePadding {
612 nsStylePadding(void);
613 nsStylePadding(const nsStylePadding& aPadding);
614 ~nsStylePadding(void) {
615 MOZ_COUNT_DTOR(nsStylePadding);
616 }
618 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW;
619 void Destroy(nsPresContext* aContext);
621 void RecalcData();
622 nsChangeHint CalcDifference(const nsStylePadding& aOther) const;
623 static nsChangeHint MaxDifference() {
624 return NS_SubtractHint(NS_STYLE_HINT_REFLOW,
625 nsChangeHint_ClearDescendantIntrinsics);
626 }
627 static nsChangeHint MaxDifferenceNeverInherited() {
628 // CalcDifference can return nsChangeHint_ClearAncestorIntrinsics as an
629 // inherited hint.
630 return nsChangeHint(0);
631 }
633 nsStyleSides mPadding; // [reset] coord, percent, calc
635 bool IsWidthDependent() const { return !mHasCachedPadding; }
636 bool GetPadding(nsMargin& aPadding) const
637 {
638 if (mHasCachedPadding) {
639 aPadding = mCachedPadding;
640 return true;
641 }
642 return false;
643 }
645 protected:
646 bool mHasCachedPadding;
647 nsMargin mCachedPadding;
648 };
650 struct nsBorderColors {
651 nsBorderColors* mNext;
652 nscolor mColor;
654 nsBorderColors() : mNext(nullptr), mColor(NS_RGB(0,0,0)) {}
655 nsBorderColors(const nscolor& aColor) : mNext(nullptr), mColor(aColor) {}
656 ~nsBorderColors();
658 nsBorderColors* Clone() const { return Clone(true); }
660 static bool Equal(const nsBorderColors* c1,
661 const nsBorderColors* c2) {
662 if (c1 == c2)
663 return true;
664 while (c1 && c2) {
665 if (c1->mColor != c2->mColor)
666 return false;
667 c1 = c1->mNext;
668 c2 = c2->mNext;
669 }
670 // both should be nullptr if these are equal, otherwise one
671 // has more colors than another
672 return !c1 && !c2;
673 }
675 private:
676 nsBorderColors* Clone(bool aDeep) const;
677 };
679 struct nsCSSShadowItem {
680 nscoord mXOffset;
681 nscoord mYOffset;
682 nscoord mRadius;
683 nscoord mSpread;
685 nscolor mColor;
686 bool mHasColor; // Whether mColor should be used
687 bool mInset;
689 nsCSSShadowItem() : mHasColor(false) {
690 MOZ_COUNT_CTOR(nsCSSShadowItem);
691 }
692 ~nsCSSShadowItem() {
693 MOZ_COUNT_DTOR(nsCSSShadowItem);
694 }
696 bool operator==(const nsCSSShadowItem& aOther) const {
697 return (mXOffset == aOther.mXOffset &&
698 mYOffset == aOther.mYOffset &&
699 mRadius == aOther.mRadius &&
700 mHasColor == aOther.mHasColor &&
701 mSpread == aOther.mSpread &&
702 mInset == aOther.mInset &&
703 (!mHasColor || mColor == aOther.mColor));
704 }
705 bool operator!=(const nsCSSShadowItem& aOther) const {
706 return !(*this == aOther);
707 }
708 };
710 class nsCSSShadowArray MOZ_FINAL {
711 public:
712 void* operator new(size_t aBaseSize, uint32_t aArrayLen) {
713 // We can allocate both this nsCSSShadowArray and the
714 // actual array in one allocation. The amount of memory to
715 // allocate is equal to the class's size + the number of bytes for all
716 // but the first array item (because aBaseSize includes one
717 // item, see the private declarations)
718 return ::operator new(aBaseSize +
719 (aArrayLen - 1) * sizeof(nsCSSShadowItem));
720 }
722 nsCSSShadowArray(uint32_t aArrayLen) :
723 mLength(aArrayLen)
724 {
725 MOZ_COUNT_CTOR(nsCSSShadowArray);
726 for (uint32_t i = 1; i < mLength; ++i) {
727 // Make sure we call the constructors of each nsCSSShadowItem
728 // (the first one is called for us because we declared it under private)
729 new (&mArray[i]) nsCSSShadowItem();
730 }
731 }
733 private:
734 // Private destructor, to discourage deletion outside of Release():
735 ~nsCSSShadowArray() {
736 MOZ_COUNT_DTOR(nsCSSShadowArray);
737 for (uint32_t i = 1; i < mLength; ++i) {
738 mArray[i].~nsCSSShadowItem();
739 }
740 }
742 public:
743 uint32_t Length() const { return mLength; }
744 nsCSSShadowItem* ShadowAt(uint32_t i) {
745 NS_ABORT_IF_FALSE(i < mLength, "Accessing too high an index in the text shadow array!");
746 return &mArray[i];
747 }
748 const nsCSSShadowItem* ShadowAt(uint32_t i) const {
749 NS_ABORT_IF_FALSE(i < mLength, "Accessing too high an index in the text shadow array!");
750 return &mArray[i];
751 }
753 bool HasShadowWithInset(bool aInset) {
754 for (uint32_t i = 0; i < mLength; ++i) {
755 if (mArray[i].mInset == aInset)
756 return true;
757 }
758 return false;
759 }
761 bool operator==(const nsCSSShadowArray& aOther) const {
762 if (mLength != aOther.Length())
763 return false;
765 for (uint32_t i = 0; i < mLength; ++i) {
766 if (ShadowAt(i) != aOther.ShadowAt(i))
767 return false;
768 }
770 return true;
771 }
773 NS_INLINE_DECL_REFCOUNTING(nsCSSShadowArray)
775 private:
776 uint32_t mLength;
777 nsCSSShadowItem mArray[1]; // This MUST be the last item
778 };
780 // Border widths are rounded to the nearest-below integer number of pixels,
781 // but values between zero and one device pixels are always rounded up to
782 // one device pixel.
783 #define NS_ROUND_BORDER_TO_PIXELS(l,tpp) \
784 ((l) == 0) ? 0 : std::max((tpp), (l) / (tpp) * (tpp))
785 // Outline offset is rounded to the nearest integer number of pixels, but values
786 // between zero and one device pixels are always rounded up to one device pixel.
787 // Note that the offset can be negative.
788 #define NS_ROUND_OFFSET_TO_PIXELS(l,tpp) \
789 (((l) == 0) ? 0 : \
790 ((l) > 0) ? std::max( (tpp), ((l) + ((tpp) / 2)) / (tpp) * (tpp)) : \
791 std::min(-(tpp), ((l) - ((tpp) / 2)) / (tpp) * (tpp)))
793 // Returns if the given border style type is visible or not
794 static bool IsVisibleBorderStyle(uint8_t aStyle)
795 {
796 return (aStyle != NS_STYLE_BORDER_STYLE_NONE &&
797 aStyle != NS_STYLE_BORDER_STYLE_HIDDEN);
798 }
800 struct nsStyleBorder {
801 nsStyleBorder(nsPresContext* aContext);
802 nsStyleBorder(const nsStyleBorder& aBorder);
803 ~nsStyleBorder();
805 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW;
806 void Destroy(nsPresContext* aContext);
808 nsChangeHint CalcDifference(const nsStyleBorder& aOther) const;
809 static nsChangeHint MaxDifference() {
810 return NS_CombineHint(NS_STYLE_HINT_REFLOW,
811 nsChangeHint_BorderStyleNoneChange);
812 }
813 static nsChangeHint MaxDifferenceNeverInherited() {
814 // CalcDifference never returns nsChangeHint_NeedReflow or
815 // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
816 return NS_CombineHint(nsChangeHint_NeedReflow,
817 nsChangeHint_ClearAncestorIntrinsics);
818 }
820 void EnsureBorderColors() {
821 if (!mBorderColors) {
822 mBorderColors = new nsBorderColors*[4];
823 if (mBorderColors)
824 for (int32_t i = 0; i < 4; i++)
825 mBorderColors[i] = nullptr;
826 }
827 }
829 void ClearBorderColors(mozilla::css::Side aSide) {
830 if (mBorderColors && mBorderColors[aSide]) {
831 delete mBorderColors[aSide];
832 mBorderColors[aSide] = nullptr;
833 }
834 }
836 // Return whether aStyle is a visible style. Invisible styles cause
837 // the relevant computed border width to be 0.
838 // Note that this does *not* consider the effects of 'border-image':
839 // if border-style is none, but there is a loaded border image,
840 // HasVisibleStyle will be false even though there *is* a border.
841 bool HasVisibleStyle(mozilla::css::Side aSide) const
842 {
843 return IsVisibleBorderStyle(GetBorderStyle(aSide));
844 }
846 // aBorderWidth is in twips
847 void SetBorderWidth(mozilla::css::Side aSide, nscoord aBorderWidth)
848 {
849 nscoord roundedWidth =
850 NS_ROUND_BORDER_TO_PIXELS(aBorderWidth, mTwipsPerPixel);
851 mBorder.Side(aSide) = roundedWidth;
852 if (HasVisibleStyle(aSide))
853 mComputedBorder.Side(aSide) = roundedWidth;
854 }
856 // Get the computed border (plus rounding). This does consider the
857 // effects of 'border-style: none', but does not consider
858 // 'border-image'.
859 const nsMargin& GetComputedBorder() const
860 {
861 return mComputedBorder;
862 }
864 bool HasBorder() const
865 {
866 return mComputedBorder != nsMargin(0,0,0,0) || !mBorderImageSource.IsEmpty();
867 }
869 // Get the actual border width for a particular side, in appunits. Note that
870 // this is zero if and only if there is no border to be painted for this
871 // side. That is, this value takes into account the border style and the
872 // value is rounded to the nearest device pixel by NS_ROUND_BORDER_TO_PIXELS.
873 nscoord GetComputedBorderWidth(mozilla::css::Side aSide) const
874 {
875 return GetComputedBorder().Side(aSide);
876 }
878 uint8_t GetBorderStyle(mozilla::css::Side aSide) const
879 {
880 NS_ASSERTION(aSide <= NS_SIDE_LEFT, "bad side");
881 return (mBorderStyle[aSide] & BORDER_STYLE_MASK);
882 }
884 void SetBorderStyle(mozilla::css::Side aSide, uint8_t aStyle)
885 {
886 NS_ASSERTION(aSide <= NS_SIDE_LEFT, "bad side");
887 mBorderStyle[aSide] &= ~BORDER_STYLE_MASK;
888 mBorderStyle[aSide] |= (aStyle & BORDER_STYLE_MASK);
889 mComputedBorder.Side(aSide) =
890 (HasVisibleStyle(aSide) ? mBorder.Side(aSide) : 0);
891 }
893 inline bool IsBorderImageLoaded() const
894 {
895 return mBorderImageSource.IsLoaded();
896 }
898 // Defined in nsStyleStructInlines.h
899 inline nsresult RequestDecode();
901 void GetBorderColor(mozilla::css::Side aSide, nscolor& aColor,
902 bool& aForeground) const
903 {
904 aForeground = false;
905 NS_ASSERTION(aSide <= NS_SIDE_LEFT, "bad side");
906 if ((mBorderStyle[aSide] & BORDER_COLOR_SPECIAL) == 0)
907 aColor = mBorderColor[aSide];
908 else if (mBorderStyle[aSide] & BORDER_COLOR_FOREGROUND)
909 aForeground = true;
910 else
911 NS_NOTREACHED("OUTLINE_COLOR_INITIAL should not be set here");
912 }
914 void SetBorderColor(mozilla::css::Side aSide, nscolor aColor)
915 {
916 NS_ASSERTION(aSide <= NS_SIDE_LEFT, "bad side");
917 mBorderColor[aSide] = aColor;
918 mBorderStyle[aSide] &= ~BORDER_COLOR_SPECIAL;
919 }
921 void TrackImage(nsPresContext* aContext)
922 {
923 if (mBorderImageSource.GetType() == eStyleImageType_Image) {
924 mBorderImageSource.TrackImage(aContext);
925 }
926 }
927 void UntrackImage(nsPresContext* aContext)
928 {
929 if (mBorderImageSource.GetType() == eStyleImageType_Image) {
930 mBorderImageSource.UntrackImage(aContext);
931 }
932 }
934 nsMargin GetImageOutset() const;
936 void GetCompositeColors(int32_t aIndex, nsBorderColors** aColors) const
937 {
938 if (!mBorderColors)
939 *aColors = nullptr;
940 else
941 *aColors = mBorderColors[aIndex];
942 }
944 void AppendBorderColor(int32_t aIndex, nscolor aColor)
945 {
946 NS_ASSERTION(aIndex >= 0 && aIndex <= 3, "bad side for composite border color");
947 nsBorderColors* colorEntry = new nsBorderColors(aColor);
948 if (!mBorderColors[aIndex])
949 mBorderColors[aIndex] = colorEntry;
950 else {
951 nsBorderColors* last = mBorderColors[aIndex];
952 while (last->mNext)
953 last = last->mNext;
954 last->mNext = colorEntry;
955 }
956 mBorderStyle[aIndex] &= ~BORDER_COLOR_SPECIAL;
957 }
959 void SetBorderToForeground(mozilla::css::Side aSide)
960 {
961 NS_ASSERTION(aSide <= NS_SIDE_LEFT, "bad side");
962 mBorderStyle[aSide] &= ~BORDER_COLOR_SPECIAL;
963 mBorderStyle[aSide] |= BORDER_COLOR_FOREGROUND;
964 }
966 imgIRequest* GetBorderImageRequest() const
967 {
968 if (mBorderImageSource.GetType() == eStyleImageType_Image) {
969 return mBorderImageSource.GetImageData();
970 }
971 return nullptr;
972 }
974 public:
975 nsBorderColors** mBorderColors; // [reset] composite (stripe) colors
976 nsRefPtr<nsCSSShadowArray> mBoxShadow; // [reset] nullptr for 'none'
978 public:
979 nsStyleCorners mBorderRadius; // [reset] coord, percent
980 nsStyleImage mBorderImageSource; // [reset]
981 nsStyleSides mBorderImageSlice; // [reset] factor, percent
982 nsStyleSides mBorderImageWidth; // [reset] length, factor, percent, auto
983 nsStyleSides mBorderImageOutset; // [reset] length, factor
985 uint8_t mBorderImageFill; // [reset]
986 uint8_t mBorderImageRepeatH; // [reset] see nsStyleConsts.h
987 uint8_t mBorderImageRepeatV; // [reset]
988 uint8_t mFloatEdge; // [reset]
990 protected:
991 // mComputedBorder holds the CSS2.1 computed border-width values.
992 // In particular, these widths take into account the border-style
993 // for the relevant side, and the values are rounded to the nearest
994 // device pixel (which is not part of the definition of computed
995 // values). The presence or absence of a border-image does not
996 // affect border-width values.
997 nsMargin mComputedBorder;
999 // mBorder holds the nscoord values for the border widths as they
1000 // would be if all the border-style values were visible (not hidden
1001 // or none). This member exists so that when we create structs
1002 // using the copy constructor during style resolution the new
1003 // structs will know what the specified values of the border were in
1004 // case they have more specific rules setting the border style.
1005 //
1006 // Note that this isn't quite the CSS specified value, since this
1007 // has had the enumerated border widths converted to lengths, and
1008 // all lengths converted to twips. But it's not quite the computed
1009 // value either. The values are rounded to the nearest device pixel.
1010 nsMargin mBorder;
1012 uint8_t mBorderStyle[4]; // [reset] See nsStyleConsts.h
1013 nscolor mBorderColor[4]; // [reset] the colors to use for a simple
1014 // border. not used for -moz-border-colors
1015 private:
1016 nscoord mTwipsPerPixel;
1018 nsStyleBorder& operator=(const nsStyleBorder& aOther) MOZ_DELETE;
1019 };
1022 struct nsStyleOutline {
1023 nsStyleOutline(nsPresContext* aPresContext);
1024 nsStyleOutline(const nsStyleOutline& aOutline);
1025 ~nsStyleOutline(void) {
1026 MOZ_COUNT_DTOR(nsStyleOutline);
1027 }
1029 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
1030 return aContext->AllocateFromShell(sz);
1031 }
1032 void Destroy(nsPresContext* aContext) {
1033 this->~nsStyleOutline();
1034 aContext->FreeToShell(sizeof(nsStyleOutline), this);
1035 }
1037 void RecalcData(nsPresContext* aContext);
1038 nsChangeHint CalcDifference(const nsStyleOutline& aOther) const;
1039 static nsChangeHint MaxDifference() {
1040 return NS_CombineHint(nsChangeHint_AllReflowHints,
1041 nsChangeHint_RepaintFrame);
1042 }
1043 static nsChangeHint MaxDifferenceNeverInherited() {
1044 // CalcDifference never returns nsChangeHint_NeedReflow or
1045 // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
1046 return NS_CombineHint(nsChangeHint_NeedReflow,
1047 nsChangeHint_ClearAncestorIntrinsics);
1048 }
1050 nsStyleCorners mOutlineRadius; // [reset] coord, percent, calc
1052 // Note that this is a specified value. You can get the actual values
1053 // with GetOutlineWidth. You cannot get the computed value directly.
1054 nsStyleCoord mOutlineWidth; // [reset] coord, enum (see nsStyleConsts.h)
1055 nscoord mOutlineOffset; // [reset]
1057 bool GetOutlineWidth(nscoord& aWidth) const
1058 {
1059 if (mHasCachedOutline) {
1060 aWidth = mCachedOutlineWidth;
1061 return true;
1062 }
1063 return false;
1064 }
1066 uint8_t GetOutlineStyle(void) const
1067 {
1068 return (mOutlineStyle & BORDER_STYLE_MASK);
1069 }
1071 void SetOutlineStyle(uint8_t aStyle)
1072 {
1073 mOutlineStyle &= ~BORDER_STYLE_MASK;
1074 mOutlineStyle |= (aStyle & BORDER_STYLE_MASK);
1075 }
1077 // false means initial value
1078 bool GetOutlineColor(nscolor& aColor) const
1079 {
1080 if ((mOutlineStyle & BORDER_COLOR_SPECIAL) == 0) {
1081 aColor = mOutlineColor;
1082 return true;
1083 }
1084 return false;
1085 }
1087 void SetOutlineColor(nscolor aColor)
1088 {
1089 mOutlineColor = aColor;
1090 mOutlineStyle &= ~BORDER_COLOR_SPECIAL;
1091 }
1093 void SetOutlineInitialColor()
1094 {
1095 mOutlineStyle |= OUTLINE_COLOR_INITIAL;
1096 }
1098 bool GetOutlineInitialColor() const
1099 {
1100 return !!(mOutlineStyle & OUTLINE_COLOR_INITIAL);
1101 }
1103 protected:
1104 // This value is the actual value, so it's rounded to the nearest device
1105 // pixel.
1106 nscoord mCachedOutlineWidth;
1108 nscolor mOutlineColor; // [reset]
1110 bool mHasCachedOutline;
1111 uint8_t mOutlineStyle; // [reset] See nsStyleConsts.h
1113 nscoord mTwipsPerPixel;
1114 };
1117 struct nsStyleList {
1118 nsStyleList(void);
1119 nsStyleList(const nsStyleList& aStyleList);
1120 ~nsStyleList(void);
1122 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
1123 return aContext->AllocateFromShell(sz);
1124 }
1125 void Destroy(nsPresContext* aContext) {
1126 this->~nsStyleList();
1127 aContext->FreeToShell(sizeof(nsStyleList), this);
1128 }
1130 nsChangeHint CalcDifference(const nsStyleList& aOther) const;
1131 static nsChangeHint MaxDifference() {
1132 return NS_STYLE_HINT_FRAMECHANGE;
1133 }
1134 static nsChangeHint MaxDifferenceNeverInherited() {
1135 // CalcDifference never returns nsChangeHint_NeedReflow or
1136 // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
1137 return NS_CombineHint(nsChangeHint_NeedReflow,
1138 nsChangeHint_ClearAncestorIntrinsics);
1139 }
1141 imgRequestProxy* GetListStyleImage() const { return mListStyleImage; }
1142 void SetListStyleImage(imgRequestProxy* aReq)
1143 {
1144 if (mListStyleImage)
1145 mListStyleImage->UnlockImage();
1146 mListStyleImage = aReq;
1147 if (mListStyleImage)
1148 mListStyleImage->LockImage();
1149 }
1151 uint8_t mListStyleType; // [inherited] See nsStyleConsts.h
1152 uint8_t mListStylePosition; // [inherited]
1153 private:
1154 nsRefPtr<imgRequestProxy> mListStyleImage; // [inherited]
1155 nsStyleList& operator=(const nsStyleList& aOther) MOZ_DELETE;
1156 public:
1157 nsRect mImageRegion; // [inherited] the rect to use within an image
1158 };
1160 // Computed value of the grid-template-columns or grid-columns-rows property
1161 // (but *not* grid-template-areas.)
1162 // http://dev.w3.org/csswg/css-grid/#track-sizing
1163 //
1164 // This represents either:
1165 // * none:
1166 // mIsSubgrid is false, all three arrays are empty
1167 // * <track-list>:
1168 // mIsSubgrid is false,
1169 // mMinTrackSizingFunctions and mMaxTrackSizingFunctions
1170 // are of identical non-zero size,
1171 // and mLineNameLists is one element longer than that.
1172 // (Delimiting N columns requires N+1 lines:
1173 // one before each track, plus one at the very end.)
1174 //
1175 // An omitted <line-names> is still represented in mLineNameLists,
1176 // as an empty sub-array.
1177 //
1178 // A <track-size> specified as a single <track-breadth> is represented
1179 // as identical min and max sizing functions.
1180 //
1181 // The units for nsStyleCoord are:
1182 // * eStyleUnit_Percent represents a <percentage>
1183 // * eStyleUnit_FlexFraction represents a <flex> flexible fraction
1184 // * eStyleUnit_Coord represents a <length>
1185 // * eStyleUnit_Enumerated represents min-content or max-content
1186 // * subgrid <line-name-list>?:
1187 // mIsSubgrid is true,
1188 // mLineNameLists may or may not be empty,
1189 // mMinTrackSizingFunctions and mMaxTrackSizingFunctions are empty.
1190 struct nsStyleGridTemplate {
1191 bool mIsSubgrid;
1192 nsTArray<nsTArray<nsString>> mLineNameLists;
1193 nsTArray<nsStyleCoord> mMinTrackSizingFunctions;
1194 nsTArray<nsStyleCoord> mMaxTrackSizingFunctions;
1196 nsStyleGridTemplate()
1197 : mIsSubgrid(false)
1198 {
1199 }
1201 inline bool operator!=(const nsStyleGridTemplate& aOther) const {
1202 return mLineNameLists != aOther.mLineNameLists ||
1203 mMinTrackSizingFunctions != aOther.mMinTrackSizingFunctions ||
1204 mMaxTrackSizingFunctions != aOther.mMaxTrackSizingFunctions;
1205 }
1206 };
1208 struct nsStyleGridLine {
1209 // http://dev.w3.org/csswg/css-grid/#typedef-grid-line
1210 bool mHasSpan;
1211 int32_t mInteger; // 0 means not provided
1212 nsString mLineName; // Empty string means not provided.
1214 nsStyleGridLine()
1215 : mHasSpan(false)
1216 , mInteger(0)
1217 // mLineName get its default constructor, the empty string
1218 {
1219 }
1221 nsStyleGridLine(const nsStyleGridLine& aOther)
1222 {
1223 (*this) = aOther;
1224 }
1226 void operator=(const nsStyleGridLine& aOther)
1227 {
1228 mHasSpan = aOther.mHasSpan;
1229 mInteger = aOther.mInteger;
1230 mLineName = aOther.mLineName;
1231 }
1233 bool operator!=(const nsStyleGridLine& aOther) const
1234 {
1235 return mHasSpan != aOther.mHasSpan ||
1236 mInteger != aOther.mInteger ||
1237 mLineName != aOther.mLineName;
1238 }
1240 void SetToInteger(uint32_t value)
1241 {
1242 mHasSpan = false;
1243 mInteger = value;
1244 mLineName.Truncate();
1245 }
1247 void SetAuto()
1248 {
1249 mHasSpan = false;
1250 mInteger = 0;
1251 mLineName.Truncate();
1252 }
1254 bool IsAuto() const
1255 {
1256 bool haveInitialValues = mInteger == 0 && mLineName.IsEmpty();
1257 MOZ_ASSERT(!(haveInitialValues && mHasSpan),
1258 "should not have 'span' when other components are "
1259 "at their initial values");
1260 return haveInitialValues;
1261 }
1262 };
1264 struct nsStylePosition {
1265 nsStylePosition(void);
1266 nsStylePosition(const nsStylePosition& aOther);
1267 ~nsStylePosition(void);
1269 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
1270 return aContext->AllocateFromShell(sz);
1271 }
1272 void Destroy(nsPresContext* aContext) {
1273 this->~nsStylePosition();
1274 aContext->FreeToShell(sizeof(nsStylePosition), this);
1275 }
1277 nsChangeHint CalcDifference(const nsStylePosition& aOther) const;
1278 static nsChangeHint MaxDifference() {
1279 return NS_CombineHint(NS_STYLE_HINT_REFLOW,
1280 nsChangeHint(nsChangeHint_RecomputePosition |
1281 nsChangeHint_UpdateOverflow));
1282 }
1283 static nsChangeHint MaxDifferenceNeverInherited() {
1284 // CalcDifference can return both nsChangeHint_ClearAncestorIntrinsics and
1285 // nsChangeHint_NeedReflow as inherited hints.
1286 return nsChangeHint(0);
1287 }
1289 nsStyleSides mOffset; // [reset] coord, percent, calc, auto
1290 nsStyleCoord mWidth; // [reset] coord, percent, enum, calc, auto
1291 nsStyleCoord mMinWidth; // [reset] coord, percent, enum, calc
1292 nsStyleCoord mMaxWidth; // [reset] coord, percent, enum, calc, none
1293 nsStyleCoord mHeight; // [reset] coord, percent, calc, auto
1294 nsStyleCoord mMinHeight; // [reset] coord, percent, calc
1295 nsStyleCoord mMaxHeight; // [reset] coord, percent, calc, none
1296 nsStyleCoord mFlexBasis; // [reset] coord, percent, enum, calc, auto
1297 nsStyleCoord mGridAutoColumnsMin; // [reset] coord, percent, enum, calc, flex
1298 nsStyleCoord mGridAutoColumnsMax; // [reset] coord, percent, enum, calc, flex
1299 nsStyleCoord mGridAutoRowsMin; // [reset] coord, percent, enum, calc, flex
1300 nsStyleCoord mGridAutoRowsMax; // [reset] coord, percent, enum, calc, flex
1301 uint8_t mGridAutoFlow; // [reset] enumerated. See nsStyleConsts.h
1302 uint8_t mBoxSizing; // [reset] see nsStyleConsts.h
1303 uint8_t mAlignContent; // [reset] see nsStyleConsts.h
1304 uint8_t mAlignItems; // [reset] see nsStyleConsts.h
1305 uint8_t mAlignSelf; // [reset] see nsStyleConsts.h
1306 uint8_t mFlexDirection; // [reset] see nsStyleConsts.h
1307 uint8_t mFlexWrap; // [reset] see nsStyleConsts.h
1308 uint8_t mJustifyContent; // [reset] see nsStyleConsts.h
1309 int32_t mOrder; // [reset] integer
1310 float mFlexGrow; // [reset] float
1311 float mFlexShrink; // [reset] float
1312 nsStyleCoord mZIndex; // [reset] integer, auto
1313 // NOTE: Fields so far can be memcpy()'ed, while following fields
1314 // need to have their copy constructor called when we're being copied.
1315 // See nsStylePosition::nsStylePosition(const nsStylePosition& aSource)
1316 // in nsStyleStruct.cpp
1317 nsStyleGridTemplate mGridTemplateColumns;
1318 nsStyleGridTemplate mGridTemplateRows;
1320 // nullptr for 'none'
1321 nsRefPtr<mozilla::css::GridTemplateAreasValue> mGridTemplateAreas;
1323 // We represent the "grid-auto-position" property in two parts:
1324 nsStyleGridLine mGridAutoPositionColumn;
1325 nsStyleGridLine mGridAutoPositionRow;
1327 nsStyleGridLine mGridColumnStart;
1328 nsStyleGridLine mGridColumnEnd;
1329 nsStyleGridLine mGridRowStart;
1330 nsStyleGridLine mGridRowEnd;
1332 bool WidthDependsOnContainer() const
1333 { return WidthCoordDependsOnContainer(mWidth); }
1334 bool MinWidthDependsOnContainer() const
1335 { return WidthCoordDependsOnContainer(mMinWidth); }
1336 bool MaxWidthDependsOnContainer() const
1337 { return WidthCoordDependsOnContainer(mMaxWidth); }
1339 // Note that these functions count 'auto' as depending on the
1340 // container since that's the case for absolutely positioned elements.
1341 // However, some callers do not care about this case and should check
1342 // for it, since it is the most common case.
1343 // FIXME: We should probably change the assumption to be the other way
1344 // around.
1345 bool HeightDependsOnContainer() const
1346 { return HeightCoordDependsOnContainer(mHeight); }
1347 bool MinHeightDependsOnContainer() const
1348 { return HeightCoordDependsOnContainer(mMinHeight); }
1349 bool MaxHeightDependsOnContainer() const
1350 { return HeightCoordDependsOnContainer(mMaxHeight); }
1352 bool OffsetHasPercent(mozilla::css::Side aSide) const
1353 {
1354 return mOffset.Get(aSide).HasPercent();
1355 }
1357 private:
1358 static bool WidthCoordDependsOnContainer(const nsStyleCoord &aCoord);
1359 static bool HeightCoordDependsOnContainer(const nsStyleCoord &aCoord)
1360 {
1361 return aCoord.GetUnit() == eStyleUnit_Auto || // CSS 2.1, 10.6.4, item (5)
1362 aCoord.HasPercent();
1363 }
1364 };
1366 struct nsStyleTextOverflowSide {
1367 nsStyleTextOverflowSide() : mType(NS_STYLE_TEXT_OVERFLOW_CLIP) {}
1369 bool operator==(const nsStyleTextOverflowSide& aOther) const {
1370 return mType == aOther.mType &&
1371 (mType != NS_STYLE_TEXT_OVERFLOW_STRING ||
1372 mString == aOther.mString);
1373 }
1374 bool operator!=(const nsStyleTextOverflowSide& aOther) const {
1375 return !(*this == aOther);
1376 }
1378 nsString mString;
1379 uint8_t mType;
1380 };
1382 struct nsStyleTextOverflow {
1383 nsStyleTextOverflow() : mLogicalDirections(true) {}
1384 bool operator==(const nsStyleTextOverflow& aOther) const {
1385 return mLeft == aOther.mLeft && mRight == aOther.mRight;
1386 }
1387 bool operator!=(const nsStyleTextOverflow& aOther) const {
1388 return !(*this == aOther);
1389 }
1391 // Returns the value to apply on the left side.
1392 const nsStyleTextOverflowSide& GetLeft(uint8_t aDirection) const {
1393 NS_ASSERTION(aDirection == NS_STYLE_DIRECTION_LTR ||
1394 aDirection == NS_STYLE_DIRECTION_RTL, "bad direction");
1395 return !mLogicalDirections || aDirection == NS_STYLE_DIRECTION_LTR ?
1396 mLeft : mRight;
1397 }
1399 // Returns the value to apply on the right side.
1400 const nsStyleTextOverflowSide& GetRight(uint8_t aDirection) const {
1401 NS_ASSERTION(aDirection == NS_STYLE_DIRECTION_LTR ||
1402 aDirection == NS_STYLE_DIRECTION_RTL, "bad direction");
1403 return !mLogicalDirections || aDirection == NS_STYLE_DIRECTION_LTR ?
1404 mRight : mLeft;
1405 }
1407 // Returns the first value that was specified.
1408 const nsStyleTextOverflowSide* GetFirstValue() const {
1409 return mLogicalDirections ? &mRight : &mLeft;
1410 }
1412 // Returns the second value, or null if there was only one value specified.
1413 const nsStyleTextOverflowSide* GetSecondValue() const {
1414 return mLogicalDirections ? nullptr : &mRight;
1415 }
1417 nsStyleTextOverflowSide mLeft; // start side when mLogicalDirections is true
1418 nsStyleTextOverflowSide mRight; // end side when mLogicalDirections is true
1419 bool mLogicalDirections; // true when only one value was specified
1420 };
1422 struct nsStyleTextReset {
1423 nsStyleTextReset(void);
1424 nsStyleTextReset(const nsStyleTextReset& aOther);
1425 ~nsStyleTextReset(void);
1427 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
1428 return aContext->AllocateFromShell(sz);
1429 }
1430 void Destroy(nsPresContext* aContext) {
1431 this->~nsStyleTextReset();
1432 aContext->FreeToShell(sizeof(nsStyleTextReset), this);
1433 }
1435 uint8_t GetDecorationStyle() const
1436 {
1437 return (mTextDecorationStyle & BORDER_STYLE_MASK);
1438 }
1440 void SetDecorationStyle(uint8_t aStyle)
1441 {
1442 NS_ABORT_IF_FALSE((aStyle & BORDER_STYLE_MASK) == aStyle,
1443 "style doesn't fit");
1444 mTextDecorationStyle &= ~BORDER_STYLE_MASK;
1445 mTextDecorationStyle |= (aStyle & BORDER_STYLE_MASK);
1446 }
1448 void GetDecorationColor(nscolor& aColor, bool& aForeground) const
1449 {
1450 aForeground = false;
1451 if ((mTextDecorationStyle & BORDER_COLOR_SPECIAL) == 0) {
1452 aColor = mTextDecorationColor;
1453 } else if (mTextDecorationStyle & BORDER_COLOR_FOREGROUND) {
1454 aForeground = true;
1455 } else {
1456 NS_NOTREACHED("OUTLINE_COLOR_INITIAL should not be set here");
1457 }
1458 }
1460 void SetDecorationColor(nscolor aColor)
1461 {
1462 mTextDecorationColor = aColor;
1463 mTextDecorationStyle &= ~BORDER_COLOR_SPECIAL;
1464 }
1466 void SetDecorationColorToForeground()
1467 {
1468 mTextDecorationStyle &= ~BORDER_COLOR_SPECIAL;
1469 mTextDecorationStyle |= BORDER_COLOR_FOREGROUND;
1470 }
1472 nsChangeHint CalcDifference(const nsStyleTextReset& aOther) const;
1473 static nsChangeHint MaxDifference() {
1474 return NS_STYLE_HINT_REFLOW;
1475 }
1476 static nsChangeHint MaxDifferenceNeverInherited() {
1477 // CalcDifference never returns nsChangeHint_NeedReflow or
1478 // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
1479 return NS_CombineHint(nsChangeHint_NeedReflow,
1480 nsChangeHint_ClearAncestorIntrinsics);
1481 }
1483 nsStyleCoord mVerticalAlign; // [reset] coord, percent, calc, enum (see nsStyleConsts.h)
1484 nsStyleTextOverflow mTextOverflow; // [reset] enum, string
1486 uint8_t mTextDecorationLine; // [reset] see nsStyleConsts.h
1487 uint8_t mUnicodeBidi; // [reset] see nsStyleConsts.h
1488 protected:
1489 uint8_t mTextDecorationStyle; // [reset] see nsStyleConsts.h
1491 nscolor mTextDecorationColor; // [reset] the colors to use for a decoration lines, not used at currentColor
1492 };
1494 struct nsStyleText {
1495 nsStyleText(void);
1496 nsStyleText(const nsStyleText& aOther);
1497 ~nsStyleText(void);
1499 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
1500 return aContext->AllocateFromShell(sz);
1501 }
1502 void Destroy(nsPresContext* aContext) {
1503 this->~nsStyleText();
1504 aContext->FreeToShell(sizeof(nsStyleText), this);
1505 }
1507 nsChangeHint CalcDifference(const nsStyleText& aOther) const;
1508 static nsChangeHint MaxDifference() {
1509 return NS_STYLE_HINT_FRAMECHANGE;
1510 }
1511 static nsChangeHint MaxDifferenceNeverInherited() {
1512 // CalcDifference never returns nsChangeHint_NeedReflow or
1513 // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
1514 return NS_CombineHint(nsChangeHint_NeedReflow,
1515 nsChangeHint_ClearAncestorIntrinsics);
1516 }
1518 uint8_t mTextAlign; // [inherited] see nsStyleConsts.h
1519 uint8_t mTextAlignLast; // [inherited] see nsStyleConsts.h
1520 bool mTextAlignTrue : 1; // [inherited] see nsStyleConsts.h
1521 bool mTextAlignLastTrue : 1; // [inherited] see nsStyleConsts.h
1522 uint8_t mTextTransform; // [inherited] see nsStyleConsts.h
1523 uint8_t mWhiteSpace; // [inherited] see nsStyleConsts.h
1524 uint8_t mWordBreak; // [inherited] see nsStyleConsts.h
1525 uint8_t mWordWrap; // [inherited] see nsStyleConsts.h
1526 uint8_t mHyphens; // [inherited] see nsStyleConsts.h
1527 uint8_t mTextSizeAdjust; // [inherited] see nsStyleConsts.h
1528 uint8_t mTextOrientation; // [inherited] see nsStyleConsts.h
1529 uint8_t mTextCombineUpright; // [inherited] see nsStyleConsts.h
1530 uint8_t mControlCharacterVisibility; // [inherited] see nsStyleConsts.h
1531 int32_t mTabSize; // [inherited] see nsStyleConsts.h
1533 nscoord mWordSpacing; // [inherited]
1534 nsStyleCoord mLetterSpacing; // [inherited] coord, normal
1535 nsStyleCoord mLineHeight; // [inherited] coord, factor, normal
1536 nsStyleCoord mTextIndent; // [inherited] coord, percent, calc
1538 nsRefPtr<nsCSSShadowArray> mTextShadow; // [inherited] nullptr in case of a zero-length
1540 bool WhiteSpaceIsSignificant() const {
1541 return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
1542 mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
1543 mWhiteSpace == NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES;
1544 }
1546 bool NewlineIsSignificant() const {
1547 return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
1548 mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
1549 mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE;
1550 }
1552 bool NewlineIsDiscarded() const {
1553 return mWhiteSpace == NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES;
1554 }
1556 bool WhiteSpaceOrNewlineIsSignificant() const {
1557 return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
1558 mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
1559 mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE ||
1560 mWhiteSpace == NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES;
1561 }
1563 bool WhiteSpaceCanWrapStyle() const {
1564 return mWhiteSpace == NS_STYLE_WHITESPACE_NORMAL ||
1565 mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
1566 mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE;
1567 }
1569 bool WordCanWrapStyle() const {
1570 return WhiteSpaceCanWrapStyle() &&
1571 mWordWrap == NS_STYLE_WORDWRAP_BREAK_WORD;
1572 }
1574 // These are defined in nsStyleStructInlines.h.
1575 inline bool HasTextShadow() const;
1576 inline nsCSSShadowArray* GetTextShadow() const;
1578 // The aContextFrame argument on each of these is the frame this
1579 // style struct is for. If the frame is for SVG text, the return
1580 // value will be massaged to be something that makes sense for
1581 // SVG text.
1582 inline bool WhiteSpaceCanWrap(const nsIFrame* aContextFrame) const;
1583 inline bool WordCanWrap(const nsIFrame* aContextFrame) const;
1584 };
1586 struct nsStyleImageOrientation {
1587 static nsStyleImageOrientation CreateAsAngleAndFlip(double aRadians,
1588 bool aFlip) {
1589 uint8_t orientation(0);
1591 // Compute the final angle value, rounding to the closest quarter turn.
1592 double roundedAngle = fmod(aRadians, 2 * M_PI);
1593 if (roundedAngle < 0.25 * M_PI) orientation = ANGLE_0;
1594 else if (roundedAngle < 0.75 * M_PI) orientation = ANGLE_90;
1595 else if (roundedAngle < 1.25 * M_PI) orientation = ANGLE_180;
1596 else if (roundedAngle < 1.75 * M_PI) orientation = ANGLE_270;
1597 else orientation = ANGLE_0;
1599 // Add a bit for 'flip' if needed.
1600 if (aFlip)
1601 orientation |= FLIP_MASK;
1603 return nsStyleImageOrientation(orientation);
1604 }
1606 static nsStyleImageOrientation CreateAsFlip() {
1607 return nsStyleImageOrientation(FLIP_MASK);
1608 }
1610 static nsStyleImageOrientation CreateAsFromImage() {
1611 return nsStyleImageOrientation(FROM_IMAGE_MASK);
1612 }
1614 // The default constructor yields 0 degrees of rotation and no flip.
1615 nsStyleImageOrientation() : mOrientation(0) { }
1617 bool IsDefault() const { return mOrientation == 0; }
1618 bool IsFlipped() const { return mOrientation & FLIP_MASK; }
1619 bool IsFromImage() const { return mOrientation & FROM_IMAGE_MASK; }
1621 mozilla::image::Angle Angle() const {
1622 switch (mOrientation & ORIENTATION_MASK) {
1623 case ANGLE_0: return mozilla::image::Angle::D0;
1624 case ANGLE_90: return mozilla::image::Angle::D90;
1625 case ANGLE_180: return mozilla::image::Angle::D180;
1626 case ANGLE_270: return mozilla::image::Angle::D270;
1627 default:
1628 NS_NOTREACHED("Unexpected angle");
1629 return mozilla::image::Angle::D0;
1630 }
1631 }
1633 nsStyleCoord AngleAsCoord() const {
1634 switch (mOrientation & ORIENTATION_MASK) {
1635 case ANGLE_0: return nsStyleCoord(0.0f, eStyleUnit_Degree);
1636 case ANGLE_90: return nsStyleCoord(90.0f, eStyleUnit_Degree);
1637 case ANGLE_180: return nsStyleCoord(180.0f, eStyleUnit_Degree);
1638 case ANGLE_270: return nsStyleCoord(270.0f, eStyleUnit_Degree);
1639 default:
1640 NS_NOTREACHED("Unexpected angle");
1641 return nsStyleCoord();
1642 }
1643 }
1645 bool operator==(const nsStyleImageOrientation& aOther) const {
1646 return aOther.mOrientation == mOrientation;
1647 }
1649 bool operator!=(const nsStyleImageOrientation& aOther) const {
1650 return !(*this == aOther);
1651 }
1653 protected:
1654 enum Bits {
1655 ORIENTATION_MASK = 0x1 | 0x2, // The bottom two bits are the angle.
1656 FLIP_MASK = 0x4, // Whether the image should be flipped.
1657 FROM_IMAGE_MASK = 0x8, // Whether the image's inherent orientation
1658 }; // should be used.
1660 enum Angles {
1661 ANGLE_0 = 0,
1662 ANGLE_90 = 1,
1663 ANGLE_180 = 2,
1664 ANGLE_270 = 3,
1665 };
1667 explicit nsStyleImageOrientation(uint8_t aOrientation)
1668 : mOrientation(aOrientation)
1669 { }
1671 uint8_t mOrientation;
1672 };
1674 struct nsStyleVisibility {
1675 nsStyleVisibility(nsPresContext* aPresContext);
1676 nsStyleVisibility(const nsStyleVisibility& aVisibility);
1677 ~nsStyleVisibility() {
1678 MOZ_COUNT_DTOR(nsStyleVisibility);
1679 }
1681 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
1682 return aContext->AllocateFromShell(sz);
1683 }
1684 void Destroy(nsPresContext* aContext) {
1685 this->~nsStyleVisibility();
1686 aContext->FreeToShell(sizeof(nsStyleVisibility), this);
1687 }
1689 nsChangeHint CalcDifference(const nsStyleVisibility& aOther) const;
1690 static nsChangeHint MaxDifference() {
1691 return NS_STYLE_HINT_FRAMECHANGE;
1692 }
1693 static nsChangeHint MaxDifferenceNeverInherited() {
1694 // CalcDifference never returns nsChangeHint_NeedReflow or
1695 // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
1696 return NS_CombineHint(nsChangeHint_NeedReflow,
1697 nsChangeHint_ClearAncestorIntrinsics);
1698 }
1700 nsStyleImageOrientation mImageOrientation; // [inherited]
1701 uint8_t mDirection; // [inherited] see nsStyleConsts.h NS_STYLE_DIRECTION_*
1702 uint8_t mVisible; // [inherited]
1703 uint8_t mPointerEvents; // [inherited] see nsStyleConsts.h
1704 uint8_t mWritingMode; // [inherited] see nsStyleConsts.h
1706 bool IsVisible() const {
1707 return (mVisible == NS_STYLE_VISIBILITY_VISIBLE);
1708 }
1710 bool IsVisibleOrCollapsed() const {
1711 return ((mVisible == NS_STYLE_VISIBILITY_VISIBLE) ||
1712 (mVisible == NS_STYLE_VISIBILITY_COLLAPSE));
1713 }
1715 inline uint8_t GetEffectivePointerEvents(nsIFrame* aFrame) const;
1716 };
1718 struct nsTimingFunction {
1719 enum Type { Function, StepStart, StepEnd };
1721 explicit nsTimingFunction(int32_t aTimingFunctionType
1722 = NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE)
1723 {
1724 AssignFromKeyword(aTimingFunctionType);
1725 }
1727 nsTimingFunction(float x1, float y1, float x2, float y2)
1728 : mType(Function)
1729 {
1730 mFunc.mX1 = x1;
1731 mFunc.mY1 = y1;
1732 mFunc.mX2 = x2;
1733 mFunc.mY2 = y2;
1734 }
1736 nsTimingFunction(Type aType, uint32_t aSteps)
1737 : mType(aType)
1738 {
1739 NS_ABORT_IF_FALSE(mType == StepStart || mType == StepEnd, "wrong type");
1740 mSteps = aSteps;
1741 }
1743 nsTimingFunction(const nsTimingFunction& aOther)
1744 {
1745 *this = aOther;
1746 }
1748 Type mType;
1749 union {
1750 struct {
1751 float mX1;
1752 float mY1;
1753 float mX2;
1754 float mY2;
1755 } mFunc;
1756 uint32_t mSteps;
1757 };
1759 nsTimingFunction&
1760 operator=(const nsTimingFunction& aOther)
1761 {
1762 if (&aOther == this)
1763 return *this;
1765 mType = aOther.mType;
1767 if (mType == Function) {
1768 mFunc.mX1 = aOther.mFunc.mX1;
1769 mFunc.mY1 = aOther.mFunc.mY1;
1770 mFunc.mX2 = aOther.mFunc.mX2;
1771 mFunc.mY2 = aOther.mFunc.mY2;
1772 } else {
1773 mSteps = aOther.mSteps;
1774 }
1776 return *this;
1777 }
1779 bool operator==(const nsTimingFunction& aOther) const
1780 {
1781 if (mType != aOther.mType) {
1782 return false;
1783 }
1784 if (mType == Function) {
1785 return mFunc.mX1 == aOther.mFunc.mX1 && mFunc.mY1 == aOther.mFunc.mY1 &&
1786 mFunc.mX2 == aOther.mFunc.mX2 && mFunc.mY2 == aOther.mFunc.mY2;
1787 }
1788 return mSteps == aOther.mSteps;
1789 }
1791 bool operator!=(const nsTimingFunction& aOther) const
1792 {
1793 return !(*this == aOther);
1794 }
1796 private:
1797 void AssignFromKeyword(int32_t aTimingFunctionType);
1798 };
1800 struct nsTransition {
1801 nsTransition() { /* leaves uninitialized; see also SetInitialValues */ }
1802 explicit nsTransition(const nsTransition& aCopy);
1804 void SetInitialValues();
1806 // Delay and Duration are in milliseconds
1808 const nsTimingFunction& GetTimingFunction() const { return mTimingFunction; }
1809 float GetDelay() const { return mDelay; }
1810 float GetDuration() const { return mDuration; }
1811 nsCSSProperty GetProperty() const { return mProperty; }
1812 nsIAtom* GetUnknownProperty() const { return mUnknownProperty; }
1814 void SetTimingFunction(const nsTimingFunction& aTimingFunction)
1815 { mTimingFunction = aTimingFunction; }
1816 void SetDelay(float aDelay) { mDelay = aDelay; }
1817 void SetDuration(float aDuration) { mDuration = aDuration; }
1818 void SetProperty(nsCSSProperty aProperty)
1819 {
1820 NS_ASSERTION(aProperty != eCSSProperty_UNKNOWN, "invalid property");
1821 mProperty = aProperty;
1822 }
1823 void SetUnknownProperty(const nsAString& aUnknownProperty);
1824 void CopyPropertyFrom(const nsTransition& aOther)
1825 {
1826 mProperty = aOther.mProperty;
1827 mUnknownProperty = aOther.mUnknownProperty;
1828 }
1830 nsTimingFunction& TimingFunctionSlot() { return mTimingFunction; }
1832 private:
1833 nsTimingFunction mTimingFunction;
1834 float mDuration;
1835 float mDelay;
1836 nsCSSProperty mProperty;
1837 nsCOMPtr<nsIAtom> mUnknownProperty; // used when mProperty is
1838 // eCSSProperty_UNKNOWN
1839 };
1841 struct nsAnimation {
1842 nsAnimation() { /* leaves uninitialized; see also SetInitialValues */ }
1843 explicit nsAnimation(const nsAnimation& aCopy);
1845 void SetInitialValues();
1847 // Delay and Duration are in milliseconds
1849 const nsTimingFunction& GetTimingFunction() const { return mTimingFunction; }
1850 float GetDelay() const { return mDelay; }
1851 float GetDuration() const { return mDuration; }
1852 const nsString& GetName() const { return mName; }
1853 uint8_t GetDirection() const { return mDirection; }
1854 uint8_t GetFillMode() const { return mFillMode; }
1855 uint8_t GetPlayState() const { return mPlayState; }
1856 float GetIterationCount() const { return mIterationCount; }
1858 void SetTimingFunction(const nsTimingFunction& aTimingFunction)
1859 { mTimingFunction = aTimingFunction; }
1860 void SetDelay(float aDelay) { mDelay = aDelay; }
1861 void SetDuration(float aDuration) { mDuration = aDuration; }
1862 void SetName(const nsSubstring& aName) { mName = aName; }
1863 void SetDirection(uint8_t aDirection) { mDirection = aDirection; }
1864 void SetFillMode(uint8_t aFillMode) { mFillMode = aFillMode; }
1865 void SetPlayState(uint8_t aPlayState) { mPlayState = aPlayState; }
1866 void SetIterationCount(float aIterationCount)
1867 { mIterationCount = aIterationCount; }
1869 nsTimingFunction& TimingFunctionSlot() { return mTimingFunction; }
1871 private:
1872 nsTimingFunction mTimingFunction;
1873 float mDuration;
1874 float mDelay;
1875 nsString mName; // empty string for 'none'
1876 uint8_t mDirection;
1877 uint8_t mFillMode;
1878 uint8_t mPlayState;
1879 float mIterationCount; // NS_IEEEPositiveInfinity() means infinite
1880 };
1882 struct nsStyleDisplay {
1883 nsStyleDisplay();
1884 nsStyleDisplay(const nsStyleDisplay& aOther);
1885 ~nsStyleDisplay() {
1886 MOZ_COUNT_DTOR(nsStyleDisplay);
1887 }
1889 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
1890 return aContext->AllocateFromShell(sz);
1891 }
1892 void Destroy(nsPresContext* aContext) {
1893 this->~nsStyleDisplay();
1894 aContext->FreeToShell(sizeof(nsStyleDisplay), this);
1895 }
1897 nsChangeHint CalcDifference(const nsStyleDisplay& aOther) const;
1898 static nsChangeHint MaxDifference() {
1899 // All the parts of FRAMECHANGE are present in CalcDifference.
1900 return nsChangeHint(NS_STYLE_HINT_FRAMECHANGE |
1901 nsChangeHint_UpdateOpacityLayer |
1902 nsChangeHint_UpdateTransformLayer |
1903 nsChangeHint_UpdateOverflow |
1904 nsChangeHint_UpdatePostTransformOverflow |
1905 nsChangeHint_AddOrRemoveTransform);
1906 }
1907 static nsChangeHint MaxDifferenceNeverInherited() {
1908 // CalcDifference can return both nsChangeHint_ClearAncestorIntrinsics and
1909 // nsChangeHint_NeedReflow as inherited hints.
1910 return nsChangeHint(0);
1911 }
1913 // We guarantee that if mBinding is non-null, so are mBinding->GetURI() and
1914 // mBinding->mOriginPrincipal.
1915 nsRefPtr<mozilla::css::URLValue> mBinding; // [reset]
1916 nsRect mClip; // [reset] offsets from upper-left border edge
1917 float mOpacity; // [reset]
1918 uint8_t mDisplay; // [reset] see nsStyleConsts.h NS_STYLE_DISPLAY_*
1919 uint8_t mOriginalDisplay; // [reset] saved mDisplay for position:absolute/fixed
1920 // and float:left/right; otherwise equal
1921 // to mDisplay
1922 uint8_t mAppearance; // [reset]
1923 uint8_t mPosition; // [reset] see nsStyleConsts.h
1924 uint8_t mFloats; // [reset] see nsStyleConsts.h NS_STYLE_FLOAT_*
1925 uint8_t mOriginalFloats; // [reset] saved mFloats for position:absolute/fixed;
1926 // otherwise equal to mFloats
1927 uint8_t mBreakType; // [reset] see nsStyleConsts.h NS_STYLE_CLEAR_*
1928 uint8_t mBreakInside; // [reset] NS_STYLE_PAGE_BREAK_AUTO/AVOID
1929 bool mBreakBefore; // [reset]
1930 bool mBreakAfter; // [reset]
1931 uint8_t mOverflowX; // [reset] see nsStyleConsts.h
1932 uint8_t mOverflowY; // [reset] see nsStyleConsts.h
1933 uint8_t mOverflowClipBox; // [reset] see nsStyleConsts.h
1934 uint8_t mResize; // [reset] see nsStyleConsts.h
1935 uint8_t mClipFlags; // [reset] see nsStyleConsts.h
1936 uint8_t mOrient; // [reset] see nsStyleConsts.h
1937 uint8_t mMixBlendMode; // [reset] see nsStyleConsts.h
1938 uint8_t mWillChangeBitField; // [reset] see nsStyleConsts.h. Stores a
1939 // bitfield representation of the properties
1940 // that are frequently queried. This should
1941 // match mWillChange. Also tracks if any of the
1942 // properties in the will-change list require
1943 // a stacking context.
1944 nsAutoTArray<nsString, 1> mWillChange;
1946 uint8_t mTouchAction; // [reset] see nsStyleConsts.h
1948 // mSpecifiedTransform is the list of transform functions as
1949 // specified, or null to indicate there is no transform. (inherit or
1950 // initial are replaced by an actual list of transform functions, or
1951 // null, as appropriate.)
1952 uint8_t mBackfaceVisibility;
1953 uint8_t mTransformStyle;
1954 nsRefPtr<nsCSSValueSharedList> mSpecifiedTransform; // [reset]
1955 nsStyleCoord mTransformOrigin[3]; // [reset] percent, coord, calc, 3rd param is coord, calc only
1956 nsStyleCoord mChildPerspective; // [reset] coord
1957 nsStyleCoord mPerspectiveOrigin[2]; // [reset] percent, coord, calc
1959 nsAutoTArray<nsTransition, 1> mTransitions; // [reset]
1960 // The number of elements in mTransitions that are not from repeating
1961 // a list due to another property being longer.
1962 uint32_t mTransitionTimingFunctionCount,
1963 mTransitionDurationCount,
1964 mTransitionDelayCount,
1965 mTransitionPropertyCount;
1967 nsAutoTArray<nsAnimation, 1> mAnimations; // [reset]
1968 // The number of elements in mAnimations that are not from repeating
1969 // a list due to another property being longer.
1970 uint32_t mAnimationTimingFunctionCount,
1971 mAnimationDurationCount,
1972 mAnimationDelayCount,
1973 mAnimationNameCount,
1974 mAnimationDirectionCount,
1975 mAnimationFillModeCount,
1976 mAnimationPlayStateCount,
1977 mAnimationIterationCountCount;
1979 bool IsBlockInsideStyle() const {
1980 return NS_STYLE_DISPLAY_BLOCK == mDisplay ||
1981 NS_STYLE_DISPLAY_LIST_ITEM == mDisplay ||
1982 NS_STYLE_DISPLAY_INLINE_BLOCK == mDisplay;
1983 // Should TABLE_CELL and TABLE_CAPTION go here? They have
1984 // block frames nested inside of them.
1985 // (But please audit all callers before changing.)
1986 }
1988 bool IsBlockOutsideStyle() const {
1989 return NS_STYLE_DISPLAY_BLOCK == mDisplay ||
1990 NS_STYLE_DISPLAY_FLEX == mDisplay ||
1991 NS_STYLE_DISPLAY_GRID == mDisplay ||
1992 NS_STYLE_DISPLAY_LIST_ITEM == mDisplay ||
1993 NS_STYLE_DISPLAY_TABLE == mDisplay;
1994 }
1996 static bool IsDisplayTypeInlineOutside(uint8_t aDisplay) {
1997 return NS_STYLE_DISPLAY_INLINE == aDisplay ||
1998 NS_STYLE_DISPLAY_INLINE_BLOCK == aDisplay ||
1999 NS_STYLE_DISPLAY_INLINE_TABLE == aDisplay ||
2000 NS_STYLE_DISPLAY_INLINE_BOX == aDisplay ||
2001 NS_STYLE_DISPLAY_INLINE_FLEX == aDisplay ||
2002 NS_STYLE_DISPLAY_INLINE_GRID == aDisplay ||
2003 NS_STYLE_DISPLAY_INLINE_XUL_GRID == aDisplay ||
2004 NS_STYLE_DISPLAY_INLINE_STACK == aDisplay;
2005 }
2007 bool IsInlineOutsideStyle() const {
2008 return IsDisplayTypeInlineOutside(mDisplay);
2009 }
2011 bool IsOriginalDisplayInlineOutsideStyle() const {
2012 return IsDisplayTypeInlineOutside(mOriginalDisplay);
2013 }
2015 bool IsInnerTableStyle() const {
2016 return NS_STYLE_DISPLAY_TABLE_CAPTION == mDisplay ||
2017 NS_STYLE_DISPLAY_TABLE_CELL == mDisplay ||
2018 NS_STYLE_DISPLAY_TABLE_ROW == mDisplay ||
2019 NS_STYLE_DISPLAY_TABLE_ROW_GROUP == mDisplay ||
2020 NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == mDisplay ||
2021 NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == mDisplay ||
2022 NS_STYLE_DISPLAY_TABLE_COLUMN == mDisplay ||
2023 NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == mDisplay;
2024 }
2026 bool IsFloatingStyle() const {
2027 return NS_STYLE_FLOAT_NONE != mFloats;
2028 }
2030 bool IsAbsolutelyPositionedStyle() const {
2031 return NS_STYLE_POSITION_ABSOLUTE == mPosition ||
2032 NS_STYLE_POSITION_FIXED == mPosition;
2033 }
2035 bool IsRelativelyPositionedStyle() const {
2036 return NS_STYLE_POSITION_RELATIVE == mPosition ||
2037 NS_STYLE_POSITION_STICKY == mPosition;
2038 }
2040 bool IsScrollableOverflow() const {
2041 // mOverflowX and mOverflowY always match when one of them is
2042 // NS_STYLE_OVERFLOW_VISIBLE or NS_STYLE_OVERFLOW_CLIP.
2043 return mOverflowX != NS_STYLE_OVERFLOW_VISIBLE &&
2044 mOverflowX != NS_STYLE_OVERFLOW_CLIP;
2045 }
2047 /* Returns whether the element has the -moz-transform property
2048 * or a related property. */
2049 bool HasTransformStyle() const {
2050 return mSpecifiedTransform != nullptr ||
2051 mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D ||
2052 (mWillChangeBitField & NS_STYLE_WILL_CHANGE_TRANSFORM);
2053 }
2055 bool HasPerspectiveStyle() const {
2056 return mChildPerspective.GetUnit() == eStyleUnit_Coord;
2057 }
2059 bool BackfaceIsHidden() const {
2060 return mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN;
2061 }
2063 // These are defined in nsStyleStructInlines.h.
2065 // The aContextFrame argument on each of these is the frame this
2066 // style struct is for. If the frame is for SVG text, the return
2067 // value will be massaged to be something that makes sense for
2068 // SVG text.
2069 inline bool IsBlockInside(const nsIFrame* aContextFrame) const;
2070 inline bool IsBlockOutside(const nsIFrame* aContextFrame) const;
2071 inline bool IsInlineOutside(const nsIFrame* aContextFrame) const;
2072 inline bool IsOriginalDisplayInlineOutside(const nsIFrame* aContextFrame) const;
2073 inline uint8_t GetDisplay(const nsIFrame* aContextFrame) const;
2074 inline bool IsFloating(const nsIFrame* aContextFrame) const;
2075 inline bool IsPositioned(const nsIFrame* aContextFrame) const;
2076 inline bool IsRelativelyPositioned(const nsIFrame* aContextFrame) const;
2077 inline bool IsAbsolutelyPositioned(const nsIFrame* aContextFrame) const;
2079 /* Returns whether the element has the -moz-transform property
2080 * or a related property, and supports CSS transforms. */
2081 inline bool HasTransform(const nsIFrame* aContextFrame) const;
2082 };
2084 struct nsStyleTable {
2085 nsStyleTable(void);
2086 nsStyleTable(const nsStyleTable& aOther);
2087 ~nsStyleTable(void);
2089 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
2090 return aContext->AllocateFromShell(sz);
2091 }
2092 void Destroy(nsPresContext* aContext) {
2093 this->~nsStyleTable();
2094 aContext->FreeToShell(sizeof(nsStyleTable), this);
2095 }
2097 nsChangeHint CalcDifference(const nsStyleTable& aOther) const;
2098 static nsChangeHint MaxDifference() {
2099 return NS_STYLE_HINT_FRAMECHANGE;
2100 }
2101 static nsChangeHint MaxDifferenceNeverInherited() {
2102 // CalcDifference never returns nsChangeHint_NeedReflow or
2103 // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
2104 return NS_CombineHint(nsChangeHint_NeedReflow,
2105 nsChangeHint_ClearAncestorIntrinsics);
2106 }
2108 uint8_t mLayoutStrategy;// [reset] see nsStyleConsts.h NS_STYLE_TABLE_LAYOUT_*
2109 uint8_t mFrame; // [reset] see nsStyleConsts.h NS_STYLE_TABLE_FRAME_*
2110 uint8_t mRules; // [reset] see nsStyleConsts.h NS_STYLE_TABLE_RULES_*
2111 int32_t mSpan; // [reset] the number of columns spanned by a colgroup or col
2112 };
2114 struct nsStyleTableBorder {
2115 nsStyleTableBorder(nsPresContext* aContext);
2116 nsStyleTableBorder(const nsStyleTableBorder& aOther);
2117 ~nsStyleTableBorder(void);
2119 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
2120 return aContext->AllocateFromShell(sz);
2121 }
2122 void Destroy(nsPresContext* aContext) {
2123 this->~nsStyleTableBorder();
2124 aContext->FreeToShell(sizeof(nsStyleTableBorder), this);
2125 }
2127 nsChangeHint CalcDifference(const nsStyleTableBorder& aOther) const;
2128 static nsChangeHint MaxDifference() {
2129 return NS_STYLE_HINT_FRAMECHANGE;
2130 }
2131 static nsChangeHint MaxDifferenceNeverInherited() {
2132 // CalcDifference never returns nsChangeHint_NeedReflow or
2133 // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
2134 return NS_CombineHint(nsChangeHint_NeedReflow,
2135 nsChangeHint_ClearAncestorIntrinsics);
2136 }
2138 nscoord mBorderSpacingX;// [inherited]
2139 nscoord mBorderSpacingY;// [inherited]
2140 uint8_t mBorderCollapse;// [inherited]
2141 uint8_t mCaptionSide; // [inherited]
2142 uint8_t mEmptyCells; // [inherited]
2143 };
2145 enum nsStyleContentType {
2146 eStyleContentType_String = 1,
2147 eStyleContentType_Image = 10,
2148 eStyleContentType_Attr = 20,
2149 eStyleContentType_Counter = 30,
2150 eStyleContentType_Counters = 31,
2151 eStyleContentType_OpenQuote = 40,
2152 eStyleContentType_CloseQuote = 41,
2153 eStyleContentType_NoOpenQuote = 42,
2154 eStyleContentType_NoCloseQuote = 43,
2155 eStyleContentType_AltContent = 50,
2156 eStyleContentType_Uninitialized
2157 };
2159 struct nsStyleContentData {
2160 nsStyleContentType mType;
2161 union {
2162 char16_t *mString;
2163 imgRequestProxy *mImage;
2164 nsCSSValue::Array* mCounters;
2165 } mContent;
2166 #ifdef DEBUG
2167 bool mImageTracked;
2168 #endif
2170 nsStyleContentData()
2171 : mType(eStyleContentType_Uninitialized)
2172 #ifdef DEBUG
2173 , mImageTracked(false)
2174 #endif
2175 { mContent.mString = nullptr; }
2177 ~nsStyleContentData();
2178 nsStyleContentData& operator=(const nsStyleContentData& aOther);
2179 bool operator==(const nsStyleContentData& aOther) const;
2181 bool operator!=(const nsStyleContentData& aOther) const {
2182 return !(*this == aOther);
2183 }
2185 void TrackImage(nsPresContext* aContext);
2186 void UntrackImage(nsPresContext* aContext);
2188 void SetImage(imgRequestProxy* aRequest)
2189 {
2190 NS_ABORT_IF_FALSE(!mImageTracked,
2191 "Setting a new image without untracking the old one!");
2192 NS_ABORT_IF_FALSE(mType == eStyleContentType_Image, "Wrong type!");
2193 NS_IF_ADDREF(mContent.mImage = aRequest);
2194 }
2195 private:
2196 nsStyleContentData(const nsStyleContentData&); // not to be implemented
2197 };
2199 struct nsStyleCounterData {
2200 nsString mCounter;
2201 int32_t mValue;
2202 };
2205 #define DELETE_ARRAY_IF(array) if (array) { delete[] array; array = nullptr; }
2207 struct nsStyleQuotes {
2208 nsStyleQuotes();
2209 nsStyleQuotes(const nsStyleQuotes& aQuotes);
2210 ~nsStyleQuotes();
2212 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
2213 return aContext->AllocateFromShell(sz);
2214 }
2215 void Destroy(nsPresContext* aContext) {
2216 this->~nsStyleQuotes();
2217 aContext->FreeToShell(sizeof(nsStyleQuotes), this);
2218 }
2220 void SetInitial();
2221 void CopyFrom(const nsStyleQuotes& aSource);
2223 nsChangeHint CalcDifference(const nsStyleQuotes& aOther) const;
2224 static nsChangeHint MaxDifference() {
2225 return NS_STYLE_HINT_FRAMECHANGE;
2226 }
2227 static nsChangeHint MaxDifferenceNeverInherited() {
2228 // CalcDifference never returns nsChangeHint_NeedReflow or
2229 // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
2230 return NS_CombineHint(nsChangeHint_NeedReflow,
2231 nsChangeHint_ClearAncestorIntrinsics);
2232 }
2234 uint32_t QuotesCount(void) const { return mQuotesCount; } // [inherited]
2236 const nsString* OpenQuoteAt(uint32_t aIndex) const
2237 {
2238 NS_ASSERTION(aIndex < mQuotesCount, "out of range");
2239 return mQuotes + (aIndex * 2);
2240 }
2241 const nsString* CloseQuoteAt(uint32_t aIndex) const
2242 {
2243 NS_ASSERTION(aIndex < mQuotesCount, "out of range");
2244 return mQuotes + (aIndex * 2 + 1);
2245 }
2246 nsresult GetQuotesAt(uint32_t aIndex, nsString& aOpen, nsString& aClose) const {
2247 if (aIndex < mQuotesCount) {
2248 aIndex *= 2;
2249 aOpen = mQuotes[aIndex];
2250 aClose = mQuotes[++aIndex];
2251 return NS_OK;
2252 }
2253 return NS_ERROR_ILLEGAL_VALUE;
2254 }
2256 nsresult AllocateQuotes(uint32_t aCount) {
2257 if (aCount != mQuotesCount) {
2258 DELETE_ARRAY_IF(mQuotes);
2259 if (aCount) {
2260 mQuotes = new nsString[aCount * 2];
2261 if (! mQuotes) {
2262 mQuotesCount = 0;
2263 return NS_ERROR_OUT_OF_MEMORY;
2264 }
2265 }
2266 mQuotesCount = aCount;
2267 }
2268 return NS_OK;
2269 }
2271 nsresult SetQuotesAt(uint32_t aIndex, const nsString& aOpen, const nsString& aClose) {
2272 if (aIndex < mQuotesCount) {
2273 aIndex *= 2;
2274 mQuotes[aIndex] = aOpen;
2275 mQuotes[++aIndex] = aClose;
2276 return NS_OK;
2277 }
2278 return NS_ERROR_ILLEGAL_VALUE;
2279 }
2281 protected:
2282 uint32_t mQuotesCount;
2283 nsString* mQuotes;
2284 };
2286 struct nsStyleContent {
2287 nsStyleContent(void);
2288 nsStyleContent(const nsStyleContent& aContent);
2289 ~nsStyleContent(void);
2291 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
2292 return aContext->AllocateFromShell(sz);
2293 }
2294 void Destroy(nsPresContext* aContext);
2296 nsChangeHint CalcDifference(const nsStyleContent& aOther) const;
2297 static nsChangeHint MaxDifference() {
2298 return NS_STYLE_HINT_FRAMECHANGE;
2299 }
2300 static nsChangeHint MaxDifferenceNeverInherited() {
2301 // CalcDifference never returns nsChangeHint_NeedReflow or
2302 // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
2303 return NS_CombineHint(nsChangeHint_NeedReflow,
2304 nsChangeHint_ClearAncestorIntrinsics);
2305 }
2307 uint32_t ContentCount(void) const { return mContentCount; } // [reset]
2309 const nsStyleContentData& ContentAt(uint32_t aIndex) const {
2310 NS_ASSERTION(aIndex < mContentCount, "out of range");
2311 return mContents[aIndex];
2312 }
2314 nsStyleContentData& ContentAt(uint32_t aIndex) {
2315 NS_ASSERTION(aIndex < mContentCount, "out of range");
2316 return mContents[aIndex];
2317 }
2319 nsresult AllocateContents(uint32_t aCount);
2321 uint32_t CounterIncrementCount(void) const { return mIncrementCount; } // [reset]
2322 const nsStyleCounterData* GetCounterIncrementAt(uint32_t aIndex) const {
2323 NS_ASSERTION(aIndex < mIncrementCount, "out of range");
2324 return &mIncrements[aIndex];
2325 }
2327 nsresult AllocateCounterIncrements(uint32_t aCount) {
2328 if (aCount != mIncrementCount) {
2329 DELETE_ARRAY_IF(mIncrements);
2330 if (aCount) {
2331 mIncrements = new nsStyleCounterData[aCount];
2332 if (! mIncrements) {
2333 mIncrementCount = 0;
2334 return NS_ERROR_OUT_OF_MEMORY;
2335 }
2336 }
2337 mIncrementCount = aCount;
2338 }
2339 return NS_OK;
2340 }
2342 nsresult SetCounterIncrementAt(uint32_t aIndex, const nsString& aCounter, int32_t aIncrement) {
2343 if (aIndex < mIncrementCount) {
2344 mIncrements[aIndex].mCounter = aCounter;
2345 mIncrements[aIndex].mValue = aIncrement;
2346 return NS_OK;
2347 }
2348 return NS_ERROR_ILLEGAL_VALUE;
2349 }
2351 uint32_t CounterResetCount(void) const { return mResetCount; } // [reset]
2352 const nsStyleCounterData* GetCounterResetAt(uint32_t aIndex) const {
2353 NS_ASSERTION(aIndex < mResetCount, "out of range");
2354 return &mResets[aIndex];
2355 }
2357 nsresult AllocateCounterResets(uint32_t aCount) {
2358 if (aCount != mResetCount) {
2359 DELETE_ARRAY_IF(mResets);
2360 if (aCount) {
2361 mResets = new nsStyleCounterData[aCount];
2362 if (! mResets) {
2363 mResetCount = 0;
2364 return NS_ERROR_OUT_OF_MEMORY;
2365 }
2366 }
2367 mResetCount = aCount;
2368 }
2369 return NS_OK;
2370 }
2372 nsresult SetCounterResetAt(uint32_t aIndex, const nsString& aCounter, int32_t aValue) {
2373 if (aIndex < mResetCount) {
2374 mResets[aIndex].mCounter = aCounter;
2375 mResets[aIndex].mValue = aValue;
2376 return NS_OK;
2377 }
2378 return NS_ERROR_ILLEGAL_VALUE;
2379 }
2381 nsStyleCoord mMarkerOffset; // [reset] coord, auto
2383 protected:
2384 nsStyleContentData* mContents;
2385 nsStyleCounterData* mIncrements;
2386 nsStyleCounterData* mResets;
2388 uint32_t mContentCount;
2389 uint32_t mIncrementCount;
2390 uint32_t mResetCount;
2391 };
2393 struct nsStyleUIReset {
2394 nsStyleUIReset(void);
2395 nsStyleUIReset(const nsStyleUIReset& aOther);
2396 ~nsStyleUIReset(void);
2398 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
2399 return aContext->AllocateFromShell(sz);
2400 }
2401 void Destroy(nsPresContext* aContext) {
2402 this->~nsStyleUIReset();
2403 aContext->FreeToShell(sizeof(nsStyleUIReset), this);
2404 }
2406 nsChangeHint CalcDifference(const nsStyleUIReset& aOther) const;
2407 static nsChangeHint MaxDifference() {
2408 return NS_STYLE_HINT_FRAMECHANGE;
2409 }
2410 static nsChangeHint MaxDifferenceNeverInherited() {
2411 // CalcDifference never returns nsChangeHint_NeedReflow or
2412 // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
2413 return NS_CombineHint(nsChangeHint_NeedReflow,
2414 nsChangeHint_ClearAncestorIntrinsics);
2415 }
2417 uint8_t mUserSelect; // [reset] (selection-style)
2418 uint8_t mForceBrokenImageIcon; // [reset] (0 if not forcing, otherwise forcing)
2419 uint8_t mIMEMode; // [reset]
2420 uint8_t mWindowShadow; // [reset]
2421 };
2423 struct nsCursorImage {
2424 bool mHaveHotspot;
2425 float mHotspotX, mHotspotY;
2427 nsCursorImage();
2428 nsCursorImage(const nsCursorImage& aOther);
2429 ~nsCursorImage();
2431 nsCursorImage& operator=(const nsCursorImage& aOther);
2432 /*
2433 * We hide mImage and force access through the getter and setter so that we
2434 * can lock the images we use. Cursor images are likely to be small, so we
2435 * don't care about discarding them. See bug 512260.
2436 * */
2437 void SetImage(imgIRequest *aImage) {
2438 if (mImage)
2439 mImage->UnlockImage();
2440 mImage = aImage;
2441 if (mImage)
2442 mImage->LockImage();
2443 }
2444 imgIRequest* GetImage() const {
2445 return mImage;
2446 }
2448 private:
2449 nsCOMPtr<imgIRequest> mImage;
2450 };
2452 struct nsStyleUserInterface {
2453 nsStyleUserInterface(void);
2454 nsStyleUserInterface(const nsStyleUserInterface& aOther);
2455 ~nsStyleUserInterface(void);
2457 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
2458 return aContext->AllocateFromShell(sz);
2459 }
2460 void Destroy(nsPresContext* aContext) {
2461 this->~nsStyleUserInterface();
2462 aContext->FreeToShell(sizeof(nsStyleUserInterface), this);
2463 }
2465 nsChangeHint CalcDifference(const nsStyleUserInterface& aOther) const;
2466 static nsChangeHint MaxDifference() {
2467 return nsChangeHint(nsChangeHint_UpdateCursor | NS_STYLE_HINT_FRAMECHANGE);
2468 }
2469 static nsChangeHint MaxDifferenceNeverInherited() {
2470 // CalcDifference never returns nsChangeHint_NeedReflow or
2471 // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
2472 return NS_CombineHint(nsChangeHint_NeedReflow,
2473 nsChangeHint_ClearAncestorIntrinsics);
2474 }
2476 uint8_t mUserInput; // [inherited]
2477 uint8_t mUserModify; // [inherited] (modify-content)
2478 uint8_t mUserFocus; // [inherited] (auto-select)
2480 uint8_t mCursor; // [inherited] See nsStyleConsts.h
2482 uint32_t mCursorArrayLength;
2483 nsCursorImage *mCursorArray;// [inherited] The specified URL values
2484 // and coordinates. Takes precedence over
2485 // mCursor. Zero-length array is represented
2486 // by null pointer.
2488 // Does not free mCursorArray; the caller is responsible for calling
2489 // |delete [] mCursorArray| first if it is needed.
2490 void CopyCursorArrayFrom(const nsStyleUserInterface& aSource);
2491 };
2493 struct nsStyleXUL {
2494 nsStyleXUL();
2495 nsStyleXUL(const nsStyleXUL& aSource);
2496 ~nsStyleXUL();
2498 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
2499 return aContext->AllocateFromShell(sz);
2500 }
2501 void Destroy(nsPresContext* aContext) {
2502 this->~nsStyleXUL();
2503 aContext->FreeToShell(sizeof(nsStyleXUL), this);
2504 }
2506 nsChangeHint CalcDifference(const nsStyleXUL& aOther) const;
2507 static nsChangeHint MaxDifference() {
2508 return NS_STYLE_HINT_FRAMECHANGE;
2509 }
2510 static nsChangeHint MaxDifferenceNeverInherited() {
2511 // CalcDifference never returns nsChangeHint_NeedReflow or
2512 // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
2513 return NS_CombineHint(nsChangeHint_NeedReflow,
2514 nsChangeHint_ClearAncestorIntrinsics);
2515 }
2517 float mBoxFlex; // [reset] see nsStyleConsts.h
2518 uint32_t mBoxOrdinal; // [reset] see nsStyleConsts.h
2519 uint8_t mBoxAlign; // [reset] see nsStyleConsts.h
2520 uint8_t mBoxDirection; // [reset] see nsStyleConsts.h
2521 uint8_t mBoxOrient; // [reset] see nsStyleConsts.h
2522 uint8_t mBoxPack; // [reset] see nsStyleConsts.h
2523 bool mStretchStack; // [reset] see nsStyleConsts.h
2524 };
2526 struct nsStyleColumn {
2527 nsStyleColumn(nsPresContext* aPresContext);
2528 nsStyleColumn(const nsStyleColumn& aSource);
2529 ~nsStyleColumn();
2531 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
2532 return aContext->AllocateFromShell(sz);
2533 }
2534 void Destroy(nsPresContext* aContext) {
2535 this->~nsStyleColumn();
2536 aContext->FreeToShell(sizeof(nsStyleColumn), this);
2537 }
2539 nsChangeHint CalcDifference(const nsStyleColumn& aOther) const;
2540 static nsChangeHint MaxDifference() {
2541 return NS_STYLE_HINT_FRAMECHANGE;
2542 }
2543 static nsChangeHint MaxDifferenceNeverInherited() {
2544 // CalcDifference never returns nsChangeHint_NeedReflow or
2545 // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
2546 return NS_CombineHint(nsChangeHint_NeedReflow,
2547 nsChangeHint_ClearAncestorIntrinsics);
2548 }
2550 /**
2551 * This is the maximum number of columns we can process. It's used in both
2552 * nsColumnSetFrame and nsRuleNode.
2553 */
2554 static const uint32_t kMaxColumnCount;
2556 uint32_t mColumnCount; // [reset] see nsStyleConsts.h
2557 nsStyleCoord mColumnWidth; // [reset] coord, auto
2558 nsStyleCoord mColumnGap; // [reset] coord, normal
2560 nscolor mColumnRuleColor; // [reset]
2561 uint8_t mColumnRuleStyle; // [reset]
2562 uint8_t mColumnFill; // [reset] see nsStyleConsts.h
2564 // See https://bugzilla.mozilla.org/show_bug.cgi?id=271586#c43 for why
2565 // this is hard to replace with 'currentColor'.
2566 bool mColumnRuleColorIsForeground;
2568 void SetColumnRuleWidth(nscoord aWidth) {
2569 mColumnRuleWidth = NS_ROUND_BORDER_TO_PIXELS(aWidth, mTwipsPerPixel);
2570 }
2572 nscoord GetComputedColumnRuleWidth() const {
2573 return (IsVisibleBorderStyle(mColumnRuleStyle) ? mColumnRuleWidth : 0);
2574 }
2576 protected:
2577 nscoord mColumnRuleWidth; // [reset] coord
2578 nscoord mTwipsPerPixel;
2579 };
2581 enum nsStyleSVGPaintType {
2582 eStyleSVGPaintType_None = 1,
2583 eStyleSVGPaintType_Color,
2584 eStyleSVGPaintType_Server,
2585 eStyleSVGPaintType_ContextFill,
2586 eStyleSVGPaintType_ContextStroke
2587 };
2589 enum nsStyleSVGOpacitySource {
2590 eStyleSVGOpacitySource_Normal,
2591 eStyleSVGOpacitySource_ContextFillOpacity,
2592 eStyleSVGOpacitySource_ContextStrokeOpacity
2593 };
2595 struct nsStyleSVGPaint
2596 {
2597 union {
2598 nscolor mColor;
2599 nsIURI *mPaintServer;
2600 } mPaint;
2601 nsStyleSVGPaintType mType;
2602 nscolor mFallbackColor;
2604 nsStyleSVGPaint() : mType(nsStyleSVGPaintType(0)) { mPaint.mPaintServer = nullptr; }
2605 ~nsStyleSVGPaint();
2606 void SetType(nsStyleSVGPaintType aType);
2607 nsStyleSVGPaint& operator=(const nsStyleSVGPaint& aOther);
2608 bool operator==(const nsStyleSVGPaint& aOther) const;
2610 bool operator!=(const nsStyleSVGPaint& aOther) const {
2611 return !(*this == aOther);
2612 }
2613 };
2615 struct nsStyleSVG {
2616 nsStyleSVG();
2617 nsStyleSVG(const nsStyleSVG& aSource);
2618 ~nsStyleSVG();
2620 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
2621 return aContext->AllocateFromShell(sz);
2622 }
2623 void Destroy(nsPresContext* aContext) {
2624 this->~nsStyleSVG();
2625 aContext->FreeToShell(sizeof(nsStyleSVG), this);
2626 }
2628 nsChangeHint CalcDifference(const nsStyleSVG& aOther) const;
2629 static nsChangeHint MaxDifference() {
2630 return NS_CombineHint(NS_CombineHint(nsChangeHint_UpdateEffects,
2631 NS_CombineHint(nsChangeHint_NeedReflow, nsChangeHint_NeedDirtyReflow)), // XXX remove nsChangeHint_NeedDirtyReflow: bug 876085
2632 nsChangeHint_RepaintFrame);
2633 }
2634 static nsChangeHint MaxDifferenceNeverInherited() {
2635 // CalcDifference never returns nsChangeHint_NeedReflow as an inherited hint
2636 // and never returns nsChangeHint_ClearAncestorIntrinsics at all.
2637 return nsChangeHint_NeedReflow;
2638 }
2640 nsStyleSVGPaint mFill; // [inherited]
2641 nsStyleSVGPaint mStroke; // [inherited]
2642 nsCOMPtr<nsIURI> mMarkerEnd; // [inherited]
2643 nsCOMPtr<nsIURI> mMarkerMid; // [inherited]
2644 nsCOMPtr<nsIURI> mMarkerStart; // [inherited]
2645 nsStyleCoord *mStrokeDasharray; // [inherited] coord, percent, factor
2647 nsStyleCoord mStrokeDashoffset; // [inherited] coord, percent, factor
2648 nsStyleCoord mStrokeWidth; // [inherited] coord, percent, factor
2650 float mFillOpacity; // [inherited]
2651 float mStrokeMiterlimit; // [inherited]
2652 float mStrokeOpacity; // [inherited]
2654 uint32_t mStrokeDasharrayLength;
2655 uint8_t mClipRule; // [inherited]
2656 uint8_t mColorInterpolation; // [inherited] see nsStyleConsts.h
2657 uint8_t mColorInterpolationFilters; // [inherited] see nsStyleConsts.h
2658 uint8_t mFillRule; // [inherited] see nsStyleConsts.h
2659 uint8_t mImageRendering; // [inherited] see nsStyleConsts.h
2660 uint8_t mPaintOrder; // [inherited] see nsStyleConsts.h
2661 uint8_t mShapeRendering; // [inherited] see nsStyleConsts.h
2662 uint8_t mStrokeLinecap; // [inherited] see nsStyleConsts.h
2663 uint8_t mStrokeLinejoin; // [inherited] see nsStyleConsts.h
2664 uint8_t mTextAnchor; // [inherited] see nsStyleConsts.h
2665 uint8_t mTextRendering; // [inherited] see nsStyleConsts.h
2667 // In SVG glyphs, whether we inherit fill or stroke opacity from the outer
2668 // text object.
2669 // Use 3 bits to avoid signedness problems in MSVC.
2670 nsStyleSVGOpacitySource mFillOpacitySource : 3;
2671 nsStyleSVGOpacitySource mStrokeOpacitySource : 3;
2673 // SVG glyph outer object inheritance for other properties
2674 bool mStrokeDasharrayFromObject : 1;
2675 bool mStrokeDashoffsetFromObject : 1;
2676 bool mStrokeWidthFromObject : 1;
2678 bool HasMarker() const {
2679 return mMarkerStart || mMarkerMid || mMarkerEnd;
2680 }
2682 /**
2683 * Returns true if the stroke is not "none" and the stroke-opacity is greater
2684 * than zero. This ignores stroke-widths as that depends on the context.
2685 */
2686 bool HasStroke() const {
2687 return mStroke.mType != eStyleSVGPaintType_None && mStrokeOpacity > 0;
2688 }
2690 /**
2691 * Returns true if the fill is not "none" and the fill-opacity is greater
2692 * than zero.
2693 */
2694 bool HasFill() const {
2695 return mFill.mType != eStyleSVGPaintType_None && mFillOpacity > 0;
2696 }
2697 };
2699 struct nsStyleFilter {
2700 nsStyleFilter();
2701 nsStyleFilter(const nsStyleFilter& aSource);
2702 ~nsStyleFilter();
2704 nsStyleFilter& operator=(const nsStyleFilter& aOther);
2706 bool operator==(const nsStyleFilter& aOther) const;
2708 int32_t GetType() const {
2709 return mType;
2710 }
2712 const nsStyleCoord& GetFilterParameter() const {
2713 NS_ASSERTION(mType != NS_STYLE_FILTER_DROP_SHADOW &&
2714 mType != NS_STYLE_FILTER_URL &&
2715 mType != NS_STYLE_FILTER_NONE, "wrong filter type");
2716 return mFilterParameter;
2717 }
2718 void SetFilterParameter(const nsStyleCoord& aFilterParameter,
2719 int32_t aType);
2721 nsIURI* GetURL() const {
2722 NS_ASSERTION(mType == NS_STYLE_FILTER_URL, "wrong filter type");
2723 return mURL;
2724 }
2725 void SetURL(nsIURI* aURL);
2727 nsCSSShadowArray* GetDropShadow() const {
2728 NS_ASSERTION(mType == NS_STYLE_FILTER_DROP_SHADOW, "wrong filter type");
2729 return mDropShadow;
2730 }
2731 void SetDropShadow(nsCSSShadowArray* aDropShadow);
2733 private:
2734 void ReleaseRef();
2736 int32_t mType; // see NS_STYLE_FILTER_* constants in nsStyleConsts.h
2737 nsStyleCoord mFilterParameter; // coord, percent, factor, angle
2738 union {
2739 nsIURI* mURL;
2740 nsCSSShadowArray* mDropShadow;
2741 };
2742 };
2744 template<>
2745 struct nsTArray_CopyChooser<nsStyleFilter> {
2746 typedef nsTArray_CopyWithConstructors<nsStyleFilter> Type;
2747 };
2749 struct nsStyleSVGReset {
2750 nsStyleSVGReset();
2751 nsStyleSVGReset(const nsStyleSVGReset& aSource);
2752 ~nsStyleSVGReset();
2754 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
2755 return aContext->AllocateFromShell(sz);
2756 }
2757 void Destroy(nsPresContext* aContext) {
2758 this->~nsStyleSVGReset();
2759 aContext->FreeToShell(sizeof(nsStyleSVGReset), this);
2760 }
2762 nsChangeHint CalcDifference(const nsStyleSVGReset& aOther) const;
2763 static nsChangeHint MaxDifference() {
2764 return NS_CombineHint(nsChangeHint_UpdateEffects,
2765 NS_CombineHint(nsChangeHint_UpdateOverflow, NS_STYLE_HINT_REFLOW));
2766 }
2767 static nsChangeHint MaxDifferenceNeverInherited() {
2768 // CalcDifference never returns nsChangeHint_NeedReflow or
2769 // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
2770 return NS_CombineHint(nsChangeHint_NeedReflow,
2771 nsChangeHint_ClearAncestorIntrinsics);
2772 }
2774 bool HasFilters() const {
2775 return mFilters.Length() > 0;
2776 }
2778 nsCOMPtr<nsIURI> mClipPath; // [reset]
2779 nsTArray<nsStyleFilter> mFilters; // [reset]
2780 nsCOMPtr<nsIURI> mMask; // [reset]
2781 nscolor mStopColor; // [reset]
2782 nscolor mFloodColor; // [reset]
2783 nscolor mLightingColor; // [reset]
2785 float mStopOpacity; // [reset]
2786 float mFloodOpacity; // [reset]
2788 uint8_t mDominantBaseline; // [reset] see nsStyleConsts.h
2789 uint8_t mVectorEffect; // [reset] see nsStyleConsts.h
2790 uint8_t mMaskType; // [reset] see nsStyleConsts.h
2791 };
2793 struct nsStyleVariables {
2794 nsStyleVariables();
2795 nsStyleVariables(const nsStyleVariables& aSource);
2796 ~nsStyleVariables();
2798 void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
2799 return aContext->AllocateFromShell(sz);
2800 }
2801 void Destroy(nsPresContext* aContext) {
2802 this->~nsStyleVariables();
2803 aContext->FreeToShell(sizeof(nsStyleVariables), this);
2804 }
2806 nsChangeHint CalcDifference(const nsStyleVariables& aOther) const;
2807 static nsChangeHint MaxDifference() {
2808 return nsChangeHint(0);
2809 }
2810 static nsChangeHint MaxDifferenceNeverInherited() {
2811 // CalcDifference never returns nsChangeHint_NeedReflow or
2812 // nsChangeHint_ClearAncestorIntrinsics at all.
2813 return nsChangeHint(0);
2814 }
2816 mozilla::CSSVariableValues mVariables;
2817 };
2819 #endif /* nsStyleStruct_h___ */