Bug 461267, bump version to 3.0.5pre/1.9.0.5pre, p=joduinn, r=nthomas
[mozilla-1.9.git] / layout / style / nsStyleStruct.cpp
blob56facf68de26971b75257ea193f30b3d2f244f40
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
13 * License.
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.
22 * Contributor(s):
23 * David Hyatt (hyatt@netscape.com)
24 * Mats Palmgren <mats.palmgren@bredband.net>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
41 * structs that contain the data provided by nsStyleContext, the
42 * internal API for computed style data for an element
45 #include "nsStyleStruct.h"
46 #include "nsStyleConsts.h"
47 #include "nsThemeConstants.h"
48 #include "nsString.h"
49 #include "nsPresContext.h"
50 #include "nsIDeviceContext.h"
51 #include "nsIStyleRule.h"
52 #include "nsCRT.h"
54 #include "nsCOMPtr.h"
55 #include "nsIPresShell.h"
56 #include "nsIFrame.h"
57 #include "nsHTMLReflowState.h"
58 #include "prenv.h"
60 #include "nsBidiUtils.h"
62 #include "imgIRequest.h"
63 #include "prlog.h"
65 // Make sure we have enough bits in NS_STYLE_INHERIT_MASK.
66 PR_STATIC_ASSERT((((1 << nsStyleStructID_Length) - 1) &
67 ~(NS_STYLE_INHERIT_MASK)) == 0);
69 inline PRBool IsFixedUnit(nsStyleUnit aUnit, PRBool aEnumOK)
71 return PRBool((aUnit == eStyleUnit_Coord) ||
72 (aEnumOK && (aUnit == eStyleUnit_Enumerated)));
75 static PRBool EqualURIs(nsIURI *aURI1, nsIURI *aURI2)
77 PRBool eq;
78 return aURI1 == aURI2 || // handle null==null, and optimize
79 (aURI1 && aURI2 &&
80 NS_SUCCEEDED(aURI1->Equals(aURI2, &eq)) && // not equal on fail
81 eq);
84 static PRBool EqualURIs(nsCSSValue::URL *aURI1, nsCSSValue::URL *aURI2)
86 return aURI1 == aURI2 || // handle null==null, and optimize
87 (aURI1 && aURI2 && aURI1->URIEquals(*aURI2));
90 static PRBool EqualImages(imgIRequest *aImage1, imgIRequest* aImage2)
92 if (aImage1 == aImage2) {
93 return PR_TRUE;
96 if (!aImage1 || !aImage2) {
97 return PR_FALSE;
100 nsCOMPtr<nsIURI> uri1, uri2;
101 aImage1->GetURI(getter_AddRefs(uri1));
102 aImage2->GetURI(getter_AddRefs(uri2));
103 return EqualURIs(uri1, uri2);
106 // --------------------
107 // nsStyleFont
109 nsStyleFont::nsStyleFont(const nsFont& aFont, nsPresContext *aPresContext)
110 : mFont(aFont),
111 mFlags(NS_STYLE_FONT_DEFAULT)
113 mSize = mFont.size = nsStyleFont::ZoomText(aPresContext, mFont.size);
114 #ifdef MOZ_MATHML
115 mScriptUnconstrainedSize = mSize;
116 mScriptMinSize = aPresContext->TwipsToAppUnits(
117 NS_POINTS_TO_TWIPS(NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT));
118 mScriptLevel = 0;
119 mScriptSizeMultiplier = NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER;
120 #endif
123 nsStyleFont::nsStyleFont(const nsStyleFont& aSrc)
124 : mFont(aSrc.mFont)
125 , mSize(aSrc.mSize)
126 , mFlags(aSrc.mFlags)
127 #ifdef MOZ_MATHML
128 , mScriptLevel(aSrc.mScriptLevel)
129 , mScriptUnconstrainedSize(aSrc.mScriptUnconstrainedSize)
130 , mScriptMinSize(aSrc.mScriptMinSize)
131 , mScriptSizeMultiplier(aSrc.mScriptSizeMultiplier)
132 #endif
136 nsStyleFont::nsStyleFont(nsPresContext* aPresContext)
137 : mFont(*(aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID))),
138 mFlags(NS_STYLE_FONT_DEFAULT)
140 mSize = mFont.size = nsStyleFont::ZoomText(aPresContext, mFont.size);
141 #ifdef MOZ_MATHML
142 mScriptUnconstrainedSize = mSize;
143 mScriptMinSize = aPresContext->TwipsToAppUnits(
144 NS_POINTS_TO_TWIPS(NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT));
145 mScriptLevel = 0;
146 mScriptSizeMultiplier = NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER;
147 #endif
150 void*
151 nsStyleFont::operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
152 void* result = aContext->AllocateFromShell(sz);
153 if (result)
154 memset(result, 0, sz);
155 return result;
158 void
159 nsStyleFont::Destroy(nsPresContext* aContext) {
160 this->~nsStyleFont();
161 aContext->FreeToShell(sizeof(nsStyleFont), this);
164 nsChangeHint nsStyleFont::CalcDifference(const nsStyleFont& aOther) const
166 if (mSize == aOther.mSize) {
167 return CalcFontDifference(mFont, aOther.mFont);
169 return NS_STYLE_HINT_REFLOW;
172 #ifdef DEBUG
173 /* static */
174 nsChangeHint nsStyleFont::MaxDifference()
176 return NS_STYLE_HINT_REFLOW;
178 #endif
180 /* static */ nscoord
181 nsStyleFont::ZoomText(nsPresContext *aPresContext, nscoord aSize)
183 return nscoord(float(aSize) * aPresContext->TextZoom());
186 /* static */ nscoord
187 nsStyleFont::UnZoomText(nsPresContext *aPresContext, nscoord aSize)
189 return nscoord(float(aSize) / aPresContext->TextZoom());
192 nsChangeHint nsStyleFont::CalcFontDifference(const nsFont& aFont1, const nsFont& aFont2)
194 if ((aFont1.size == aFont2.size) &&
195 (aFont1.sizeAdjust == aFont2.sizeAdjust) &&
196 (aFont1.style == aFont2.style) &&
197 (aFont1.variant == aFont2.variant) &&
198 (aFont1.familyNameQuirks == aFont2.familyNameQuirks) &&
199 (aFont1.weight == aFont2.weight) &&
200 (aFont1.name == aFont2.name)) {
201 if ((aFont1.decorations == aFont2.decorations)) {
202 return NS_STYLE_HINT_NONE;
204 return NS_STYLE_HINT_VISUAL;
206 return NS_STYLE_HINT_REFLOW;
209 static PRBool IsFixedData(const nsStyleSides& aSides, PRBool aEnumOK)
211 NS_FOR_CSS_SIDES(side) {
212 if (!IsFixedUnit(aSides.GetUnit(side), aEnumOK))
213 return PR_FALSE;
215 return PR_TRUE;
218 static nscoord CalcCoord(const nsStyleCoord& aCoord,
219 const nscoord* aEnumTable,
220 PRInt32 aNumEnums)
222 switch (aCoord.GetUnit()) {
223 case eStyleUnit_Coord:
224 return aCoord.GetCoordValue();
225 case eStyleUnit_Enumerated:
226 if (nsnull != aEnumTable) {
227 PRInt32 value = aCoord.GetIntValue();
228 if ((0 <= value) && (value < aNumEnums)) {
229 return aEnumTable[aCoord.GetIntValue()];
232 break;
233 case eStyleUnit_Chars:
234 // XXX we need a frame and a rendering context to calculate this, bug 281972, bug 282126.
235 NS_NOTYETIMPLEMENTED("CalcCoord: eStyleUnit_Chars");
236 return 0;
237 default:
238 NS_ERROR("bad unit type");
239 break;
241 return 0;
244 nsStyleMargin::nsStyleMargin() {
245 nsStyleCoord zero(0);
246 NS_FOR_CSS_SIDES(side) {
247 mMargin.Set(side, zero);
249 mHasCachedMargin = PR_FALSE;
252 nsStyleMargin::nsStyleMargin(const nsStyleMargin& aSrc) {
253 mMargin = aSrc.mMargin;
254 mHasCachedMargin = PR_FALSE;
257 void*
258 nsStyleMargin::operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
259 void* result = aContext->AllocateFromShell(sz);
260 if (result)
261 memset(result, 0, sz);
262 return result;
265 void
266 nsStyleMargin::Destroy(nsPresContext* aContext) {
267 this->~nsStyleMargin();
268 aContext->FreeToShell(sizeof(nsStyleMargin), this);
272 void nsStyleMargin::RecalcData()
274 if (IsFixedData(mMargin, PR_FALSE)) {
275 NS_FOR_CSS_SIDES(side) {
276 mCachedMargin.side(side) = CalcCoord(mMargin.Get(side), nsnull, 0);
278 mHasCachedMargin = PR_TRUE;
280 else
281 mHasCachedMargin = PR_FALSE;
284 nsChangeHint nsStyleMargin::CalcDifference(const nsStyleMargin& aOther) const
286 if (mMargin == aOther.mMargin) {
287 return NS_STYLE_HINT_NONE;
289 return NS_STYLE_HINT_REFLOW;
292 #ifdef DEBUG
293 /* static */
294 nsChangeHint nsStyleMargin::MaxDifference()
296 return NS_STYLE_HINT_REFLOW;
298 #endif
300 nsStylePadding::nsStylePadding() {
301 nsStyleCoord zero(0);
302 NS_FOR_CSS_SIDES(side) {
303 mPadding.Set(side, zero);
305 mHasCachedPadding = PR_FALSE;
308 nsStylePadding::nsStylePadding(const nsStylePadding& aSrc) {
309 mPadding = aSrc.mPadding;
310 mHasCachedPadding = PR_FALSE;
313 void*
314 nsStylePadding::operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
315 void* result = aContext->AllocateFromShell(sz);
316 if (result)
317 memset(result, 0, sz);
318 return result;
321 void
322 nsStylePadding::Destroy(nsPresContext* aContext) {
323 this->~nsStylePadding();
324 aContext->FreeToShell(sizeof(nsStylePadding), this);
327 void nsStylePadding::RecalcData()
329 if (IsFixedData(mPadding, PR_FALSE)) {
330 NS_FOR_CSS_SIDES(side) {
331 mCachedPadding.side(side) = CalcCoord(mPadding.Get(side), nsnull, 0);
333 mHasCachedPadding = PR_TRUE;
335 else
336 mHasCachedPadding = PR_FALSE;
339 nsChangeHint nsStylePadding::CalcDifference(const nsStylePadding& aOther) const
341 if (mPadding == aOther.mPadding) {
342 return NS_STYLE_HINT_NONE;
344 return NS_STYLE_HINT_REFLOW;
347 #ifdef DEBUG
348 /* static */
349 nsChangeHint nsStylePadding::MaxDifference()
351 return NS_STYLE_HINT_REFLOW;
353 #endif
355 nsStyleBorder::nsStyleBorder(nsPresContext* aPresContext)
356 : mActualBorder(0, 0, 0, 0)
358 nscoord medium =
359 (aPresContext->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM];
360 NS_FOR_CSS_SIDES(side) {
361 mBorder.side(side) = medium;
362 mBorderStyle[side] = NS_STYLE_BORDER_STYLE_NONE | BORDER_COLOR_FOREGROUND;
363 mBorderColor[side] = NS_RGB(0, 0, 0);
364 mBorderRadius.Set(side, nsStyleCoord(0));
367 mBorderColors = nsnull;
369 mFloatEdge = NS_STYLE_FLOAT_EDGE_CONTENT;
371 mTwipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
374 nsStyleBorder::nsStyleBorder(const nsStyleBorder& aSrc)
376 memcpy((nsStyleBorder*)this, &aSrc, sizeof(nsStyleBorder));
377 mBorderColors = nsnull;
378 if (aSrc.mBorderColors) {
379 EnsureBorderColors();
380 for (PRInt32 i = 0; i < 4; i++)
381 if (aSrc.mBorderColors[i])
382 mBorderColors[i] = aSrc.mBorderColors[i]->CopyColors();
383 else
384 mBorderColors[i] = nsnull;
388 void*
389 nsStyleBorder::operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
390 void* result = aContext->AllocateFromShell(sz);
391 if (result)
392 memset(result, 0, sz);
393 return result;
396 void
397 nsStyleBorder::Destroy(nsPresContext* aContext) {
398 this->~nsStyleBorder();
399 aContext->FreeToShell(sizeof(nsStyleBorder), this);
403 nsChangeHint nsStyleBorder::CalcDifference(const nsStyleBorder& aOther) const
405 // Note that differences in mBorder don't affect rendering (which should only
406 // use mComputedBorder), so don't need to be tested for here.
407 if (mTwipsPerPixel == aOther.mTwipsPerPixel &&
408 mActualBorder == aOther.mActualBorder &&
409 mFloatEdge == aOther.mFloatEdge) {
410 // Note that mBorderStyle stores not only the border style but also
411 // color-related flags. Given that we've already done an mComputedBorder
412 // comparison, border-style differences can only lead to a VISUAL hint. So
413 // it's OK to just compare the values directly -- if either the actual
414 // style or the color flags differ we want to repaint.
415 NS_FOR_CSS_SIDES(ix) {
416 if (mBorderStyle[ix] != aOther.mBorderStyle[ix] ||
417 mBorderColor[ix] != aOther.mBorderColor[ix]) {
418 return NS_STYLE_HINT_VISUAL;
422 if (mBorderRadius != aOther.mBorderRadius ||
423 !mBorderColors != !aOther.mBorderColors) {
424 return NS_STYLE_HINT_VISUAL;
427 // Note that at this point if mBorderColors is non-null so is
428 // aOther.mBorderColors
429 if (mBorderColors) {
430 NS_FOR_CSS_SIDES(ix) {
431 if (!mBorderColors[ix] != !aOther.mBorderColors[ix]) {
432 return NS_STYLE_HINT_VISUAL;
433 } else if (mBorderColors[ix] && aOther.mBorderColors[ix]) {
434 if (!mBorderColors[ix]->Equals(aOther.mBorderColors[ix]))
435 return NS_STYLE_HINT_VISUAL;
441 return NS_STYLE_HINT_NONE;
443 return NS_STYLE_HINT_REFLOW;
446 #ifdef DEBUG
447 /* static */
448 nsChangeHint nsStyleBorder::MaxDifference()
450 return NS_STYLE_HINT_REFLOW;
452 #endif
454 nsStyleOutline::nsStyleOutline(nsPresContext* aPresContext)
456 // spacing values not inherited
457 nsStyleCoord zero(0);
458 NS_FOR_CSS_SIDES(side) {
459 mOutlineRadius.Set(side, zero);
462 mOutlineOffset.SetCoordValue(0);
464 mOutlineWidth = nsStyleCoord(NS_STYLE_BORDER_WIDTH_MEDIUM, eStyleUnit_Enumerated);
465 mOutlineStyle = NS_STYLE_BORDER_STYLE_NONE;
466 mOutlineColor = NS_RGB(0, 0, 0);
468 mHasCachedOutline = PR_FALSE;
469 mTwipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
472 nsStyleOutline::nsStyleOutline(const nsStyleOutline& aSrc) {
473 memcpy((nsStyleOutline*)this, &aSrc, sizeof(nsStyleOutline));
476 void
477 nsStyleOutline::RecalcData(nsPresContext* aContext)
479 if (NS_STYLE_BORDER_STYLE_NONE == GetOutlineStyle()) {
480 mCachedOutlineWidth = 0;
481 mHasCachedOutline = PR_TRUE;
482 } else if (IsFixedUnit(mOutlineWidth.GetUnit(), PR_TRUE)) {
483 mCachedOutlineWidth =
484 CalcCoord(mOutlineWidth, aContext->GetBorderWidthTable(), 3);
485 mCachedOutlineWidth =
486 NS_ROUND_BORDER_TO_PIXELS(mCachedOutlineWidth, mTwipsPerPixel);
487 mHasCachedOutline = PR_TRUE;
489 else
490 mHasCachedOutline = PR_FALSE;
493 nsChangeHint nsStyleOutline::CalcDifference(const nsStyleOutline& aOther) const
495 PRBool outlineWasVisible =
496 mCachedOutlineWidth > 0 && mOutlineStyle != NS_STYLE_BORDER_STYLE_NONE;
497 PRBool outlineIsVisible =
498 aOther.mCachedOutlineWidth > 0 && aOther.mOutlineStyle != NS_STYLE_BORDER_STYLE_NONE;
499 if (outlineWasVisible != outlineIsVisible ||
500 (outlineIsVisible && (mOutlineOffset != aOther.mOutlineOffset ||
501 mOutlineWidth != aOther.mOutlineWidth ||
502 mTwipsPerPixel != aOther.mTwipsPerPixel))) {
503 return NS_CombineHint(nsChangeHint_ReflowFrame, nsChangeHint_RepaintFrame);
505 if ((mOutlineStyle != aOther.mOutlineStyle) ||
506 (mOutlineColor != aOther.mOutlineColor) ||
507 (mOutlineRadius != aOther.mOutlineRadius)) {
508 return nsChangeHint_RepaintFrame;
510 return NS_STYLE_HINT_NONE;
513 #ifdef DEBUG
514 /* static */
515 nsChangeHint nsStyleOutline::MaxDifference()
517 return NS_CombineHint(nsChangeHint_ReflowFrame, nsChangeHint_RepaintFrame);
519 #endif
521 // --------------------
522 // nsStyleList
524 nsStyleList::nsStyleList()
525 : mListStyleType(NS_STYLE_LIST_STYLE_DISC),
526 mListStylePosition(NS_STYLE_LIST_STYLE_POSITION_OUTSIDE)
530 nsStyleList::~nsStyleList()
534 nsStyleList::nsStyleList(const nsStyleList& aSource)
535 : mListStyleType(aSource.mListStyleType),
536 mListStylePosition(aSource.mListStylePosition),
537 mListStyleImage(aSource.mListStyleImage),
538 mImageRegion(aSource.mImageRegion)
542 nsChangeHint nsStyleList::CalcDifference(const nsStyleList& aOther) const
544 if (mListStylePosition != aOther.mListStylePosition)
545 return NS_STYLE_HINT_FRAMECHANGE;
546 if (EqualImages(mListStyleImage, aOther.mListStyleImage) &&
547 mListStyleType == aOther.mListStyleType) {
548 if (mImageRegion == aOther.mImageRegion)
549 return NS_STYLE_HINT_NONE;
550 if (mImageRegion.width == aOther.mImageRegion.width &&
551 mImageRegion.height == aOther.mImageRegion.height)
552 return NS_STYLE_HINT_VISUAL;
554 return NS_STYLE_HINT_REFLOW;
557 #ifdef DEBUG
558 /* static */
559 nsChangeHint nsStyleList::MaxDifference()
561 return NS_STYLE_HINT_FRAMECHANGE;
563 #endif
565 // --------------------
566 // nsStyleXUL
568 nsStyleXUL::nsStyleXUL()
570 mBoxAlign = NS_STYLE_BOX_ALIGN_STRETCH;
571 mBoxDirection = NS_STYLE_BOX_DIRECTION_NORMAL;
572 mBoxFlex = 0.0f;
573 mBoxOrient = NS_STYLE_BOX_ORIENT_HORIZONTAL;
574 mBoxPack = NS_STYLE_BOX_PACK_START;
575 mBoxOrdinal = 1;
578 nsStyleXUL::~nsStyleXUL()
582 nsStyleXUL::nsStyleXUL(const nsStyleXUL& aSource)
584 memcpy((nsStyleXUL*)this, &aSource, sizeof(nsStyleXUL));
587 nsChangeHint nsStyleXUL::CalcDifference(const nsStyleXUL& aOther) const
589 if (mBoxAlign == aOther.mBoxAlign &&
590 mBoxDirection == aOther.mBoxDirection &&
591 mBoxFlex == aOther.mBoxFlex &&
592 mBoxOrient == aOther.mBoxOrient &&
593 mBoxPack == aOther.mBoxPack &&
594 mBoxOrdinal == aOther.mBoxOrdinal)
595 return NS_STYLE_HINT_NONE;
596 if (mBoxOrdinal != aOther.mBoxOrdinal)
597 return NS_STYLE_HINT_FRAMECHANGE;
598 return NS_STYLE_HINT_REFLOW;
601 #ifdef DEBUG
602 /* static */
603 nsChangeHint nsStyleXUL::MaxDifference()
605 return NS_STYLE_HINT_FRAMECHANGE;
607 #endif
609 // --------------------
610 // nsStyleColumn
612 nsStyleColumn::nsStyleColumn()
614 mColumnCount = NS_STYLE_COLUMN_COUNT_AUTO;
615 mColumnWidth.SetAutoValue();
616 mColumnGap.SetNormalValue();
619 nsStyleColumn::~nsStyleColumn()
623 nsStyleColumn::nsStyleColumn(const nsStyleColumn& aSource)
625 memcpy((nsStyleColumn*)this, &aSource, sizeof(nsStyleColumn));
628 nsChangeHint nsStyleColumn::CalcDifference(const nsStyleColumn& aOther) const
630 if ((mColumnWidth.GetUnit() == eStyleUnit_Auto)
631 != (aOther.mColumnWidth.GetUnit() == eStyleUnit_Auto) ||
632 mColumnCount != aOther.mColumnCount)
633 // We force column count changes to do a reframe, because it's tricky to handle
634 // some edge cases where the column count gets smaller and content overflows.
635 // XXX not ideal
636 return nsChangeHint_ReconstructFrame;
638 if (mColumnWidth != aOther.mColumnWidth ||
639 mColumnGap != aOther.mColumnGap)
640 return nsChangeHint_ReflowFrame;
642 return NS_STYLE_HINT_NONE;
645 #ifdef DEBUG
646 /* static */
647 nsChangeHint nsStyleColumn::MaxDifference()
649 return NS_CombineHint(nsChangeHint_ReconstructFrame,
650 nsChangeHint_ReflowFrame);
652 #endif
654 #ifdef MOZ_SVG
655 // --------------------
656 // nsStyleSVG
658 nsStyleSVG::nsStyleSVG()
660 mFill.mType = eStyleSVGPaintType_Color;
661 mFill.mPaint.mColor = NS_RGB(0,0,0);
662 mFill.mFallbackColor = NS_RGB(0,0,0);
663 mStroke.mType = eStyleSVGPaintType_None;
664 mStroke.mPaint.mColor = NS_RGB(0,0,0);
665 mStroke.mFallbackColor = NS_RGB(0,0,0);
666 mStrokeDasharray = nsnull;
668 mStrokeDashoffset.SetCoordValue(0);
669 mStrokeWidth.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1));
671 mFillOpacity = 1.0f;
672 mStrokeMiterlimit = 4.0f;
673 mStrokeOpacity = 1.0f;
675 mStrokeDasharrayLength = 0;
676 mClipRule = NS_STYLE_FILL_RULE_NONZERO;
677 mColorInterpolation = NS_STYLE_COLOR_INTERPOLATION_SRGB;
678 mColorInterpolationFilters = NS_STYLE_COLOR_INTERPOLATION_LINEARRGB;
679 mFillRule = NS_STYLE_FILL_RULE_NONZERO;
680 mPointerEvents = NS_STYLE_POINTER_EVENTS_VISIBLEPAINTED;
681 mShapeRendering = NS_STYLE_SHAPE_RENDERING_AUTO;
682 mStrokeLinecap = NS_STYLE_STROKE_LINECAP_BUTT;
683 mStrokeLinejoin = NS_STYLE_STROKE_LINEJOIN_MITER;
684 mTextAnchor = NS_STYLE_TEXT_ANCHOR_START;
685 mTextRendering = NS_STYLE_TEXT_RENDERING_AUTO;
688 nsStyleSVG::~nsStyleSVG()
690 delete [] mStrokeDasharray;
693 nsStyleSVG::nsStyleSVG(const nsStyleSVG& aSource)
695 //memcpy((nsStyleSVG*)this, &aSource, sizeof(nsStyleSVG));
697 mFill = aSource.mFill;
698 mStroke = aSource.mStroke;
700 mMarkerEnd = aSource.mMarkerEnd;
701 mMarkerMid = aSource.mMarkerMid;
702 mMarkerStart = aSource.mMarkerStart;
704 mStrokeDasharrayLength = aSource.mStrokeDasharrayLength;
705 if (aSource.mStrokeDasharray) {
706 mStrokeDasharray = new nsStyleCoord[mStrokeDasharrayLength];
707 if (mStrokeDasharray)
708 memcpy(mStrokeDasharray,
709 aSource.mStrokeDasharray,
710 mStrokeDasharrayLength * sizeof(nsStyleCoord));
711 else
712 mStrokeDasharrayLength = 0;
713 } else {
714 mStrokeDasharray = nsnull;
717 mStrokeDashoffset = aSource.mStrokeDashoffset;
718 mStrokeWidth = aSource.mStrokeWidth;
720 mFillOpacity = aSource.mFillOpacity;
721 mStrokeMiterlimit = aSource.mStrokeMiterlimit;
722 mStrokeOpacity = aSource.mStrokeOpacity;
724 mClipRule = aSource.mClipRule;
725 mColorInterpolation = aSource.mColorInterpolation;
726 mColorInterpolationFilters = aSource.mColorInterpolationFilters;
727 mFillRule = aSource.mFillRule;
728 mPointerEvents = aSource.mPointerEvents;
729 mShapeRendering = aSource.mShapeRendering;
730 mStrokeLinecap = aSource.mStrokeLinecap;
731 mStrokeLinejoin = aSource.mStrokeLinejoin;
732 mTextAnchor = aSource.mTextAnchor;
733 mTextRendering = aSource.mTextRendering;
736 nsChangeHint nsStyleSVG::CalcDifference(const nsStyleSVG& aOther) const
738 if ( mFill != aOther.mFill ||
739 mStroke != aOther.mStroke ||
741 !EqualURIs(mMarkerEnd, aOther.mMarkerEnd) ||
742 !EqualURIs(mMarkerMid, aOther.mMarkerMid) ||
743 !EqualURIs(mMarkerStart, aOther.mMarkerStart) ||
745 mStrokeDashoffset != aOther.mStrokeDashoffset ||
746 mStrokeWidth != aOther.mStrokeWidth ||
748 mFillOpacity != aOther.mFillOpacity ||
749 mStrokeMiterlimit != aOther.mStrokeMiterlimit ||
750 mStrokeOpacity != aOther.mStrokeOpacity ||
752 mClipRule != aOther.mClipRule ||
753 mColorInterpolation != aOther.mColorInterpolation ||
754 mColorInterpolationFilters != aOther.mColorInterpolationFilters ||
755 mFillRule != aOther.mFillRule ||
756 mPointerEvents != aOther.mPointerEvents ||
757 mShapeRendering != aOther.mShapeRendering ||
758 mStrokeDasharrayLength != aOther.mStrokeDasharrayLength ||
759 mStrokeLinecap != aOther.mStrokeLinecap ||
760 mStrokeLinejoin != aOther.mStrokeLinejoin ||
761 mTextAnchor != aOther.mTextAnchor ||
762 mTextRendering != aOther.mTextRendering)
763 return NS_STYLE_HINT_VISUAL;
765 // length of stroke dasharrays are the same (tested above) - check entries
766 for (PRUint32 i=0; i<mStrokeDasharrayLength; i++)
767 if (mStrokeDasharray[i] != aOther.mStrokeDasharray[i])
768 return NS_STYLE_HINT_VISUAL;
770 return NS_STYLE_HINT_NONE;
773 #ifdef DEBUG
774 /* static */
775 nsChangeHint nsStyleSVG::MaxDifference()
777 return NS_STYLE_HINT_VISUAL;
779 #endif
781 // --------------------
782 // nsStyleSVGReset
784 nsStyleSVGReset::nsStyleSVGReset()
786 mStopColor = NS_RGB(0,0,0);
787 mFloodColor = NS_RGB(0,0,0);
788 mLightingColor = NS_RGB(255,255,255);
789 mClipPath = nsnull;
790 mFilter = nsnull;
791 mMask = nsnull;
792 mStopOpacity = 1.0f;
793 mFloodOpacity = 1.0f;
794 mDominantBaseline = NS_STYLE_DOMINANT_BASELINE_AUTO;
797 nsStyleSVGReset::~nsStyleSVGReset()
801 nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset& aSource)
803 mStopColor = aSource.mStopColor;
804 mFloodColor = aSource.mFloodColor;
805 mLightingColor = aSource.mLightingColor;
806 mClipPath = aSource.mClipPath;
807 mFilter = aSource.mFilter;
808 mMask = aSource.mMask;
809 mStopOpacity = aSource.mStopOpacity;
810 mFloodOpacity = aSource.mFloodOpacity;
811 mDominantBaseline = aSource.mDominantBaseline;
814 nsChangeHint nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aOther) const
816 if (mStopColor != aOther.mStopColor ||
817 mFloodColor != aOther.mFloodColor ||
818 mLightingColor != aOther.mLightingColor ||
819 !EqualURIs(mClipPath, aOther.mClipPath) ||
820 !EqualURIs(mFilter, aOther.mFilter) ||
821 !EqualURIs(mMask, aOther.mMask) ||
822 mStopOpacity != aOther.mStopOpacity ||
823 mFloodOpacity != aOther.mFloodOpacity ||
824 mDominantBaseline != aOther.mDominantBaseline)
825 return NS_STYLE_HINT_VISUAL;
827 return NS_STYLE_HINT_NONE;
830 #ifdef DEBUG
831 /* static */
832 nsChangeHint nsStyleSVGReset::MaxDifference()
834 return NS_STYLE_HINT_VISUAL;
836 #endif
838 // nsStyleSVGPaint implementation
839 nsStyleSVGPaint::~nsStyleSVGPaint()
841 if (mType == eStyleSVGPaintType_Server) {
842 NS_IF_RELEASE(mPaint.mPaintServer);
846 void
847 nsStyleSVGPaint::SetType(nsStyleSVGPaintType aType)
849 if (mType == eStyleSVGPaintType_Server) {
850 this->~nsStyleSVGPaint();
851 new (this) nsStyleSVGPaint();
853 mType = aType;
856 nsStyleSVGPaint& nsStyleSVGPaint::operator=(const nsStyleSVGPaint& aOther)
858 if (this == &aOther)
859 return *this;
861 SetType(aOther.mType);
863 mFallbackColor = aOther.mFallbackColor;
864 if (mType == eStyleSVGPaintType_Server) {
865 mPaint.mPaintServer = aOther.mPaint.mPaintServer;
866 NS_IF_ADDREF(mPaint.mPaintServer);
867 } else {
868 mPaint.mColor = aOther.mPaint.mColor;
870 return *this;
873 PRBool nsStyleSVGPaint::operator==(const nsStyleSVGPaint& aOther) const
875 if (mType != aOther.mType)
876 return PR_FALSE;
877 if (mType == eStyleSVGPaintType_Server)
878 return EqualURIs(mPaint.mPaintServer, aOther.mPaint.mPaintServer) &&
879 mFallbackColor == aOther.mFallbackColor;
880 if (mType == eStyleSVGPaintType_None)
881 return PR_TRUE;
882 return mPaint.mColor == aOther.mPaint.mColor;
885 #endif // MOZ_SVG
888 // --------------------
889 // nsStylePosition
891 nsStylePosition::nsStylePosition(void)
893 // positioning values not inherited
894 nsStyleCoord autoCoord(eStyleUnit_Auto);
895 mOffset.SetLeft(autoCoord);
896 mOffset.SetTop(autoCoord);
897 mOffset.SetRight(autoCoord);
898 mOffset.SetBottom(autoCoord);
899 mWidth.SetAutoValue();
900 mMinWidth.SetCoordValue(0);
901 mMaxWidth.SetNoneValue();
902 mHeight.SetAutoValue();
903 mMinHeight.SetCoordValue(0);
904 mMaxHeight.SetNoneValue();
905 mBoxSizing = NS_STYLE_BOX_SIZING_CONTENT;
906 mZIndex.SetAutoValue();
909 nsStylePosition::~nsStylePosition(void)
913 nsStylePosition::nsStylePosition(const nsStylePosition& aSource)
915 memcpy((nsStylePosition*)this, &aSource, sizeof(nsStylePosition));
918 nsChangeHint nsStylePosition::CalcDifference(const nsStylePosition& aOther) const
920 if (mZIndex != aOther.mZIndex) {
921 return NS_STYLE_HINT_REFLOW;
924 if ((mOffset == aOther.mOffset) &&
925 (mWidth == aOther.mWidth) &&
926 (mMinWidth == aOther.mMinWidth) &&
927 (mMaxWidth == aOther.mMaxWidth) &&
928 (mHeight == aOther.mHeight) &&
929 (mMinHeight == aOther.mMinHeight) &&
930 (mMaxHeight == aOther.mMaxHeight) &&
931 (mBoxSizing == aOther.mBoxSizing))
932 return NS_STYLE_HINT_NONE;
934 return nsChangeHint_ReflowFrame;
937 #ifdef DEBUG
938 /* static */
939 nsChangeHint nsStylePosition::MaxDifference()
941 return NS_STYLE_HINT_REFLOW;
943 #endif
945 // --------------------
946 // nsStyleTable
949 nsStyleTable::nsStyleTable()
951 // values not inherited
952 mLayoutStrategy = NS_STYLE_TABLE_LAYOUT_AUTO;
953 mCols = NS_STYLE_TABLE_COLS_NONE;
954 mFrame = NS_STYLE_TABLE_FRAME_NONE;
955 mRules = NS_STYLE_TABLE_RULES_NONE;
956 mSpan = 1;
959 nsStyleTable::~nsStyleTable(void)
963 nsStyleTable::nsStyleTable(const nsStyleTable& aSource)
965 memcpy((nsStyleTable*)this, &aSource, sizeof(nsStyleTable));
968 nsChangeHint nsStyleTable::CalcDifference(const nsStyleTable& aOther) const
970 // Changes in mRules may require reframing (if border-collapse stuff changes, for example).
971 if (mRules != aOther.mRules || mSpan != aOther.mSpan ||
972 mLayoutStrategy != aOther.mLayoutStrategy)
973 return NS_STYLE_HINT_FRAMECHANGE;
974 if (mFrame != aOther.mFrame || mCols != aOther.mCols)
975 return NS_STYLE_HINT_REFLOW;
976 return NS_STYLE_HINT_NONE;
979 #ifdef DEBUG
980 /* static */
981 nsChangeHint nsStyleTable::MaxDifference()
983 return NS_STYLE_HINT_FRAMECHANGE;
985 #endif
987 // -----------------------
988 // nsStyleTableBorder
990 nsStyleTableBorder::nsStyleTableBorder(nsPresContext* aPresContext)
992 mBorderCollapse = NS_STYLE_BORDER_SEPARATE;
994 nsCompatibility compatMode = eCompatibility_FullStandards;
995 if (aPresContext)
996 compatMode = aPresContext->CompatibilityMode();
997 mEmptyCells = (compatMode == eCompatibility_NavQuirks)
998 ? NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND
999 : NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
1000 mCaptionSide = NS_STYLE_CAPTION_SIDE_TOP;
1001 mBorderSpacingX.SetCoordValue(0);
1002 mBorderSpacingY.SetCoordValue(0);
1005 nsStyleTableBorder::~nsStyleTableBorder(void)
1009 nsStyleTableBorder::nsStyleTableBorder(const nsStyleTableBorder& aSource)
1011 memcpy((nsStyleTableBorder*)this, &aSource, sizeof(nsStyleTableBorder));
1014 nsChangeHint nsStyleTableBorder::CalcDifference(const nsStyleTableBorder& aOther) const
1016 // Border-collapse changes need a reframe, because we use a different frame
1017 // class for table cells in the collapsed border model. This is used to
1018 // conserve memory when using the separated border model (collapsed borders
1019 // require extra state to be stored).
1020 if (mBorderCollapse != aOther.mBorderCollapse) {
1021 return NS_STYLE_HINT_FRAMECHANGE;
1024 if ((mCaptionSide == aOther.mCaptionSide) &&
1025 (mBorderSpacingX == aOther.mBorderSpacingX) &&
1026 (mBorderSpacingY == aOther.mBorderSpacingY)) {
1027 if (mEmptyCells == aOther.mEmptyCells)
1028 return NS_STYLE_HINT_NONE;
1029 return NS_STYLE_HINT_VISUAL;
1031 else
1032 return NS_STYLE_HINT_REFLOW;
1035 #ifdef DEBUG
1036 /* static */
1037 nsChangeHint nsStyleTableBorder::MaxDifference()
1039 return NS_STYLE_HINT_FRAMECHANGE;
1041 #endif
1043 // --------------------
1044 // nsStyleColor
1047 nsStyleColor::nsStyleColor(nsPresContext* aPresContext)
1049 mColor = aPresContext->DefaultColor();
1052 nsStyleColor::nsStyleColor(const nsStyleColor& aSource)
1054 mColor = aSource.mColor;
1057 nsChangeHint nsStyleColor::CalcDifference(const nsStyleColor& aOther) const
1059 if (mColor == aOther.mColor)
1060 return NS_STYLE_HINT_NONE;
1061 return NS_STYLE_HINT_VISUAL;
1064 #ifdef DEBUG
1065 /* static */
1066 nsChangeHint nsStyleColor::MaxDifference()
1068 return NS_STYLE_HINT_VISUAL;
1070 #endif
1072 // --------------------
1073 // nsStyleBackground
1076 nsStyleBackground::nsStyleBackground(nsPresContext* aPresContext)
1077 : mBackgroundFlags(NS_STYLE_BG_COLOR_TRANSPARENT | NS_STYLE_BG_IMAGE_NONE),
1078 mBackgroundAttachment(NS_STYLE_BG_ATTACHMENT_SCROLL),
1079 mBackgroundClip(NS_STYLE_BG_CLIP_BORDER),
1080 mBackgroundInlinePolicy(NS_STYLE_BG_INLINE_POLICY_CONTINUOUS),
1081 mBackgroundOrigin(NS_STYLE_BG_ORIGIN_PADDING),
1082 mBackgroundRepeat(NS_STYLE_BG_REPEAT_XY)
1084 mBackgroundColor = aPresContext->DefaultBackgroundColor();
1087 nsStyleBackground::nsStyleBackground(const nsStyleBackground& aSource)
1088 : mBackgroundFlags(aSource.mBackgroundFlags),
1089 mBackgroundAttachment(aSource.mBackgroundAttachment),
1090 mBackgroundClip(aSource.mBackgroundClip),
1091 mBackgroundInlinePolicy(aSource.mBackgroundInlinePolicy),
1092 mBackgroundOrigin(aSource.mBackgroundOrigin),
1093 mBackgroundRepeat(aSource.mBackgroundRepeat),
1094 mBackgroundXPosition(aSource.mBackgroundXPosition),
1095 mBackgroundYPosition(aSource.mBackgroundYPosition),
1096 mBackgroundColor(aSource.mBackgroundColor),
1097 mBackgroundImage(aSource.mBackgroundImage)
1101 nsStyleBackground::~nsStyleBackground()
1105 nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther) const
1107 if ((mBackgroundAttachment == aOther.mBackgroundAttachment) &&
1108 (mBackgroundFlags == aOther.mBackgroundFlags) &&
1109 (mBackgroundRepeat == aOther.mBackgroundRepeat) &&
1110 (mBackgroundColor == aOther.mBackgroundColor) &&
1111 (mBackgroundClip == aOther.mBackgroundClip) &&
1112 (mBackgroundInlinePolicy == aOther.mBackgroundInlinePolicy) &&
1113 (mBackgroundOrigin == aOther.mBackgroundOrigin) &&
1114 EqualImages(mBackgroundImage, aOther.mBackgroundImage) &&
1115 ((!(mBackgroundFlags & NS_STYLE_BG_X_POSITION_PERCENT) ||
1116 (mBackgroundXPosition.mFloat == aOther.mBackgroundXPosition.mFloat)) &&
1117 (!(mBackgroundFlags & NS_STYLE_BG_X_POSITION_LENGTH) ||
1118 (mBackgroundXPosition.mCoord == aOther.mBackgroundXPosition.mCoord))) &&
1119 ((!(mBackgroundFlags & NS_STYLE_BG_Y_POSITION_PERCENT) ||
1120 (mBackgroundYPosition.mFloat == aOther.mBackgroundYPosition.mFloat)) &&
1121 (!(mBackgroundFlags & NS_STYLE_BG_Y_POSITION_LENGTH) ||
1122 (mBackgroundYPosition.mCoord == aOther.mBackgroundYPosition.mCoord))))
1123 return NS_STYLE_HINT_NONE;
1124 return NS_STYLE_HINT_VISUAL;
1127 #ifdef DEBUG
1128 /* static */
1129 nsChangeHint nsStyleBackground::MaxDifference()
1131 return NS_STYLE_HINT_VISUAL;
1133 #endif
1135 PRBool nsStyleBackground::HasFixedBackground() const
1137 return mBackgroundAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
1138 mBackgroundImage;
1141 // --------------------
1142 // nsStyleDisplay
1145 nsStyleDisplay::nsStyleDisplay()
1147 mAppearance = NS_THEME_NONE;
1148 mDisplay = NS_STYLE_DISPLAY_INLINE;
1149 mOriginalDisplay = NS_STYLE_DISPLAY_NONE;
1150 mPosition = NS_STYLE_POSITION_STATIC;
1151 mFloats = NS_STYLE_FLOAT_NONE;
1152 mBreakType = NS_STYLE_CLEAR_NONE;
1153 mBreakBefore = PR_FALSE;
1154 mBreakAfter = PR_FALSE;
1155 mOverflowX = NS_STYLE_OVERFLOW_VISIBLE;
1156 mOverflowY = NS_STYLE_OVERFLOW_VISIBLE;
1157 mClipFlags = NS_STYLE_CLIP_AUTO;
1158 mClip.SetRect(0,0,0,0);
1159 mOpacity = 1.0f;
1162 nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource)
1164 mAppearance = aSource.mAppearance;
1165 mDisplay = aSource.mDisplay;
1166 mOriginalDisplay = aSource.mOriginalDisplay;
1167 mBinding = aSource.mBinding;
1168 mPosition = aSource.mPosition;
1169 mFloats = aSource.mFloats;
1170 mBreakType = aSource.mBreakType;
1171 mBreakBefore = aSource.mBreakBefore;
1172 mBreakAfter = aSource.mBreakAfter;
1173 mOverflowX = aSource.mOverflowX;
1174 mOverflowY = aSource.mOverflowY;
1175 mClipFlags = aSource.mClipFlags;
1176 mClip = aSource.mClip;
1177 mOpacity = aSource.mOpacity;
1180 nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
1182 nsChangeHint hint = nsChangeHint(0);
1184 if (!EqualURIs(mBinding, aOther.mBinding)
1185 || mPosition != aOther.mPosition
1186 || mDisplay != aOther.mDisplay
1187 || (mFloats == NS_STYLE_FLOAT_NONE) != (aOther.mFloats == NS_STYLE_FLOAT_NONE)
1188 || mOverflowX != aOther.mOverflowX
1189 || mOverflowY != aOther.mOverflowY)
1190 NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
1192 if (mFloats != aOther.mFloats)
1193 NS_UpdateHint(hint, nsChangeHint_ReflowFrame);
1195 if (mClipFlags != aOther.mClipFlags || mClip != aOther.mClip) {
1196 NS_UpdateHint(hint, nsChangeHint_ReflowFrame);
1198 // XXX the following is conservative, for now: changing float breaking shouldn't
1199 // necessarily require a repaint, reflow should suffice.
1200 if (mBreakType != aOther.mBreakType
1201 || mBreakBefore != aOther.mBreakBefore
1202 || mBreakAfter != aOther.mBreakAfter
1203 || mAppearance != aOther.mAppearance)
1204 NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_ReflowFrame, nsChangeHint_RepaintFrame));
1206 if (mOpacity != aOther.mOpacity)
1207 NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
1209 return hint;
1212 #ifdef DEBUG
1213 /* static */
1214 nsChangeHint nsStyleDisplay::MaxDifference()
1216 // All the parts of FRAMECHANGE are present above in CalcDifference.
1217 return NS_STYLE_HINT_FRAMECHANGE;
1219 #endif
1221 // --------------------
1222 // nsStyleVisibility
1225 nsStyleVisibility::nsStyleVisibility(nsPresContext* aPresContext)
1227 PRUint32 bidiOptions = aPresContext->GetBidi();
1228 if (GET_BIDI_OPTION_DIRECTION(bidiOptions) == IBMBIDI_TEXTDIRECTION_RTL)
1229 mDirection = NS_STYLE_DIRECTION_RTL;
1230 else
1231 mDirection = NS_STYLE_DIRECTION_LTR;
1233 mLangGroup = aPresContext->GetLangGroup();
1234 mVisible = NS_STYLE_VISIBILITY_VISIBLE;
1237 nsStyleVisibility::nsStyleVisibility(const nsStyleVisibility& aSource)
1239 mDirection = aSource.mDirection;
1240 mVisible = aSource.mVisible;
1241 mLangGroup = aSource.mLangGroup;
1244 nsChangeHint nsStyleVisibility::CalcDifference(const nsStyleVisibility& aOther) const
1246 if ((mDirection == aOther.mDirection) &&
1247 (mLangGroup == aOther.mLangGroup)) {
1248 if ((mVisible == aOther.mVisible)) {
1249 return NS_STYLE_HINT_NONE;
1251 if ((NS_STYLE_VISIBILITY_COLLAPSE == mVisible) ||
1252 (NS_STYLE_VISIBILITY_COLLAPSE == aOther.mVisible)) {
1253 return NS_STYLE_HINT_REFLOW;
1255 return NS_STYLE_HINT_VISUAL;
1257 return NS_STYLE_HINT_REFLOW;
1260 #ifdef DEBUG
1261 /* static */
1262 nsChangeHint nsStyleVisibility::MaxDifference()
1264 return NS_STYLE_HINT_REFLOW;
1266 #endif
1268 nsStyleContentData::~nsStyleContentData()
1270 if (mType == eStyleContentType_Image) {
1271 NS_IF_RELEASE(mContent.mImage);
1272 } else if (mType == eStyleContentType_Counter ||
1273 mType == eStyleContentType_Counters) {
1274 mContent.mCounters->Release();
1275 } else if (mContent.mString) {
1276 NS_Free(mContent.mString);
1280 nsStyleContentData& nsStyleContentData::operator=(const nsStyleContentData& aOther)
1282 if (this == &aOther)
1283 return *this;
1284 this->~nsStyleContentData();
1285 new (this) nsStyleContentData();
1287 mType = aOther.mType;
1288 if (mType == eStyleContentType_Image) {
1289 mContent.mImage = aOther.mContent.mImage;
1290 NS_IF_ADDREF(mContent.mImage);
1291 } else if (mType == eStyleContentType_Counter ||
1292 mType == eStyleContentType_Counters) {
1293 mContent.mCounters = aOther.mContent.mCounters;
1294 mContent.mCounters->AddRef();
1295 } else if (aOther.mContent.mString) {
1296 mContent.mString = NS_strdup(aOther.mContent.mString);
1297 } else {
1298 mContent.mString = nsnull;
1300 return *this;
1303 PRBool nsStyleContentData::operator==(const nsStyleContentData& aOther) const
1305 if (mType != aOther.mType)
1306 return PR_FALSE;
1307 if (mType == eStyleContentType_Image) {
1308 if (!mContent.mImage || !aOther.mContent.mImage)
1309 return mContent.mImage == aOther.mContent.mImage;
1310 PRBool eq;
1311 nsCOMPtr<nsIURI> thisURI, otherURI;
1312 mContent.mImage->GetURI(getter_AddRefs(thisURI));
1313 aOther.mContent.mImage->GetURI(getter_AddRefs(otherURI));
1314 return thisURI == otherURI || // handles null==null
1315 (thisURI && otherURI &&
1316 NS_SUCCEEDED(thisURI->Equals(otherURI, &eq)) &&
1317 eq);
1319 if (mType == eStyleContentType_Counter ||
1320 mType == eStyleContentType_Counters)
1321 return *mContent.mCounters == *aOther.mContent.mCounters;
1322 return nsCRT::strcmp(mContent.mString, aOther.mContent.mString) == 0;
1325 //-----------------------
1326 // nsStyleContent
1329 nsStyleContent::nsStyleContent(void)
1330 : mMarkerOffset(),
1331 mContentCount(0),
1332 mContents(nsnull),
1333 mIncrementCount(0),
1334 mIncrements(nsnull),
1335 mResetCount(0),
1336 mResets(nsnull)
1338 mMarkerOffset.SetAutoValue();
1341 nsStyleContent::~nsStyleContent(void)
1343 DELETE_ARRAY_IF(mContents);
1344 DELETE_ARRAY_IF(mIncrements);
1345 DELETE_ARRAY_IF(mResets);
1348 nsStyleContent::nsStyleContent(const nsStyleContent& aSource)
1349 :mMarkerOffset(),
1350 mContentCount(0),
1351 mContents(nsnull),
1352 mIncrementCount(0),
1353 mIncrements(nsnull),
1354 mResetCount(0),
1355 mResets(nsnull)
1358 mMarkerOffset = aSource.mMarkerOffset;
1360 PRUint32 index;
1361 if (NS_SUCCEEDED(AllocateContents(aSource.ContentCount()))) {
1362 for (index = 0; index < mContentCount; index++) {
1363 ContentAt(index) = aSource.ContentAt(index);
1367 if (NS_SUCCEEDED(AllocateCounterIncrements(aSource.CounterIncrementCount()))) {
1368 for (index = 0; index < mIncrementCount; index++) {
1369 const nsStyleCounterData *data = aSource.GetCounterIncrementAt(index);
1370 mIncrements[index].mCounter = data->mCounter;
1371 mIncrements[index].mValue = data->mValue;
1375 if (NS_SUCCEEDED(AllocateCounterResets(aSource.CounterResetCount()))) {
1376 for (index = 0; index < mResetCount; index++) {
1377 const nsStyleCounterData *data = aSource.GetCounterResetAt(index);
1378 mResets[index].mCounter = data->mCounter;
1379 mResets[index].mValue = data->mValue;
1384 nsChangeHint nsStyleContent::CalcDifference(const nsStyleContent& aOther) const
1386 if (mContentCount != aOther.mContentCount ||
1387 mIncrementCount != aOther.mIncrementCount ||
1388 mResetCount != aOther.mResetCount) {
1389 return NS_STYLE_HINT_FRAMECHANGE;
1392 PRUint32 ix = mContentCount;
1393 while (0 < ix--) {
1394 if (mContents[ix] != aOther.mContents[ix]) {
1395 // Unfortunately we need to reframe here; a simple reflow
1396 // will not pick up different text or different image URLs,
1397 // since we set all that up in the CSSFrameConstructor
1398 return NS_STYLE_HINT_FRAMECHANGE;
1401 ix = mIncrementCount;
1402 while (0 < ix--) {
1403 if ((mIncrements[ix].mValue != aOther.mIncrements[ix].mValue) ||
1404 (mIncrements[ix].mCounter != aOther.mIncrements[ix].mCounter)) {
1405 return NS_STYLE_HINT_FRAMECHANGE;
1408 ix = mResetCount;
1409 while (0 < ix--) {
1410 if ((mResets[ix].mValue != aOther.mResets[ix].mValue) ||
1411 (mResets[ix].mCounter != aOther.mResets[ix].mCounter)) {
1412 return NS_STYLE_HINT_FRAMECHANGE;
1415 if (mMarkerOffset != aOther.mMarkerOffset) {
1416 return NS_STYLE_HINT_REFLOW;
1418 return NS_STYLE_HINT_NONE;
1421 #ifdef DEBUG
1422 /* static */
1423 nsChangeHint nsStyleContent::MaxDifference()
1425 return NS_STYLE_HINT_FRAMECHANGE;
1427 #endif
1429 nsresult nsStyleContent::AllocateContents(PRUint32 aCount)
1431 // We need to run the destructors of the elements of mContents, so we
1432 // delete and reallocate even if aCount == mContentCount. (If
1433 // nsStyleContentData had its members private and managed their
1434 // ownership on setting, we wouldn't need this, but that seems
1435 // unnecessary at this point.)
1436 DELETE_ARRAY_IF(mContents);
1437 if (aCount) {
1438 mContents = new nsStyleContentData[aCount];
1439 if (! mContents) {
1440 mContentCount = 0;
1441 return NS_ERROR_OUT_OF_MEMORY;
1444 mContentCount = aCount;
1445 return NS_OK;
1448 // ---------------------
1449 // nsStyleQuotes
1452 nsStyleQuotes::nsStyleQuotes(void)
1453 : mQuotesCount(0),
1454 mQuotes(nsnull)
1458 nsStyleQuotes::~nsStyleQuotes(void)
1460 DELETE_ARRAY_IF(mQuotes);
1463 nsStyleQuotes::nsStyleQuotes(const nsStyleQuotes& aSource)
1464 : mQuotesCount(0),
1465 mQuotes(nsnull)
1467 if (NS_SUCCEEDED(AllocateQuotes(aSource.QuotesCount()))) {
1468 PRUint32 count = (mQuotesCount * 2);
1469 for (PRUint32 index = 0; index < count; index += 2) {
1470 aSource.GetQuotesAt(index, mQuotes[index], mQuotes[index + 1]);
1475 nsChangeHint nsStyleQuotes::CalcDifference(const nsStyleQuotes& aOther) const
1477 // If the quotes implementation is ever going to change we might not need
1478 // a framechange here and a reflow should be sufficient. See bug 35768.
1479 if (mQuotesCount == aOther.mQuotesCount) {
1480 PRUint32 ix = (mQuotesCount * 2);
1481 while (0 < ix--) {
1482 if (mQuotes[ix] != aOther.mQuotes[ix]) {
1483 return NS_STYLE_HINT_FRAMECHANGE;
1487 return NS_STYLE_HINT_NONE;
1489 return NS_STYLE_HINT_FRAMECHANGE;
1492 #ifdef DEBUG
1493 /* static */
1494 nsChangeHint nsStyleQuotes::MaxDifference()
1496 return NS_STYLE_HINT_FRAMECHANGE;
1498 #endif
1500 // --------------------
1501 // nsStyleTextReset
1504 nsStyleTextReset::nsStyleTextReset(void)
1506 mVerticalAlign.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE, eStyleUnit_Enumerated);
1507 mTextDecoration = NS_STYLE_TEXT_DECORATION_NONE;
1508 mUnicodeBidi = NS_STYLE_UNICODE_BIDI_NORMAL;
1511 nsStyleTextReset::nsStyleTextReset(const nsStyleTextReset& aSource)
1513 memcpy((nsStyleTextReset*)this, &aSource, sizeof(nsStyleTextReset));
1516 nsStyleTextReset::~nsStyleTextReset(void) { }
1518 nsChangeHint nsStyleTextReset::CalcDifference(const nsStyleTextReset& aOther) const
1520 if (mVerticalAlign == aOther.mVerticalAlign
1521 && mUnicodeBidi == aOther.mUnicodeBidi) {
1522 if (mTextDecoration != aOther.mTextDecoration) {
1523 // Reflow for blink changes, repaint for others
1524 return
1525 (mTextDecoration & NS_STYLE_TEXT_DECORATION_BLINK) ==
1526 (aOther.mTextDecoration & NS_STYLE_TEXT_DECORATION_BLINK) ?
1527 NS_STYLE_HINT_VISUAL : NS_STYLE_HINT_REFLOW;
1530 return NS_STYLE_HINT_NONE;
1532 return NS_STYLE_HINT_REFLOW;
1535 #ifdef DEBUG
1536 /* static */
1537 nsChangeHint nsStyleTextReset::MaxDifference()
1539 return NS_STYLE_HINT_REFLOW;
1541 #endif
1543 // --------------------
1544 // nsStyleText
1547 nsStyleText::nsStyleText(void)
1549 mTextAlign = NS_STYLE_TEXT_ALIGN_DEFAULT;
1550 mTextTransform = NS_STYLE_TEXT_TRANSFORM_NONE;
1551 mWhiteSpace = NS_STYLE_WHITESPACE_NORMAL;
1553 mLetterSpacing.SetNormalValue();
1554 mLineHeight.SetNormalValue();
1555 mTextIndent.SetCoordValue(0);
1556 mWordSpacing.SetNormalValue();
1559 nsStyleText::nsStyleText(const nsStyleText& aSource)
1561 memcpy((nsStyleText*)this, &aSource, sizeof(nsStyleText));
1564 nsStyleText::~nsStyleText(void) { }
1566 nsChangeHint nsStyleText::CalcDifference(const nsStyleText& aOther) const
1568 if ((mTextAlign == aOther.mTextAlign) &&
1569 (mTextTransform == aOther.mTextTransform) &&
1570 (mWhiteSpace == aOther.mWhiteSpace) &&
1571 (mLetterSpacing == aOther.mLetterSpacing) &&
1572 (mLineHeight == aOther.mLineHeight) &&
1573 (mTextIndent == aOther.mTextIndent) &&
1574 (mWordSpacing == aOther.mWordSpacing))
1575 return NS_STYLE_HINT_NONE;
1576 return NS_STYLE_HINT_REFLOW;
1579 #ifdef DEBUG
1580 /* static */
1581 nsChangeHint nsStyleText::MaxDifference()
1583 return NS_STYLE_HINT_REFLOW;
1585 #endif
1587 //-----------------------
1588 // nsStyleUserInterface
1591 nsCursorImage::nsCursorImage()
1592 : mHaveHotspot(PR_FALSE)
1593 , mHotspotX(0.0f)
1594 , mHotspotY(0.0f)
1598 nsStyleUserInterface::nsStyleUserInterface(void)
1600 mUserInput = NS_STYLE_USER_INPUT_AUTO;
1601 mUserModify = NS_STYLE_USER_MODIFY_READ_ONLY;
1602 mUserFocus = NS_STYLE_USER_FOCUS_NONE;
1604 mCursor = NS_STYLE_CURSOR_AUTO; // fix for bugzilla bug 51113
1606 mCursorArrayLength = 0;
1607 mCursorArray = nsnull;
1610 nsStyleUserInterface::nsStyleUserInterface(const nsStyleUserInterface& aSource) :
1611 mUserInput(aSource.mUserInput),
1612 mUserModify(aSource.mUserModify),
1613 mUserFocus(aSource.mUserFocus),
1614 mCursor(aSource.mCursor)
1616 CopyCursorArrayFrom(aSource);
1619 nsStyleUserInterface::~nsStyleUserInterface(void)
1621 delete [] mCursorArray;
1624 nsChangeHint nsStyleUserInterface::CalcDifference(const nsStyleUserInterface& aOther) const
1626 nsChangeHint hint = nsChangeHint(0);
1627 if (mCursor != aOther.mCursor)
1628 NS_UpdateHint(hint, nsChangeHint_UpdateCursor);
1630 // We could do better. But it wouldn't be worth it, URL-specified cursors are
1631 // rare.
1632 if (mCursorArrayLength > 0 || aOther.mCursorArrayLength > 0)
1633 NS_UpdateHint(hint, nsChangeHint_UpdateCursor);
1635 if (mUserModify != aOther.mUserModify)
1636 NS_UpdateHint(hint, NS_STYLE_HINT_VISUAL);
1638 if ((mUserInput != aOther.mUserInput) &&
1639 ((NS_STYLE_USER_INPUT_NONE == mUserInput) ||
1640 (NS_STYLE_USER_INPUT_NONE == aOther.mUserInput))) {
1641 NS_UpdateHint(hint, NS_STYLE_HINT_FRAMECHANGE);
1644 // ignore mUserFocus
1646 return hint;
1649 #ifdef DEBUG
1650 /* static */
1651 nsChangeHint nsStyleUserInterface::MaxDifference()
1653 return nsChangeHint(nsChangeHint_UpdateCursor | NS_STYLE_HINT_FRAMECHANGE);
1655 #endif
1657 void
1658 nsStyleUserInterface::CopyCursorArrayFrom(const nsStyleUserInterface& aSource)
1660 mCursorArray = nsnull;
1661 mCursorArrayLength = 0;
1662 if (aSource.mCursorArrayLength) {
1663 mCursorArray = new nsCursorImage[aSource.mCursorArrayLength];
1664 if (mCursorArray) {
1665 mCursorArrayLength = aSource.mCursorArrayLength;
1666 for (PRUint32 i = 0; i < mCursorArrayLength; ++i)
1667 mCursorArray[i] = aSource.mCursorArray[i];
1672 //-----------------------
1673 // nsStyleUIReset
1676 nsStyleUIReset::nsStyleUIReset(void)
1678 mUserSelect = NS_STYLE_USER_SELECT_AUTO;
1679 mForceBrokenImageIcon = 0;
1680 mIMEMode = NS_STYLE_IME_MODE_AUTO;
1683 nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset& aSource)
1685 mUserSelect = aSource.mUserSelect;
1686 mForceBrokenImageIcon = aSource.mForceBrokenImageIcon;
1687 mIMEMode = aSource.mIMEMode;
1690 nsStyleUIReset::~nsStyleUIReset(void)
1694 nsChangeHint nsStyleUIReset::CalcDifference(const nsStyleUIReset& aOther) const
1696 // ignore mIMEMode
1697 if (mForceBrokenImageIcon == aOther.mForceBrokenImageIcon) {
1698 if (mUserSelect == aOther.mUserSelect) {
1699 return NS_STYLE_HINT_NONE;
1701 return NS_STYLE_HINT_VISUAL;
1703 return NS_STYLE_HINT_FRAMECHANGE;
1706 #ifdef DEBUG
1707 /* static */
1708 nsChangeHint nsStyleUIReset::MaxDifference()
1710 return NS_STYLE_HINT_FRAMECHANGE;
1712 #endif