1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * David Hyatt (hyatt@netscape.com)
24 * Mats Palmgren <mats.palmgren@bredband.net>
25 * Michael Ventnor <m.ventnor@gmail.com>
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
42 * structs that contain the data provided by nsStyleContext, the
43 * internal API for computed style data for an element
46 #include "nsStyleStruct.h"
47 #include "nsStyleStructInlines.h"
48 #include "nsStyleConsts.h"
49 #include "nsThemeConstants.h"
51 #include "nsPresContext.h"
52 #include "nsIDeviceContext.h"
53 #include "nsIStyleRule.h"
57 #include "nsIPresShell.h"
59 #include "nsHTMLReflowState.h"
62 #include "nsBidiUtils.h"
64 #include "imgIRequest.h"
67 // Make sure we have enough bits in NS_STYLE_INHERIT_MASK.
68 PR_STATIC_ASSERT((((1 << nsStyleStructID_Length
) - 1) &
69 ~(NS_STYLE_INHERIT_MASK
)) == 0);
71 inline PRBool
IsFixedUnit(nsStyleUnit aUnit
, PRBool aEnumOK
)
73 return PRBool((aUnit
== eStyleUnit_Coord
) ||
74 (aEnumOK
&& (aUnit
== eStyleUnit_Enumerated
)));
77 static PRBool
EqualURIs(nsIURI
*aURI1
, nsIURI
*aURI2
)
80 return aURI1
== aURI2
|| // handle null==null, and optimize
82 NS_SUCCEEDED(aURI1
->Equals(aURI2
, &eq
)) && // not equal on fail
86 static PRBool
EqualURIs(nsCSSValue::URL
*aURI1
, nsCSSValue::URL
*aURI2
)
88 return aURI1
== aURI2
|| // handle null==null, and optimize
89 (aURI1
&& aURI2
&& aURI1
->URIEquals(*aURI2
));
92 static PRBool
EqualImages(imgIRequest
*aImage1
, imgIRequest
* aImage2
)
94 if (aImage1
== aImage2
) {
98 if (!aImage1
|| !aImage2
) {
102 nsCOMPtr
<nsIURI
> uri1
, uri2
;
103 aImage1
->GetURI(getter_AddRefs(uri1
));
104 aImage2
->GetURI(getter_AddRefs(uri2
));
105 return EqualURIs(uri1
, uri2
);
108 static nsChangeHint
CalcShadowDifference(nsCSSShadowArray
* lhs
,
109 nsCSSShadowArray
* rhs
);
111 // --------------------
114 nsStyleFont::nsStyleFont(const nsFont
& aFont
, nsPresContext
*aPresContext
)
116 mGenericID(kGenericFont_NONE
)
118 mSize
= mFont
.size
= nsStyleFont::ZoomText(aPresContext
, mFont
.size
);
120 mScriptUnconstrainedSize
= mSize
;
121 mScriptMinSize
= aPresContext
->TwipsToAppUnits(
122 NS_POINTS_TO_TWIPS(NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT
));
124 mScriptSizeMultiplier
= NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER
;
128 nsStyleFont::nsStyleFont(const nsStyleFont
& aSrc
)
131 , mGenericID(aSrc
.mGenericID
)
133 , mScriptLevel(aSrc
.mScriptLevel
)
134 , mScriptUnconstrainedSize(aSrc
.mScriptUnconstrainedSize
)
135 , mScriptMinSize(aSrc
.mScriptMinSize
)
136 , mScriptSizeMultiplier(aSrc
.mScriptSizeMultiplier
)
141 nsStyleFont::nsStyleFont(nsPresContext
* aPresContext
)
142 : mFont(*(aPresContext
->GetDefaultFont(kPresContext_DefaultVariableFont_ID
))),
143 mGenericID(kGenericFont_NONE
)
145 mSize
= mFont
.size
= nsStyleFont::ZoomText(aPresContext
, mFont
.size
);
147 mScriptUnconstrainedSize
= mSize
;
148 mScriptMinSize
= aPresContext
->TwipsToAppUnits(
149 NS_POINTS_TO_TWIPS(NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT
));
151 mScriptSizeMultiplier
= NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER
;
156 nsStyleFont::operator new(size_t sz
, nsPresContext
* aContext
) CPP_THROW_NEW
{
157 void* result
= aContext
->AllocateFromShell(sz
);
159 memset(result
, 0, sz
);
164 nsStyleFont::Destroy(nsPresContext
* aContext
) {
165 this->~nsStyleFont();
166 aContext
->FreeToShell(sizeof(nsStyleFont
), this);
169 nsChangeHint
nsStyleFont::CalcDifference(const nsStyleFont
& aOther
) const
171 if (mSize
== aOther
.mSize
) {
172 return CalcFontDifference(mFont
, aOther
.mFont
);
174 return NS_STYLE_HINT_REFLOW
;
179 nsChangeHint
nsStyleFont::MaxDifference()
181 return NS_STYLE_HINT_REFLOW
;
186 nsStyleFont::ZoomText(nsPresContext
*aPresContext
, nscoord aSize
)
188 return nscoord(float(aSize
) * aPresContext
->TextZoom());
192 nsStyleFont::UnZoomText(nsPresContext
*aPresContext
, nscoord aSize
)
194 return nscoord(float(aSize
) / aPresContext
->TextZoom());
197 nsChangeHint
nsStyleFont::CalcFontDifference(const nsFont
& aFont1
, const nsFont
& aFont2
)
199 if ((aFont1
.size
== aFont2
.size
) &&
200 (aFont1
.sizeAdjust
== aFont2
.sizeAdjust
) &&
201 (aFont1
.style
== aFont2
.style
) &&
202 (aFont1
.variant
== aFont2
.variant
) &&
203 (aFont1
.familyNameQuirks
== aFont2
.familyNameQuirks
) &&
204 (aFont1
.weight
== aFont2
.weight
) &&
205 (aFont1
.name
== aFont2
.name
)) {
206 if ((aFont1
.decorations
== aFont2
.decorations
)) {
207 return NS_STYLE_HINT_NONE
;
209 return NS_STYLE_HINT_VISUAL
;
211 return NS_STYLE_HINT_REFLOW
;
214 static PRBool
IsFixedData(const nsStyleSides
& aSides
, PRBool aEnumOK
)
216 NS_FOR_CSS_SIDES(side
) {
217 if (!IsFixedUnit(aSides
.GetUnit(side
), aEnumOK
))
223 static nscoord
CalcCoord(const nsStyleCoord
& aCoord
,
224 const nscoord
* aEnumTable
,
227 switch (aCoord
.GetUnit()) {
228 case eStyleUnit_Coord
:
229 return aCoord
.GetCoordValue();
230 case eStyleUnit_Enumerated
:
231 if (nsnull
!= aEnumTable
) {
232 PRInt32 value
= aCoord
.GetIntValue();
233 if ((0 <= value
) && (value
< aNumEnums
)) {
234 return aEnumTable
[aCoord
.GetIntValue()];
239 NS_ERROR("bad unit type");
245 nsStyleMargin::nsStyleMargin() {
246 nsStyleCoord
zero(0);
247 NS_FOR_CSS_SIDES(side
) {
248 mMargin
.Set(side
, zero
);
250 mHasCachedMargin
= PR_FALSE
;
253 nsStyleMargin::nsStyleMargin(const nsStyleMargin
& aSrc
) {
254 mMargin
= aSrc
.mMargin
;
255 mHasCachedMargin
= PR_FALSE
;
259 nsStyleMargin::operator new(size_t sz
, nsPresContext
* aContext
) CPP_THROW_NEW
{
260 void* result
= aContext
->AllocateFromShell(sz
);
262 memset(result
, 0, sz
);
267 nsStyleMargin::Destroy(nsPresContext
* aContext
) {
268 this->~nsStyleMargin();
269 aContext
->FreeToShell(sizeof(nsStyleMargin
), this);
273 void nsStyleMargin::RecalcData()
275 if (IsFixedData(mMargin
, PR_FALSE
)) {
276 NS_FOR_CSS_SIDES(side
) {
277 mCachedMargin
.side(side
) = CalcCoord(mMargin
.Get(side
), nsnull
, 0);
279 mHasCachedMargin
= PR_TRUE
;
282 mHasCachedMargin
= PR_FALSE
;
285 nsChangeHint
nsStyleMargin::CalcDifference(const nsStyleMargin
& aOther
) const
287 if (mMargin
== aOther
.mMargin
) {
288 return NS_STYLE_HINT_NONE
;
290 return NS_STYLE_HINT_REFLOW
;
295 nsChangeHint
nsStyleMargin::MaxDifference()
297 return NS_STYLE_HINT_REFLOW
;
301 nsStylePadding::nsStylePadding() {
302 nsStyleCoord
zero(0);
303 NS_FOR_CSS_SIDES(side
) {
304 mPadding
.Set(side
, zero
);
306 mHasCachedPadding
= PR_FALSE
;
309 nsStylePadding::nsStylePadding(const nsStylePadding
& aSrc
) {
310 mPadding
= aSrc
.mPadding
;
311 mHasCachedPadding
= PR_FALSE
;
315 nsStylePadding::operator new(size_t sz
, nsPresContext
* aContext
) CPP_THROW_NEW
{
316 void* result
= aContext
->AllocateFromShell(sz
);
318 memset(result
, 0, sz
);
323 nsStylePadding::Destroy(nsPresContext
* aContext
) {
324 this->~nsStylePadding();
325 aContext
->FreeToShell(sizeof(nsStylePadding
), this);
328 void nsStylePadding::RecalcData()
330 if (IsFixedData(mPadding
, PR_FALSE
)) {
331 NS_FOR_CSS_SIDES(side
) {
332 mCachedPadding
.side(side
) = CalcCoord(mPadding
.Get(side
), nsnull
, 0);
334 mHasCachedPadding
= PR_TRUE
;
337 mHasCachedPadding
= PR_FALSE
;
340 nsChangeHint
nsStylePadding::CalcDifference(const nsStylePadding
& aOther
) const
342 if (mPadding
== aOther
.mPadding
) {
343 return NS_STYLE_HINT_NONE
;
345 return NS_STYLE_HINT_REFLOW
;
350 nsChangeHint
nsStylePadding::MaxDifference()
352 return NS_STYLE_HINT_REFLOW
;
356 nsStyleBorder::nsStyleBorder(nsPresContext
* aPresContext
)
357 : mHaveBorderImageWidth(PR_FALSE
),
358 mComputedBorder(0, 0, 0, 0),
362 (aPresContext
->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM
];
363 NS_FOR_CSS_SIDES(side
) {
364 mBorder
.side(side
) = medium
;
365 mBorderStyle
[side
] = NS_STYLE_BORDER_STYLE_NONE
| BORDER_COLOR_FOREGROUND
;
366 mBorderColor
[side
] = NS_RGB(0, 0, 0);
368 NS_FOR_CSS_HALF_CORNERS(corner
) {
369 mBorderRadius
.Set(corner
, nsStyleCoord(0));
372 mBorderColors
= nsnull
;
375 mFloatEdge
= NS_STYLE_FLOAT_EDGE_CONTENT
;
377 mTwipsPerPixel
= aPresContext
->DevPixelsToAppUnits(1);
380 nsBorderColors::~nsBorderColors()
382 NS_CSS_DELETE_LIST_MEMBER(nsBorderColors
, this, mNext
);
386 nsBorderColors::Clone(PRBool aDeep
) const
388 nsBorderColors
* result
= new nsBorderColors(mColor
);
389 if (NS_UNLIKELY(!result
))
392 NS_CSS_CLONE_LIST_MEMBER(nsBorderColors
, this, mNext
, result
, (PR_FALSE
));
396 nsStyleBorder::nsStyleBorder(const nsStyleBorder
& aSrc
)
397 : mBorderRadius(aSrc
.mBorderRadius
),
398 mBorderImageSplit(aSrc
.mBorderImageSplit
),
399 mFloatEdge(aSrc
.mFloatEdge
),
400 mBorderImageHFill(aSrc
.mBorderImageHFill
),
401 mBorderImageVFill(aSrc
.mBorderImageVFill
),
402 mBorderColors(nsnull
),
403 mBoxShadow(aSrc
.mBoxShadow
),
404 mHaveBorderImageWidth(aSrc
.mHaveBorderImageWidth
),
405 mBorderImageWidth(aSrc
.mBorderImageWidth
),
406 mComputedBorder(aSrc
.mComputedBorder
),
407 mBorder(aSrc
.mBorder
),
408 mBorderImage(aSrc
.mBorderImage
),
409 mTwipsPerPixel(aSrc
.mTwipsPerPixel
)
411 if (aSrc
.mBorderColors
) {
412 EnsureBorderColors();
413 for (PRInt32 i
= 0; i
< 4; i
++)
414 if (aSrc
.mBorderColors
[i
])
415 mBorderColors
[i
] = aSrc
.mBorderColors
[i
]->Clone();
417 mBorderColors
[i
] = nsnull
;
420 NS_FOR_CSS_SIDES(side
) {
421 mBorderStyle
[side
] = aSrc
.mBorderStyle
[side
];
422 mBorderColor
[side
] = aSrc
.mBorderColor
[side
];
424 NS_FOR_CSS_HALF_CORNERS(corner
) {
425 mBorderRadius
.Set(corner
, aSrc
.mBorderRadius
.Get(corner
));
429 nsStyleBorder::~nsStyleBorder()
432 for (PRInt32 i
= 0; i
< 4; i
++)
433 delete mBorderColors
[i
];
434 delete [] mBorderColors
;
439 nsStyleBorder::operator new(size_t sz
, nsPresContext
* aContext
) CPP_THROW_NEW
{
440 void* result
= aContext
->AllocateFromShell(sz
);
442 memset(result
, 0, sz
);
447 nsStyleBorder::Destroy(nsPresContext
* aContext
) {
448 this->~nsStyleBorder();
449 aContext
->FreeToShell(sizeof(nsStyleBorder
), this);
453 nsChangeHint
nsStyleBorder::CalcDifference(const nsStyleBorder
& aOther
) const
455 nsChangeHint shadowDifference
=
456 CalcShadowDifference(mBoxShadow
, aOther
.mBoxShadow
);
458 // Note that differences in mBorder don't affect rendering (which should only
459 // use mComputedBorder), so don't need to be tested for here.
460 if (mTwipsPerPixel
!= aOther
.mTwipsPerPixel
||
461 GetActualBorder() != aOther
.GetActualBorder() ||
462 mFloatEdge
!= aOther
.mFloatEdge
||
463 (shadowDifference
& nsChangeHint_ReflowFrame
))
464 return NS_STYLE_HINT_REFLOW
;
466 // Note that mBorderStyle stores not only the border style but also
467 // color-related flags. Given that we've already done an mComputedBorder
468 // comparison, border-style differences can only lead to a VISUAL hint. So
469 // it's OK to just compare the values directly -- if either the actual
470 // style or the color flags differ we want to repaint.
471 NS_FOR_CSS_SIDES(ix
) {
472 if (mBorderStyle
[ix
] != aOther
.mBorderStyle
[ix
] ||
473 mBorderColor
[ix
] != aOther
.mBorderColor
[ix
])
474 return NS_STYLE_HINT_VISUAL
;
477 if (mBorderRadius
!= aOther
.mBorderRadius
||
478 !mBorderColors
!= !aOther
.mBorderColors
)
479 return NS_STYLE_HINT_VISUAL
;
481 if (IsBorderImageLoaded() || aOther
.IsBorderImageLoaded()) {
482 if (mBorderImage
!= aOther
.mBorderImage
||
483 mBorderImageHFill
!= aOther
.mBorderImageHFill
||
484 mBorderImageVFill
!= aOther
.mBorderImageVFill
||
485 mBorderImageSplit
!= aOther
.mBorderImageSplit
)
486 return NS_STYLE_HINT_VISUAL
;
487 // The call to GetActualBorder above already considered
488 // mBorderImageWidth and mHaveBorderImageWidth.
491 // Note that at this point if mBorderColors is non-null so is
492 // aOther.mBorderColors
494 NS_FOR_CSS_SIDES(ix
) {
495 if (!nsBorderColors::Equal(mBorderColors
[ix
],
496 aOther
.mBorderColors
[ix
]))
497 return NS_STYLE_HINT_VISUAL
;
501 return shadowDifference
;
506 nsChangeHint
nsStyleBorder::MaxDifference()
508 return NS_STYLE_HINT_REFLOW
;
513 nsStyleBorder::ImageBorderDiffers() const
515 return mComputedBorder
!=
516 (mHaveBorderImageWidth
? mBorderImageWidth
: mBorder
);
520 nsStyleBorder::GetActualBorder() const
522 if (IsBorderImageLoaded())
523 if (mHaveBorderImageWidth
)
524 return mBorderImageWidth
;
528 return mComputedBorder
;
531 nsStyleOutline::nsStyleOutline(nsPresContext
* aPresContext
)
533 // spacing values not inherited
534 nsStyleCoord
zero(0);
535 NS_FOR_CSS_HALF_CORNERS(corner
) {
536 mOutlineRadius
.Set(corner
, zero
);
541 mOutlineWidth
= nsStyleCoord(NS_STYLE_BORDER_WIDTH_MEDIUM
, eStyleUnit_Enumerated
);
542 mOutlineStyle
= NS_STYLE_BORDER_STYLE_NONE
;
543 mOutlineColor
= NS_RGB(0, 0, 0);
545 mHasCachedOutline
= PR_FALSE
;
546 mTwipsPerPixel
= aPresContext
->DevPixelsToAppUnits(1);
549 nsStyleOutline::nsStyleOutline(const nsStyleOutline
& aSrc
) {
550 memcpy((nsStyleOutline
*)this, &aSrc
, sizeof(nsStyleOutline
));
554 nsStyleOutline::RecalcData(nsPresContext
* aContext
)
556 if (NS_STYLE_BORDER_STYLE_NONE
== GetOutlineStyle()) {
557 mCachedOutlineWidth
= 0;
558 mHasCachedOutline
= PR_TRUE
;
559 } else if (IsFixedUnit(mOutlineWidth
.GetUnit(), PR_TRUE
)) {
560 mCachedOutlineWidth
=
561 CalcCoord(mOutlineWidth
, aContext
->GetBorderWidthTable(), 3);
562 mCachedOutlineWidth
=
563 NS_ROUND_BORDER_TO_PIXELS(mCachedOutlineWidth
, mTwipsPerPixel
);
564 mHasCachedOutline
= PR_TRUE
;
567 mHasCachedOutline
= PR_FALSE
;
570 nsChangeHint
nsStyleOutline::CalcDifference(const nsStyleOutline
& aOther
) const
572 PRBool outlineWasVisible
=
573 mCachedOutlineWidth
> 0 && mOutlineStyle
!= NS_STYLE_BORDER_STYLE_NONE
;
574 PRBool outlineIsVisible
=
575 aOther
.mCachedOutlineWidth
> 0 && aOther
.mOutlineStyle
!= NS_STYLE_BORDER_STYLE_NONE
;
576 if (outlineWasVisible
!= outlineIsVisible
||
577 (outlineIsVisible
&& (mOutlineOffset
!= aOther
.mOutlineOffset
||
578 mOutlineWidth
!= aOther
.mOutlineWidth
||
579 mTwipsPerPixel
!= aOther
.mTwipsPerPixel
))) {
580 return NS_CombineHint(nsChangeHint_ReflowFrame
, nsChangeHint_RepaintFrame
);
582 if ((mOutlineStyle
!= aOther
.mOutlineStyle
) ||
583 (mOutlineColor
!= aOther
.mOutlineColor
) ||
584 (mOutlineRadius
!= aOther
.mOutlineRadius
)) {
585 return nsChangeHint_RepaintFrame
;
587 return NS_STYLE_HINT_NONE
;
592 nsChangeHint
nsStyleOutline::MaxDifference()
594 return NS_CombineHint(nsChangeHint_ReflowFrame
, nsChangeHint_RepaintFrame
);
598 // --------------------
601 nsStyleList::nsStyleList()
602 : mListStyleType(NS_STYLE_LIST_STYLE_DISC
),
603 mListStylePosition(NS_STYLE_LIST_STYLE_POSITION_OUTSIDE
)
607 nsStyleList::~nsStyleList()
611 nsStyleList::nsStyleList(const nsStyleList
& aSource
)
612 : mListStyleType(aSource
.mListStyleType
),
613 mListStylePosition(aSource
.mListStylePosition
),
614 mListStyleImage(aSource
.mListStyleImage
),
615 mImageRegion(aSource
.mImageRegion
)
619 nsChangeHint
nsStyleList::CalcDifference(const nsStyleList
& aOther
) const
621 if (mListStylePosition
!= aOther
.mListStylePosition
)
622 return NS_STYLE_HINT_FRAMECHANGE
;
623 if (EqualImages(mListStyleImage
, aOther
.mListStyleImage
) &&
624 mListStyleType
== aOther
.mListStyleType
) {
625 if (mImageRegion
== aOther
.mImageRegion
)
626 return NS_STYLE_HINT_NONE
;
627 if (mImageRegion
.width
== aOther
.mImageRegion
.width
&&
628 mImageRegion
.height
== aOther
.mImageRegion
.height
)
629 return NS_STYLE_HINT_VISUAL
;
631 return NS_STYLE_HINT_REFLOW
;
636 nsChangeHint
nsStyleList::MaxDifference()
638 return NS_STYLE_HINT_FRAMECHANGE
;
642 // --------------------
645 nsStyleXUL::nsStyleXUL()
647 mBoxAlign
= NS_STYLE_BOX_ALIGN_STRETCH
;
648 mBoxDirection
= NS_STYLE_BOX_DIRECTION_NORMAL
;
650 mBoxOrient
= NS_STYLE_BOX_ORIENT_HORIZONTAL
;
651 mBoxPack
= NS_STYLE_BOX_PACK_START
;
653 mStretchStack
= PR_TRUE
;
656 nsStyleXUL::~nsStyleXUL()
660 nsStyleXUL::nsStyleXUL(const nsStyleXUL
& aSource
)
662 memcpy((nsStyleXUL
*)this, &aSource
, sizeof(nsStyleXUL
));
665 nsChangeHint
nsStyleXUL::CalcDifference(const nsStyleXUL
& aOther
) const
667 if (mBoxAlign
== aOther
.mBoxAlign
&&
668 mBoxDirection
== aOther
.mBoxDirection
&&
669 mBoxFlex
== aOther
.mBoxFlex
&&
670 mBoxOrient
== aOther
.mBoxOrient
&&
671 mBoxPack
== aOther
.mBoxPack
&&
672 mBoxOrdinal
== aOther
.mBoxOrdinal
)
673 return NS_STYLE_HINT_NONE
;
674 if (mBoxOrdinal
!= aOther
.mBoxOrdinal
)
675 return NS_STYLE_HINT_FRAMECHANGE
;
676 return NS_STYLE_HINT_REFLOW
;
681 nsChangeHint
nsStyleXUL::MaxDifference()
683 return NS_STYLE_HINT_FRAMECHANGE
;
687 // --------------------
690 nsStyleColumn::nsStyleColumn(nsPresContext
* aPresContext
)
692 mColumnCount
= NS_STYLE_COLUMN_COUNT_AUTO
;
693 mColumnWidth
.SetAutoValue();
694 mColumnGap
.SetNormalValue();
696 mColumnRuleWidth
= (aPresContext
->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM
];
697 mColumnRuleStyle
= NS_STYLE_BORDER_STYLE_NONE
;
698 mColumnRuleColor
= NS_RGB(0, 0, 0);
699 mColumnRuleColorIsForeground
= PR_TRUE
;
701 mTwipsPerPixel
= aPresContext
->AppUnitsPerDevPixel();
704 nsStyleColumn::~nsStyleColumn()
708 nsStyleColumn::nsStyleColumn(const nsStyleColumn
& aSource
)
710 memcpy((nsStyleColumn
*)this, &aSource
, sizeof(nsStyleColumn
));
713 nsChangeHint
nsStyleColumn::CalcDifference(const nsStyleColumn
& aOther
) const
715 if ((mColumnWidth
.GetUnit() == eStyleUnit_Auto
)
716 != (aOther
.mColumnWidth
.GetUnit() == eStyleUnit_Auto
) ||
717 mColumnCount
!= aOther
.mColumnCount
)
718 // We force column count changes to do a reframe, because it's tricky to handle
719 // some edge cases where the column count gets smaller and content overflows.
721 return NS_STYLE_HINT_FRAMECHANGE
;
723 if (mColumnWidth
!= aOther
.mColumnWidth
||
724 mColumnGap
!= aOther
.mColumnGap
)
725 return NS_STYLE_HINT_REFLOW
;
727 if (GetComputedColumnRuleWidth() != aOther
.GetComputedColumnRuleWidth() ||
728 mColumnRuleStyle
!= aOther
.mColumnRuleStyle
||
729 mColumnRuleColor
!= aOther
.mColumnRuleColor
||
730 mColumnRuleColorIsForeground
!= aOther
.mColumnRuleColorIsForeground
)
731 return NS_STYLE_HINT_VISUAL
;
733 return NS_STYLE_HINT_NONE
;
738 nsChangeHint
nsStyleColumn::MaxDifference()
740 return NS_STYLE_HINT_FRAMECHANGE
;
745 // --------------------
748 nsStyleSVG::nsStyleSVG()
750 mFill
.mType
= eStyleSVGPaintType_Color
;
751 mFill
.mPaint
.mColor
= NS_RGB(0,0,0);
752 mFill
.mFallbackColor
= NS_RGB(0,0,0);
753 mStroke
.mType
= eStyleSVGPaintType_None
;
754 mStroke
.mPaint
.mColor
= NS_RGB(0,0,0);
755 mStroke
.mFallbackColor
= NS_RGB(0,0,0);
756 mStrokeDasharray
= nsnull
;
758 mStrokeDashoffset
.SetCoordValue(0);
759 mStrokeWidth
.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1));
762 mStrokeMiterlimit
= 4.0f
;
763 mStrokeOpacity
= 1.0f
;
765 mStrokeDasharrayLength
= 0;
766 mClipRule
= NS_STYLE_FILL_RULE_NONZERO
;
767 mColorInterpolation
= NS_STYLE_COLOR_INTERPOLATION_SRGB
;
768 mColorInterpolationFilters
= NS_STYLE_COLOR_INTERPOLATION_LINEARRGB
;
769 mFillRule
= NS_STYLE_FILL_RULE_NONZERO
;
770 mPointerEvents
= NS_STYLE_POINTER_EVENTS_VISIBLEPAINTED
;
771 mShapeRendering
= NS_STYLE_SHAPE_RENDERING_AUTO
;
772 mStrokeLinecap
= NS_STYLE_STROKE_LINECAP_BUTT
;
773 mStrokeLinejoin
= NS_STYLE_STROKE_LINEJOIN_MITER
;
774 mTextAnchor
= NS_STYLE_TEXT_ANCHOR_START
;
775 mTextRendering
= NS_STYLE_TEXT_RENDERING_AUTO
;
778 nsStyleSVG::~nsStyleSVG()
780 delete [] mStrokeDasharray
;
783 nsStyleSVG::nsStyleSVG(const nsStyleSVG
& aSource
)
785 //memcpy((nsStyleSVG*)this, &aSource, sizeof(nsStyleSVG));
787 mFill
= aSource
.mFill
;
788 mStroke
= aSource
.mStroke
;
790 mMarkerEnd
= aSource
.mMarkerEnd
;
791 mMarkerMid
= aSource
.mMarkerMid
;
792 mMarkerStart
= aSource
.mMarkerStart
;
794 mStrokeDasharrayLength
= aSource
.mStrokeDasharrayLength
;
795 if (aSource
.mStrokeDasharray
) {
796 mStrokeDasharray
= new nsStyleCoord
[mStrokeDasharrayLength
];
797 if (mStrokeDasharray
)
798 memcpy(mStrokeDasharray
,
799 aSource
.mStrokeDasharray
,
800 mStrokeDasharrayLength
* sizeof(nsStyleCoord
));
802 mStrokeDasharrayLength
= 0;
804 mStrokeDasharray
= nsnull
;
807 mStrokeDashoffset
= aSource
.mStrokeDashoffset
;
808 mStrokeWidth
= aSource
.mStrokeWidth
;
810 mFillOpacity
= aSource
.mFillOpacity
;
811 mStrokeMiterlimit
= aSource
.mStrokeMiterlimit
;
812 mStrokeOpacity
= aSource
.mStrokeOpacity
;
814 mClipRule
= aSource
.mClipRule
;
815 mColorInterpolation
= aSource
.mColorInterpolation
;
816 mColorInterpolationFilters
= aSource
.mColorInterpolationFilters
;
817 mFillRule
= aSource
.mFillRule
;
818 mPointerEvents
= aSource
.mPointerEvents
;
819 mShapeRendering
= aSource
.mShapeRendering
;
820 mStrokeLinecap
= aSource
.mStrokeLinecap
;
821 mStrokeLinejoin
= aSource
.mStrokeLinejoin
;
822 mTextAnchor
= aSource
.mTextAnchor
;
823 mTextRendering
= aSource
.mTextRendering
;
826 static PRBool
PaintURIChanged(const nsStyleSVGPaint
& aPaint1
,
827 const nsStyleSVGPaint
& aPaint2
)
829 if (aPaint1
.mType
!= aPaint2
.mType
) {
830 return aPaint1
.mType
== eStyleSVGPaintType_Server
||
831 aPaint2
.mType
== eStyleSVGPaintType_Server
;
833 return aPaint1
.mType
== eStyleSVGPaintType_Server
&&
834 !EqualURIs(aPaint1
.mPaint
.mPaintServer
, aPaint2
.mPaint
.mPaintServer
);
837 nsChangeHint
nsStyleSVG::CalcDifference(const nsStyleSVG
& aOther
) const
839 nsChangeHint hint
= nsChangeHint(0);
841 if (mTextRendering
!= aOther
.mTextRendering
) {
842 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
843 // May be needed for non-svg frames
844 NS_UpdateHint(hint
, nsChangeHint_ReflowFrame
);
847 if (mFill
!= aOther
.mFill
||
848 mStroke
!= aOther
.mStroke
) {
849 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
850 if (PaintURIChanged(mFill
, aOther
.mFill
) ||
851 PaintURIChanged(mStroke
, aOther
.mStroke
)) {
852 NS_UpdateHint(hint
, nsChangeHint_UpdateEffects
);
854 // Nothing more to do, below we can only set "repaint"
858 if ( !EqualURIs(mMarkerEnd
, aOther
.mMarkerEnd
) ||
859 !EqualURIs(mMarkerMid
, aOther
.mMarkerMid
) ||
860 !EqualURIs(mMarkerStart
, aOther
.mMarkerStart
) ||
862 mStrokeDashoffset
!= aOther
.mStrokeDashoffset
||
863 mStrokeWidth
!= aOther
.mStrokeWidth
||
865 mFillOpacity
!= aOther
.mFillOpacity
||
866 mStrokeMiterlimit
!= aOther
.mStrokeMiterlimit
||
867 mStrokeOpacity
!= aOther
.mStrokeOpacity
||
869 mClipRule
!= aOther
.mClipRule
||
870 mColorInterpolation
!= aOther
.mColorInterpolation
||
871 mColorInterpolationFilters
!= aOther
.mColorInterpolationFilters
||
872 mFillRule
!= aOther
.mFillRule
||
873 mShapeRendering
!= aOther
.mShapeRendering
||
874 mStrokeDasharrayLength
!= aOther
.mStrokeDasharrayLength
||
875 mStrokeLinecap
!= aOther
.mStrokeLinecap
||
876 mStrokeLinejoin
!= aOther
.mStrokeLinejoin
||
877 mTextAnchor
!= aOther
.mTextAnchor
) {
878 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
882 // length of stroke dasharrays are the same (tested above) - check entries
883 for (PRUint32 i
=0; i
<mStrokeDasharrayLength
; i
++)
884 if (mStrokeDasharray
[i
] != aOther
.mStrokeDasharray
[i
]) {
885 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
894 nsChangeHint
nsStyleSVG::MaxDifference()
896 return NS_CombineHint(NS_CombineHint(nsChangeHint_UpdateEffects
,
897 nsChangeHint_ReflowFrame
),
898 nsChangeHint_RepaintFrame
);
902 // --------------------
905 nsStyleSVGReset::nsStyleSVGReset()
907 mStopColor
= NS_RGB(0,0,0);
908 mFloodColor
= NS_RGB(0,0,0);
909 mLightingColor
= NS_RGB(255,255,255);
914 mFloodOpacity
= 1.0f
;
915 mDominantBaseline
= NS_STYLE_DOMINANT_BASELINE_AUTO
;
918 nsStyleSVGReset::~nsStyleSVGReset()
922 nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset
& aSource
)
924 mStopColor
= aSource
.mStopColor
;
925 mFloodColor
= aSource
.mFloodColor
;
926 mLightingColor
= aSource
.mLightingColor
;
927 mClipPath
= aSource
.mClipPath
;
928 mFilter
= aSource
.mFilter
;
929 mMask
= aSource
.mMask
;
930 mStopOpacity
= aSource
.mStopOpacity
;
931 mFloodOpacity
= aSource
.mFloodOpacity
;
932 mDominantBaseline
= aSource
.mDominantBaseline
;
935 nsChangeHint
nsStyleSVGReset::CalcDifference(const nsStyleSVGReset
& aOther
) const
937 nsChangeHint hint
= nsChangeHint(0);
939 if (!EqualURIs(mClipPath
, aOther
.mClipPath
) ||
940 !EqualURIs(mFilter
, aOther
.mFilter
) ||
941 !EqualURIs(mMask
, aOther
.mMask
)) {
942 NS_UpdateHint(hint
, nsChangeHint_UpdateEffects
);
943 NS_UpdateHint(hint
, nsChangeHint_ReflowFrame
);
944 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
945 } else if (mStopColor
!= aOther
.mStopColor
||
946 mFloodColor
!= aOther
.mFloodColor
||
947 mLightingColor
!= aOther
.mLightingColor
||
948 mStopOpacity
!= aOther
.mStopOpacity
||
949 mFloodOpacity
!= aOther
.mFloodOpacity
||
950 mDominantBaseline
!= aOther
.mDominantBaseline
)
951 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
958 nsChangeHint
nsStyleSVGReset::MaxDifference()
960 return NS_CombineHint(NS_CombineHint(nsChangeHint_UpdateEffects
,
961 nsChangeHint_ReflowFrame
),
962 nsChangeHint_RepaintFrame
);
966 // nsStyleSVGPaint implementation
967 nsStyleSVGPaint::~nsStyleSVGPaint()
969 if (mType
== eStyleSVGPaintType_Server
) {
970 NS_IF_RELEASE(mPaint
.mPaintServer
);
975 nsStyleSVGPaint::SetType(nsStyleSVGPaintType aType
)
977 if (mType
== eStyleSVGPaintType_Server
) {
978 this->~nsStyleSVGPaint();
979 new (this) nsStyleSVGPaint();
984 nsStyleSVGPaint
& nsStyleSVGPaint::operator=(const nsStyleSVGPaint
& aOther
)
989 SetType(aOther
.mType
);
991 mFallbackColor
= aOther
.mFallbackColor
;
992 if (mType
== eStyleSVGPaintType_Server
) {
993 mPaint
.mPaintServer
= aOther
.mPaint
.mPaintServer
;
994 NS_IF_ADDREF(mPaint
.mPaintServer
);
996 mPaint
.mColor
= aOther
.mPaint
.mColor
;
1001 PRBool
nsStyleSVGPaint::operator==(const nsStyleSVGPaint
& aOther
) const
1003 if (mType
!= aOther
.mType
)
1005 if (mType
== eStyleSVGPaintType_Server
)
1006 return EqualURIs(mPaint
.mPaintServer
, aOther
.mPaint
.mPaintServer
) &&
1007 mFallbackColor
== aOther
.mFallbackColor
;
1008 if (mType
== eStyleSVGPaintType_None
)
1010 return mPaint
.mColor
== aOther
.mPaint
.mColor
;
1016 // --------------------
1019 nsStylePosition::nsStylePosition(void)
1021 // positioning values not inherited
1022 nsStyleCoord
autoCoord(eStyleUnit_Auto
);
1023 mOffset
.SetLeft(autoCoord
);
1024 mOffset
.SetTop(autoCoord
);
1025 mOffset
.SetRight(autoCoord
);
1026 mOffset
.SetBottom(autoCoord
);
1027 mWidth
.SetAutoValue();
1028 mMinWidth
.SetCoordValue(0);
1029 mMaxWidth
.SetNoneValue();
1030 mHeight
.SetAutoValue();
1031 mMinHeight
.SetCoordValue(0);
1032 mMaxHeight
.SetNoneValue();
1033 mBoxSizing
= NS_STYLE_BOX_SIZING_CONTENT
;
1034 mZIndex
.SetAutoValue();
1037 nsStylePosition::~nsStylePosition(void)
1041 nsStylePosition::nsStylePosition(const nsStylePosition
& aSource
)
1043 memcpy((nsStylePosition
*)this, &aSource
, sizeof(nsStylePosition
));
1046 nsChangeHint
nsStylePosition::CalcDifference(const nsStylePosition
& aOther
) const
1048 if (mZIndex
!= aOther
.mZIndex
) {
1049 return NS_STYLE_HINT_REFLOW
;
1052 if ((mOffset
== aOther
.mOffset
) &&
1053 (mWidth
== aOther
.mWidth
) &&
1054 (mMinWidth
== aOther
.mMinWidth
) &&
1055 (mMaxWidth
== aOther
.mMaxWidth
) &&
1056 (mHeight
== aOther
.mHeight
) &&
1057 (mMinHeight
== aOther
.mMinHeight
) &&
1058 (mMaxHeight
== aOther
.mMaxHeight
) &&
1059 (mBoxSizing
== aOther
.mBoxSizing
))
1060 return NS_STYLE_HINT_NONE
;
1062 return nsChangeHint_ReflowFrame
;
1067 nsChangeHint
nsStylePosition::MaxDifference()
1069 return NS_STYLE_HINT_REFLOW
;
1073 // --------------------
1077 nsStyleTable::nsStyleTable()
1079 // values not inherited
1080 mLayoutStrategy
= NS_STYLE_TABLE_LAYOUT_AUTO
;
1081 mCols
= NS_STYLE_TABLE_COLS_NONE
;
1082 mFrame
= NS_STYLE_TABLE_FRAME_NONE
;
1083 mRules
= NS_STYLE_TABLE_RULES_NONE
;
1087 nsStyleTable::~nsStyleTable(void)
1091 nsStyleTable::nsStyleTable(const nsStyleTable
& aSource
)
1093 memcpy((nsStyleTable
*)this, &aSource
, sizeof(nsStyleTable
));
1096 nsChangeHint
nsStyleTable::CalcDifference(const nsStyleTable
& aOther
) const
1098 // Changes in mRules may require reframing (if border-collapse stuff changes, for example).
1099 if (mRules
!= aOther
.mRules
|| mSpan
!= aOther
.mSpan
||
1100 mLayoutStrategy
!= aOther
.mLayoutStrategy
)
1101 return NS_STYLE_HINT_FRAMECHANGE
;
1102 if (mFrame
!= aOther
.mFrame
|| mCols
!= aOther
.mCols
)
1103 return NS_STYLE_HINT_REFLOW
;
1104 return NS_STYLE_HINT_NONE
;
1109 nsChangeHint
nsStyleTable::MaxDifference()
1111 return NS_STYLE_HINT_FRAMECHANGE
;
1115 // -----------------------
1116 // nsStyleTableBorder
1118 nsStyleTableBorder::nsStyleTableBorder(nsPresContext
* aPresContext
)
1120 mBorderCollapse
= NS_STYLE_BORDER_SEPARATE
;
1122 nsCompatibility compatMode
= eCompatibility_FullStandards
;
1124 compatMode
= aPresContext
->CompatibilityMode();
1125 mEmptyCells
= (compatMode
== eCompatibility_NavQuirks
)
1126 ? NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND
1127 : NS_STYLE_TABLE_EMPTY_CELLS_SHOW
;
1128 mCaptionSide
= NS_STYLE_CAPTION_SIDE_TOP
;
1129 mBorderSpacingX
= 0;
1130 mBorderSpacingY
= 0;
1133 nsStyleTableBorder::~nsStyleTableBorder(void)
1137 nsStyleTableBorder::nsStyleTableBorder(const nsStyleTableBorder
& aSource
)
1139 memcpy((nsStyleTableBorder
*)this, &aSource
, sizeof(nsStyleTableBorder
));
1142 nsChangeHint
nsStyleTableBorder::CalcDifference(const nsStyleTableBorder
& aOther
) const
1144 // Border-collapse changes need a reframe, because we use a different frame
1145 // class for table cells in the collapsed border model. This is used to
1146 // conserve memory when using the separated border model (collapsed borders
1147 // require extra state to be stored).
1148 if (mBorderCollapse
!= aOther
.mBorderCollapse
) {
1149 return NS_STYLE_HINT_FRAMECHANGE
;
1152 if ((mCaptionSide
== aOther
.mCaptionSide
) &&
1153 (mBorderSpacingX
== aOther
.mBorderSpacingX
) &&
1154 (mBorderSpacingY
== aOther
.mBorderSpacingY
)) {
1155 if (mEmptyCells
== aOther
.mEmptyCells
)
1156 return NS_STYLE_HINT_NONE
;
1157 return NS_STYLE_HINT_VISUAL
;
1160 return NS_STYLE_HINT_REFLOW
;
1165 nsChangeHint
nsStyleTableBorder::MaxDifference()
1167 return NS_STYLE_HINT_FRAMECHANGE
;
1171 // --------------------
1175 nsStyleColor::nsStyleColor(nsPresContext
* aPresContext
)
1177 mColor
= aPresContext
->DefaultColor();
1180 nsStyleColor::nsStyleColor(const nsStyleColor
& aSource
)
1182 mColor
= aSource
.mColor
;
1185 nsChangeHint
nsStyleColor::CalcDifference(const nsStyleColor
& aOther
) const
1187 if (mColor
== aOther
.mColor
)
1188 return NS_STYLE_HINT_NONE
;
1189 return NS_STYLE_HINT_VISUAL
;
1194 nsChangeHint
nsStyleColor::MaxDifference()
1196 return NS_STYLE_HINT_VISUAL
;
1200 // --------------------
1201 // nsStyleBackground
1204 nsStyleBackground::nsStyleBackground()
1205 : mBackgroundFlags(NS_STYLE_BG_IMAGE_NONE
),
1206 mBackgroundAttachment(NS_STYLE_BG_ATTACHMENT_SCROLL
),
1207 mBackgroundClip(NS_STYLE_BG_CLIP_BORDER
),
1208 mBackgroundInlinePolicy(NS_STYLE_BG_INLINE_POLICY_CONTINUOUS
),
1209 mBackgroundOrigin(NS_STYLE_BG_ORIGIN_PADDING
),
1210 mBackgroundRepeat(NS_STYLE_BG_REPEAT_XY
),
1211 mBackgroundColor(NS_RGBA(0, 0, 0, 0))
1215 nsStyleBackground::nsStyleBackground(const nsStyleBackground
& aSource
)
1216 : mBackgroundFlags(aSource
.mBackgroundFlags
),
1217 mBackgroundAttachment(aSource
.mBackgroundAttachment
),
1218 mBackgroundClip(aSource
.mBackgroundClip
),
1219 mBackgroundInlinePolicy(aSource
.mBackgroundInlinePolicy
),
1220 mBackgroundOrigin(aSource
.mBackgroundOrigin
),
1221 mBackgroundRepeat(aSource
.mBackgroundRepeat
),
1222 mBackgroundXPosition(aSource
.mBackgroundXPosition
),
1223 mBackgroundYPosition(aSource
.mBackgroundYPosition
),
1224 mBackgroundColor(aSource
.mBackgroundColor
),
1225 mBackgroundImage(aSource
.mBackgroundImage
)
1229 nsStyleBackground::~nsStyleBackground()
1233 nsChangeHint
nsStyleBackground::CalcDifference(const nsStyleBackground
& aOther
) const
1235 if ((mBackgroundAttachment
== aOther
.mBackgroundAttachment
) &&
1236 (mBackgroundFlags
== aOther
.mBackgroundFlags
) &&
1237 (mBackgroundRepeat
== aOther
.mBackgroundRepeat
) &&
1238 (mBackgroundColor
== aOther
.mBackgroundColor
) &&
1239 (mBackgroundClip
== aOther
.mBackgroundClip
) &&
1240 (mBackgroundInlinePolicy
== aOther
.mBackgroundInlinePolicy
) &&
1241 (mBackgroundOrigin
== aOther
.mBackgroundOrigin
) &&
1242 EqualImages(mBackgroundImage
, aOther
.mBackgroundImage
) &&
1243 ((!(mBackgroundFlags
& NS_STYLE_BG_X_POSITION_PERCENT
) ||
1244 (mBackgroundXPosition
.mFloat
== aOther
.mBackgroundXPosition
.mFloat
)) &&
1245 (!(mBackgroundFlags
& NS_STYLE_BG_X_POSITION_LENGTH
) ||
1246 (mBackgroundXPosition
.mCoord
== aOther
.mBackgroundXPosition
.mCoord
))) &&
1247 ((!(mBackgroundFlags
& NS_STYLE_BG_Y_POSITION_PERCENT
) ||
1248 (mBackgroundYPosition
.mFloat
== aOther
.mBackgroundYPosition
.mFloat
)) &&
1249 (!(mBackgroundFlags
& NS_STYLE_BG_Y_POSITION_LENGTH
) ||
1250 (mBackgroundYPosition
.mCoord
== aOther
.mBackgroundYPosition
.mCoord
))))
1251 return NS_STYLE_HINT_NONE
;
1252 return NS_STYLE_HINT_VISUAL
;
1257 nsChangeHint
nsStyleBackground::MaxDifference()
1259 return NS_STYLE_HINT_VISUAL
;
1263 PRBool
nsStyleBackground::HasFixedBackground() const
1265 return mBackgroundAttachment
== NS_STYLE_BG_ATTACHMENT_FIXED
&&
1269 // --------------------
1273 nsStyleDisplay::nsStyleDisplay()
1275 mAppearance
= NS_THEME_NONE
;
1276 mDisplay
= NS_STYLE_DISPLAY_INLINE
;
1277 mOriginalDisplay
= NS_STYLE_DISPLAY_NONE
;
1278 mPosition
= NS_STYLE_POSITION_STATIC
;
1279 mFloats
= NS_STYLE_FLOAT_NONE
;
1280 mBreakType
= NS_STYLE_CLEAR_NONE
;
1281 mBreakBefore
= PR_FALSE
;
1282 mBreakAfter
= PR_FALSE
;
1283 mOverflowX
= NS_STYLE_OVERFLOW_VISIBLE
;
1284 mOverflowY
= NS_STYLE_OVERFLOW_VISIBLE
;
1285 mClipFlags
= NS_STYLE_CLIP_AUTO
;
1286 mClip
.SetRect(0,0,0,0);
1288 mTransformPresent
= PR_FALSE
; // No transform
1289 mTransformOrigin
[0].SetPercentValue(0.5f
); // Transform is centered on origin
1290 mTransformOrigin
[1].SetPercentValue(0.5f
);
1293 nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay
& aSource
)
1295 mAppearance
= aSource
.mAppearance
;
1296 mDisplay
= aSource
.mDisplay
;
1297 mOriginalDisplay
= aSource
.mOriginalDisplay
;
1298 mBinding
= aSource
.mBinding
;
1299 mPosition
= aSource
.mPosition
;
1300 mFloats
= aSource
.mFloats
;
1301 mBreakType
= aSource
.mBreakType
;
1302 mBreakBefore
= aSource
.mBreakBefore
;
1303 mBreakAfter
= aSource
.mBreakAfter
;
1304 mOverflowX
= aSource
.mOverflowX
;
1305 mOverflowY
= aSource
.mOverflowY
;
1306 mClipFlags
= aSource
.mClipFlags
;
1307 mClip
= aSource
.mClip
;
1308 mOpacity
= aSource
.mOpacity
;
1310 /* Copy over the transformation information. */
1311 mTransformPresent
= aSource
.mTransformPresent
;
1312 if (mTransformPresent
)
1313 mTransform
= aSource
.mTransform
;
1315 /* Copy over transform origin. */
1316 mTransformOrigin
[0] = aSource
.mTransformOrigin
[0];
1317 mTransformOrigin
[1] = aSource
.mTransformOrigin
[1];
1320 nsChangeHint
nsStyleDisplay::CalcDifference(const nsStyleDisplay
& aOther
) const
1322 nsChangeHint hint
= nsChangeHint(0);
1324 if (!EqualURIs(mBinding
, aOther
.mBinding
)
1325 || mPosition
!= aOther
.mPosition
1326 || mDisplay
!= aOther
.mDisplay
1327 || (mFloats
== NS_STYLE_FLOAT_NONE
) != (aOther
.mFloats
== NS_STYLE_FLOAT_NONE
)
1328 || mOverflowX
!= aOther
.mOverflowX
1329 || mOverflowY
!= aOther
.mOverflowY
)
1330 NS_UpdateHint(hint
, nsChangeHint_ReconstructFrame
);
1332 if (mFloats
!= aOther
.mFloats
)
1333 NS_UpdateHint(hint
, nsChangeHint_ReflowFrame
);
1335 if (mClipFlags
!= aOther
.mClipFlags
|| mClip
!= aOther
.mClip
) {
1336 NS_UpdateHint(hint
, nsChangeHint_ReflowFrame
);
1338 // XXX the following is conservative, for now: changing float breaking shouldn't
1339 // necessarily require a repaint, reflow should suffice.
1340 if (mBreakType
!= aOther
.mBreakType
1341 || mBreakBefore
!= aOther
.mBreakBefore
1342 || mBreakAfter
!= aOther
.mBreakAfter
1343 || mAppearance
!= aOther
.mAppearance
)
1344 NS_UpdateHint(hint
, NS_CombineHint(nsChangeHint_ReflowFrame
, nsChangeHint_RepaintFrame
));
1346 if (mOpacity
!= aOther
.mOpacity
)
1347 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
1349 /* If we've added or removed the transform property, we need to reconstruct the frame to add
1350 * or remove the view object, and also to handle abs-pos and fixed-pos containers.
1352 if (mTransformPresent
!= aOther
.mTransformPresent
) {
1353 NS_UpdateHint(hint
, nsChangeHint_ReconstructFrame
);
1355 else if (mTransformPresent
) {
1356 /* Otherwise, if we've kept the property lying around and we already had a
1357 * transform, we need to see whether or not we've changed the transform.
1358 * If so, we need to do a reflow and a repaint. The reflow is to recompute
1359 * the overflow rect (which probably changed if the transform changed)
1360 * and to redraw within the bounds of that new overflow rect.
1362 if (mTransform
!= aOther
.mTransform
)
1363 NS_UpdateHint(hint
, NS_CombineHint(nsChangeHint_ReflowFrame
,
1364 nsChangeHint_RepaintFrame
));
1366 for (PRUint8 index
= 0; index
< 2; ++index
)
1367 if (mTransformOrigin
[index
] != aOther
.mTransformOrigin
[index
]) {
1368 NS_UpdateHint(hint
, NS_CombineHint(nsChangeHint_ReflowFrame
,
1369 nsChangeHint_RepaintFrame
));
1380 nsChangeHint
nsStyleDisplay::MaxDifference()
1382 // All the parts of FRAMECHANGE are present above in CalcDifference.
1383 return NS_STYLE_HINT_FRAMECHANGE
;
1387 // --------------------
1388 // nsStyleVisibility
1391 nsStyleVisibility::nsStyleVisibility(nsPresContext
* aPresContext
)
1393 PRUint32 bidiOptions
= aPresContext
->GetBidi();
1394 if (GET_BIDI_OPTION_DIRECTION(bidiOptions
) == IBMBIDI_TEXTDIRECTION_RTL
)
1395 mDirection
= NS_STYLE_DIRECTION_RTL
;
1397 mDirection
= NS_STYLE_DIRECTION_LTR
;
1399 mLangGroup
= aPresContext
->GetLangGroup();
1400 mVisible
= NS_STYLE_VISIBILITY_VISIBLE
;
1403 nsStyleVisibility::nsStyleVisibility(const nsStyleVisibility
& aSource
)
1405 mDirection
= aSource
.mDirection
;
1406 mVisible
= aSource
.mVisible
;
1407 mLangGroup
= aSource
.mLangGroup
;
1410 nsChangeHint
nsStyleVisibility::CalcDifference(const nsStyleVisibility
& aOther
) const
1412 if ((mDirection
== aOther
.mDirection
) &&
1413 (mLangGroup
== aOther
.mLangGroup
)) {
1414 if ((mVisible
== aOther
.mVisible
)) {
1415 return NS_STYLE_HINT_NONE
;
1417 if ((NS_STYLE_VISIBILITY_COLLAPSE
== mVisible
) ||
1418 (NS_STYLE_VISIBILITY_COLLAPSE
== aOther
.mVisible
)) {
1419 return NS_STYLE_HINT_REFLOW
;
1421 return NS_STYLE_HINT_VISUAL
;
1423 return NS_STYLE_HINT_REFLOW
;
1428 nsChangeHint
nsStyleVisibility::MaxDifference()
1430 return NS_STYLE_HINT_REFLOW
;
1434 nsStyleContentData::~nsStyleContentData()
1436 if (mType
== eStyleContentType_Image
) {
1437 NS_IF_RELEASE(mContent
.mImage
);
1438 } else if (mType
== eStyleContentType_Counter
||
1439 mType
== eStyleContentType_Counters
) {
1440 mContent
.mCounters
->Release();
1441 } else if (mContent
.mString
) {
1442 NS_Free(mContent
.mString
);
1446 nsStyleContentData
& nsStyleContentData::operator=(const nsStyleContentData
& aOther
)
1448 if (this == &aOther
)
1450 this->~nsStyleContentData();
1451 new (this) nsStyleContentData();
1453 mType
= aOther
.mType
;
1454 if (mType
== eStyleContentType_Image
) {
1455 mContent
.mImage
= aOther
.mContent
.mImage
;
1456 NS_IF_ADDREF(mContent
.mImage
);
1457 } else if (mType
== eStyleContentType_Counter
||
1458 mType
== eStyleContentType_Counters
) {
1459 mContent
.mCounters
= aOther
.mContent
.mCounters
;
1460 mContent
.mCounters
->AddRef();
1461 } else if (aOther
.mContent
.mString
) {
1462 mContent
.mString
= NS_strdup(aOther
.mContent
.mString
);
1464 mContent
.mString
= nsnull
;
1469 PRBool
nsStyleContentData::operator==(const nsStyleContentData
& aOther
) const
1471 if (mType
!= aOther
.mType
)
1473 if (mType
== eStyleContentType_Image
) {
1474 if (!mContent
.mImage
|| !aOther
.mContent
.mImage
)
1475 return mContent
.mImage
== aOther
.mContent
.mImage
;
1477 nsCOMPtr
<nsIURI
> thisURI
, otherURI
;
1478 mContent
.mImage
->GetURI(getter_AddRefs(thisURI
));
1479 aOther
.mContent
.mImage
->GetURI(getter_AddRefs(otherURI
));
1480 return thisURI
== otherURI
|| // handles null==null
1481 (thisURI
&& otherURI
&&
1482 NS_SUCCEEDED(thisURI
->Equals(otherURI
, &eq
)) &&
1485 if (mType
== eStyleContentType_Counter
||
1486 mType
== eStyleContentType_Counters
)
1487 return *mContent
.mCounters
== *aOther
.mContent
.mCounters
;
1488 return nsCRT::strcmp(mContent
.mString
, aOther
.mContent
.mString
) == 0;
1491 //-----------------------
1495 nsStyleContent::nsStyleContent(void)
1500 mIncrements(nsnull
),
1504 mMarkerOffset
.SetAutoValue();
1507 nsStyleContent::~nsStyleContent(void)
1509 DELETE_ARRAY_IF(mContents
);
1510 DELETE_ARRAY_IF(mIncrements
);
1511 DELETE_ARRAY_IF(mResets
);
1514 nsStyleContent::nsStyleContent(const nsStyleContent
& aSource
)
1519 mIncrements(nsnull
),
1524 mMarkerOffset
= aSource
.mMarkerOffset
;
1527 if (NS_SUCCEEDED(AllocateContents(aSource
.ContentCount()))) {
1528 for (index
= 0; index
< mContentCount
; index
++) {
1529 ContentAt(index
) = aSource
.ContentAt(index
);
1533 if (NS_SUCCEEDED(AllocateCounterIncrements(aSource
.CounterIncrementCount()))) {
1534 for (index
= 0; index
< mIncrementCount
; index
++) {
1535 const nsStyleCounterData
*data
= aSource
.GetCounterIncrementAt(index
);
1536 mIncrements
[index
].mCounter
= data
->mCounter
;
1537 mIncrements
[index
].mValue
= data
->mValue
;
1541 if (NS_SUCCEEDED(AllocateCounterResets(aSource
.CounterResetCount()))) {
1542 for (index
= 0; index
< mResetCount
; index
++) {
1543 const nsStyleCounterData
*data
= aSource
.GetCounterResetAt(index
);
1544 mResets
[index
].mCounter
= data
->mCounter
;
1545 mResets
[index
].mValue
= data
->mValue
;
1550 nsChangeHint
nsStyleContent::CalcDifference(const nsStyleContent
& aOther
) const
1552 if (mContentCount
!= aOther
.mContentCount
||
1553 mIncrementCount
!= aOther
.mIncrementCount
||
1554 mResetCount
!= aOther
.mResetCount
) {
1555 return NS_STYLE_HINT_FRAMECHANGE
;
1558 PRUint32 ix
= mContentCount
;
1560 if (mContents
[ix
] != aOther
.mContents
[ix
]) {
1561 // Unfortunately we need to reframe here; a simple reflow
1562 // will not pick up different text or different image URLs,
1563 // since we set all that up in the CSSFrameConstructor
1564 return NS_STYLE_HINT_FRAMECHANGE
;
1567 ix
= mIncrementCount
;
1569 if ((mIncrements
[ix
].mValue
!= aOther
.mIncrements
[ix
].mValue
) ||
1570 (mIncrements
[ix
].mCounter
!= aOther
.mIncrements
[ix
].mCounter
)) {
1571 return NS_STYLE_HINT_FRAMECHANGE
;
1576 if ((mResets
[ix
].mValue
!= aOther
.mResets
[ix
].mValue
) ||
1577 (mResets
[ix
].mCounter
!= aOther
.mResets
[ix
].mCounter
)) {
1578 return NS_STYLE_HINT_FRAMECHANGE
;
1581 if (mMarkerOffset
!= aOther
.mMarkerOffset
) {
1582 return NS_STYLE_HINT_REFLOW
;
1584 return NS_STYLE_HINT_NONE
;
1589 nsChangeHint
nsStyleContent::MaxDifference()
1591 return NS_STYLE_HINT_FRAMECHANGE
;
1595 nsresult
nsStyleContent::AllocateContents(PRUint32 aCount
)
1597 // We need to run the destructors of the elements of mContents, so we
1598 // delete and reallocate even if aCount == mContentCount. (If
1599 // nsStyleContentData had its members private and managed their
1600 // ownership on setting, we wouldn't need this, but that seems
1601 // unnecessary at this point.)
1602 DELETE_ARRAY_IF(mContents
);
1604 mContents
= new nsStyleContentData
[aCount
];
1607 return NS_ERROR_OUT_OF_MEMORY
;
1610 mContentCount
= aCount
;
1614 // ---------------------
1618 nsStyleQuotes::nsStyleQuotes(void)
1625 nsStyleQuotes::~nsStyleQuotes(void)
1627 DELETE_ARRAY_IF(mQuotes
);
1630 nsStyleQuotes::nsStyleQuotes(const nsStyleQuotes
& aSource
)
1638 nsStyleQuotes::SetInitial()
1640 // The initial value for quotes is the en-US typographic convention:
1641 // outermost are LEFT and RIGHT DOUBLE QUOTATION MARK, alternating
1642 // with LEFT and RIGHT SINGLE QUOTATION MARK.
1643 static const PRUnichar initialQuotes
[8] = {
1644 0x201C, 0, 0x201D, 0, 0x2018, 0, 0x2019, 0
1647 if (NS_SUCCEEDED(AllocateQuotes(2))) {
1649 nsDependentString(&initialQuotes
[0], 1),
1650 nsDependentString(&initialQuotes
[2], 1));
1652 nsDependentString(&initialQuotes
[4], 1),
1653 nsDependentString(&initialQuotes
[6], 1));
1658 nsStyleQuotes::CopyFrom(const nsStyleQuotes
& aSource
)
1660 if (NS_SUCCEEDED(AllocateQuotes(aSource
.QuotesCount()))) {
1661 PRUint32 count
= (mQuotesCount
* 2);
1662 for (PRUint32 index
= 0; index
< count
; index
+= 2) {
1663 aSource
.GetQuotesAt(index
, mQuotes
[index
], mQuotes
[index
+ 1]);
1668 nsChangeHint
nsStyleQuotes::CalcDifference(const nsStyleQuotes
& aOther
) const
1670 // If the quotes implementation is ever going to change we might not need
1671 // a framechange here and a reflow should be sufficient. See bug 35768.
1672 if (mQuotesCount
== aOther
.mQuotesCount
) {
1673 PRUint32 ix
= (mQuotesCount
* 2);
1675 if (mQuotes
[ix
] != aOther
.mQuotes
[ix
]) {
1676 return NS_STYLE_HINT_FRAMECHANGE
;
1680 return NS_STYLE_HINT_NONE
;
1682 return NS_STYLE_HINT_FRAMECHANGE
;
1687 nsChangeHint
nsStyleQuotes::MaxDifference()
1689 return NS_STYLE_HINT_FRAMECHANGE
;
1693 // --------------------
1697 nsStyleTextReset::nsStyleTextReset(void)
1699 mVerticalAlign
.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE
, eStyleUnit_Enumerated
);
1700 mTextDecoration
= NS_STYLE_TEXT_DECORATION_NONE
;
1701 mUnicodeBidi
= NS_STYLE_UNICODE_BIDI_NORMAL
;
1704 nsStyleTextReset::nsStyleTextReset(const nsStyleTextReset
& aSource
)
1706 memcpy((nsStyleTextReset
*)this, &aSource
, sizeof(nsStyleTextReset
));
1709 nsStyleTextReset::~nsStyleTextReset(void) { }
1711 nsChangeHint
nsStyleTextReset::CalcDifference(const nsStyleTextReset
& aOther
) const
1713 if (mVerticalAlign
== aOther
.mVerticalAlign
1714 && mUnicodeBidi
== aOther
.mUnicodeBidi
) {
1715 if (mTextDecoration
!= aOther
.mTextDecoration
) {
1716 // Reflow for blink changes, repaint for others
1718 (mTextDecoration
& NS_STYLE_TEXT_DECORATION_BLINK
) ==
1719 (aOther
.mTextDecoration
& NS_STYLE_TEXT_DECORATION_BLINK
) ?
1720 NS_STYLE_HINT_VISUAL
: NS_STYLE_HINT_REFLOW
;
1723 return NS_STYLE_HINT_NONE
;
1725 return NS_STYLE_HINT_REFLOW
;
1730 nsChangeHint
nsStyleTextReset::MaxDifference()
1732 return NS_STYLE_HINT_REFLOW
;
1736 // --------------------
1742 nsCSSShadowArray::Release()
1752 // Allowed to return one of NS_STYLE_HINT_NONE, NS_STYLE_HINT_REFLOW
1753 // or NS_STYLE_HINT_VISUAL. Currently we just return NONE or REFLOW, though.
1755 CalcShadowDifference(nsCSSShadowArray
* lhs
,
1756 nsCSSShadowArray
* rhs
)
1759 return NS_STYLE_HINT_NONE
;
1761 if (!lhs
|| !rhs
|| lhs
->Length() != rhs
->Length())
1762 return NS_STYLE_HINT_REFLOW
;
1764 for (PRUint32 i
= 0; i
< lhs
->Length(); ++i
) {
1765 if (*lhs
->ShadowAt(i
) != *rhs
->ShadowAt(i
))
1766 return NS_STYLE_HINT_REFLOW
;
1768 return NS_STYLE_HINT_NONE
;
1771 // --------------------
1775 nsStyleText::nsStyleText(void)
1777 mTextAlign
= NS_STYLE_TEXT_ALIGN_DEFAULT
;
1778 mTextTransform
= NS_STYLE_TEXT_TRANSFORM_NONE
;
1779 mWhiteSpace
= NS_STYLE_WHITESPACE_NORMAL
;
1780 mWordWrap
= NS_STYLE_WORDWRAP_NORMAL
;
1782 mLetterSpacing
.SetNormalValue();
1783 mLineHeight
.SetNormalValue();
1784 mTextIndent
.SetCoordValue(0);
1785 mWordSpacing
.SetNormalValue();
1787 mTextShadow
= nsnull
;
1790 nsStyleText::nsStyleText(const nsStyleText
& aSource
)
1791 : mTextAlign(aSource
.mTextAlign
),
1792 mTextTransform(aSource
.mTextTransform
),
1793 mWhiteSpace(aSource
.mWhiteSpace
),
1794 mWordWrap(aSource
.mWordWrap
),
1795 mLetterSpacing(aSource
.mLetterSpacing
),
1796 mLineHeight(aSource
.mLineHeight
),
1797 mTextIndent(aSource
.mTextIndent
),
1798 mWordSpacing(aSource
.mWordSpacing
),
1799 mTextShadow(aSource
.mTextShadow
)
1802 nsStyleText::~nsStyleText(void) { }
1804 nsChangeHint
nsStyleText::CalcDifference(const nsStyleText
& aOther
) const
1806 if ((mTextAlign
!= aOther
.mTextAlign
) ||
1807 (mTextTransform
!= aOther
.mTextTransform
) ||
1808 (mWhiteSpace
!= aOther
.mWhiteSpace
) ||
1809 (mWordWrap
!= aOther
.mWordWrap
) ||
1810 (mLetterSpacing
!= aOther
.mLetterSpacing
) ||
1811 (mLineHeight
!= aOther
.mLineHeight
) ||
1812 (mTextIndent
!= aOther
.mTextIndent
) ||
1813 (mWordSpacing
!= aOther
.mWordSpacing
))
1814 return NS_STYLE_HINT_REFLOW
;
1816 return CalcShadowDifference(mTextShadow
, aOther
.mTextShadow
);
1821 nsChangeHint
nsStyleText::MaxDifference()
1823 return NS_STYLE_HINT_REFLOW
;
1827 //-----------------------
1828 // nsStyleUserInterface
1831 nsCursorImage::nsCursorImage()
1832 : mHaveHotspot(PR_FALSE
)
1838 nsStyleUserInterface::nsStyleUserInterface(void)
1840 mUserInput
= NS_STYLE_USER_INPUT_AUTO
;
1841 mUserModify
= NS_STYLE_USER_MODIFY_READ_ONLY
;
1842 mUserFocus
= NS_STYLE_USER_FOCUS_NONE
;
1844 mCursor
= NS_STYLE_CURSOR_AUTO
; // fix for bugzilla bug 51113
1846 mCursorArrayLength
= 0;
1847 mCursorArray
= nsnull
;
1850 nsStyleUserInterface::nsStyleUserInterface(const nsStyleUserInterface
& aSource
) :
1851 mUserInput(aSource
.mUserInput
),
1852 mUserModify(aSource
.mUserModify
),
1853 mUserFocus(aSource
.mUserFocus
),
1854 mCursor(aSource
.mCursor
)
1856 CopyCursorArrayFrom(aSource
);
1859 nsStyleUserInterface::~nsStyleUserInterface(void)
1861 delete [] mCursorArray
;
1864 nsChangeHint
nsStyleUserInterface::CalcDifference(const nsStyleUserInterface
& aOther
) const
1866 nsChangeHint hint
= nsChangeHint(0);
1867 if (mCursor
!= aOther
.mCursor
)
1868 NS_UpdateHint(hint
, nsChangeHint_UpdateCursor
);
1870 // We could do better. But it wouldn't be worth it, URL-specified cursors are
1872 if (mCursorArrayLength
> 0 || aOther
.mCursorArrayLength
> 0)
1873 NS_UpdateHint(hint
, nsChangeHint_UpdateCursor
);
1875 if (mUserModify
!= aOther
.mUserModify
)
1876 NS_UpdateHint(hint
, NS_STYLE_HINT_VISUAL
);
1878 if ((mUserInput
!= aOther
.mUserInput
) &&
1879 ((NS_STYLE_USER_INPUT_NONE
== mUserInput
) ||
1880 (NS_STYLE_USER_INPUT_NONE
== aOther
.mUserInput
))) {
1881 NS_UpdateHint(hint
, NS_STYLE_HINT_FRAMECHANGE
);
1884 // ignore mUserFocus
1891 nsChangeHint
nsStyleUserInterface::MaxDifference()
1893 return nsChangeHint(nsChangeHint_UpdateCursor
| NS_STYLE_HINT_FRAMECHANGE
);
1898 nsStyleUserInterface::CopyCursorArrayFrom(const nsStyleUserInterface
& aSource
)
1900 mCursorArray
= nsnull
;
1901 mCursorArrayLength
= 0;
1902 if (aSource
.mCursorArrayLength
) {
1903 mCursorArray
= new nsCursorImage
[aSource
.mCursorArrayLength
];
1905 mCursorArrayLength
= aSource
.mCursorArrayLength
;
1906 for (PRUint32 i
= 0; i
< mCursorArrayLength
; ++i
)
1907 mCursorArray
[i
] = aSource
.mCursorArray
[i
];
1912 //-----------------------
1916 nsStyleUIReset::nsStyleUIReset(void)
1918 mUserSelect
= NS_STYLE_USER_SELECT_AUTO
;
1919 mForceBrokenImageIcon
= 0;
1920 mIMEMode
= NS_STYLE_IME_MODE_AUTO
;
1921 mWindowShadow
= NS_STYLE_WINDOW_SHADOW_DEFAULT
;
1924 nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset
& aSource
)
1926 mUserSelect
= aSource
.mUserSelect
;
1927 mForceBrokenImageIcon
= aSource
.mForceBrokenImageIcon
;
1928 mIMEMode
= aSource
.mIMEMode
;
1929 mWindowShadow
= aSource
.mWindowShadow
;
1932 nsStyleUIReset::~nsStyleUIReset(void)
1936 nsChangeHint
nsStyleUIReset::CalcDifference(const nsStyleUIReset
& aOther
) const
1939 if (mForceBrokenImageIcon
!= aOther
.mForceBrokenImageIcon
)
1940 return NS_STYLE_HINT_FRAMECHANGE
;
1941 if (mWindowShadow
!= aOther
.mWindowShadow
) {
1942 // We really need just an nsChangeHint_SyncFrameView, except
1943 // on an ancestor of the frame, so we get that by doing a
1945 return NS_STYLE_HINT_REFLOW
;
1947 if (mUserSelect
!= aOther
.mUserSelect
)
1948 return NS_STYLE_HINT_VISUAL
;
1949 return NS_STYLE_HINT_NONE
;
1954 nsChangeHint
nsStyleUIReset::MaxDifference()
1956 return NS_STYLE_HINT_FRAMECHANGE
;