Back to index

lightning-sunbird  0.9+nobinonly
nsStyleStruct.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   David Hyatt (hyatt@netscape.com)
00024  *   Mats Palmgren <mats.palmgren@bredband.net>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "nsStyleStruct.h"
00041 #include "nsStyleConsts.h"
00042 #include "nsString.h"
00043 #include "nsUnitConversion.h"
00044 #include "nsPresContext.h"
00045 #include "nsIDeviceContext.h"
00046 #include "nsIStyleRule.h"
00047 #include "nsCRT.h"
00048 
00049 #include "nsCOMPtr.h"
00050 #include "nsIPresShell.h"
00051 #include "nsIFrame.h"
00052 #include "nsLayoutAtoms.h"
00053 #include "nsHTMLReflowState.h"
00054 #include "prenv.h"
00055 
00056 #include "nsBidiUtils.h"
00057 
00058 #include "imgIRequest.h"
00059 
00060 inline PRBool IsFixedUnit(nsStyleUnit aUnit, PRBool aEnumOK)
00061 {
00062   return PRBool((aUnit == eStyleUnit_Null) || 
00063                 (aUnit == eStyleUnit_Coord) || 
00064                 (aEnumOK && (aUnit == eStyleUnit_Enumerated)));
00065 }
00066 
00067 // XXX this is here to support deprecated calc spacing methods only
00068 // XXXldb Probably shouldn't be inline.
00069 inline nscoord CalcSideFor(const nsIFrame* aFrame, const nsStyleCoord& aCoord, 
00070                            PRUint8 aSpacing, PRUint8 aSide)
00071 {
00072   nscoord result = 0;
00073 
00074   switch (aCoord.GetUnit()) {
00075     case eStyleUnit_Auto:
00076       // Auto margins are handled by layout
00077       break;
00078 
00079     case eStyleUnit_Percent:
00080       {
00081         nscoord baseWidth = 0;
00082         nsIFrame* frame = aFrame ?
00083             nsHTMLReflowState::GetContainingBlockFor(aFrame) : nsnull;
00084         if (frame) {
00085           baseWidth = frame->GetSize().width;
00086           // subtract border of containing block
00087           nsMargin border;
00088           frame->GetStyleBorder()->CalcBorderFor(frame, border);
00089           baseWidth -= (border.left + border.right);
00090           // if aFrame is not absolutely positioned, subtract
00091           // padding of containing block
00092           const nsStyleDisplay* displayData = aFrame->GetStyleDisplay();
00093           if (displayData->mPosition != NS_STYLE_POSITION_ABSOLUTE &&
00094               displayData->mPosition != NS_STYLE_POSITION_FIXED) {
00095             nsMargin padding;
00096             frame->GetStylePadding()->CalcPaddingFor(frame, padding);
00097             baseWidth -= (padding.left + padding.right);
00098           }
00099         }
00100         result = (nscoord)((float)baseWidth * aCoord.GetPercentValue());
00101       }
00102       break;
00103 
00104     case eStyleUnit_Coord:
00105       result = aCoord.GetCoordValue();
00106       break;
00107 
00108     case eStyleUnit_Enumerated:
00109     case eStyleUnit_Null:
00110     case eStyleUnit_Normal:
00111     case eStyleUnit_Integer:
00112     case eStyleUnit_Proportional:
00113     default:
00114       result = 0;
00115       break;
00116   }
00117   if ((NS_SPACING_PADDING == aSpacing) || (NS_SPACING_BORDER == aSpacing)) {
00118     if (result < 0) {
00119       result = 0;
00120     }
00121   }
00122   return result;
00123 }
00124 
00125 // XXXldb Probably shouldn't be inline.
00126 inline void CalcSidesFor(const nsIFrame* aFrame, const nsStyleSides& aSides, 
00127                          PRUint8 aSpacing, nsMargin& aResult)
00128 {
00129   nsStyleCoord  coord;
00130 
00131   aResult.left = CalcSideFor(aFrame, aSides.GetLeft(coord), aSpacing,
00132                              NS_SIDE_LEFT);
00133   aResult.top = CalcSideFor(aFrame, aSides.GetTop(coord), aSpacing,
00134                             NS_SIDE_TOP);
00135   aResult.right = CalcSideFor(aFrame, aSides.GetRight(coord), aSpacing,
00136                               NS_SIDE_RIGHT);
00137   aResult.bottom = CalcSideFor(aFrame, aSides.GetBottom(coord), aSpacing,
00138                                NS_SIDE_BOTTOM);
00139 }
00140 
00141 static PRBool EqualURIs(nsIURI *aURI1, nsIURI *aURI2)
00142 {
00143   PRBool eq;
00144   return aURI1 == aURI2 ||    // handle null==null, and optimize
00145          (aURI1 && aURI2 &&
00146           NS_SUCCEEDED(aURI1->Equals(aURI2, &eq)) && // not equal on fail
00147           eq);
00148 }
00149 
00150 static PRBool EqualImages(imgIRequest *aImage1, imgIRequest* aImage2)
00151 {
00152   if (aImage1 == aImage2) {
00153     return PR_TRUE;
00154   }
00155 
00156   if (!aImage1 || !aImage2) {
00157     return PR_FALSE;
00158   }
00159 
00160   nsCOMPtr<nsIURI> uri1, uri2;
00161   aImage1->GetURI(getter_AddRefs(uri1));
00162   aImage2->GetURI(getter_AddRefs(uri2));
00163   return EqualURIs(uri1, uri2);
00164 }
00165 
00166 // --------------------
00167 // nsStyleFont
00168 //
00169 nsStyleFont::nsStyleFont()
00170   : mFlags(NS_STYLE_FONT_DEFAULT),
00171     mFont(nsnull, NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
00172           NS_FONT_WEIGHT_NORMAL, NS_FONT_DECORATION_NONE, 0),
00173     mSize(0)
00174 { }
00175 
00176 nsStyleFont::nsStyleFont(const nsFont& aFont)
00177   : mFlags(NS_STYLE_FONT_DEFAULT),
00178     mFont(aFont),
00179     mSize(aFont.size)
00180 {
00181 }
00182 
00183 nsStyleFont::nsStyleFont(const nsStyleFont& aSrc)
00184   : mFlags(aSrc.mFlags),
00185     mFont(aSrc.mFont),
00186     mSize(aSrc.mSize)
00187 {
00188 }
00189 
00190 
00191 nsStyleFont::nsStyleFont(nsPresContext* aPresContext)
00192   : mFlags(NS_STYLE_FONT_DEFAULT),
00193     mFont(*(aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID)))
00194 {
00195   mSize = mFont.size = nsStyleFont::ZoomText(aPresContext, mFont.size);
00196 }
00197 
00198 void* 
00199 nsStyleFont::operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
00200   void* result = aContext->AllocateFromShell(sz);
00201   if (result)
00202     memset(result, 0, sz);
00203   return result;
00204 }
00205   
00206 void 
00207 nsStyleFont::Destroy(nsPresContext* aContext) {
00208   this->~nsStyleFont();
00209   aContext->FreeToShell(sizeof(nsStyleFont), this);
00210 }
00211 
00212 nsChangeHint nsStyleFont::CalcDifference(const nsStyleFont& aOther) const
00213 {
00214   if (mSize == aOther.mSize) {
00215     return CalcFontDifference(mFont, aOther.mFont);
00216   }
00217   return NS_STYLE_HINT_REFLOW;
00218 }
00219 
00220 #ifdef DEBUG
00221 /* static */
00222 nsChangeHint nsStyleFont::MaxDifference()
00223 {
00224   return NS_STYLE_HINT_REFLOW;
00225 }
00226 #endif
00227 
00228 /* static */ nscoord
00229 nsStyleFont::ZoomText(nsPresContext *aPresContext, nscoord aSize)
00230 {
00231   return nscoord(float(aSize) * aPresContext->TextZoom());
00232 }
00233 
00234 /* static */ nscoord
00235 nsStyleFont::UnZoomText(nsPresContext *aPresContext, nscoord aSize)
00236 {
00237   return nscoord(float(aSize) / aPresContext->TextZoom());
00238 }
00239 
00240 nsChangeHint nsStyleFont::CalcFontDifference(const nsFont& aFont1, const nsFont& aFont2)
00241 {
00242   if ((aFont1.size == aFont2.size) && 
00243       (aFont1.sizeAdjust == aFont2.sizeAdjust) && 
00244       (aFont1.style == aFont2.style) &&
00245       (aFont1.variant == aFont2.variant) &&
00246       (aFont1.familyNameQuirks == aFont2.familyNameQuirks) &&
00247       (aFont1.weight == aFont2.weight) &&
00248       (aFont1.name == aFont2.name)) {
00249     if ((aFont1.decorations == aFont2.decorations)) {
00250       return NS_STYLE_HINT_NONE;
00251     }
00252     return NS_STYLE_HINT_VISUAL;
00253   }
00254   return NS_STYLE_HINT_REFLOW;
00255 }
00256 
00257 static PRBool IsFixedData(const nsStyleSides& aSides, PRBool aEnumOK)
00258 {
00259   NS_FOR_CSS_SIDES(side) {
00260     if (!IsFixedUnit(aSides.GetUnit(side), aEnumOK))
00261       return PR_FALSE;
00262   }
00263   return PR_TRUE;
00264 }
00265 
00266 static nscoord CalcCoord(const nsStyleCoord& aCoord, 
00267                          const nscoord* aEnumTable, 
00268                          PRInt32 aNumEnums)
00269 {
00270   switch (aCoord.GetUnit()) {
00271     case eStyleUnit_Null:
00272       return 0;
00273     case eStyleUnit_Coord:
00274       return aCoord.GetCoordValue();
00275     case eStyleUnit_Enumerated:
00276       if (nsnull != aEnumTable) {
00277         PRInt32 value = aCoord.GetIntValue();
00278         if ((0 <= value) && (value < aNumEnums)) {
00279           return aEnumTable[aCoord.GetIntValue()];
00280         }
00281       }
00282       break;
00283     case eStyleUnit_Chars:
00284       // XXX we need a frame and a rendering context to calculate this, bug 281972, bug 282126.
00285       NS_NOTYETIMPLEMENTED("CalcCoord: eStyleUnit_Chars");
00286       return 0;
00287     default:
00288       NS_ERROR("bad unit type");
00289       break;
00290   }
00291   return 0;
00292 }
00293 
00294 nsStyleMargin::nsStyleMargin() {
00295   mMargin.Reset();
00296   mHasCachedMargin = PR_FALSE;
00297 }
00298 
00299 nsStyleMargin::nsStyleMargin(const nsStyleMargin& aSrc) {
00300   mMargin = aSrc.mMargin;
00301   mHasCachedMargin = PR_FALSE;
00302 }
00303 
00304 void* 
00305 nsStyleMargin::operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
00306   void* result = aContext->AllocateFromShell(sz);
00307   if (result)
00308     memset(result, 0, sz);
00309   return result;
00310 }
00311   
00312 void 
00313 nsStyleMargin::Destroy(nsPresContext* aContext) {
00314   this->~nsStyleMargin();
00315   aContext->FreeToShell(sizeof(nsStyleMargin), this);
00316 }
00317 
00318 
00319 void nsStyleMargin::RecalcData()
00320 {
00321   if (IsFixedData(mMargin, PR_FALSE)) {
00322     nsStyleCoord coord;
00323     NS_FOR_CSS_SIDES(side) {
00324       mCachedMargin.side(side) =
00325         CalcCoord(mMargin.Get(side, coord), nsnull, 0);
00326     }
00327     mHasCachedMargin = PR_TRUE;
00328   }
00329   else
00330     mHasCachedMargin = PR_FALSE;
00331 }
00332 
00333 nsChangeHint nsStyleMargin::CalcDifference(const nsStyleMargin& aOther) const
00334 {
00335   if (mMargin == aOther.mMargin) {
00336     return NS_STYLE_HINT_NONE;
00337   }
00338   return NS_STYLE_HINT_REFLOW;
00339 }
00340 
00341 #ifdef DEBUG
00342 /* static */
00343 nsChangeHint nsStyleMargin::MaxDifference()
00344 {
00345   return NS_STYLE_HINT_REFLOW;
00346 }
00347 #endif
00348 
00349 void 
00350 nsStyleMargin::CalcMarginFor(const nsIFrame* aFrame, nsMargin& aMargin) const
00351 {
00352   if (mHasCachedMargin) {
00353     aMargin = mCachedMargin;
00354   } else {
00355     CalcSidesFor(aFrame, mMargin, NS_SPACING_MARGIN, aMargin);
00356   }
00357 }
00358 
00359 nsStylePadding::nsStylePadding() {
00360   mPadding.Reset();
00361   mHasCachedPadding = PR_FALSE;
00362 }
00363 
00364 nsStylePadding::nsStylePadding(const nsStylePadding& aSrc) {
00365   mPadding = aSrc.mPadding;
00366   mHasCachedPadding = PR_FALSE;
00367 }
00368 
00369 void* 
00370 nsStylePadding::operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
00371   void* result = aContext->AllocateFromShell(sz);
00372   if (result)
00373     memset(result, 0, sz);
00374   return result;
00375 }
00376   
00377 void 
00378 nsStylePadding::Destroy(nsPresContext* aContext) {
00379   this->~nsStylePadding();
00380   aContext->FreeToShell(sizeof(nsStylePadding), this);
00381 }
00382 
00383 void nsStylePadding::RecalcData()
00384 {
00385   if (IsFixedData(mPadding, PR_FALSE)) {
00386     nsStyleCoord coord;
00387     NS_FOR_CSS_SIDES(side) {
00388       mCachedPadding.side(side) =
00389         CalcCoord(mPadding.Get(side, coord), nsnull, 0);
00390     }
00391     mHasCachedPadding = PR_TRUE;
00392   }
00393   else
00394     mHasCachedPadding = PR_FALSE;
00395 }
00396 
00397 nsChangeHint nsStylePadding::CalcDifference(const nsStylePadding& aOther) const
00398 {
00399   if (mPadding == aOther.mPadding) {
00400     return NS_STYLE_HINT_NONE;
00401   }
00402   return NS_STYLE_HINT_REFLOW;
00403 }
00404 
00405 #ifdef DEBUG
00406 /* static */
00407 nsChangeHint nsStylePadding::MaxDifference()
00408 {
00409   return NS_STYLE_HINT_REFLOW;
00410 }
00411 #endif
00412 
00413 void 
00414 nsStylePadding::CalcPaddingFor(const nsIFrame* aFrame, nsMargin& aPadding) const
00415 {
00416   if (mHasCachedPadding) {
00417     aPadding = mCachedPadding;
00418   } else {
00419     CalcSidesFor(aFrame, mPadding, NS_SPACING_PADDING, aPadding);
00420   }
00421 }
00422 
00423 nsStyleBorder::nsStyleBorder(nsPresContext* aPresContext)
00424   : mComputedBorder(0, 0, 0, 0)
00425 {
00426   nscoord medium =
00427     (aPresContext->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM];
00428   NS_FOR_CSS_SIDES(side) {
00429     mBorder.side(side) = medium;
00430     mBorderStyle[side] = NS_STYLE_BORDER_STYLE_NONE | BORDER_COLOR_FOREGROUND;
00431     mBorderColor[side] = NS_RGB(0, 0, 0);
00432   }
00433 
00434   mBorderColors = nsnull;
00435 
00436   mBorderRadius.Reset();
00437 
00438   mFloatEdge = NS_STYLE_FLOAT_EDGE_CONTENT;
00439 }
00440 
00441 nsStyleBorder::nsStyleBorder(const nsStyleBorder& aSrc)
00442 {
00443   memcpy((nsStyleBorder*)this, &aSrc, sizeof(nsStyleBorder));
00444   mBorderColors = nsnull;
00445   if (aSrc.mBorderColors) {
00446     EnsureBorderColors();
00447     for (PRInt32 i = 0; i < 4; i++)
00448       if (aSrc.mBorderColors[i])
00449         mBorderColors[i] = aSrc.mBorderColors[i]->CopyColors();
00450       else
00451         mBorderColors[i] = nsnull;
00452   }
00453 }
00454 
00455 void* 
00456 nsStyleBorder::operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
00457   void* result = aContext->AllocateFromShell(sz);
00458   if (result)
00459     memset(result, 0, sz);
00460   return result;
00461 }
00462   
00463 void 
00464 nsStyleBorder::Destroy(nsPresContext* aContext) {
00465   this->~nsStyleBorder();
00466   aContext->FreeToShell(sizeof(nsStyleBorder), this);
00467 }
00468 
00469 
00470 nsChangeHint nsStyleBorder::CalcDifference(const nsStyleBorder& aOther) const
00471 {
00472   // Note that differences in mBorder don't affect rendering (which should only
00473   // use mComputedBorder), so don't need to be tested for here.
00474   if (mComputedBorder == aOther.mComputedBorder && 
00475       mFloatEdge == aOther.mFloatEdge) {
00476     // Note that mBorderStyle stores not only the border style but also
00477     // color-related flags.  Given that we've already done an mComputedBorder
00478     // comparison, border-style differences can only lead to a VISUAL hint.  So
00479     // it's OK to just compare the values directly -- if either the actual
00480     // style or the color flags differ we want to repaint.
00481     NS_FOR_CSS_SIDES(ix) {
00482       if (mBorderStyle[ix] != aOther.mBorderStyle[ix] || 
00483           mBorderColor[ix] != aOther.mBorderColor[ix]) {
00484         return NS_STYLE_HINT_VISUAL;
00485       }
00486     }
00487 
00488     if (mBorderRadius != aOther.mBorderRadius ||
00489         !mBorderColors != !aOther.mBorderColors) {
00490       return NS_STYLE_HINT_VISUAL;
00491     }
00492 
00493     // Note that at this point if mBorderColors is non-null so is
00494     // aOther.mBorderColors
00495     if (mBorderColors) {
00496       NS_FOR_CSS_SIDES(ix) {
00497         if (!mBorderColors[ix] != !aOther.mBorderColors[ix]) {
00498           return NS_STYLE_HINT_VISUAL;
00499         } else if (mBorderColors[ix] && aOther.mBorderColors[ix]) {
00500           if (!mBorderColors[ix]->Equals(aOther.mBorderColors[ix]))
00501             return NS_STYLE_HINT_VISUAL;
00502         }
00503       }
00504     }
00505 
00506 
00507     return NS_STYLE_HINT_NONE;
00508   }
00509   return NS_STYLE_HINT_REFLOW;
00510 }
00511 
00512 #ifdef DEBUG
00513 /* static */
00514 nsChangeHint nsStyleBorder::MaxDifference()
00515 {
00516   return NS_STYLE_HINT_REFLOW;
00517 }
00518 #endif
00519 
00520 nsStyleOutline::nsStyleOutline(nsPresContext* aPresContext)
00521 {
00522   // spacing values not inherited
00523   mOutlineRadius.Reset();
00524   mOutlineOffset.SetCoordValue(0);
00525 
00526   mOutlineWidth = nsStyleCoord(NS_STYLE_BORDER_WIDTH_MEDIUM, eStyleUnit_Enumerated);
00527   mOutlineStyle = NS_STYLE_BORDER_STYLE_NONE;
00528   mOutlineColor = NS_RGB(0, 0, 0);
00529 
00530   mHasCachedOutline = PR_FALSE;
00531 }
00532 
00533 nsStyleOutline::nsStyleOutline(const nsStyleOutline& aSrc) {
00534   memcpy((nsStyleOutline*)this, &aSrc, sizeof(nsStyleOutline));
00535 }
00536 
00537 void 
00538 nsStyleOutline::RecalcData(nsPresContext* aContext)
00539 {
00540   if (NS_STYLE_BORDER_STYLE_NONE == GetOutlineStyle()) {
00541     mCachedOutlineWidth = 0;
00542     mHasCachedOutline = PR_TRUE;
00543   } else if (IsFixedUnit(mOutlineWidth.GetUnit(), PR_TRUE)) {
00544     mCachedOutlineWidth = CalcCoord(mOutlineWidth, aContext->GetBorderWidthTable(), 3);
00545     mHasCachedOutline = PR_TRUE;
00546   }
00547   else
00548     mHasCachedOutline = PR_FALSE;
00549 }
00550 
00551 nsChangeHint nsStyleOutline::CalcDifference(const nsStyleOutline& aOther) const
00552 {
00553   PRBool outlineWasVisible =
00554     mCachedOutlineWidth > 0 && mOutlineStyle != NS_STYLE_BORDER_STYLE_NONE;
00555   PRBool outlineIsVisible = 
00556     aOther.mCachedOutlineWidth > 0 && aOther.mOutlineStyle != NS_STYLE_BORDER_STYLE_NONE;
00557   if (outlineWasVisible != outlineIsVisible ||
00558       (outlineIsVisible && (mOutlineOffset != aOther.mOutlineOffset ||
00559                             mOutlineWidth != aOther.mOutlineWidth))) {
00560     return NS_CombineHint(nsChangeHint_ReflowFrame, nsChangeHint_RepaintFrame);
00561   }
00562   if ((mOutlineStyle != aOther.mOutlineStyle) ||
00563       (mOutlineColor != aOther.mOutlineColor) ||
00564       (mOutlineRadius != aOther.mOutlineRadius)) {
00565     return nsChangeHint_RepaintFrame;
00566   }
00567   return NS_STYLE_HINT_NONE;
00568 }
00569 
00570 #ifdef DEBUG
00571 /* static */
00572 nsChangeHint nsStyleOutline::MaxDifference()
00573 {
00574   return NS_CombineHint(nsChangeHint_ReflowFrame, nsChangeHint_RepaintFrame);
00575 }
00576 #endif
00577 
00578 // --------------------
00579 // nsStyleList
00580 //
00581 nsStyleList::nsStyleList() 
00582   : mListStyleType(NS_STYLE_LIST_STYLE_DISC),
00583     mListStylePosition(NS_STYLE_LIST_STYLE_POSITION_OUTSIDE)
00584 {
00585 }
00586 
00587 nsStyleList::~nsStyleList() 
00588 {
00589 }
00590 
00591 nsStyleList::nsStyleList(const nsStyleList& aSource)
00592   : mListStyleType(aSource.mListStyleType),
00593     mListStylePosition(aSource.mListStylePosition),
00594     mListStyleImage(aSource.mListStyleImage),
00595     mImageRegion(aSource.mImageRegion)
00596 {
00597 }
00598 
00599 nsChangeHint nsStyleList::CalcDifference(const nsStyleList& aOther) const
00600 {
00601   if (mListStylePosition == aOther.mListStylePosition &&
00602       EqualImages(mListStyleImage, aOther.mListStyleImage) &&
00603       mListStyleType == aOther.mListStyleType) {
00604     if (mImageRegion == aOther.mImageRegion)
00605       return NS_STYLE_HINT_NONE;
00606     if (mImageRegion.width == aOther.mImageRegion.width &&
00607         mImageRegion.height == aOther.mImageRegion.height)
00608       return NS_STYLE_HINT_VISUAL;
00609   }
00610   return NS_STYLE_HINT_REFLOW;
00611 }
00612 
00613 #ifdef DEBUG
00614 /* static */
00615 nsChangeHint nsStyleList::MaxDifference()
00616 {
00617   return NS_STYLE_HINT_REFLOW;
00618 }
00619 #endif
00620 
00621 // --------------------
00622 // nsStyleXUL
00623 //
00624 nsStyleXUL::nsStyleXUL() 
00625 { 
00626   mBoxAlign  = NS_STYLE_BOX_ALIGN_STRETCH;
00627   mBoxDirection = NS_STYLE_BOX_DIRECTION_NORMAL;
00628   mBoxFlex = 0.0f;
00629   mBoxOrient = NS_STYLE_BOX_ORIENT_HORIZONTAL;
00630   mBoxPack   = NS_STYLE_BOX_PACK_START;
00631   mBoxOrdinal = 1;
00632 }
00633 
00634 nsStyleXUL::~nsStyleXUL() 
00635 {
00636 }
00637 
00638 nsStyleXUL::nsStyleXUL(const nsStyleXUL& aSource)
00639 {
00640   memcpy((nsStyleXUL*)this, &aSource, sizeof(nsStyleXUL));
00641 }
00642 
00643 nsChangeHint nsStyleXUL::CalcDifference(const nsStyleXUL& aOther) const
00644 {
00645   if (mBoxAlign == aOther.mBoxAlign &&
00646       mBoxDirection == aOther.mBoxDirection &&
00647       mBoxFlex == aOther.mBoxFlex &&
00648       mBoxOrient == aOther.mBoxOrient &&
00649       mBoxPack == aOther.mBoxPack &&
00650       mBoxOrdinal == aOther.mBoxOrdinal)
00651     return NS_STYLE_HINT_NONE;
00652   if (mBoxOrdinal != aOther.mBoxOrdinal)
00653     return NS_STYLE_HINT_FRAMECHANGE;
00654   return NS_STYLE_HINT_REFLOW;
00655 }
00656 
00657 #ifdef DEBUG
00658 /* static */
00659 nsChangeHint nsStyleXUL::MaxDifference()
00660 {
00661   return NS_STYLE_HINT_FRAMECHANGE;
00662 }
00663 #endif
00664 
00665 // --------------------
00666 // nsStyleColumn
00667 //
00668 nsStyleColumn::nsStyleColumn() 
00669 { 
00670   mColumnCount = NS_STYLE_COLUMN_COUNT_AUTO;
00671   mColumnWidth.SetAutoValue();
00672   mColumnGap.SetCoordValue(0);
00673 }
00674 
00675 nsStyleColumn::~nsStyleColumn() 
00676 {
00677 }
00678 
00679 nsStyleColumn::nsStyleColumn(const nsStyleColumn& aSource)
00680 {
00681   memcpy((nsStyleColumn*)this, &aSource, sizeof(nsStyleColumn));
00682 }
00683 
00684 nsChangeHint nsStyleColumn::CalcDifference(const nsStyleColumn& aOther) const
00685 {
00686   if ((mColumnWidth.GetUnit() == eStyleUnit_Auto)
00687       != (aOther.mColumnWidth.GetUnit() == eStyleUnit_Auto) ||
00688       mColumnCount != aOther.mColumnCount)
00689     // We force column count changes to do a reframe, because it's tricky to handle
00690     // some edge cases where the column count gets smaller and content overflows.
00691     // XXX not ideal
00692     return nsChangeHint_ReconstructFrame;
00693 
00694   if (mColumnWidth != aOther.mColumnWidth ||
00695       mColumnGap != aOther.mColumnGap)
00696     return nsChangeHint_ReflowFrame;
00697 
00698   return NS_STYLE_HINT_NONE;
00699 }
00700 
00701 #ifdef DEBUG
00702 /* static */
00703 nsChangeHint nsStyleColumn::MaxDifference()
00704 {
00705   return NS_CombineHint(nsChangeHint_ReconstructFrame,
00706                         nsChangeHint_ReflowFrame);
00707 }
00708 #endif
00709 
00710 #ifdef MOZ_SVG
00711 // --------------------
00712 // nsStyleSVG
00713 //
00714 nsStyleSVG::nsStyleSVG() 
00715 {
00716     mFill.mType              = eStyleSVGPaintType_Color;
00717     mFill.mPaint.mColor      = NS_RGB(0,0,0);
00718     mStroke.mType            = eStyleSVGPaintType_None;
00719     mStroke.mPaint.mColor    = NS_RGB(0,0,0);
00720     mStrokeDasharray         = nsnull;
00721 
00722     mStrokeDashoffset.SetFactorValue(0.0f);
00723     mStrokeWidth.SetFactorValue(1.0f);
00724 
00725     mFillOpacity             = 1.0f;
00726     mStrokeMiterlimit        = 4.0f;
00727     mStrokeOpacity           = 1.0f;
00728 
00729     mStrokeDasharrayLength   = 0;
00730     mClipRule                = NS_STYLE_FILL_RULE_NONZERO;
00731     mFillRule                = NS_STYLE_FILL_RULE_NONZERO;
00732     mPointerEvents           = NS_STYLE_POINTER_EVENTS_VISIBLEPAINTED;
00733     mShapeRendering          = NS_STYLE_SHAPE_RENDERING_AUTO;
00734     mStrokeLinecap           = NS_STYLE_STROKE_LINECAP_BUTT;
00735     mStrokeLinejoin          = NS_STYLE_STROKE_LINEJOIN_MITER;
00736     mTextAnchor              = NS_STYLE_TEXT_ANCHOR_START;
00737     mTextRendering           = NS_STYLE_TEXT_RENDERING_AUTO;
00738 }
00739 
00740 nsStyleSVG::~nsStyleSVG() 
00741 {
00742   delete [] mStrokeDasharray;
00743 }
00744 
00745 nsStyleSVG::nsStyleSVG(const nsStyleSVG& aSource)
00746 {
00747   //memcpy((nsStyleSVG*)this, &aSource, sizeof(nsStyleSVG));
00748 
00749   mFill = aSource.mFill;
00750   mStroke = aSource.mStroke;
00751 
00752   mMarkerEnd = aSource.mMarkerEnd;
00753   mMarkerMid = aSource.mMarkerMid;
00754   mMarkerEnd = aSource.mMarkerStart;
00755 
00756   mStrokeDasharrayLength = aSource.mStrokeDasharrayLength;
00757   if (aSource.mStrokeDasharray) {
00758     mStrokeDasharray = new nsStyleCoord[mStrokeDasharrayLength];
00759     if (mStrokeDasharray)
00760       memcpy(mStrokeDasharray,
00761              aSource.mStrokeDasharray,
00762              mStrokeDasharrayLength * sizeof(nsStyleCoord));
00763     else
00764       mStrokeDasharrayLength = 0;
00765   } else {
00766     mStrokeDasharray = nsnull;
00767   }
00768 
00769   mStrokeDashoffset = aSource.mStrokeDashoffset;
00770   mStrokeWidth = aSource.mStrokeWidth;
00771 
00772   mFillOpacity = aSource.mFillOpacity;
00773   mStrokeMiterlimit = aSource.mStrokeMiterlimit;
00774   mStrokeOpacity = aSource.mStrokeOpacity;
00775 
00776   mClipRule = aSource.mClipRule;
00777   mFillRule = aSource.mFillRule;
00778   mPointerEvents = aSource.mPointerEvents;
00779   mShapeRendering = aSource.mShapeRendering;
00780   mStrokeLinecap = aSource.mStrokeLinecap;
00781   mStrokeLinejoin = aSource.mStrokeLinejoin;
00782   mTextAnchor = aSource.mTextAnchor;
00783   mTextRendering = aSource.mTextRendering;
00784 }
00785 
00786 nsChangeHint nsStyleSVG::CalcDifference(const nsStyleSVG& aOther) const
00787 {
00788   if ( mFill                  != aOther.mFill                  ||
00789 
00790        mStroke                != aOther.mStroke                ||
00791        !EqualURIs(mMarkerEnd, aOther.mMarkerEnd)               ||
00792        !EqualURIs(mMarkerMid, aOther.mMarkerMid)               ||
00793        !EqualURIs(mMarkerStart, aOther.mMarkerStart)           ||
00794 
00795        mStrokeDashoffset      != aOther.mStrokeDashoffset      ||
00796        mStrokeWidth           != aOther.mStrokeWidth           ||
00797 
00798        mFillOpacity           != aOther.mFillOpacity           ||
00799        mStrokeMiterlimit      != aOther.mStrokeMiterlimit      ||
00800        mStrokeOpacity         != aOther.mStrokeOpacity         ||
00801 
00802        mClipRule              != aOther.mClipRule              ||
00803        mFillRule              != aOther.mFillRule              ||
00804        mPointerEvents         != aOther.mPointerEvents         ||
00805        mShapeRendering        != aOther.mShapeRendering        ||
00806        mStrokeDasharrayLength != aOther.mStrokeDasharrayLength ||
00807        mStrokeLinecap         != aOther.mStrokeLinecap         ||
00808        mStrokeLinejoin        != aOther.mStrokeLinejoin        ||
00809        mTextAnchor            != aOther.mTextAnchor            ||
00810        mTextRendering         != aOther.mTextRendering)
00811     return NS_STYLE_HINT_VISUAL;
00812 
00813   // length of stroke dasharrays are the same (tested above) - check entries
00814   for (PRUint32 i=0; i<mStrokeDasharrayLength; i++)
00815     if (mStrokeDasharray[i] != aOther.mStrokeDasharray[i])
00816       return NS_STYLE_HINT_VISUAL;
00817 
00818   return NS_STYLE_HINT_NONE;
00819 }
00820 
00821 #ifdef DEBUG
00822 /* static */
00823 nsChangeHint nsStyleSVG::MaxDifference()
00824 {
00825   return NS_STYLE_HINT_VISUAL;
00826 }
00827 #endif
00828 
00829 // --------------------
00830 // nsStyleSVGReset
00831 //
00832 nsStyleSVGReset::nsStyleSVGReset() 
00833 {
00834     mStopColor.mType         = eStyleSVGPaintType_Color;
00835     mStopColor.mPaint.mColor = NS_RGB(0,0,0);
00836     mClipPath                = nsnull;
00837     mStopOpacity             = 1.0f;
00838     mDominantBaseline        = NS_STYLE_DOMINANT_BASELINE_AUTO;
00839 }
00840 
00841 nsStyleSVGReset::~nsStyleSVGReset() 
00842 {
00843 }
00844 
00845 nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset& aSource)
00846 {
00847   mStopColor = aSource.mStopColor;
00848   mClipPath = aSource.mClipPath;
00849   mStopOpacity = aSource.mStopOpacity;
00850   mDominantBaseline = aSource.mDominantBaseline;
00851 }
00852 
00853 nsChangeHint nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aOther) const
00854 {
00855   if (mStopColor             != aOther.mStopColor   ||
00856       !EqualURIs(mClipPath, aOther.mClipPath)       ||
00857       mStopOpacity           != aOther.mStopOpacity ||
00858       mDominantBaseline != aOther.mDominantBaseline)
00859     return NS_STYLE_HINT_VISUAL;
00860   
00861   return NS_STYLE_HINT_NONE;
00862 }
00863 
00864 #ifdef DEBUG
00865 /* static */
00866 nsChangeHint nsStyleSVGReset::MaxDifference()
00867 {
00868   return NS_STYLE_HINT_VISUAL;
00869 }
00870 #endif
00871 
00872 // nsStyleSVGPaint implementation
00873 nsStyleSVGPaint::~nsStyleSVGPaint() {
00874   if (mType == eStyleSVGPaintType_Server) {
00875     NS_IF_RELEASE(mPaint.mPaintServer);
00876   } 
00877 }
00878 
00879 nsStyleSVGPaint& nsStyleSVGPaint::operator=(const nsStyleSVGPaint& aOther) 
00880 {
00881   mType = aOther.mType;
00882   if (mType == eStyleSVGPaintType_Server) {
00883     mPaint.mPaintServer = aOther.mPaint.mPaintServer;
00884     NS_IF_ADDREF(mPaint.mPaintServer);
00885   } else {
00886     mPaint.mColor = aOther.mPaint.mColor;
00887   }
00888   return *this;
00889 }
00890 
00891 PRBool nsStyleSVGPaint::operator==(const nsStyleSVGPaint& aOther) const
00892 {
00893   if (mType != aOther.mType)
00894     return PR_FALSE;
00895   if (mType == eStyleSVGPaintType_Server)
00896     return EqualURIs(mPaint.mPaintServer, aOther.mPaint.mPaintServer);
00897   if (mType == eStyleSVGPaintType_None)
00898     return PR_TRUE;
00899   return mPaint.mColor == aOther.mPaint.mColor;
00900 }
00901 
00902 #endif // MOZ_SVG
00903 
00904 
00905 // --------------------
00906 // nsStylePosition
00907 //
00908 nsStylePosition::nsStylePosition(void) 
00909 { 
00910   // positioning values not inherited
00911   nsStyleCoord  autoCoord(eStyleUnit_Auto);
00912   mOffset.SetLeft(autoCoord);
00913   mOffset.SetTop(autoCoord);
00914   mOffset.SetRight(autoCoord);
00915   mOffset.SetBottom(autoCoord);
00916   mWidth.SetAutoValue();
00917   mMinWidth.SetCoordValue(0);
00918   mMaxWidth.Reset();
00919   mHeight.SetAutoValue();
00920   mMinHeight.SetCoordValue(0);
00921   mMaxHeight.Reset();
00922   mBoxSizing = NS_STYLE_BOX_SIZING_CONTENT;
00923   mZIndex.SetAutoValue();
00924 }
00925 
00926 nsStylePosition::~nsStylePosition(void) 
00927 { 
00928 }
00929 
00930 nsStylePosition::nsStylePosition(const nsStylePosition& aSource)
00931 {
00932   memcpy((nsStylePosition*)this, &aSource, sizeof(nsStylePosition));
00933 }
00934 
00935 nsChangeHint nsStylePosition::CalcDifference(const nsStylePosition& aOther) const
00936 {
00937   if (mZIndex != aOther.mZIndex) {
00938     return NS_STYLE_HINT_REFLOW;
00939   }
00940   
00941   if ((mOffset == aOther.mOffset) &&
00942       (mWidth == aOther.mWidth) &&
00943       (mMinWidth == aOther.mMinWidth) &&
00944       (mMaxWidth == aOther.mMaxWidth) &&
00945       (mHeight == aOther.mHeight) &&
00946       (mMinHeight == aOther.mMinHeight) &&
00947       (mMaxHeight == aOther.mMaxHeight) &&
00948       (mBoxSizing == aOther.mBoxSizing))
00949     return NS_STYLE_HINT_NONE;
00950   
00951   return nsChangeHint_ReflowFrame;
00952 }
00953 
00954 #ifdef DEBUG
00955 /* static */
00956 nsChangeHint nsStylePosition::MaxDifference()
00957 {
00958   return NS_STYLE_HINT_REFLOW;
00959 }
00960 #endif
00961 
00962 // --------------------
00963 // nsStyleTable
00964 //
00965 
00966 nsStyleTable::nsStyleTable() 
00967 { 
00968   // values not inherited
00969   mLayoutStrategy = NS_STYLE_TABLE_LAYOUT_AUTO;
00970   mCols  = NS_STYLE_TABLE_COLS_NONE;
00971   mFrame = NS_STYLE_TABLE_FRAME_NONE;
00972   mRules = NS_STYLE_TABLE_RULES_NONE;
00973   mSpan = 1;
00974 }
00975 
00976 nsStyleTable::~nsStyleTable(void) 
00977 { 
00978 }
00979 
00980 nsStyleTable::nsStyleTable(const nsStyleTable& aSource)
00981 {
00982   memcpy((nsStyleTable*)this, &aSource, sizeof(nsStyleTable));
00983 }
00984 
00985 nsChangeHint nsStyleTable::CalcDifference(const nsStyleTable& aOther) const
00986 {
00987   // Changes in mRules may require reframing (if border-collapse stuff changes, for example).
00988   if (mRules != aOther.mRules)
00989     return NS_STYLE_HINT_FRAMECHANGE;
00990 
00991   if ((mLayoutStrategy == aOther.mLayoutStrategy) &&
00992       (mFrame == aOther.mFrame) &&
00993       (mCols == aOther.mCols) &&
00994       (mSpan == aOther.mSpan))
00995     return NS_STYLE_HINT_NONE;
00996   return NS_STYLE_HINT_REFLOW;
00997 }
00998 
00999 #ifdef DEBUG
01000 /* static */
01001 nsChangeHint nsStyleTable::MaxDifference()
01002 {
01003   return NS_STYLE_HINT_FRAMECHANGE;
01004 }
01005 #endif
01006 
01007 // -----------------------
01008 // nsStyleTableBorder
01009 
01010 nsStyleTableBorder::nsStyleTableBorder(nsPresContext* aPresContext) 
01011 { 
01012   mBorderCollapse = NS_STYLE_BORDER_SEPARATE;
01013 
01014   nsCompatibility compatMode = eCompatibility_FullStandards;
01015   if (aPresContext)
01016     compatMode = aPresContext->CompatibilityMode();
01017   mEmptyCells = (compatMode == eCompatibility_NavQuirks)
01018                   ? NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND     
01019                   : NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
01020   mCaptionSide = NS_SIDE_TOP;
01021   mBorderSpacingX.SetCoordValue(0);
01022   mBorderSpacingY.SetCoordValue(0);
01023 }
01024 
01025 nsStyleTableBorder::~nsStyleTableBorder(void) 
01026 { 
01027 }
01028 
01029 nsStyleTableBorder::nsStyleTableBorder(const nsStyleTableBorder& aSource)
01030 {
01031   memcpy((nsStyleTableBorder*)this, &aSource, sizeof(nsStyleTableBorder));
01032 }
01033 
01034 nsChangeHint nsStyleTableBorder::CalcDifference(const nsStyleTableBorder& aOther) const
01035 {
01036   // Border-collapse changes need a reframe, because we use a different frame
01037   // class for table cells in the collapsed border model.  This is used to
01038   // conserve memory when using the separated border model (collapsed borders
01039   // require extra state to be stored).
01040   if (mBorderCollapse != aOther.mBorderCollapse) {
01041     return NS_STYLE_HINT_FRAMECHANGE;
01042   }
01043   
01044   if ((mCaptionSide == aOther.mCaptionSide) &&
01045       (mBorderSpacingX == aOther.mBorderSpacingX) &&
01046       (mBorderSpacingY == aOther.mBorderSpacingY)) {
01047     if (mEmptyCells == aOther.mEmptyCells)
01048       return NS_STYLE_HINT_NONE;
01049     return NS_STYLE_HINT_VISUAL;
01050   }
01051   else
01052     return NS_STYLE_HINT_REFLOW;
01053 }
01054 
01055 #ifdef DEBUG
01056 /* static */
01057 nsChangeHint nsStyleTableBorder::MaxDifference()
01058 {
01059   return NS_STYLE_HINT_FRAMECHANGE;
01060 }
01061 #endif
01062 
01063 // --------------------
01064 // nsStyleColor
01065 //
01066 
01067 nsStyleColor::nsStyleColor(nsPresContext* aPresContext)
01068 {
01069   mColor = aPresContext->DefaultColor();
01070 }
01071 
01072 nsStyleColor::nsStyleColor(const nsStyleColor& aSource)
01073 {
01074   mColor = aSource.mColor;
01075 }
01076 
01077 nsChangeHint nsStyleColor::CalcDifference(const nsStyleColor& aOther) const
01078 {
01079   if (mColor == aOther.mColor)
01080     return NS_STYLE_HINT_NONE;
01081   return NS_STYLE_HINT_VISUAL;
01082 }
01083 
01084 #ifdef DEBUG
01085 /* static */
01086 nsChangeHint nsStyleColor::MaxDifference()
01087 {
01088   return NS_STYLE_HINT_VISUAL;
01089 }
01090 #endif
01091 
01092 // --------------------
01093 // nsStyleBackground
01094 //
01095 
01096 nsStyleBackground::nsStyleBackground(nsPresContext* aPresContext)
01097   : mBackgroundFlags(NS_STYLE_BG_COLOR_TRANSPARENT | NS_STYLE_BG_IMAGE_NONE),
01098     mBackgroundAttachment(NS_STYLE_BG_ATTACHMENT_SCROLL),
01099     mBackgroundClip(NS_STYLE_BG_CLIP_BORDER),
01100     mBackgroundInlinePolicy(NS_STYLE_BG_INLINE_POLICY_CONTINUOUS),
01101     mBackgroundOrigin(NS_STYLE_BG_ORIGIN_PADDING),
01102     mBackgroundRepeat(NS_STYLE_BG_REPEAT_XY)
01103 {
01104   mBackgroundColor = aPresContext->DefaultBackgroundColor();
01105 }
01106 
01107 nsStyleBackground::nsStyleBackground(const nsStyleBackground& aSource)
01108   : mBackgroundFlags(aSource.mBackgroundFlags),
01109     mBackgroundAttachment(aSource.mBackgroundAttachment),
01110     mBackgroundClip(aSource.mBackgroundClip),
01111     mBackgroundInlinePolicy(aSource.mBackgroundInlinePolicy),
01112     mBackgroundOrigin(aSource.mBackgroundOrigin),
01113     mBackgroundRepeat(aSource.mBackgroundRepeat),
01114     mBackgroundXPosition(aSource.mBackgroundXPosition),
01115     mBackgroundYPosition(aSource.mBackgroundYPosition),
01116     mBackgroundColor(aSource.mBackgroundColor),
01117     mBackgroundImage(aSource.mBackgroundImage)
01118 {
01119 }
01120 
01121 nsStyleBackground::~nsStyleBackground()
01122 {
01123 }
01124 
01125 nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther) const
01126 {
01127   if (mBackgroundAttachment != aOther.mBackgroundAttachment
01128     && ((NS_STYLE_BG_ATTACHMENT_FIXED == mBackgroundAttachment) ||
01129         (NS_STYLE_BG_ATTACHMENT_FIXED == aOther.mBackgroundAttachment)))
01130     // this might require creation of a view
01131     // XXX This probably doesn't call ApplyRenderingChangeToTree, which
01132     // means we might not invalidate the canvas if this is the body.
01133     return NS_STYLE_HINT_FRAMECHANGE;
01134 
01135   if ((mBackgroundAttachment == aOther.mBackgroundAttachment) &&
01136       (mBackgroundFlags == aOther.mBackgroundFlags) &&
01137       (mBackgroundRepeat == aOther.mBackgroundRepeat) &&
01138       (mBackgroundColor == aOther.mBackgroundColor) &&
01139       (mBackgroundClip == aOther.mBackgroundClip) &&
01140       (mBackgroundInlinePolicy == aOther.mBackgroundInlinePolicy) &&
01141       (mBackgroundOrigin == aOther.mBackgroundOrigin) &&
01142       EqualImages(mBackgroundImage, aOther.mBackgroundImage) &&
01143       ((!(mBackgroundFlags & NS_STYLE_BG_X_POSITION_PERCENT) ||
01144        (mBackgroundXPosition.mFloat == aOther.mBackgroundXPosition.mFloat)) &&
01145        (!(mBackgroundFlags & NS_STYLE_BG_X_POSITION_LENGTH) ||
01146         (mBackgroundXPosition.mCoord == aOther.mBackgroundXPosition.mCoord))) &&
01147       ((!(mBackgroundFlags & NS_STYLE_BG_Y_POSITION_PERCENT) ||
01148        (mBackgroundYPosition.mFloat == aOther.mBackgroundYPosition.mFloat)) &&
01149        (!(mBackgroundFlags & NS_STYLE_BG_Y_POSITION_LENGTH) ||
01150         (mBackgroundYPosition.mCoord == aOther.mBackgroundYPosition.mCoord))))
01151     return NS_STYLE_HINT_NONE;
01152   return NS_STYLE_HINT_VISUAL;
01153 }
01154 
01155 #ifdef DEBUG
01156 /* static */
01157 nsChangeHint nsStyleBackground::MaxDifference()
01158 {
01159   return NS_STYLE_HINT_FRAMECHANGE;
01160 }
01161 #endif
01162 
01163 PRBool nsStyleBackground::HasFixedBackground() const
01164 {
01165   return mBackgroundAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
01166          mBackgroundImage;
01167 }
01168 
01169 // --------------------
01170 // nsStyleDisplay
01171 //
01172 
01173 nsStyleDisplay::nsStyleDisplay()
01174 {
01175   mAppearance = 0;
01176   mDisplay = NS_STYLE_DISPLAY_INLINE;
01177   mOriginalDisplay = NS_STYLE_DISPLAY_NONE;
01178   mPosition = NS_STYLE_POSITION_STATIC;
01179   mFloats = NS_STYLE_FLOAT_NONE;
01180   mBreakType = NS_STYLE_CLEAR_NONE;
01181   mBreakBefore = PR_FALSE;
01182   mBreakAfter = PR_FALSE;
01183   mOverflowX = NS_STYLE_OVERFLOW_VISIBLE;
01184   mOverflowY = NS_STYLE_OVERFLOW_VISIBLE;
01185   mClipFlags = NS_STYLE_CLIP_AUTO;
01186   mClip.SetRect(0,0,0,0);
01187   mOpacity = 1.0f;
01188 }
01189 
01190 nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource)
01191 {
01192   mAppearance = aSource.mAppearance;
01193   mDisplay = aSource.mDisplay;
01194   mOriginalDisplay = aSource.mOriginalDisplay;
01195   mBinding = aSource.mBinding;
01196   mPosition = aSource.mPosition;
01197   mFloats = aSource.mFloats;
01198   mBreakType = aSource.mBreakType;
01199   mBreakBefore = aSource.mBreakBefore;
01200   mBreakAfter = aSource.mBreakAfter;
01201   mOverflowX = aSource.mOverflowX;
01202   mOverflowY = aSource.mOverflowY;
01203   mClipFlags = aSource.mClipFlags;
01204   mClip = aSource.mClip;
01205   mOpacity = aSource.mOpacity;
01206 }
01207 
01208 nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
01209 {
01210   nsChangeHint hint = nsChangeHint(0);
01211 
01212   if (!EqualURIs(mBinding, aOther.mBinding)
01213       || mPosition != aOther.mPosition
01214       || mDisplay != aOther.mDisplay
01215       || (mFloats == NS_STYLE_FLOAT_NONE) != (aOther.mFloats == NS_STYLE_FLOAT_NONE)
01216       || mOverflowX != aOther.mOverflowX
01217       || mOverflowY != aOther.mOverflowY
01218       // might need to create a view to handle change from 1.0 to partial opacity
01219       || (mOpacity != aOther.mOpacity
01220           && ((mOpacity < 1.0) != (aOther.mOpacity < 1.0))))
01221     NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
01222 
01223   if (mFloats != aOther.mFloats)
01224     NS_UpdateHint(hint, nsChangeHint_ReflowFrame);    
01225 
01226   // XXX the following is conservative, for now: changing float breaking shouldn't
01227   // necessarily require a repaint, reflow should suffice.
01228   if (mBreakType != aOther.mBreakType
01229       || mBreakBefore != aOther.mBreakBefore
01230       || mBreakAfter != aOther.mBreakAfter
01231       || mAppearance != aOther.mAppearance)
01232     NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_ReflowFrame, nsChangeHint_RepaintFrame));
01233 
01234   if (mClipFlags != aOther.mClipFlags
01235       || mClip != aOther.mClip
01236       || mOpacity != aOther.mOpacity)
01237     NS_UpdateHint(hint, nsChangeHint_SyncFrameView);
01238 
01239   return hint;
01240 }
01241 
01242 #ifdef DEBUG
01243 /* static */
01244 nsChangeHint nsStyleDisplay::MaxDifference()
01245 {
01246   // All the parts of FRAMECHANGE are present above in CalcDifference.
01247   return NS_STYLE_HINT_FRAMECHANGE;
01248 }
01249 #endif
01250 
01251 // --------------------
01252 // nsStyleVisibility
01253 //
01254 
01255 nsStyleVisibility::nsStyleVisibility(nsPresContext* aPresContext)
01256 {
01257   PRUint32 bidiOptions = aPresContext->GetBidi();
01258   if (GET_BIDI_OPTION_DIRECTION(bidiOptions) == IBMBIDI_TEXTDIRECTION_RTL)
01259     mDirection = NS_STYLE_DIRECTION_RTL;
01260   else
01261     mDirection = NS_STYLE_DIRECTION_LTR;
01262 
01263   mLangGroup = aPresContext->GetLangGroup();
01264   mVisible = NS_STYLE_VISIBILITY_VISIBLE;
01265 }
01266 
01267 nsStyleVisibility::nsStyleVisibility(const nsStyleVisibility& aSource)
01268 {
01269   mDirection = aSource.mDirection;
01270   mVisible = aSource.mVisible;
01271   mLangGroup = aSource.mLangGroup;
01272 } 
01273 
01274 nsChangeHint nsStyleVisibility::CalcDifference(const nsStyleVisibility& aOther) const
01275 {
01276   if ((mDirection == aOther.mDirection) &&
01277       (mLangGroup == aOther.mLangGroup)) {
01278     if ((mVisible == aOther.mVisible)) {
01279       return NS_STYLE_HINT_NONE;
01280     }
01281     if ((NS_STYLE_VISIBILITY_COLLAPSE == mVisible) || 
01282         (NS_STYLE_VISIBILITY_COLLAPSE == aOther.mVisible)) {
01283       return NS_STYLE_HINT_REFLOW;
01284     }
01285     return NS_STYLE_HINT_VISUAL;
01286   }
01287   return NS_STYLE_HINT_REFLOW;
01288 }
01289 
01290 #ifdef DEBUG
01291 /* static */
01292 nsChangeHint nsStyleVisibility::MaxDifference()
01293 {
01294   return NS_STYLE_HINT_REFLOW;
01295 }
01296 #endif
01297 
01298 nsStyleContentData::~nsStyleContentData()
01299 {
01300   if (mType == eStyleContentType_Image) {
01301     NS_IF_RELEASE(mContent.mImage);
01302   } else if (mType == eStyleContentType_Counter ||
01303              mType == eStyleContentType_Counters) {
01304     mContent.mCounters->Release();
01305   } else if (mContent.mString) {
01306     nsCRT::free(mContent.mString);
01307   }
01308 }
01309 
01310 nsStyleContentData& nsStyleContentData::operator=(const nsStyleContentData& aOther)
01311 {
01312   if (this == &aOther)
01313     return *this;
01314   this->~nsStyleContentData();
01315   mType = aOther.mType;
01316   if (mType == eStyleContentType_Image) {
01317     mContent.mImage = aOther.mContent.mImage;
01318     NS_IF_ADDREF(mContent.mImage);
01319   } else if (mType == eStyleContentType_Counter ||
01320              mType == eStyleContentType_Counters) {
01321     mContent.mCounters = aOther.mContent.mCounters;
01322     mContent.mCounters->AddRef();
01323   } else if (aOther.mContent.mString) {
01324     mContent.mString = nsCRT::strdup(aOther.mContent.mString);
01325   } else {
01326     mContent.mString = nsnull;
01327   }
01328   return *this;
01329 }
01330 
01331 PRBool nsStyleContentData::operator==(const nsStyleContentData& aOther)
01332 {
01333   if (mType != aOther.mType)
01334     return PR_FALSE;
01335   if (mType == eStyleContentType_Image) {
01336     if (!mContent.mImage || !aOther.mContent.mImage)
01337       return mContent.mImage == aOther.mContent.mImage;
01338     PRBool eq;
01339     nsCOMPtr<nsIURI> thisURI, otherURI;
01340     mContent.mImage->GetURI(getter_AddRefs(thisURI));
01341     aOther.mContent.mImage->GetURI(getter_AddRefs(otherURI));
01342     return thisURI == otherURI ||  // handles null==null
01343            (thisURI && otherURI &&
01344             NS_SUCCEEDED(thisURI->Equals(otherURI, &eq)) &&
01345             eq);
01346   }
01347   if (mType == eStyleContentType_Counter ||
01348       mType == eStyleContentType_Counters)
01349     return *mContent.mCounters == *aOther.mContent.mCounters;
01350   return nsCRT::strcmp(mContent.mString, aOther.mContent.mString) == 0;
01351 }
01352 
01353 //-----------------------
01354 // nsStyleContent
01355 //
01356 
01357 nsStyleContent::nsStyleContent(void)
01358   : mMarkerOffset(),
01359     mContentCount(0),
01360     mContents(nsnull),
01361     mIncrementCount(0),
01362     mIncrements(nsnull),
01363     mResetCount(0),
01364     mResets(nsnull)
01365 {
01366 }
01367 
01368 nsStyleContent::~nsStyleContent(void)
01369 {
01370   DELETE_ARRAY_IF(mContents);
01371   DELETE_ARRAY_IF(mIncrements);
01372   DELETE_ARRAY_IF(mResets);
01373 }
01374 
01375 nsStyleContent::nsStyleContent(const nsStyleContent& aSource)
01376    :mMarkerOffset(),
01377     mContentCount(0),
01378     mContents(nsnull),
01379     mIncrementCount(0),
01380     mIncrements(nsnull),
01381     mResetCount(0),
01382     mResets(nsnull)
01383 
01384 {
01385   mMarkerOffset = aSource.mMarkerOffset;
01386 
01387   PRUint32 index;
01388   if (NS_SUCCEEDED(AllocateContents(aSource.ContentCount()))) {
01389     for (index = 0; index < mContentCount; index++) {
01390       ContentAt(index) = aSource.ContentAt(index);
01391     }
01392   }
01393 
01394   if (NS_SUCCEEDED(AllocateCounterIncrements(aSource.CounterIncrementCount()))) {
01395     for (index = 0; index < mIncrementCount; index++) {
01396       const nsStyleCounterData *data = aSource.GetCounterIncrementAt(index);
01397       mIncrements[index].mCounter = data->mCounter;
01398       mIncrements[index].mValue = data->mValue;
01399     }
01400   }
01401 
01402   if (NS_SUCCEEDED(AllocateCounterResets(aSource.CounterResetCount()))) {
01403     for (index = 0; index < mResetCount; index++) {
01404       const nsStyleCounterData *data = aSource.GetCounterResetAt(index);
01405       mResets[index].mCounter = data->mCounter;
01406       mResets[index].mValue = data->mValue;
01407     }
01408   }
01409 }
01410 
01411 nsChangeHint nsStyleContent::CalcDifference(const nsStyleContent& aOther) const
01412 {
01413   if (mContentCount != aOther.mContentCount ||
01414       mIncrementCount != aOther.mIncrementCount || 
01415       mResetCount != aOther.mResetCount) {
01416     return NS_STYLE_HINT_FRAMECHANGE;
01417   }
01418 
01419   PRUint32 ix = mContentCount;
01420   while (0 < ix--) {
01421     if (mContents[ix] != aOther.mContents[ix]) {
01422       // Unfortunately we need to reframe here; a simple reflow
01423       // will not pick up different text or different image URLs,
01424       // since we set all that up in the CSSFrameConstructor
01425       return NS_STYLE_HINT_FRAMECHANGE;
01426     }
01427   }
01428   ix = mIncrementCount;
01429   while (0 < ix--) {
01430     if ((mIncrements[ix].mValue != aOther.mIncrements[ix].mValue) || 
01431         (mIncrements[ix].mCounter != aOther.mIncrements[ix].mCounter)) {
01432       return NS_STYLE_HINT_FRAMECHANGE;
01433     }
01434   }
01435   ix = mResetCount;
01436   while (0 < ix--) {
01437     if ((mResets[ix].mValue != aOther.mResets[ix].mValue) || 
01438         (mResets[ix].mCounter != aOther.mResets[ix].mCounter)) {
01439       return NS_STYLE_HINT_FRAMECHANGE;
01440     }
01441   }
01442   if (mMarkerOffset != aOther.mMarkerOffset) {
01443     return NS_STYLE_HINT_REFLOW;
01444   }
01445   return NS_STYLE_HINT_NONE;
01446 }
01447 
01448 #ifdef DEBUG
01449 /* static */
01450 nsChangeHint nsStyleContent::MaxDifference()
01451 {
01452   return NS_STYLE_HINT_FRAMECHANGE;
01453 }
01454 #endif
01455 
01456 nsresult nsStyleContent::AllocateContents(PRUint32 aCount)
01457 {
01458   if (aCount != mContentCount) {
01459     DELETE_ARRAY_IF(mContents);
01460     if (aCount) {
01461       mContents = new nsStyleContentData[aCount];
01462       if (! mContents) {
01463         mContentCount = 0;
01464         return NS_ERROR_OUT_OF_MEMORY;
01465       }
01466     }
01467     mContentCount = aCount;
01468   }
01469   return NS_OK;
01470 }
01471 
01472 // ---------------------
01473 // nsStyleQuotes
01474 //
01475 
01476 nsStyleQuotes::nsStyleQuotes(void)
01477   : mQuotesCount(0),
01478     mQuotes(nsnull)
01479 {
01480 }
01481 
01482 nsStyleQuotes::~nsStyleQuotes(void)
01483 {
01484   DELETE_ARRAY_IF(mQuotes);
01485 }
01486 
01487 nsStyleQuotes::nsStyleQuotes(const nsStyleQuotes& aSource)
01488   : mQuotesCount(0),
01489     mQuotes(nsnull)
01490 {
01491   if (NS_SUCCEEDED(AllocateQuotes(aSource.QuotesCount()))) {
01492     PRUint32 count = (mQuotesCount * 2);
01493     for (PRUint32 index = 0; index < count; index += 2) {
01494       aSource.GetQuotesAt(index, mQuotes[index], mQuotes[index + 1]);
01495     }
01496   }
01497 }
01498 
01499 nsChangeHint nsStyleQuotes::CalcDifference(const nsStyleQuotes& aOther) const
01500 {
01501   // If the quotes implementation is ever going to change we might not need
01502   // a framechange here and a reflow should be sufficient.  See bug 35768.
01503   if (mQuotesCount == aOther.mQuotesCount) {
01504     PRUint32 ix = (mQuotesCount * 2);
01505     while (0 < ix--) {
01506       if (mQuotes[ix] != aOther.mQuotes[ix]) {
01507         return NS_STYLE_HINT_FRAMECHANGE;
01508       }
01509     }
01510 
01511     return NS_STYLE_HINT_NONE;
01512   }
01513   return NS_STYLE_HINT_FRAMECHANGE;
01514 }
01515 
01516 #ifdef DEBUG
01517 /* static */
01518 nsChangeHint nsStyleQuotes::MaxDifference()
01519 {
01520   return NS_STYLE_HINT_FRAMECHANGE;
01521 }
01522 #endif
01523 
01524 // --------------------
01525 // nsStyleTextReset
01526 //
01527 
01528 nsStyleTextReset::nsStyleTextReset(void) 
01529 { 
01530   mVerticalAlign.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE, eStyleUnit_Enumerated);
01531   mTextDecoration = NS_STYLE_TEXT_DECORATION_NONE;
01532   mUnicodeBidi = NS_STYLE_UNICODE_BIDI_NORMAL;
01533 }
01534 
01535 nsStyleTextReset::nsStyleTextReset(const nsStyleTextReset& aSource) 
01536 { 
01537   memcpy((nsStyleTextReset*)this, &aSource, sizeof(nsStyleTextReset));
01538 }
01539 
01540 nsStyleTextReset::~nsStyleTextReset(void) { }
01541 
01542 nsChangeHint nsStyleTextReset::CalcDifference(const nsStyleTextReset& aOther) const
01543 {
01544   if (mVerticalAlign == aOther.mVerticalAlign
01545       && mUnicodeBidi == aOther.mUnicodeBidi) {
01546     if (mTextDecoration != aOther.mTextDecoration) {
01547       // Reflow for blink changes, repaint for others
01548       return
01549         (mTextDecoration & NS_STYLE_TEXT_DECORATION_BLINK) ==
01550         (aOther.mTextDecoration & NS_STYLE_TEXT_DECORATION_BLINK) ?
01551           NS_STYLE_HINT_VISUAL : NS_STYLE_HINT_REFLOW;
01552     }
01553     
01554     return NS_STYLE_HINT_NONE;
01555   }
01556   return NS_STYLE_HINT_REFLOW;
01557 }
01558 
01559 #ifdef DEBUG
01560 /* static */
01561 nsChangeHint nsStyleTextReset::MaxDifference()
01562 {
01563   return NS_STYLE_HINT_REFLOW;
01564 }
01565 #endif
01566 
01567 // --------------------
01568 // nsStyleText
01569 //
01570 
01571 nsStyleText::nsStyleText(void) 
01572 { 
01573   mTextAlign = NS_STYLE_TEXT_ALIGN_DEFAULT;
01574   mTextTransform = NS_STYLE_TEXT_TRANSFORM_NONE;
01575   mWhiteSpace = NS_STYLE_WHITESPACE_NORMAL;
01576 
01577   mLetterSpacing.SetNormalValue();
01578   mLineHeight.SetNormalValue();
01579   mTextIndent.SetCoordValue(0);
01580   mWordSpacing.SetNormalValue();
01581 }
01582 
01583 nsStyleText::nsStyleText(const nsStyleText& aSource) 
01584 { 
01585   memcpy((nsStyleText*)this, &aSource, sizeof(nsStyleText));
01586 }
01587 
01588 nsStyleText::~nsStyleText(void) { }
01589 
01590 nsChangeHint nsStyleText::CalcDifference(const nsStyleText& aOther) const
01591 {
01592   if ((mTextAlign == aOther.mTextAlign) &&
01593       (mTextTransform == aOther.mTextTransform) &&
01594       (mWhiteSpace == aOther.mWhiteSpace) &&
01595       (mLetterSpacing == aOther.mLetterSpacing) &&
01596       (mLineHeight == aOther.mLineHeight) &&
01597       (mTextIndent == aOther.mTextIndent) &&
01598       (mWordSpacing == aOther.mWordSpacing))
01599     return NS_STYLE_HINT_NONE;
01600   return NS_STYLE_HINT_REFLOW;
01601 }
01602 
01603 #ifdef DEBUG
01604 /* static */
01605 nsChangeHint nsStyleText::MaxDifference()
01606 {
01607   return NS_STYLE_HINT_REFLOW;
01608 }
01609 #endif
01610 
01611 //-----------------------
01612 // nsStyleUserInterface
01613 //
01614 
01615 nsCursorImage::nsCursorImage()
01616   : mHaveHotspot(PR_FALSE)
01617   , mHotspotX(0.0f)
01618   , mHotspotY(0.0f)
01619 {
01620 }
01621 
01622 nsStyleUserInterface::nsStyleUserInterface(void) 
01623 { 
01624   mUserInput = NS_STYLE_USER_INPUT_AUTO;
01625   mUserModify = NS_STYLE_USER_MODIFY_READ_ONLY;
01626   mUserFocus = NS_STYLE_USER_FOCUS_NONE;
01627 
01628   mCursor = NS_STYLE_CURSOR_AUTO; // fix for bugzilla bug 51113
01629 
01630   mCursorArrayLength = 0;
01631   mCursorArray = nsnull;
01632 }
01633 
01634 nsStyleUserInterface::nsStyleUserInterface(const nsStyleUserInterface& aSource) :
01635   mUserInput(aSource.mUserInput),
01636   mUserModify(aSource.mUserModify),
01637   mUserFocus(aSource.mUserFocus),
01638   mCursor(aSource.mCursor)
01639 { 
01640   CopyCursorArrayFrom(aSource);
01641 }
01642 
01643 nsStyleUserInterface::~nsStyleUserInterface(void) 
01644 { 
01645   delete [] mCursorArray;
01646 }
01647 
01648 nsChangeHint nsStyleUserInterface::CalcDifference(const nsStyleUserInterface& aOther) const
01649 {
01650   nsChangeHint hint = nsChangeHint(0);
01651   if (mCursor != aOther.mCursor)
01652     NS_UpdateHint(hint, nsChangeHint_UpdateCursor);
01653 
01654   // We could do better. But it wouldn't be worth it, URL-specified cursors are
01655   // rare.
01656   if (mCursorArrayLength > 0 || aOther.mCursorArrayLength > 0)
01657     NS_UpdateHint(hint, nsChangeHint_UpdateCursor);
01658 
01659   if (mUserModify != aOther.mUserModify)
01660     NS_UpdateHint(hint, NS_STYLE_HINT_VISUAL);
01661   
01662   if ((mUserInput != aOther.mUserInput) &&
01663       ((NS_STYLE_USER_INPUT_NONE == mUserInput) || 
01664        (NS_STYLE_USER_INPUT_NONE == aOther.mUserInput))) {
01665     NS_UpdateHint(hint, NS_STYLE_HINT_FRAMECHANGE);
01666   }
01667 
01668   // ignore mUserFocus
01669 
01670   return hint;
01671 }
01672 
01673 #ifdef DEBUG
01674 /* static */
01675 nsChangeHint nsStyleUserInterface::MaxDifference()
01676 {
01677   return nsChangeHint(nsChangeHint_UpdateCursor | NS_STYLE_HINT_FRAMECHANGE);
01678 }
01679 #endif
01680 
01681 void
01682 nsStyleUserInterface::CopyCursorArrayFrom(const nsStyleUserInterface& aSource)
01683 {
01684   mCursorArray = nsnull;
01685   mCursorArrayLength = 0;
01686   if (aSource.mCursorArrayLength) {
01687     mCursorArray = new nsCursorImage[aSource.mCursorArrayLength];
01688     if (mCursorArray) {
01689       mCursorArrayLength = aSource.mCursorArrayLength;
01690       for (PRUint32 i = 0; i < mCursorArrayLength; ++i)
01691         mCursorArray[i] = aSource.mCursorArray[i];
01692     }
01693   }
01694 }
01695 
01696 //-----------------------
01697 // nsStyleUIReset
01698 //
01699 
01700 nsStyleUIReset::nsStyleUIReset(void) 
01701 { 
01702   mUserSelect = NS_STYLE_USER_SELECT_AUTO;
01703   mForceBrokenImageIcon = 0;
01704 }
01705 
01706 nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset& aSource) 
01707 {
01708   mUserSelect = aSource.mUserSelect;
01709   mForceBrokenImageIcon = aSource.mForceBrokenImageIcon;
01710 }
01711 
01712 nsStyleUIReset::~nsStyleUIReset(void) 
01713 { 
01714 }
01715 
01716 nsChangeHint nsStyleUIReset::CalcDifference(const nsStyleUIReset& aOther) const
01717 {
01718   if (mForceBrokenImageIcon == aOther.mForceBrokenImageIcon) {
01719     if (mUserSelect == aOther.mUserSelect) {
01720       return NS_STYLE_HINT_NONE;
01721     }
01722     return NS_STYLE_HINT_VISUAL;
01723   }
01724   return NS_STYLE_HINT_FRAMECHANGE;
01725 }
01726 
01727 #ifdef DEBUG
01728 /* static */
01729 nsChangeHint nsStyleUIReset::MaxDifference()
01730 {
01731   return NS_STYLE_HINT_FRAMECHANGE;
01732 }
01733 #endif
01734