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
4 : *
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/
9 : *
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.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
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.
21 : *
22 : * Contributor(s):
23 : * David Hyatt (hyatt@netscape.com)
24 : * Mats Palmgren <matspal@gmail.com>
25 : * Michael Ventnor <m.ventnor@gmail.com>
26 : * Jonathon Jongsma <jonathon.jongsma@collabora.co.uk>, Collabora Ltd.
27 : * L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
28 : *
29 : * Alternatively, the contents of this file may be used under the terms of
30 : * either of the GNU General Public License Version 2 or later (the "GPL"),
31 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
32 : * in which case the provisions of the GPL or the LGPL are applicable instead
33 : * of those above. If you wish to allow use of your version of this file only
34 : * under the terms of either the GPL or the LGPL, and not to allow others to
35 : * use your version of this file under the terms of the MPL, indicate your
36 : * decision by deleting the provisions above and replace them with the notice
37 : * and other provisions required by the GPL or the LGPL. If you do not delete
38 : * the provisions above, a recipient may use your version of this file under
39 : * the terms of any one of the MPL, the GPL or the LGPL.
40 : *
41 : * ***** END LICENSE BLOCK ***** */
42 :
43 : /*
44 : * structs that contain the data provided by nsStyleContext, the
45 : * internal API for computed style data for an element
46 : */
47 :
48 : #include "nsStyleStruct.h"
49 : #include "nsStyleStructInlines.h"
50 : #include "nsStyleConsts.h"
51 : #include "nsThemeConstants.h"
52 : #include "nsString.h"
53 : #include "nsPresContext.h"
54 : #include "nsIWidget.h"
55 : #include "nsIStyleRule.h"
56 : #include "nsCRTGlue.h"
57 : #include "nsCSSProps.h"
58 :
59 : #include "nsCOMPtr.h"
60 : #include "nsIFrame.h"
61 : #include "nsHTMLReflowState.h"
62 : #include "prenv.h"
63 :
64 : #include "nsSVGUtils.h"
65 : #include "nsBidiUtils.h"
66 : #include "nsLayoutUtils.h"
67 :
68 : #include "imgIRequest.h"
69 : #include "imgIContainer.h"
70 : #include "prlog.h"
71 :
72 : MOZ_STATIC_ASSERT((((1 << nsStyleStructID_Length) - 1) &
73 : ~(NS_STYLE_INHERIT_MASK)) == 0,
74 : "Not enough bits in NS_STYLE_INHERIT_MASK");
75 :
76 0 : inline bool IsFixedUnit(const nsStyleCoord& aCoord, bool aEnumOK)
77 : {
78 0 : return aCoord.ConvertsToLength() ||
79 0 : (aEnumOK && aCoord.GetUnit() == eStyleUnit_Enumerated);
80 : }
81 :
82 0 : static bool EqualURIs(nsIURI *aURI1, nsIURI *aURI2)
83 : {
84 : bool eq;
85 : return aURI1 == aURI2 || // handle null==null, and optimize
86 : (aURI1 && aURI2 &&
87 0 : NS_SUCCEEDED(aURI1->Equals(aURI2, &eq)) && // not equal on fail
88 0 : eq);
89 : }
90 :
91 0 : static bool EqualURIs(nsCSSValue::URL *aURI1, nsCSSValue::URL *aURI2)
92 : {
93 : return aURI1 == aURI2 || // handle null==null, and optimize
94 0 : (aURI1 && aURI2 && aURI1->URIEquals(*aURI2));
95 : }
96 :
97 0 : static bool EqualImages(imgIRequest *aImage1, imgIRequest* aImage2)
98 : {
99 0 : if (aImage1 == aImage2) {
100 0 : return true;
101 : }
102 :
103 0 : if (!aImage1 || !aImage2) {
104 0 : return false;
105 : }
106 :
107 0 : nsCOMPtr<nsIURI> uri1, uri2;
108 0 : aImage1->GetURI(getter_AddRefs(uri1));
109 0 : aImage2->GetURI(getter_AddRefs(uri2));
110 0 : return EqualURIs(uri1, uri2);
111 : }
112 :
113 : // A nullsafe wrapper for strcmp. We depend on null-safety.
114 0 : static int safe_strcmp(const PRUnichar* a, const PRUnichar* b)
115 : {
116 0 : if (!a || !b) {
117 0 : return (int)(a - b);
118 : }
119 0 : return NS_strcmp(a, b);
120 : }
121 :
122 : static nsChangeHint CalcShadowDifference(nsCSSShadowArray* lhs,
123 : nsCSSShadowArray* rhs);
124 :
125 : // --------------------
126 : // nsStyleFont
127 : //
128 0 : nsStyleFont::nsStyleFont(const nsFont& aFont, nsPresContext *aPresContext)
129 : : mFont(aFont),
130 0 : mGenericID(kGenericFont_NONE)
131 : {
132 0 : MOZ_COUNT_CTOR(nsStyleFont);
133 0 : Init(aPresContext);
134 0 : }
135 :
136 0 : nsStyleFont::nsStyleFont(const nsStyleFont& aSrc)
137 : : mFont(aSrc.mFont)
138 : , mSize(aSrc.mSize)
139 : , mGenericID(aSrc.mGenericID)
140 : , mScriptLevel(aSrc.mScriptLevel)
141 : , mScriptUnconstrainedSize(aSrc.mScriptUnconstrainedSize)
142 : , mScriptMinSize(aSrc.mScriptMinSize)
143 : , mScriptSizeMultiplier(aSrc.mScriptSizeMultiplier)
144 0 : , mLanguage(aSrc.mLanguage)
145 : {
146 0 : MOZ_COUNT_CTOR(nsStyleFont);
147 0 : }
148 :
149 0 : nsStyleFont::nsStyleFont(nsPresContext* aPresContext)
150 : // passing nsnull to GetDefaultFont make it use the doc language
151 0 : : mFont(*(aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID, nsnull))),
152 0 : mGenericID(kGenericFont_NONE)
153 : {
154 0 : MOZ_COUNT_CTOR(nsStyleFont);
155 0 : Init(aPresContext);
156 0 : }
157 :
158 : void
159 0 : nsStyleFont::Init(nsPresContext* aPresContext)
160 : {
161 0 : mSize = mFont.size = nsStyleFont::ZoomText(aPresContext, mFont.size);
162 0 : mScriptUnconstrainedSize = mSize;
163 : mScriptMinSize = aPresContext->CSSTwipsToAppUnits(
164 0 : NS_POINTS_TO_TWIPS(NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT));
165 0 : mScriptLevel = 0;
166 0 : mScriptSizeMultiplier = NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER;
167 :
168 0 : nsAutoString language;
169 0 : aPresContext->Document()->GetContentLanguage(language);
170 0 : language.StripWhitespace();
171 :
172 : // Content-Language may be a comma-separated list of language codes,
173 : // in which case the HTML5 spec says to treat it as unknown
174 0 : if (!language.IsEmpty() &&
175 0 : language.FindChar(PRUnichar(',')) == kNotFound) {
176 0 : mLanguage = do_GetAtom(language);
177 : } else {
178 : // we didn't find a (usable) Content-Language, so we fall back
179 : // to whatever the presContext guessed from the charset
180 0 : mLanguage = aPresContext->GetLanguageFromCharset();
181 : }
182 0 : }
183 :
184 : void*
185 0 : nsStyleFont::operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
186 0 : void* result = aContext->AllocateFromShell(sz);
187 0 : if (result)
188 0 : memset(result, 0, sz);
189 0 : return result;
190 : }
191 :
192 : void
193 0 : nsStyleFont::Destroy(nsPresContext* aContext) {
194 0 : this->~nsStyleFont();
195 0 : aContext->FreeToShell(sizeof(nsStyleFont), this);
196 0 : }
197 :
198 0 : nsChangeHint nsStyleFont::CalcDifference(const nsStyleFont& aOther) const
199 : {
200 0 : if (mSize != aOther.mSize ||
201 0 : mLanguage != aOther.mLanguage) {
202 0 : return NS_STYLE_HINT_REFLOW;
203 : }
204 0 : return CalcFontDifference(mFont, aOther.mFont);
205 : }
206 :
207 : #ifdef DEBUG
208 : /* static */
209 0 : nsChangeHint nsStyleFont::MaxDifference()
210 : {
211 0 : return NS_STYLE_HINT_REFLOW;
212 : }
213 : #endif
214 :
215 : /* static */ nscoord
216 0 : nsStyleFont::ZoomText(nsPresContext *aPresContext, nscoord aSize)
217 : {
218 0 : return nscoord(float(aSize) * aPresContext->TextZoom());
219 : }
220 :
221 : /* static */ nscoord
222 0 : nsStyleFont::UnZoomText(nsPresContext *aPresContext, nscoord aSize)
223 : {
224 0 : return nscoord(float(aSize) / aPresContext->TextZoom());
225 : }
226 :
227 0 : nsChangeHint nsStyleFont::CalcFontDifference(const nsFont& aFont1, const nsFont& aFont2)
228 : {
229 0 : if ((aFont1.size == aFont2.size) &&
230 : (aFont1.sizeAdjust == aFont2.sizeAdjust) &&
231 : (aFont1.style == aFont2.style) &&
232 : (aFont1.variant == aFont2.variant) &&
233 : (aFont1.weight == aFont2.weight) &&
234 : (aFont1.stretch == aFont2.stretch) &&
235 0 : (aFont1.name == aFont2.name) &&
236 0 : (aFont1.featureSettings == aFont2.featureSettings) &&
237 0 : (aFont1.languageOverride == aFont2.languageOverride)) {
238 0 : if ((aFont1.decorations == aFont2.decorations)) {
239 0 : return NS_STYLE_HINT_NONE;
240 : }
241 0 : return NS_STYLE_HINT_VISUAL;
242 : }
243 0 : return NS_STYLE_HINT_REFLOW;
244 : }
245 :
246 0 : static bool IsFixedData(const nsStyleSides& aSides, bool aEnumOK)
247 : {
248 0 : NS_FOR_CSS_SIDES(side) {
249 0 : if (!IsFixedUnit(aSides.Get(side), aEnumOK))
250 0 : return false;
251 : }
252 0 : return true;
253 : }
254 :
255 0 : static nscoord CalcCoord(const nsStyleCoord& aCoord,
256 : const nscoord* aEnumTable,
257 : PRInt32 aNumEnums)
258 : {
259 0 : if (aCoord.GetUnit() == eStyleUnit_Enumerated) {
260 0 : NS_ABORT_IF_FALSE(aEnumTable, "must have enum table");
261 0 : PRInt32 value = aCoord.GetIntValue();
262 0 : if (0 <= value && value < aNumEnums) {
263 0 : return aEnumTable[aCoord.GetIntValue()];
264 : }
265 0 : NS_NOTREACHED("unexpected enum value");
266 0 : return 0;
267 : }
268 0 : NS_ABORT_IF_FALSE(aCoord.ConvertsToLength(), "unexpected unit");
269 0 : return nsRuleNode::ComputeCoordPercentCalc(aCoord, 0);
270 : }
271 :
272 0 : nsStyleMargin::nsStyleMargin() {
273 0 : MOZ_COUNT_CTOR(nsStyleMargin);
274 0 : nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
275 0 : NS_FOR_CSS_SIDES(side) {
276 0 : mMargin.Set(side, zero);
277 : }
278 0 : mHasCachedMargin = false;
279 0 : }
280 :
281 0 : nsStyleMargin::nsStyleMargin(const nsStyleMargin& aSrc) {
282 0 : MOZ_COUNT_CTOR(nsStyleMargin);
283 0 : mMargin = aSrc.mMargin;
284 0 : mHasCachedMargin = false;
285 0 : }
286 :
287 : void*
288 0 : nsStyleMargin::operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
289 0 : void* result = aContext->AllocateFromShell(sz);
290 0 : if (result)
291 0 : memset(result, 0, sz);
292 0 : return result;
293 : }
294 :
295 : void
296 0 : nsStyleMargin::Destroy(nsPresContext* aContext) {
297 0 : this->~nsStyleMargin();
298 0 : aContext->FreeToShell(sizeof(nsStyleMargin), this);
299 0 : }
300 :
301 :
302 0 : void nsStyleMargin::RecalcData()
303 : {
304 0 : if (IsFixedData(mMargin, false)) {
305 0 : NS_FOR_CSS_SIDES(side) {
306 0 : mCachedMargin.Side(side) = CalcCoord(mMargin.Get(side), nsnull, 0);
307 : }
308 0 : mHasCachedMargin = true;
309 : }
310 : else
311 0 : mHasCachedMargin = false;
312 0 : }
313 :
314 0 : nsChangeHint nsStyleMargin::CalcDifference(const nsStyleMargin& aOther) const
315 : {
316 0 : if (mMargin == aOther.mMargin) {
317 0 : return NS_STYLE_HINT_NONE;
318 : }
319 : // Margin differences can't affect descendant intrinsic sizes and
320 : // don't need to force children to reflow.
321 : return NS_SubtractHint(NS_STYLE_HINT_REFLOW,
322 : NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics,
323 0 : nsChangeHint_NeedDirtyReflow));
324 : }
325 :
326 : #ifdef DEBUG
327 : /* static */
328 0 : nsChangeHint nsStyleMargin::MaxDifference()
329 : {
330 : return NS_SubtractHint(NS_STYLE_HINT_REFLOW,
331 : NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics,
332 0 : nsChangeHint_NeedDirtyReflow));
333 : }
334 : #endif
335 :
336 0 : nsStylePadding::nsStylePadding() {
337 0 : MOZ_COUNT_CTOR(nsStylePadding);
338 0 : nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
339 0 : NS_FOR_CSS_SIDES(side) {
340 0 : mPadding.Set(side, zero);
341 : }
342 0 : mHasCachedPadding = false;
343 0 : }
344 :
345 0 : nsStylePadding::nsStylePadding(const nsStylePadding& aSrc) {
346 0 : MOZ_COUNT_CTOR(nsStylePadding);
347 0 : mPadding = aSrc.mPadding;
348 0 : mHasCachedPadding = false;
349 0 : }
350 :
351 : void*
352 0 : nsStylePadding::operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
353 0 : void* result = aContext->AllocateFromShell(sz);
354 0 : if (result)
355 0 : memset(result, 0, sz);
356 0 : return result;
357 : }
358 :
359 : void
360 0 : nsStylePadding::Destroy(nsPresContext* aContext) {
361 0 : this->~nsStylePadding();
362 0 : aContext->FreeToShell(sizeof(nsStylePadding), this);
363 0 : }
364 :
365 0 : void nsStylePadding::RecalcData()
366 : {
367 0 : if (IsFixedData(mPadding, false)) {
368 0 : NS_FOR_CSS_SIDES(side) {
369 : // Clamp negative calc() to 0.
370 0 : mCachedPadding.Side(side) =
371 0 : NS_MAX(CalcCoord(mPadding.Get(side), nsnull, 0), 0);
372 : }
373 0 : mHasCachedPadding = true;
374 : }
375 : else
376 0 : mHasCachedPadding = false;
377 0 : }
378 :
379 0 : nsChangeHint nsStylePadding::CalcDifference(const nsStylePadding& aOther) const
380 : {
381 0 : if (mPadding == aOther.mPadding) {
382 0 : return NS_STYLE_HINT_NONE;
383 : }
384 : // Padding differences can't affect descendant intrinsic sizes, but do need
385 : // to force children to reflow so that we can reposition them, since their
386 : // offsets are from our frame bounds but our content rect's position within
387 : // those bounds is moving.
388 : return NS_SubtractHint(NS_STYLE_HINT_REFLOW,
389 0 : nsChangeHint_ClearDescendantIntrinsics);
390 : }
391 :
392 : #ifdef DEBUG
393 : /* static */
394 0 : nsChangeHint nsStylePadding::MaxDifference()
395 : {
396 : return NS_SubtractHint(NS_STYLE_HINT_REFLOW,
397 0 : nsChangeHint_ClearDescendantIntrinsics);
398 : }
399 : #endif
400 :
401 0 : nsStyleBorder::nsStyleBorder(nsPresContext* aPresContext)
402 : : mHaveBorderImageWidth(false)
403 : #ifdef DEBUG
404 : , mImageTracked(false)
405 : #endif
406 : , mComputedBorder(0, 0, 0, 0)
407 0 : , mBorderImage(nsnull)
408 : {
409 0 : MOZ_COUNT_CTOR(nsStyleBorder);
410 : nscoord medium =
411 0 : (aPresContext->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM];
412 0 : NS_FOR_CSS_SIDES(side) {
413 0 : mBorder.Side(side) = medium;
414 0 : mBorderStyle[side] = NS_STYLE_BORDER_STYLE_NONE | BORDER_COLOR_FOREGROUND;
415 0 : mBorderColor[side] = NS_RGB(0, 0, 0);
416 : }
417 0 : NS_FOR_CSS_HALF_CORNERS(corner) {
418 0 : mBorderRadius.Set(corner, nsStyleCoord(0, nsStyleCoord::CoordConstructor));
419 : }
420 :
421 0 : mBorderColors = nsnull;
422 0 : mBoxShadow = nsnull;
423 :
424 0 : mFloatEdge = NS_STYLE_FLOAT_EDGE_CONTENT;
425 :
426 0 : mTwipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
427 0 : }
428 :
429 0 : nsBorderColors::~nsBorderColors()
430 : {
431 0 : NS_CSS_DELETE_LIST_MEMBER(nsBorderColors, this, mNext);
432 0 : }
433 :
434 : nsBorderColors*
435 0 : nsBorderColors::Clone(bool aDeep) const
436 : {
437 0 : nsBorderColors* result = new nsBorderColors(mColor);
438 0 : if (NS_UNLIKELY(!result))
439 0 : return result;
440 0 : if (aDeep)
441 0 : NS_CSS_CLONE_LIST_MEMBER(nsBorderColors, this, mNext, result, (false));
442 0 : return result;
443 : }
444 :
445 0 : nsStyleBorder::nsStyleBorder(const nsStyleBorder& aSrc)
446 : : mBorderRadius(aSrc.mBorderRadius),
447 : mBorderImageSplit(aSrc.mBorderImageSplit),
448 : mFloatEdge(aSrc.mFloatEdge),
449 : mBorderImageHFill(aSrc.mBorderImageHFill),
450 : mBorderImageVFill(aSrc.mBorderImageVFill),
451 : mBorderColors(nsnull),
452 : mBoxShadow(aSrc.mBoxShadow),
453 : mHaveBorderImageWidth(aSrc.mHaveBorderImageWidth),
454 : mBorderImageWidth(aSrc.mBorderImageWidth),
455 : mComputedBorder(aSrc.mComputedBorder),
456 : mBorder(aSrc.mBorder),
457 : mBorderImage(aSrc.mBorderImage),
458 0 : mTwipsPerPixel(aSrc.mTwipsPerPixel)
459 : {
460 0 : MOZ_COUNT_CTOR(nsStyleBorder);
461 0 : if (aSrc.mBorderColors) {
462 0 : EnsureBorderColors();
463 0 : for (PRInt32 i = 0; i < 4; i++)
464 0 : if (aSrc.mBorderColors[i])
465 0 : mBorderColors[i] = aSrc.mBorderColors[i]->Clone();
466 : else
467 0 : mBorderColors[i] = nsnull;
468 : }
469 :
470 0 : NS_FOR_CSS_SIDES(side) {
471 0 : mBorderStyle[side] = aSrc.mBorderStyle[side];
472 0 : mBorderColor[side] = aSrc.mBorderColor[side];
473 : }
474 0 : NS_FOR_CSS_HALF_CORNERS(corner) {
475 0 : mBorderRadius.Set(corner, aSrc.mBorderRadius.Get(corner));
476 : }
477 0 : }
478 :
479 0 : nsStyleBorder::~nsStyleBorder()
480 : {
481 0 : NS_ABORT_IF_FALSE(!mImageTracked,
482 : "nsStyleBorder being destroyed while still tracking image!");
483 0 : MOZ_COUNT_DTOR(nsStyleBorder);
484 0 : if (mBorderColors) {
485 0 : for (PRInt32 i = 0; i < 4; i++)
486 0 : delete mBorderColors[i];
487 0 : delete [] mBorderColors;
488 : }
489 0 : }
490 :
491 : void*
492 0 : nsStyleBorder::operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
493 0 : void* result = aContext->AllocateFromShell(sz);
494 0 : if (result)
495 0 : memset(result, 0, sz);
496 0 : return result;
497 : }
498 :
499 : void
500 0 : nsStyleBorder::Destroy(nsPresContext* aContext) {
501 0 : if (mBorderImage)
502 0 : UntrackImage(aContext);
503 0 : this->~nsStyleBorder();
504 0 : aContext->FreeToShell(sizeof(nsStyleBorder), this);
505 0 : }
506 :
507 :
508 0 : nsChangeHint nsStyleBorder::CalcDifference(const nsStyleBorder& aOther) const
509 : {
510 : nsChangeHint shadowDifference =
511 0 : CalcShadowDifference(mBoxShadow, aOther.mBoxShadow);
512 :
513 : // Note that differences in mBorder don't affect rendering (which should only
514 : // use mComputedBorder), so don't need to be tested for here.
515 : // XXXbz we should be able to return a more specific change hint for
516 : // at least GetActualBorder() differences...
517 0 : if (mTwipsPerPixel != aOther.mTwipsPerPixel ||
518 0 : GetActualBorder() != aOther.GetActualBorder() ||
519 : mFloatEdge != aOther.mFloatEdge ||
520 : (shadowDifference & nsChangeHint_ReflowFrame))
521 0 : return NS_STYLE_HINT_REFLOW;
522 :
523 : // Note that mBorderStyle stores not only the border style but also
524 : // color-related flags. Given that we've already done an mComputedBorder
525 : // comparison, border-style differences can only lead to a VISUAL hint. So
526 : // it's OK to just compare the values directly -- if either the actual
527 : // style or the color flags differ we want to repaint.
528 0 : NS_FOR_CSS_SIDES(ix) {
529 0 : if (mBorderStyle[ix] != aOther.mBorderStyle[ix] ||
530 0 : mBorderColor[ix] != aOther.mBorderColor[ix])
531 0 : return NS_STYLE_HINT_VISUAL;
532 : }
533 :
534 0 : if (mBorderRadius != aOther.mBorderRadius ||
535 0 : !mBorderColors != !aOther.mBorderColors)
536 0 : return NS_STYLE_HINT_VISUAL;
537 :
538 0 : if (IsBorderImageLoaded() || aOther.IsBorderImageLoaded()) {
539 0 : if (mBorderImage != aOther.mBorderImage ||
540 : mBorderImageHFill != aOther.mBorderImageHFill ||
541 : mBorderImageVFill != aOther.mBorderImageVFill ||
542 0 : mBorderImageSplit != aOther.mBorderImageSplit)
543 0 : return NS_STYLE_HINT_VISUAL;
544 : // The call to GetActualBorder above already considered
545 : // mBorderImageWidth and mHaveBorderImageWidth.
546 : }
547 :
548 : // Note that at this point if mBorderColors is non-null so is
549 : // aOther.mBorderColors
550 0 : if (mBorderColors) {
551 0 : NS_FOR_CSS_SIDES(ix) {
552 0 : if (!nsBorderColors::Equal(mBorderColors[ix],
553 0 : aOther.mBorderColors[ix]))
554 0 : return NS_STYLE_HINT_VISUAL;
555 : }
556 : }
557 :
558 0 : return shadowDifference;
559 : }
560 :
561 : #ifdef DEBUG
562 : /* static */
563 0 : nsChangeHint nsStyleBorder::MaxDifference()
564 : {
565 0 : return NS_STYLE_HINT_REFLOW;
566 : }
567 : #endif
568 :
569 : bool
570 0 : nsStyleBorder::ImageBorderDiffers() const
571 : {
572 : return mComputedBorder !=
573 0 : (mHaveBorderImageWidth ? mBorderImageWidth : mBorder);
574 : }
575 :
576 : const nsMargin&
577 0 : nsStyleBorder::GetActualBorder() const
578 : {
579 0 : if (IsBorderImageLoaded())
580 0 : if (mHaveBorderImageWidth)
581 0 : return mBorderImageWidth;
582 : else
583 0 : return mBorder;
584 : else
585 0 : return mComputedBorder;
586 : }
587 :
588 : void
589 0 : nsStyleBorder::TrackImage(nsPresContext* aContext)
590 : {
591 : // Sanity
592 0 : NS_ABORT_IF_FALSE(!mImageTracked, "Already tracking image!");
593 0 : NS_ABORT_IF_FALSE(mBorderImage, "Can't track null image!");
594 :
595 : // Register the image with the document
596 0 : nsIDocument* doc = aContext->Document();
597 0 : if (doc)
598 0 : doc->AddImage(mBorderImage);
599 :
600 : // Mark state
601 : #ifdef DEBUG
602 0 : mImageTracked = true;
603 : #endif
604 0 : }
605 :
606 : void
607 0 : nsStyleBorder::UntrackImage(nsPresContext* aContext)
608 : {
609 : // Sanity
610 0 : NS_ABORT_IF_FALSE(mImageTracked, "Image not tracked!");
611 0 : NS_ABORT_IF_FALSE(mBorderImage, "Can't track null image!");
612 :
613 : // Unregister the image with the document
614 0 : nsIDocument* doc = aContext->Document();
615 0 : if (doc)
616 0 : doc->RemoveImage(mBorderImage);
617 :
618 : // Mark state
619 : #ifdef DEBUG
620 0 : mImageTracked = false;
621 : #endif
622 0 : }
623 :
624 0 : nsStyleOutline::nsStyleOutline(nsPresContext* aPresContext)
625 : {
626 0 : MOZ_COUNT_CTOR(nsStyleOutline);
627 : // spacing values not inherited
628 0 : nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
629 0 : NS_FOR_CSS_HALF_CORNERS(corner) {
630 0 : mOutlineRadius.Set(corner, zero);
631 : }
632 :
633 0 : mOutlineOffset = 0;
634 :
635 0 : mOutlineWidth = nsStyleCoord(NS_STYLE_BORDER_WIDTH_MEDIUM, eStyleUnit_Enumerated);
636 0 : mOutlineStyle = NS_STYLE_BORDER_STYLE_NONE;
637 0 : mOutlineColor = NS_RGB(0, 0, 0);
638 :
639 0 : mHasCachedOutline = false;
640 0 : mTwipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
641 0 : }
642 :
643 0 : nsStyleOutline::nsStyleOutline(const nsStyleOutline& aSrc) {
644 0 : MOZ_COUNT_CTOR(nsStyleOutline);
645 0 : memcpy((nsStyleOutline*)this, &aSrc, sizeof(nsStyleOutline));
646 0 : }
647 :
648 : void
649 0 : nsStyleOutline::RecalcData(nsPresContext* aContext)
650 : {
651 0 : if (NS_STYLE_BORDER_STYLE_NONE == GetOutlineStyle()) {
652 0 : mCachedOutlineWidth = 0;
653 0 : mHasCachedOutline = true;
654 0 : } else if (IsFixedUnit(mOutlineWidth, true)) {
655 : // Clamp negative calc() to 0.
656 : mCachedOutlineWidth =
657 0 : NS_MAX(CalcCoord(mOutlineWidth, aContext->GetBorderWidthTable(), 3), 0);
658 : mCachedOutlineWidth =
659 0 : NS_ROUND_BORDER_TO_PIXELS(mCachedOutlineWidth, mTwipsPerPixel);
660 0 : mHasCachedOutline = true;
661 : }
662 : else
663 0 : mHasCachedOutline = false;
664 0 : }
665 :
666 0 : nsChangeHint nsStyleOutline::CalcDifference(const nsStyleOutline& aOther) const
667 : {
668 : bool outlineWasVisible =
669 0 : mCachedOutlineWidth > 0 && mOutlineStyle != NS_STYLE_BORDER_STYLE_NONE;
670 : bool outlineIsVisible =
671 0 : aOther.mCachedOutlineWidth > 0 && aOther.mOutlineStyle != NS_STYLE_BORDER_STYLE_NONE;
672 0 : if (outlineWasVisible != outlineIsVisible ||
673 : (outlineIsVisible && (mOutlineOffset != aOther.mOutlineOffset ||
674 0 : mOutlineWidth != aOther.mOutlineWidth ||
675 : mTwipsPerPixel != aOther.mTwipsPerPixel))) {
676 0 : return NS_CombineHint(nsChangeHint_ReflowFrame, nsChangeHint_RepaintFrame);
677 : }
678 0 : if ((mOutlineStyle != aOther.mOutlineStyle) ||
679 : (mOutlineColor != aOther.mOutlineColor) ||
680 0 : (mOutlineRadius != aOther.mOutlineRadius)) {
681 0 : return nsChangeHint_RepaintFrame;
682 : }
683 0 : return NS_STYLE_HINT_NONE;
684 : }
685 :
686 : #ifdef DEBUG
687 : /* static */
688 0 : nsChangeHint nsStyleOutline::MaxDifference()
689 : {
690 0 : return NS_CombineHint(nsChangeHint_ReflowFrame, nsChangeHint_RepaintFrame);
691 : }
692 : #endif
693 :
694 : // --------------------
695 : // nsStyleList
696 : //
697 0 : nsStyleList::nsStyleList()
698 : : mListStyleType(NS_STYLE_LIST_STYLE_DISC),
699 0 : mListStylePosition(NS_STYLE_LIST_STYLE_POSITION_OUTSIDE)
700 : {
701 0 : MOZ_COUNT_CTOR(nsStyleList);
702 0 : }
703 :
704 0 : nsStyleList::~nsStyleList()
705 : {
706 0 : MOZ_COUNT_DTOR(nsStyleList);
707 0 : }
708 :
709 0 : nsStyleList::nsStyleList(const nsStyleList& aSource)
710 : : mListStyleType(aSource.mListStyleType),
711 : mListStylePosition(aSource.mListStylePosition),
712 0 : mImageRegion(aSource.mImageRegion)
713 : {
714 0 : SetListStyleImage(aSource.GetListStyleImage());
715 0 : MOZ_COUNT_CTOR(nsStyleList);
716 0 : }
717 :
718 0 : nsChangeHint nsStyleList::CalcDifference(const nsStyleList& aOther) const
719 : {
720 0 : if (mListStylePosition != aOther.mListStylePosition)
721 0 : return NS_STYLE_HINT_FRAMECHANGE;
722 0 : if (EqualImages(mListStyleImage, aOther.mListStyleImage) &&
723 : mListStyleType == aOther.mListStyleType) {
724 0 : if (mImageRegion.IsEqualInterior(aOther.mImageRegion))
725 0 : return NS_STYLE_HINT_NONE;
726 0 : if (mImageRegion.width == aOther.mImageRegion.width &&
727 : mImageRegion.height == aOther.mImageRegion.height)
728 0 : return NS_STYLE_HINT_VISUAL;
729 : }
730 0 : return NS_STYLE_HINT_REFLOW;
731 : }
732 :
733 : #ifdef DEBUG
734 : /* static */
735 0 : nsChangeHint nsStyleList::MaxDifference()
736 : {
737 0 : return NS_STYLE_HINT_FRAMECHANGE;
738 : }
739 : #endif
740 :
741 : // --------------------
742 : // nsStyleXUL
743 : //
744 0 : nsStyleXUL::nsStyleXUL()
745 : {
746 0 : MOZ_COUNT_CTOR(nsStyleXUL);
747 0 : mBoxAlign = NS_STYLE_BOX_ALIGN_STRETCH;
748 0 : mBoxDirection = NS_STYLE_BOX_DIRECTION_NORMAL;
749 0 : mBoxFlex = 0.0f;
750 0 : mBoxOrient = NS_STYLE_BOX_ORIENT_HORIZONTAL;
751 0 : mBoxPack = NS_STYLE_BOX_PACK_START;
752 0 : mBoxOrdinal = 1;
753 0 : mStretchStack = true;
754 0 : }
755 :
756 0 : nsStyleXUL::~nsStyleXUL()
757 : {
758 0 : MOZ_COUNT_DTOR(nsStyleXUL);
759 0 : }
760 :
761 0 : nsStyleXUL::nsStyleXUL(const nsStyleXUL& aSource)
762 : {
763 0 : MOZ_COUNT_CTOR(nsStyleXUL);
764 0 : memcpy((nsStyleXUL*)this, &aSource, sizeof(nsStyleXUL));
765 0 : }
766 :
767 0 : nsChangeHint nsStyleXUL::CalcDifference(const nsStyleXUL& aOther) const
768 : {
769 0 : if (mBoxAlign == aOther.mBoxAlign &&
770 : mBoxDirection == aOther.mBoxDirection &&
771 : mBoxFlex == aOther.mBoxFlex &&
772 : mBoxOrient == aOther.mBoxOrient &&
773 : mBoxPack == aOther.mBoxPack &&
774 : mBoxOrdinal == aOther.mBoxOrdinal)
775 0 : return NS_STYLE_HINT_NONE;
776 0 : if (mBoxOrdinal != aOther.mBoxOrdinal)
777 0 : return NS_STYLE_HINT_FRAMECHANGE;
778 0 : return NS_STYLE_HINT_REFLOW;
779 : }
780 :
781 : #ifdef DEBUG
782 : /* static */
783 0 : nsChangeHint nsStyleXUL::MaxDifference()
784 : {
785 0 : return NS_STYLE_HINT_FRAMECHANGE;
786 : }
787 : #endif
788 :
789 : // --------------------
790 : // nsStyleColumn
791 : //
792 0 : nsStyleColumn::nsStyleColumn(nsPresContext* aPresContext)
793 : {
794 0 : MOZ_COUNT_CTOR(nsStyleColumn);
795 0 : mColumnCount = NS_STYLE_COLUMN_COUNT_AUTO;
796 0 : mColumnWidth.SetAutoValue();
797 0 : mColumnGap.SetNormalValue();
798 0 : mColumnFill = NS_STYLE_COLUMN_FILL_BALANCE;
799 :
800 0 : mColumnRuleWidth = (aPresContext->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM];
801 0 : mColumnRuleStyle = NS_STYLE_BORDER_STYLE_NONE;
802 0 : mColumnRuleColor = NS_RGB(0, 0, 0);
803 0 : mColumnRuleColorIsForeground = true;
804 :
805 0 : mTwipsPerPixel = aPresContext->AppUnitsPerDevPixel();
806 0 : }
807 :
808 0 : nsStyleColumn::~nsStyleColumn()
809 : {
810 0 : MOZ_COUNT_DTOR(nsStyleColumn);
811 0 : }
812 :
813 0 : nsStyleColumn::nsStyleColumn(const nsStyleColumn& aSource)
814 : {
815 0 : MOZ_COUNT_CTOR(nsStyleColumn);
816 0 : memcpy((nsStyleColumn*)this, &aSource, sizeof(nsStyleColumn));
817 0 : }
818 :
819 0 : nsChangeHint nsStyleColumn::CalcDifference(const nsStyleColumn& aOther) const
820 : {
821 0 : if ((mColumnWidth.GetUnit() == eStyleUnit_Auto)
822 0 : != (aOther.mColumnWidth.GetUnit() == eStyleUnit_Auto) ||
823 : mColumnCount != aOther.mColumnCount)
824 : // We force column count changes to do a reframe, because it's tricky to handle
825 : // some edge cases where the column count gets smaller and content overflows.
826 : // XXX not ideal
827 0 : return NS_STYLE_HINT_FRAMECHANGE;
828 :
829 0 : if (mColumnWidth != aOther.mColumnWidth ||
830 0 : mColumnGap != aOther.mColumnGap ||
831 : mColumnFill != aOther.mColumnFill)
832 0 : return NS_STYLE_HINT_REFLOW;
833 :
834 0 : if (GetComputedColumnRuleWidth() != aOther.GetComputedColumnRuleWidth() ||
835 : mColumnRuleStyle != aOther.mColumnRuleStyle ||
836 : mColumnRuleColor != aOther.mColumnRuleColor ||
837 : mColumnRuleColorIsForeground != aOther.mColumnRuleColorIsForeground)
838 0 : return NS_STYLE_HINT_VISUAL;
839 :
840 0 : return NS_STYLE_HINT_NONE;
841 : }
842 :
843 : #ifdef DEBUG
844 : /* static */
845 0 : nsChangeHint nsStyleColumn::MaxDifference()
846 : {
847 0 : return NS_STYLE_HINT_FRAMECHANGE;
848 : }
849 : #endif
850 :
851 : // --------------------
852 : // nsStyleSVG
853 : //
854 0 : nsStyleSVG::nsStyleSVG()
855 : {
856 0 : MOZ_COUNT_CTOR(nsStyleSVG);
857 0 : mFill.mType = eStyleSVGPaintType_Color;
858 0 : mFill.mPaint.mColor = NS_RGB(0,0,0);
859 0 : mFill.mFallbackColor = NS_RGB(0,0,0);
860 0 : mStroke.mType = eStyleSVGPaintType_None;
861 0 : mStroke.mPaint.mColor = NS_RGB(0,0,0);
862 0 : mStroke.mFallbackColor = NS_RGB(0,0,0);
863 0 : mStrokeDasharray = nsnull;
864 :
865 0 : mStrokeDashoffset.SetCoordValue(0);
866 0 : mStrokeWidth.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1));
867 :
868 0 : mFillOpacity = 1.0f;
869 0 : mStrokeMiterlimit = 4.0f;
870 0 : mStrokeOpacity = 1.0f;
871 :
872 0 : mStrokeDasharrayLength = 0;
873 0 : mClipRule = NS_STYLE_FILL_RULE_NONZERO;
874 0 : mColorInterpolation = NS_STYLE_COLOR_INTERPOLATION_SRGB;
875 0 : mColorInterpolationFilters = NS_STYLE_COLOR_INTERPOLATION_LINEARRGB;
876 0 : mFillRule = NS_STYLE_FILL_RULE_NONZERO;
877 0 : mImageRendering = NS_STYLE_IMAGE_RENDERING_AUTO;
878 0 : mShapeRendering = NS_STYLE_SHAPE_RENDERING_AUTO;
879 0 : mStrokeLinecap = NS_STYLE_STROKE_LINECAP_BUTT;
880 0 : mStrokeLinejoin = NS_STYLE_STROKE_LINEJOIN_MITER;
881 0 : mTextAnchor = NS_STYLE_TEXT_ANCHOR_START;
882 0 : mTextRendering = NS_STYLE_TEXT_RENDERING_AUTO;
883 0 : }
884 :
885 0 : nsStyleSVG::~nsStyleSVG()
886 : {
887 0 : MOZ_COUNT_DTOR(nsStyleSVG);
888 0 : delete [] mStrokeDasharray;
889 0 : }
890 :
891 0 : nsStyleSVG::nsStyleSVG(const nsStyleSVG& aSource)
892 : {
893 0 : MOZ_COUNT_CTOR(nsStyleSVG);
894 0 : mFill = aSource.mFill;
895 0 : mStroke = aSource.mStroke;
896 :
897 0 : mMarkerEnd = aSource.mMarkerEnd;
898 0 : mMarkerMid = aSource.mMarkerMid;
899 0 : mMarkerStart = aSource.mMarkerStart;
900 :
901 0 : mStrokeDasharrayLength = aSource.mStrokeDasharrayLength;
902 0 : if (aSource.mStrokeDasharray) {
903 0 : mStrokeDasharray = new nsStyleCoord[mStrokeDasharrayLength];
904 0 : if (mStrokeDasharray)
905 : memcpy(mStrokeDasharray,
906 : aSource.mStrokeDasharray,
907 0 : mStrokeDasharrayLength * sizeof(nsStyleCoord));
908 : else
909 0 : mStrokeDasharrayLength = 0;
910 : } else {
911 0 : mStrokeDasharray = nsnull;
912 : }
913 :
914 0 : mStrokeDashoffset = aSource.mStrokeDashoffset;
915 0 : mStrokeWidth = aSource.mStrokeWidth;
916 :
917 0 : mFillOpacity = aSource.mFillOpacity;
918 0 : mStrokeMiterlimit = aSource.mStrokeMiterlimit;
919 0 : mStrokeOpacity = aSource.mStrokeOpacity;
920 :
921 0 : mClipRule = aSource.mClipRule;
922 0 : mColorInterpolation = aSource.mColorInterpolation;
923 0 : mColorInterpolationFilters = aSource.mColorInterpolationFilters;
924 0 : mFillRule = aSource.mFillRule;
925 0 : mImageRendering = aSource.mImageRendering;
926 0 : mShapeRendering = aSource.mShapeRendering;
927 0 : mStrokeLinecap = aSource.mStrokeLinecap;
928 0 : mStrokeLinejoin = aSource.mStrokeLinejoin;
929 0 : mTextAnchor = aSource.mTextAnchor;
930 0 : mTextRendering = aSource.mTextRendering;
931 0 : }
932 :
933 0 : static bool PaintURIChanged(const nsStyleSVGPaint& aPaint1,
934 : const nsStyleSVGPaint& aPaint2)
935 : {
936 0 : if (aPaint1.mType != aPaint2.mType) {
937 : return aPaint1.mType == eStyleSVGPaintType_Server ||
938 0 : aPaint2.mType == eStyleSVGPaintType_Server;
939 : }
940 : return aPaint1.mType == eStyleSVGPaintType_Server &&
941 0 : !EqualURIs(aPaint1.mPaint.mPaintServer, aPaint2.mPaint.mPaintServer);
942 : }
943 :
944 0 : nsChangeHint nsStyleSVG::CalcDifference(const nsStyleSVG& aOther) const
945 : {
946 0 : nsChangeHint hint = nsChangeHint(0);
947 :
948 0 : if (mTextRendering != aOther.mTextRendering) {
949 0 : NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
950 : // May be needed for non-svg frames
951 0 : NS_UpdateHint(hint, nsChangeHint_ReflowFrame);
952 : }
953 :
954 0 : if (!EqualURIs(mMarkerEnd, aOther.mMarkerEnd) ||
955 0 : !EqualURIs(mMarkerMid, aOther.mMarkerMid) ||
956 0 : !EqualURIs(mMarkerStart, aOther.mMarkerStart)) {
957 0 : NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
958 0 : NS_UpdateHint(hint, nsChangeHint_UpdateEffects);
959 0 : return hint;
960 : }
961 :
962 0 : if (mFill != aOther.mFill ||
963 0 : mStroke != aOther.mStroke) {
964 0 : NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
965 0 : if (PaintURIChanged(mFill, aOther.mFill) ||
966 0 : PaintURIChanged(mStroke, aOther.mStroke)) {
967 0 : NS_UpdateHint(hint, nsChangeHint_UpdateEffects);
968 : }
969 : // Nothing more to do, below we can only set "repaint"
970 0 : return hint;
971 : }
972 :
973 0 : if ( mStrokeDashoffset != aOther.mStrokeDashoffset ||
974 0 : mStrokeWidth != aOther.mStrokeWidth ||
975 :
976 : mFillOpacity != aOther.mFillOpacity ||
977 : mStrokeMiterlimit != aOther.mStrokeMiterlimit ||
978 : mStrokeOpacity != aOther.mStrokeOpacity ||
979 :
980 : mClipRule != aOther.mClipRule ||
981 : mColorInterpolation != aOther.mColorInterpolation ||
982 : mColorInterpolationFilters != aOther.mColorInterpolationFilters ||
983 : mFillRule != aOther.mFillRule ||
984 : mImageRendering != aOther.mImageRendering ||
985 : mShapeRendering != aOther.mShapeRendering ||
986 : mStrokeDasharrayLength != aOther.mStrokeDasharrayLength ||
987 : mStrokeLinecap != aOther.mStrokeLinecap ||
988 : mStrokeLinejoin != aOther.mStrokeLinejoin ||
989 : mTextAnchor != aOther.mTextAnchor) {
990 0 : NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
991 0 : return hint;
992 : }
993 :
994 : // length of stroke dasharrays are the same (tested above) - check entries
995 0 : for (PRUint32 i=0; i<mStrokeDasharrayLength; i++)
996 0 : if (mStrokeDasharray[i] != aOther.mStrokeDasharray[i]) {
997 0 : NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
998 0 : return hint;
999 : }
1000 :
1001 0 : return hint;
1002 : }
1003 :
1004 : #ifdef DEBUG
1005 : /* static */
1006 0 : nsChangeHint nsStyleSVG::MaxDifference()
1007 : {
1008 : return NS_CombineHint(NS_CombineHint(nsChangeHint_UpdateEffects,
1009 : nsChangeHint_ReflowFrame),
1010 0 : nsChangeHint_RepaintFrame);
1011 : }
1012 : #endif
1013 :
1014 : // --------------------
1015 : // nsStyleSVGReset
1016 : //
1017 0 : nsStyleSVGReset::nsStyleSVGReset()
1018 : {
1019 0 : MOZ_COUNT_CTOR(nsStyleSVGReset);
1020 0 : mStopColor = NS_RGB(0,0,0);
1021 0 : mFloodColor = NS_RGB(0,0,0);
1022 0 : mLightingColor = NS_RGB(255,255,255);
1023 0 : mClipPath = nsnull;
1024 0 : mFilter = nsnull;
1025 0 : mMask = nsnull;
1026 0 : mStopOpacity = 1.0f;
1027 0 : mFloodOpacity = 1.0f;
1028 0 : mDominantBaseline = NS_STYLE_DOMINANT_BASELINE_AUTO;
1029 0 : }
1030 :
1031 0 : nsStyleSVGReset::~nsStyleSVGReset()
1032 : {
1033 0 : MOZ_COUNT_DTOR(nsStyleSVGReset);
1034 0 : }
1035 :
1036 0 : nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset& aSource)
1037 : {
1038 0 : MOZ_COUNT_CTOR(nsStyleSVGReset);
1039 0 : mStopColor = aSource.mStopColor;
1040 0 : mFloodColor = aSource.mFloodColor;
1041 0 : mLightingColor = aSource.mLightingColor;
1042 0 : mClipPath = aSource.mClipPath;
1043 0 : mFilter = aSource.mFilter;
1044 0 : mMask = aSource.mMask;
1045 0 : mStopOpacity = aSource.mStopOpacity;
1046 0 : mFloodOpacity = aSource.mFloodOpacity;
1047 0 : mDominantBaseline = aSource.mDominantBaseline;
1048 0 : }
1049 :
1050 0 : nsChangeHint nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aOther) const
1051 : {
1052 0 : nsChangeHint hint = nsChangeHint(0);
1053 :
1054 0 : if (!EqualURIs(mClipPath, aOther.mClipPath) ||
1055 0 : !EqualURIs(mFilter, aOther.mFilter) ||
1056 0 : !EqualURIs(mMask, aOther.mMask)) {
1057 0 : NS_UpdateHint(hint, nsChangeHint_UpdateEffects);
1058 0 : NS_UpdateHint(hint, nsChangeHint_ReflowFrame);
1059 0 : NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
1060 0 : } else if (mStopColor != aOther.mStopColor ||
1061 : mFloodColor != aOther.mFloodColor ||
1062 : mLightingColor != aOther.mLightingColor ||
1063 : mStopOpacity != aOther.mStopOpacity ||
1064 : mFloodOpacity != aOther.mFloodOpacity ||
1065 : mDominantBaseline != aOther.mDominantBaseline)
1066 0 : NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
1067 :
1068 0 : return hint;
1069 : }
1070 :
1071 : #ifdef DEBUG
1072 : /* static */
1073 0 : nsChangeHint nsStyleSVGReset::MaxDifference()
1074 : {
1075 : return NS_CombineHint(NS_CombineHint(nsChangeHint_UpdateEffects,
1076 : nsChangeHint_ReflowFrame),
1077 0 : nsChangeHint_RepaintFrame);
1078 : }
1079 : #endif
1080 :
1081 : // nsStyleSVGPaint implementation
1082 0 : nsStyleSVGPaint::~nsStyleSVGPaint()
1083 : {
1084 0 : if (mType == eStyleSVGPaintType_Server) {
1085 0 : NS_IF_RELEASE(mPaint.mPaintServer);
1086 : }
1087 0 : }
1088 :
1089 : void
1090 0 : nsStyleSVGPaint::SetType(nsStyleSVGPaintType aType)
1091 : {
1092 0 : if (mType == eStyleSVGPaintType_Server) {
1093 0 : this->~nsStyleSVGPaint();
1094 0 : new (this) nsStyleSVGPaint();
1095 : }
1096 0 : mType = aType;
1097 0 : }
1098 :
1099 0 : nsStyleSVGPaint& nsStyleSVGPaint::operator=(const nsStyleSVGPaint& aOther)
1100 : {
1101 0 : if (this == &aOther)
1102 0 : return *this;
1103 :
1104 0 : SetType(aOther.mType);
1105 :
1106 0 : mFallbackColor = aOther.mFallbackColor;
1107 0 : if (mType == eStyleSVGPaintType_Server) {
1108 0 : mPaint.mPaintServer = aOther.mPaint.mPaintServer;
1109 0 : NS_IF_ADDREF(mPaint.mPaintServer);
1110 : } else {
1111 0 : mPaint.mColor = aOther.mPaint.mColor;
1112 : }
1113 0 : return *this;
1114 : }
1115 :
1116 0 : bool nsStyleSVGPaint::operator==(const nsStyleSVGPaint& aOther) const
1117 : {
1118 0 : if (mType != aOther.mType)
1119 0 : return false;
1120 0 : if (mType == eStyleSVGPaintType_Server)
1121 0 : return EqualURIs(mPaint.mPaintServer, aOther.mPaint.mPaintServer) &&
1122 0 : mFallbackColor == aOther.mFallbackColor;
1123 0 : if (mType == eStyleSVGPaintType_None)
1124 0 : return true;
1125 0 : return mPaint.mColor == aOther.mPaint.mColor;
1126 : }
1127 :
1128 :
1129 : // --------------------
1130 : // nsStylePosition
1131 : //
1132 0 : nsStylePosition::nsStylePosition(void)
1133 : {
1134 0 : MOZ_COUNT_CTOR(nsStylePosition);
1135 : // positioning values not inherited
1136 0 : nsStyleCoord autoCoord(eStyleUnit_Auto);
1137 0 : mOffset.SetLeft(autoCoord);
1138 0 : mOffset.SetTop(autoCoord);
1139 0 : mOffset.SetRight(autoCoord);
1140 0 : mOffset.SetBottom(autoCoord);
1141 0 : mWidth.SetAutoValue();
1142 0 : mMinWidth.SetCoordValue(0);
1143 0 : mMaxWidth.SetNoneValue();
1144 0 : mHeight.SetAutoValue();
1145 0 : mMinHeight.SetCoordValue(0);
1146 0 : mMaxHeight.SetNoneValue();
1147 0 : mBoxSizing = NS_STYLE_BOX_SIZING_CONTENT;
1148 0 : mZIndex.SetAutoValue();
1149 0 : }
1150 :
1151 0 : nsStylePosition::~nsStylePosition(void)
1152 : {
1153 0 : MOZ_COUNT_DTOR(nsStylePosition);
1154 0 : }
1155 :
1156 0 : nsStylePosition::nsStylePosition(const nsStylePosition& aSource)
1157 : {
1158 0 : MOZ_COUNT_CTOR(nsStylePosition);
1159 0 : memcpy((nsStylePosition*)this, &aSource, sizeof(nsStylePosition));
1160 0 : }
1161 :
1162 0 : nsChangeHint nsStylePosition::CalcDifference(const nsStylePosition& aOther) const
1163 : {
1164 : nsChangeHint hint =
1165 0 : (mZIndex == aOther.mZIndex) ? NS_STYLE_HINT_NONE : nsChangeHint_RepaintFrame;
1166 :
1167 0 : if (mBoxSizing != aOther.mBoxSizing) {
1168 : // Can affect both widths and heights; just a bad scene.
1169 0 : return NS_CombineHint(hint, nsChangeHint_ReflowFrame);
1170 : }
1171 :
1172 0 : if (mHeight != aOther.mHeight ||
1173 0 : mMinHeight != aOther.mMinHeight ||
1174 0 : mMaxHeight != aOther.mMaxHeight) {
1175 : // Height changes can affect descendant intrinsic sizes due to replaced
1176 : // elements with percentage heights in descendants which also have
1177 : // percentage heights. And due to our not-so-great computation of mVResize
1178 : // in nsHTMLReflowState, they do need to force reflow of the whole subtree.
1179 : // XXXbz due to XUL caching heights as well, height changes also need to
1180 : // clear ancestor intrinsics!
1181 0 : return NS_CombineHint(hint, nsChangeHint_ReflowFrame);
1182 : }
1183 :
1184 0 : if ((mWidth == aOther.mWidth) &&
1185 0 : (mMinWidth == aOther.mMinWidth) &&
1186 0 : (mMaxWidth == aOther.mMaxWidth)) {
1187 0 : if (mOffset == aOther.mOffset) {
1188 0 : return hint;
1189 : } else {
1190 : // Offset changes only affect positioned content, and can't affect any
1191 : // intrinsic widths. They also don't need to force reflow of
1192 : // descendants.
1193 0 : return NS_CombineHint(hint, nsChangeHint_NeedReflow);
1194 : }
1195 : }
1196 :
1197 : // None of our width differences can affect descendant intrinsic
1198 : // sizes and none of them need to force children to reflow.
1199 : return
1200 : NS_CombineHint(hint,
1201 : NS_SubtractHint(nsChangeHint_ReflowFrame,
1202 : NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics,
1203 0 : nsChangeHint_NeedDirtyReflow)));
1204 : }
1205 :
1206 : #ifdef DEBUG
1207 : /* static */
1208 0 : nsChangeHint nsStylePosition::MaxDifference()
1209 : {
1210 0 : return NS_STYLE_HINT_REFLOW;
1211 : }
1212 : #endif
1213 :
1214 : /* static */ bool
1215 0 : nsStylePosition::WidthCoordDependsOnContainer(const nsStyleCoord &aCoord)
1216 : {
1217 0 : return aCoord.GetUnit() == eStyleUnit_Auto ||
1218 0 : aCoord.HasPercent() ||
1219 0 : (aCoord.GetUnit() == eStyleUnit_Enumerated &&
1220 0 : (aCoord.GetIntValue() == NS_STYLE_WIDTH_FIT_CONTENT ||
1221 0 : aCoord.GetIntValue() == NS_STYLE_WIDTH_AVAILABLE));
1222 : }
1223 :
1224 : // --------------------
1225 : // nsStyleTable
1226 : //
1227 :
1228 0 : nsStyleTable::nsStyleTable()
1229 : {
1230 0 : MOZ_COUNT_CTOR(nsStyleTable);
1231 : // values not inherited
1232 0 : mLayoutStrategy = NS_STYLE_TABLE_LAYOUT_AUTO;
1233 0 : mCols = NS_STYLE_TABLE_COLS_NONE;
1234 0 : mFrame = NS_STYLE_TABLE_FRAME_NONE;
1235 0 : mRules = NS_STYLE_TABLE_RULES_NONE;
1236 0 : mSpan = 1;
1237 0 : }
1238 :
1239 0 : nsStyleTable::~nsStyleTable(void)
1240 : {
1241 0 : MOZ_COUNT_DTOR(nsStyleTable);
1242 0 : }
1243 :
1244 0 : nsStyleTable::nsStyleTable(const nsStyleTable& aSource)
1245 : {
1246 0 : MOZ_COUNT_CTOR(nsStyleTable);
1247 0 : memcpy((nsStyleTable*)this, &aSource, sizeof(nsStyleTable));
1248 0 : }
1249 :
1250 0 : nsChangeHint nsStyleTable::CalcDifference(const nsStyleTable& aOther) const
1251 : {
1252 : // Changes in mRules may require reframing (if border-collapse stuff changes, for example).
1253 0 : if (mRules != aOther.mRules || mSpan != aOther.mSpan ||
1254 : mLayoutStrategy != aOther.mLayoutStrategy)
1255 0 : return NS_STYLE_HINT_FRAMECHANGE;
1256 0 : if (mFrame != aOther.mFrame || mCols != aOther.mCols)
1257 0 : return NS_STYLE_HINT_REFLOW;
1258 0 : return NS_STYLE_HINT_NONE;
1259 : }
1260 :
1261 : #ifdef DEBUG
1262 : /* static */
1263 0 : nsChangeHint nsStyleTable::MaxDifference()
1264 : {
1265 0 : return NS_STYLE_HINT_FRAMECHANGE;
1266 : }
1267 : #endif
1268 :
1269 : // -----------------------
1270 : // nsStyleTableBorder
1271 :
1272 0 : nsStyleTableBorder::nsStyleTableBorder(nsPresContext* aPresContext)
1273 : {
1274 0 : MOZ_COUNT_CTOR(nsStyleTableBorder);
1275 0 : mBorderCollapse = NS_STYLE_BORDER_SEPARATE;
1276 :
1277 0 : nsCompatibility compatMode = eCompatibility_FullStandards;
1278 0 : if (aPresContext)
1279 0 : compatMode = aPresContext->CompatibilityMode();
1280 : mEmptyCells = (compatMode == eCompatibility_NavQuirks)
1281 : ? NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND
1282 0 : : NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
1283 0 : mCaptionSide = NS_STYLE_CAPTION_SIDE_TOP;
1284 0 : mBorderSpacingX = 0;
1285 0 : mBorderSpacingY = 0;
1286 0 : }
1287 :
1288 0 : nsStyleTableBorder::~nsStyleTableBorder(void)
1289 : {
1290 0 : MOZ_COUNT_DTOR(nsStyleTableBorder);
1291 0 : }
1292 :
1293 0 : nsStyleTableBorder::nsStyleTableBorder(const nsStyleTableBorder& aSource)
1294 : {
1295 0 : MOZ_COUNT_CTOR(nsStyleTableBorder);
1296 0 : memcpy((nsStyleTableBorder*)this, &aSource, sizeof(nsStyleTableBorder));
1297 0 : }
1298 :
1299 0 : nsChangeHint nsStyleTableBorder::CalcDifference(const nsStyleTableBorder& aOther) const
1300 : {
1301 : // Border-collapse changes need a reframe, because we use a different frame
1302 : // class for table cells in the collapsed border model. This is used to
1303 : // conserve memory when using the separated border model (collapsed borders
1304 : // require extra state to be stored).
1305 0 : if (mBorderCollapse != aOther.mBorderCollapse) {
1306 0 : return NS_STYLE_HINT_FRAMECHANGE;
1307 : }
1308 :
1309 0 : if ((mCaptionSide == aOther.mCaptionSide) &&
1310 : (mBorderSpacingX == aOther.mBorderSpacingX) &&
1311 : (mBorderSpacingY == aOther.mBorderSpacingY)) {
1312 0 : if (mEmptyCells == aOther.mEmptyCells)
1313 0 : return NS_STYLE_HINT_NONE;
1314 0 : return NS_STYLE_HINT_VISUAL;
1315 : }
1316 : else
1317 0 : return NS_STYLE_HINT_REFLOW;
1318 : }
1319 :
1320 : #ifdef DEBUG
1321 : /* static */
1322 0 : nsChangeHint nsStyleTableBorder::MaxDifference()
1323 : {
1324 0 : return NS_STYLE_HINT_FRAMECHANGE;
1325 : }
1326 : #endif
1327 :
1328 : // --------------------
1329 : // nsStyleColor
1330 : //
1331 :
1332 0 : nsStyleColor::nsStyleColor(nsPresContext* aPresContext)
1333 : {
1334 0 : MOZ_COUNT_CTOR(nsStyleColor);
1335 0 : mColor = aPresContext->DefaultColor();
1336 0 : }
1337 :
1338 0 : nsStyleColor::nsStyleColor(const nsStyleColor& aSource)
1339 : {
1340 0 : MOZ_COUNT_CTOR(nsStyleColor);
1341 0 : mColor = aSource.mColor;
1342 0 : }
1343 :
1344 0 : nsChangeHint nsStyleColor::CalcDifference(const nsStyleColor& aOther) const
1345 : {
1346 0 : if (mColor == aOther.mColor)
1347 0 : return NS_STYLE_HINT_NONE;
1348 0 : return NS_STYLE_HINT_VISUAL;
1349 : }
1350 :
1351 : #ifdef DEBUG
1352 : /* static */
1353 0 : nsChangeHint nsStyleColor::MaxDifference()
1354 : {
1355 0 : return NS_STYLE_HINT_VISUAL;
1356 : }
1357 : #endif
1358 :
1359 : // --------------------
1360 : // nsStyleGradient
1361 : //
1362 : bool
1363 0 : nsStyleGradient::operator==(const nsStyleGradient& aOther) const
1364 : {
1365 0 : NS_ABORT_IF_FALSE(mSize == NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER ||
1366 : mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR,
1367 : "incorrect combination of shape and size");
1368 0 : NS_ABORT_IF_FALSE(aOther.mSize == NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER ||
1369 : aOther.mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR,
1370 : "incorrect combination of shape and size");
1371 :
1372 0 : if (mShape != aOther.mShape ||
1373 : mSize != aOther.mSize ||
1374 : mRepeating != aOther.mRepeating ||
1375 : mToCorner != aOther.mToCorner ||
1376 0 : mBgPosX != aOther.mBgPosX ||
1377 0 : mBgPosY != aOther.mBgPosY ||
1378 0 : mAngle != aOther.mAngle)
1379 0 : return false;
1380 :
1381 0 : if (mStops.Length() != aOther.mStops.Length())
1382 0 : return false;
1383 :
1384 0 : for (PRUint32 i = 0; i < mStops.Length(); i++) {
1385 0 : if (mStops[i].mLocation != aOther.mStops[i].mLocation ||
1386 0 : mStops[i].mColor != aOther.mStops[i].mColor)
1387 0 : return false;
1388 : }
1389 :
1390 0 : return true;
1391 : }
1392 :
1393 0 : nsStyleGradient::nsStyleGradient(void)
1394 : : mShape(NS_STYLE_GRADIENT_SHAPE_LINEAR)
1395 : , mSize(NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER)
1396 : , mRepeating(false)
1397 0 : , mToCorner(false)
1398 : {
1399 0 : }
1400 :
1401 : bool
1402 0 : nsStyleGradient::IsOpaque()
1403 : {
1404 0 : for (PRUint32 i = 0; i < mStops.Length(); i++) {
1405 0 : if (NS_GET_A(mStops[i].mColor) < 255)
1406 0 : return false;
1407 : }
1408 0 : return true;
1409 : }
1410 :
1411 : // --------------------
1412 : // nsStyleImage
1413 : //
1414 :
1415 0 : nsStyleImage::nsStyleImage()
1416 : : mType(eStyleImageType_Null)
1417 : , mCropRect(nsnull)
1418 : #ifdef DEBUG
1419 0 : , mImageTracked(false)
1420 : #endif
1421 : {
1422 0 : MOZ_COUNT_CTOR(nsStyleImage);
1423 0 : }
1424 :
1425 0 : nsStyleImage::~nsStyleImage()
1426 : {
1427 0 : MOZ_COUNT_DTOR(nsStyleImage);
1428 0 : if (mType != eStyleImageType_Null)
1429 0 : SetNull();
1430 0 : }
1431 :
1432 0 : nsStyleImage::nsStyleImage(const nsStyleImage& aOther)
1433 : : mType(eStyleImageType_Null)
1434 : , mCropRect(nsnull)
1435 : #ifdef DEBUG
1436 0 : , mImageTracked(false)
1437 : #endif
1438 : {
1439 : // We need our own copy constructor because we don't want
1440 : // to copy the reference count
1441 0 : MOZ_COUNT_CTOR(nsStyleImage);
1442 0 : DoCopy(aOther);
1443 0 : }
1444 :
1445 : nsStyleImage&
1446 0 : nsStyleImage::operator=(const nsStyleImage& aOther)
1447 : {
1448 0 : if (this != &aOther)
1449 0 : DoCopy(aOther);
1450 :
1451 0 : return *this;
1452 : }
1453 :
1454 : void
1455 0 : nsStyleImage::DoCopy(const nsStyleImage& aOther)
1456 : {
1457 0 : SetNull();
1458 :
1459 0 : if (aOther.mType == eStyleImageType_Image)
1460 0 : SetImageData(aOther.mImage);
1461 0 : else if (aOther.mType == eStyleImageType_Gradient)
1462 0 : SetGradientData(aOther.mGradient);
1463 0 : else if (aOther.mType == eStyleImageType_Element)
1464 0 : SetElementId(aOther.mElementId);
1465 :
1466 0 : SetCropRect(aOther.mCropRect);
1467 0 : }
1468 :
1469 : void
1470 0 : nsStyleImage::SetNull()
1471 : {
1472 0 : NS_ABORT_IF_FALSE(!mImageTracked,
1473 : "Calling SetNull() with image tracked!");
1474 :
1475 0 : if (mType == eStyleImageType_Gradient)
1476 0 : mGradient->Release();
1477 0 : else if (mType == eStyleImageType_Image)
1478 0 : NS_RELEASE(mImage);
1479 0 : else if (mType == eStyleImageType_Element)
1480 0 : NS_Free(mElementId);
1481 :
1482 0 : mType = eStyleImageType_Null;
1483 0 : mCropRect = nsnull;
1484 0 : }
1485 :
1486 : void
1487 0 : nsStyleImage::SetImageData(imgIRequest* aImage)
1488 : {
1489 0 : NS_ABORT_IF_FALSE(!mImageTracked,
1490 : "Setting a new image without untracking the old one!");
1491 :
1492 0 : NS_IF_ADDREF(aImage);
1493 :
1494 0 : if (mType != eStyleImageType_Null)
1495 0 : SetNull();
1496 :
1497 0 : if (aImage) {
1498 0 : mImage = aImage;
1499 0 : mType = eStyleImageType_Image;
1500 : }
1501 0 : }
1502 :
1503 : void
1504 0 : nsStyleImage::TrackImage(nsPresContext* aContext)
1505 : {
1506 : // Sanity
1507 0 : NS_ABORT_IF_FALSE(!mImageTracked, "Already tracking image!");
1508 0 : NS_ABORT_IF_FALSE(mType == eStyleImageType_Image,
1509 : "Can't track image when there isn't one!");
1510 :
1511 : // Register the image with the document
1512 0 : nsIDocument* doc = aContext->Document();
1513 0 : if (doc)
1514 0 : doc->AddImage(mImage);
1515 :
1516 : // Mark state
1517 : #ifdef DEBUG
1518 0 : mImageTracked = true;
1519 : #endif
1520 0 : }
1521 :
1522 : void
1523 0 : nsStyleImage::UntrackImage(nsPresContext* aContext)
1524 : {
1525 : // Sanity
1526 0 : NS_ABORT_IF_FALSE(mImageTracked, "Image not tracked!");
1527 0 : NS_ABORT_IF_FALSE(mType == eStyleImageType_Image,
1528 : "Can't untrack image when there isn't one!");
1529 :
1530 : // Unregister the image with the document
1531 0 : nsIDocument* doc = aContext->Document();
1532 0 : if (doc)
1533 0 : doc->RemoveImage(mImage);
1534 :
1535 : // Mark state
1536 : #ifdef DEBUG
1537 0 : mImageTracked = false;
1538 : #endif
1539 0 : }
1540 :
1541 : void
1542 0 : nsStyleImage::SetGradientData(nsStyleGradient* aGradient)
1543 : {
1544 0 : if (aGradient)
1545 0 : aGradient->AddRef();
1546 :
1547 0 : if (mType != eStyleImageType_Null)
1548 0 : SetNull();
1549 :
1550 0 : if (aGradient) {
1551 0 : mGradient = aGradient;
1552 0 : mType = eStyleImageType_Gradient;
1553 : }
1554 0 : }
1555 :
1556 : void
1557 0 : nsStyleImage::SetElementId(const PRUnichar* aElementId)
1558 : {
1559 0 : if (mType != eStyleImageType_Null)
1560 0 : SetNull();
1561 :
1562 0 : if (aElementId) {
1563 0 : mElementId = NS_strdup(aElementId);
1564 0 : mType = eStyleImageType_Element;
1565 : }
1566 0 : }
1567 :
1568 : void
1569 0 : nsStyleImage::SetCropRect(nsStyleSides* aCropRect)
1570 : {
1571 0 : if (aCropRect) {
1572 0 : mCropRect = new nsStyleSides(*aCropRect);
1573 : // There is really not much we can do if 'new' fails
1574 : } else {
1575 0 : mCropRect = nsnull;
1576 : }
1577 0 : }
1578 :
1579 : static PRInt32
1580 0 : ConvertToPixelCoord(const nsStyleCoord& aCoord, PRInt32 aPercentScale)
1581 : {
1582 : double pixelValue;
1583 0 : switch (aCoord.GetUnit()) {
1584 : case eStyleUnit_Percent:
1585 0 : pixelValue = aCoord.GetPercentValue() * aPercentScale;
1586 0 : break;
1587 : case eStyleUnit_Factor:
1588 0 : pixelValue = aCoord.GetFactorValue();
1589 0 : break;
1590 : default:
1591 0 : NS_NOTREACHED("unexpected unit for image crop rect");
1592 0 : return 0;
1593 : }
1594 0 : NS_ABORT_IF_FALSE(pixelValue >= 0, "we ensured non-negative while parsing");
1595 0 : pixelValue = NS_MIN(pixelValue, double(PR_INT32_MAX)); // avoid overflow
1596 0 : return NS_lround(pixelValue);
1597 : }
1598 :
1599 : bool
1600 0 : nsStyleImage::ComputeActualCropRect(nsIntRect& aActualCropRect,
1601 : bool* aIsEntireImage) const
1602 : {
1603 0 : if (mType != eStyleImageType_Image)
1604 0 : return false;
1605 :
1606 0 : nsCOMPtr<imgIContainer> imageContainer;
1607 0 : mImage->GetImage(getter_AddRefs(imageContainer));
1608 0 : if (!imageContainer)
1609 0 : return false;
1610 :
1611 0 : nsIntSize imageSize;
1612 0 : imageContainer->GetWidth(&imageSize.width);
1613 0 : imageContainer->GetHeight(&imageSize.height);
1614 0 : if (imageSize.width <= 0 || imageSize.height <= 0)
1615 0 : return false;
1616 :
1617 0 : PRInt32 left = ConvertToPixelCoord(mCropRect->GetLeft(), imageSize.width);
1618 0 : PRInt32 top = ConvertToPixelCoord(mCropRect->GetTop(), imageSize.height);
1619 0 : PRInt32 right = ConvertToPixelCoord(mCropRect->GetRight(), imageSize.width);
1620 0 : PRInt32 bottom = ConvertToPixelCoord(mCropRect->GetBottom(), imageSize.height);
1621 :
1622 : // IntersectRect() returns an empty rect if we get negative width or height
1623 0 : nsIntRect cropRect(left, top, right - left, bottom - top);
1624 0 : nsIntRect imageRect(nsIntPoint(0, 0), imageSize);
1625 0 : aActualCropRect.IntersectRect(imageRect, cropRect);
1626 :
1627 0 : if (aIsEntireImage)
1628 0 : *aIsEntireImage = aActualCropRect.IsEqualInterior(imageRect);
1629 0 : return true;
1630 : }
1631 :
1632 : nsresult
1633 0 : nsStyleImage::RequestDecode() const
1634 : {
1635 0 : if ((mType == eStyleImageType_Image) && mImage)
1636 0 : return mImage->RequestDecode();
1637 0 : return NS_OK;
1638 : }
1639 :
1640 : bool
1641 0 : nsStyleImage::IsOpaque() const
1642 : {
1643 0 : if (!IsComplete())
1644 0 : return false;
1645 :
1646 0 : if (mType == eStyleImageType_Gradient)
1647 0 : return mGradient->IsOpaque();
1648 :
1649 0 : if (mType == eStyleImageType_Element)
1650 0 : return false;
1651 :
1652 0 : NS_ABORT_IF_FALSE(mType == eStyleImageType_Image, "unexpected image type");
1653 :
1654 0 : nsCOMPtr<imgIContainer> imageContainer;
1655 0 : mImage->GetImage(getter_AddRefs(imageContainer));
1656 0 : NS_ABORT_IF_FALSE(imageContainer, "IsComplete() said image container is ready");
1657 :
1658 : // Check if the crop region of the current image frame is opaque
1659 : bool isOpaque;
1660 0 : if (NS_SUCCEEDED(imageContainer->GetCurrentFrameIsOpaque(&isOpaque)) &&
1661 : isOpaque) {
1662 0 : if (!mCropRect)
1663 0 : return true;
1664 :
1665 : // Must make sure if mCropRect contains at least a pixel.
1666 : // XXX Is this optimization worth it? Maybe I should just return false.
1667 0 : nsIntRect actualCropRect;
1668 0 : bool rv = ComputeActualCropRect(actualCropRect);
1669 0 : NS_ASSERTION(rv, "ComputeActualCropRect() can not fail here");
1670 0 : return rv && !actualCropRect.IsEmpty();
1671 : }
1672 :
1673 0 : return false;
1674 : }
1675 :
1676 : bool
1677 0 : nsStyleImage::IsComplete() const
1678 : {
1679 0 : switch (mType) {
1680 : case eStyleImageType_Null:
1681 0 : return false;
1682 : case eStyleImageType_Gradient:
1683 : case eStyleImageType_Element:
1684 0 : return true;
1685 : case eStyleImageType_Image:
1686 : {
1687 0 : PRUint32 status = imgIRequest::STATUS_ERROR;
1688 0 : return NS_SUCCEEDED(mImage->GetImageStatus(&status)) &&
1689 : (status & imgIRequest::STATUS_SIZE_AVAILABLE) &&
1690 0 : (status & imgIRequest::STATUS_FRAME_COMPLETE);
1691 : }
1692 : default:
1693 0 : NS_NOTREACHED("unexpected image type");
1694 0 : return false;
1695 : }
1696 : }
1697 :
1698 : static inline bool
1699 0 : EqualRects(const nsStyleSides* aRect1, const nsStyleSides* aRect2)
1700 : {
1701 : return aRect1 == aRect2 || /* handles null== null, and optimize */
1702 0 : (aRect1 && aRect2 && *aRect1 == *aRect2);
1703 : }
1704 :
1705 : bool
1706 0 : nsStyleImage::operator==(const nsStyleImage& aOther) const
1707 : {
1708 0 : if (mType != aOther.mType)
1709 0 : return false;
1710 :
1711 0 : if (!EqualRects(mCropRect, aOther.mCropRect))
1712 0 : return false;
1713 :
1714 0 : if (mType == eStyleImageType_Image)
1715 0 : return EqualImages(mImage, aOther.mImage);
1716 :
1717 0 : if (mType == eStyleImageType_Gradient)
1718 0 : return *mGradient == *aOther.mGradient;
1719 :
1720 0 : if (mType == eStyleImageType_Element)
1721 0 : return NS_strcmp(mElementId, aOther.mElementId) == 0;
1722 :
1723 0 : return true;
1724 : }
1725 :
1726 : // --------------------
1727 : // nsStyleBackground
1728 : //
1729 :
1730 0 : nsStyleBackground::nsStyleBackground()
1731 : : mAttachmentCount(1)
1732 : , mClipCount(1)
1733 : , mOriginCount(1)
1734 : , mRepeatCount(1)
1735 : , mPositionCount(1)
1736 : , mImageCount(1)
1737 : , mSizeCount(1)
1738 : , mBackgroundColor(NS_RGBA(0, 0, 0, 0))
1739 0 : , mBackgroundInlinePolicy(NS_STYLE_BG_INLINE_POLICY_CONTINUOUS)
1740 : {
1741 0 : MOZ_COUNT_CTOR(nsStyleBackground);
1742 0 : Layer *onlyLayer = mLayers.AppendElement();
1743 0 : NS_ASSERTION(onlyLayer, "auto array must have room for 1 element");
1744 0 : onlyLayer->SetInitialValues();
1745 0 : }
1746 :
1747 0 : nsStyleBackground::nsStyleBackground(const nsStyleBackground& aSource)
1748 : : mAttachmentCount(aSource.mAttachmentCount)
1749 : , mClipCount(aSource.mClipCount)
1750 : , mOriginCount(aSource.mOriginCount)
1751 : , mRepeatCount(aSource.mRepeatCount)
1752 : , mPositionCount(aSource.mPositionCount)
1753 : , mImageCount(aSource.mImageCount)
1754 : , mSizeCount(aSource.mSizeCount)
1755 : , mLayers(aSource.mLayers) // deep copy
1756 : , mBackgroundColor(aSource.mBackgroundColor)
1757 0 : , mBackgroundInlinePolicy(aSource.mBackgroundInlinePolicy)
1758 : {
1759 0 : MOZ_COUNT_CTOR(nsStyleBackground);
1760 : // If the deep copy of mLayers failed, truncate the counts.
1761 0 : PRUint32 count = mLayers.Length();
1762 0 : if (count != aSource.mLayers.Length()) {
1763 0 : NS_WARNING("truncating counts due to out-of-memory");
1764 0 : mAttachmentCount = NS_MAX(mAttachmentCount, count);
1765 0 : mClipCount = NS_MAX(mClipCount, count);
1766 0 : mOriginCount = NS_MAX(mOriginCount, count);
1767 0 : mRepeatCount = NS_MAX(mRepeatCount, count);
1768 0 : mPositionCount = NS_MAX(mPositionCount, count);
1769 0 : mImageCount = NS_MAX(mImageCount, count);
1770 0 : mSizeCount = NS_MAX(mSizeCount, count);
1771 : }
1772 0 : }
1773 :
1774 0 : nsStyleBackground::~nsStyleBackground()
1775 : {
1776 0 : MOZ_COUNT_DTOR(nsStyleBackground);
1777 0 : }
1778 :
1779 : void
1780 0 : nsStyleBackground::Destroy(nsPresContext* aContext)
1781 : {
1782 : // Untrack all the images stored in our layers
1783 0 : for (PRUint32 i = 0; i < mImageCount; ++i)
1784 0 : mLayers[i].UntrackImages(aContext);
1785 :
1786 0 : this->~nsStyleBackground();
1787 0 : aContext->FreeToShell(sizeof(nsStyleBackground), this);
1788 0 : }
1789 :
1790 0 : nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther) const
1791 : {
1792 : const nsStyleBackground* moreLayers =
1793 0 : mImageCount > aOther.mImageCount ? this : &aOther;
1794 : const nsStyleBackground* lessLayers =
1795 0 : mImageCount > aOther.mImageCount ? &aOther : this;
1796 :
1797 0 : bool hasVisualDifference = false;
1798 :
1799 0 : NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, moreLayers) {
1800 0 : if (i < lessLayers->mImageCount) {
1801 0 : if (moreLayers->mLayers[i] != lessLayers->mLayers[i]) {
1802 0 : if ((moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element) ||
1803 0 : (lessLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element))
1804 0 : return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL);
1805 0 : hasVisualDifference = true;
1806 : }
1807 : } else {
1808 0 : if (moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element)
1809 0 : return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL);
1810 0 : hasVisualDifference = true;
1811 : }
1812 : }
1813 :
1814 0 : if (hasVisualDifference ||
1815 : mBackgroundColor != aOther.mBackgroundColor ||
1816 : mBackgroundInlinePolicy != aOther.mBackgroundInlinePolicy)
1817 0 : return NS_STYLE_HINT_VISUAL;
1818 :
1819 0 : return NS_STYLE_HINT_NONE;
1820 : }
1821 :
1822 : #ifdef DEBUG
1823 : /* static */
1824 0 : nsChangeHint nsStyleBackground::MaxDifference()
1825 : {
1826 0 : return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL);
1827 : }
1828 : #endif
1829 :
1830 0 : bool nsStyleBackground::HasFixedBackground() const
1831 : {
1832 0 : NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, this) {
1833 0 : const Layer &layer = mLayers[i];
1834 0 : if (layer.mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
1835 0 : !layer.mImage.IsEmpty()) {
1836 0 : return true;
1837 : }
1838 : }
1839 0 : return false;
1840 : }
1841 :
1842 0 : bool nsStyleBackground::IsTransparent() const
1843 : {
1844 0 : return BottomLayer().mImage.IsEmpty() &&
1845 : mImageCount == 1 &&
1846 0 : NS_GET_A(mBackgroundColor) == 0;
1847 : }
1848 :
1849 : void
1850 0 : nsStyleBackground::Position::SetInitialValues()
1851 : {
1852 : // Initial value is "0% 0%"
1853 0 : mXPosition.mPercent = 0.0f;
1854 0 : mXPosition.mLength = 0;
1855 0 : mXPosition.mHasPercent = true;
1856 0 : mYPosition.mPercent = 0.0f;
1857 0 : mYPosition.mLength = 0;
1858 0 : mYPosition.mHasPercent = true;
1859 0 : }
1860 :
1861 : bool
1862 0 : nsStyleBackground::Size::DependsOnFrameSize(const nsStyleImage& aImage) const
1863 : {
1864 0 : NS_ABORT_IF_FALSE(aImage.GetType() != eStyleImageType_Null,
1865 : "caller should have handled this");
1866 :
1867 : // If either dimension contains a non-zero percentage, rendering for that
1868 : // dimension straightforwardly depends on frame size.
1869 0 : if ((mWidthType == eLengthPercentage && mWidth.mPercent != 0.0f) ||
1870 : (mHeightType == eLengthPercentage && mHeight.mPercent != 0.0f)) {
1871 0 : return true;
1872 : }
1873 :
1874 : // So too for contain and cover.
1875 0 : if (mWidthType == eContain || mWidthType == eCover) {
1876 0 : return true;
1877 : }
1878 :
1879 : // If both dimensions are fixed lengths, there's no dependency.
1880 0 : if (mWidthType == eLengthPercentage && mHeightType == eLengthPercentage) {
1881 0 : return false;
1882 : }
1883 :
1884 0 : NS_ABORT_IF_FALSE((mWidthType == eLengthPercentage && mHeightType == eAuto) ||
1885 : (mWidthType == eAuto && mHeightType == eLengthPercentage) ||
1886 : (mWidthType == eAuto && mHeightType == eAuto),
1887 : "logic error");
1888 :
1889 0 : nsStyleImageType type = aImage.GetType();
1890 :
1891 : // Gradient rendering depends on frame size when auto is involved because
1892 : // gradients have no intrinsic ratio or dimensions, and therefore the relevant
1893 : // dimension is "treat[ed] as 100%".
1894 0 : if (type == eStyleImageType_Gradient) {
1895 0 : return true;
1896 : }
1897 :
1898 : // XXX Element rendering for auto or fixed length doesn't depend on frame size
1899 : // according to the spec. However, we don't implement the spec yet, so
1900 : // for now we bail and say element() plus auto affects ultimate size.
1901 0 : if (type == eStyleImageType_Element) {
1902 0 : return true;
1903 : }
1904 :
1905 0 : if (type == eStyleImageType_Image) {
1906 0 : nsCOMPtr<imgIContainer> imgContainer;
1907 0 : aImage.GetImageData()->GetImage(getter_AddRefs(imgContainer));
1908 0 : if (imgContainer) {
1909 0 : nsIntSize imageSize;
1910 0 : nsSize imageRatio;
1911 : bool hasWidth, hasHeight;
1912 : nsLayoutUtils::ComputeSizeForDrawing(imgContainer, imageSize, imageRatio,
1913 0 : hasWidth, hasHeight);
1914 :
1915 : // If the image has a fixed width and height, rendering never depends on
1916 : // the frame size.
1917 0 : if (hasWidth && hasHeight) {
1918 0 : return false;
1919 : }
1920 :
1921 : // If the image has an intrinsic ratio, rendering will depend on frame
1922 : // size when background-size is all auto.
1923 0 : if (imageRatio != nsSize(0, 0)) {
1924 0 : return mWidthType == mHeightType;
1925 : }
1926 :
1927 : // Otherwise, rendering depends on frame size when the image dimensions
1928 : // and background-size don't complement each other.
1929 0 : return !(hasWidth && mHeightType == eLengthPercentage) &&
1930 0 : !(hasHeight && mWidthType == eLengthPercentage);
1931 : }
1932 : } else {
1933 0 : NS_NOTREACHED("missed an enum value");
1934 : }
1935 :
1936 : // Passed the gauntlet: no dependency.
1937 0 : return false;
1938 : }
1939 :
1940 : void
1941 0 : nsStyleBackground::Size::SetInitialValues()
1942 : {
1943 0 : mWidthType = mHeightType = eAuto;
1944 0 : }
1945 :
1946 : bool
1947 0 : nsStyleBackground::Size::operator==(const Size& aOther) const
1948 : {
1949 0 : NS_ABORT_IF_FALSE(mWidthType < eDimensionType_COUNT,
1950 : "bad mWidthType for this");
1951 0 : NS_ABORT_IF_FALSE(mHeightType < eDimensionType_COUNT,
1952 : "bad mHeightType for this");
1953 0 : NS_ABORT_IF_FALSE(aOther.mWidthType < eDimensionType_COUNT,
1954 : "bad mWidthType for aOther");
1955 0 : NS_ABORT_IF_FALSE(aOther.mHeightType < eDimensionType_COUNT,
1956 : "bad mHeightType for aOther");
1957 :
1958 : return mWidthType == aOther.mWidthType &&
1959 : mHeightType == aOther.mHeightType &&
1960 0 : (mWidthType != eLengthPercentage || mWidth == aOther.mWidth) &&
1961 0 : (mHeightType != eLengthPercentage || mHeight == aOther.mHeight);
1962 : }
1963 :
1964 : void
1965 0 : nsStyleBackground::Repeat::SetInitialValues()
1966 : {
1967 0 : mXRepeat = NS_STYLE_BG_REPEAT_REPEAT;
1968 0 : mYRepeat = NS_STYLE_BG_REPEAT_REPEAT;
1969 0 : }
1970 :
1971 0 : nsStyleBackground::Layer::Layer()
1972 : {
1973 0 : }
1974 :
1975 0 : nsStyleBackground::Layer::~Layer()
1976 : {
1977 0 : }
1978 :
1979 : void
1980 0 : nsStyleBackground::Layer::SetInitialValues()
1981 : {
1982 0 : mAttachment = NS_STYLE_BG_ATTACHMENT_SCROLL;
1983 0 : mClip = NS_STYLE_BG_CLIP_BORDER;
1984 0 : mOrigin = NS_STYLE_BG_ORIGIN_PADDING;
1985 0 : mRepeat.SetInitialValues();
1986 0 : mPosition.SetInitialValues();
1987 0 : mSize.SetInitialValues();
1988 0 : mImage.SetNull();
1989 0 : }
1990 :
1991 : bool
1992 0 : nsStyleBackground::Layer::RenderingMightDependOnFrameSize() const
1993 : {
1994 : // Do we even have an image?
1995 0 : if (mImage.IsEmpty()) {
1996 0 : return false;
1997 : }
1998 :
1999 0 : return mPosition.DependsOnFrameSize() || mSize.DependsOnFrameSize(mImage);
2000 : }
2001 :
2002 : bool
2003 0 : nsStyleBackground::Layer::operator==(const Layer& aOther) const
2004 : {
2005 : return mAttachment == aOther.mAttachment &&
2006 : mClip == aOther.mClip &&
2007 : mOrigin == aOther.mOrigin &&
2008 0 : mRepeat == aOther.mRepeat &&
2009 0 : mPosition == aOther.mPosition &&
2010 0 : mSize == aOther.mSize &&
2011 0 : mImage == aOther.mImage;
2012 : }
2013 :
2014 : // --------------------
2015 : // nsStyleDisplay
2016 : //
2017 0 : void nsTimingFunction::AssignFromKeyword(PRInt32 aTimingFunctionType)
2018 : {
2019 0 : switch (aTimingFunctionType) {
2020 : case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START:
2021 0 : mType = StepStart;
2022 0 : mSteps = 1;
2023 0 : return;
2024 : case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END:
2025 0 : mType = StepEnd;
2026 0 : mSteps = 1;
2027 0 : return;
2028 : default:
2029 0 : mType = Function;
2030 : break;
2031 : }
2032 :
2033 : MOZ_STATIC_ASSERT(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE == 0 &&
2034 : NS_STYLE_TRANSITION_TIMING_FUNCTION_LINEAR == 1 &&
2035 : NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN == 2 &&
2036 : NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_OUT == 3 &&
2037 : NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN_OUT == 4,
2038 : "transition timing function constants not as expected");
2039 :
2040 : static const float timingFunctionValues[5][4] = {
2041 : { 0.25, 0.10, 0.25, 1.00 }, // ease
2042 : { 0.00, 0.00, 1.00, 1.00 }, // linear
2043 : { 0.42, 0.00, 1.00, 1.00 }, // ease-in
2044 : { 0.00, 0.00, 0.58, 1.00 }, // ease-out
2045 : { 0.42, 0.00, 0.58, 1.00 } // ease-in-out
2046 : };
2047 :
2048 0 : NS_ABORT_IF_FALSE(0 <= aTimingFunctionType && aTimingFunctionType < 5,
2049 : "keyword out of range");
2050 0 : mFunc.mX1 = timingFunctionValues[aTimingFunctionType][0];
2051 0 : mFunc.mY1 = timingFunctionValues[aTimingFunctionType][1];
2052 0 : mFunc.mX2 = timingFunctionValues[aTimingFunctionType][2];
2053 0 : mFunc.mY2 = timingFunctionValues[aTimingFunctionType][3];
2054 : }
2055 :
2056 0 : nsTransition::nsTransition(const nsTransition& aCopy)
2057 : : mTimingFunction(aCopy.mTimingFunction)
2058 : , mDuration(aCopy.mDuration)
2059 : , mDelay(aCopy.mDelay)
2060 : , mProperty(aCopy.mProperty)
2061 0 : , mUnknownProperty(aCopy.mUnknownProperty)
2062 : {
2063 0 : }
2064 :
2065 0 : void nsTransition::SetInitialValues()
2066 : {
2067 0 : mTimingFunction = nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE);
2068 0 : mDuration = 0.0;
2069 0 : mDelay = 0.0;
2070 0 : mProperty = eCSSPropertyExtra_all_properties;
2071 0 : }
2072 :
2073 0 : void nsTransition::SetUnknownProperty(const nsAString& aUnknownProperty)
2074 : {
2075 0 : NS_ASSERTION(nsCSSProps::LookupProperty(aUnknownProperty) ==
2076 : eCSSProperty_UNKNOWN,
2077 : "should be unknown property");
2078 0 : mProperty = eCSSProperty_UNKNOWN;
2079 0 : mUnknownProperty = do_GetAtom(aUnknownProperty);
2080 0 : }
2081 :
2082 0 : nsAnimation::nsAnimation(const nsAnimation& aCopy)
2083 : : mTimingFunction(aCopy.mTimingFunction)
2084 : , mDuration(aCopy.mDuration)
2085 : , mDelay(aCopy.mDelay)
2086 : , mName(aCopy.mName)
2087 : , mDirection(aCopy.mDirection)
2088 : , mFillMode(aCopy.mFillMode)
2089 : , mPlayState(aCopy.mPlayState)
2090 0 : , mIterationCount(aCopy.mIterationCount)
2091 : {
2092 0 : }
2093 :
2094 : void
2095 0 : nsAnimation::SetInitialValues()
2096 : {
2097 0 : mTimingFunction = nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE);
2098 0 : mDuration = 0.0;
2099 0 : mDelay = 0.0;
2100 0 : mName = EmptyString();
2101 0 : mDirection = NS_STYLE_ANIMATION_DIRECTION_NORMAL;
2102 0 : mFillMode = NS_STYLE_ANIMATION_FILL_MODE_NONE;
2103 0 : mPlayState = NS_STYLE_ANIMATION_PLAY_STATE_RUNNING;
2104 0 : mIterationCount = 1.0f;
2105 0 : }
2106 :
2107 0 : nsStyleDisplay::nsStyleDisplay()
2108 : {
2109 0 : MOZ_COUNT_CTOR(nsStyleDisplay);
2110 0 : mAppearance = NS_THEME_NONE;
2111 0 : mDisplay = NS_STYLE_DISPLAY_INLINE;
2112 0 : mOriginalDisplay = mDisplay;
2113 0 : mPosition = NS_STYLE_POSITION_STATIC;
2114 0 : mFloats = NS_STYLE_FLOAT_NONE;
2115 0 : mOriginalFloats = mFloats;
2116 0 : mBreakType = NS_STYLE_CLEAR_NONE;
2117 0 : mBreakBefore = false;
2118 0 : mBreakAfter = false;
2119 0 : mOverflowX = NS_STYLE_OVERFLOW_VISIBLE;
2120 0 : mOverflowY = NS_STYLE_OVERFLOW_VISIBLE;
2121 0 : mResize = NS_STYLE_RESIZE_NONE;
2122 0 : mClipFlags = NS_STYLE_CLIP_AUTO;
2123 0 : mClip.SetRect(0,0,0,0);
2124 0 : mOpacity = 1.0f;
2125 0 : mSpecifiedTransform = nsnull;
2126 0 : mTransformOrigin[0].SetPercentValue(0.5f); // Transform is centered on origin
2127 0 : mTransformOrigin[1].SetPercentValue(0.5f);
2128 0 : mTransformOrigin[2].SetCoordValue(0);
2129 0 : mPerspectiveOrigin[0].SetPercentValue(0.5f);
2130 0 : mPerspectiveOrigin[1].SetPercentValue(0.5f);
2131 0 : mChildPerspective.SetCoordValue(0);
2132 0 : mBackfaceVisibility = NS_STYLE_BACKFACE_VISIBILITY_VISIBLE;
2133 0 : mTransformStyle = NS_STYLE_TRANSFORM_STYLE_FLAT;
2134 0 : mOrient = NS_STYLE_ORIENT_HORIZONTAL;
2135 :
2136 0 : mTransitions.AppendElement();
2137 0 : NS_ABORT_IF_FALSE(mTransitions.Length() == 1,
2138 : "appending within auto buffer should never fail");
2139 0 : mTransitions[0].SetInitialValues();
2140 0 : mTransitionTimingFunctionCount = 1;
2141 0 : mTransitionDurationCount = 1;
2142 0 : mTransitionDelayCount = 1;
2143 0 : mTransitionPropertyCount = 1;
2144 :
2145 0 : mAnimations.AppendElement();
2146 0 : NS_ABORT_IF_FALSE(mAnimations.Length() == 1,
2147 : "appending within auto buffer should never fail");
2148 0 : mAnimations[0].SetInitialValues();
2149 0 : mAnimationTimingFunctionCount = 1;
2150 0 : mAnimationDurationCount = 1;
2151 0 : mAnimationDelayCount = 1;
2152 0 : mAnimationNameCount = 1;
2153 0 : mAnimationDirectionCount = 1;
2154 0 : mAnimationFillModeCount = 1;
2155 0 : mAnimationPlayStateCount = 1;
2156 0 : mAnimationIterationCountCount = 1;
2157 0 : }
2158 :
2159 0 : nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource)
2160 : : mTransitions(aSource.mTransitions)
2161 : , mTransitionTimingFunctionCount(aSource.mTransitionTimingFunctionCount)
2162 : , mTransitionDurationCount(aSource.mTransitionDurationCount)
2163 : , mTransitionDelayCount(aSource.mTransitionDelayCount)
2164 : , mTransitionPropertyCount(aSource.mTransitionPropertyCount)
2165 : , mAnimations(aSource.mAnimations)
2166 : , mAnimationTimingFunctionCount(aSource.mAnimationTimingFunctionCount)
2167 : , mAnimationDurationCount(aSource.mAnimationDurationCount)
2168 : , mAnimationDelayCount(aSource.mAnimationDelayCount)
2169 : , mAnimationNameCount(aSource.mAnimationNameCount)
2170 : , mAnimationDirectionCount(aSource.mAnimationDirectionCount)
2171 : , mAnimationFillModeCount(aSource.mAnimationFillModeCount)
2172 : , mAnimationPlayStateCount(aSource.mAnimationPlayStateCount)
2173 0 : , mAnimationIterationCountCount(aSource.mAnimationIterationCountCount)
2174 : {
2175 0 : MOZ_COUNT_CTOR(nsStyleDisplay);
2176 0 : mAppearance = aSource.mAppearance;
2177 0 : mDisplay = aSource.mDisplay;
2178 0 : mOriginalDisplay = aSource.mOriginalDisplay;
2179 0 : mOriginalFloats = aSource.mOriginalFloats;
2180 0 : mBinding = aSource.mBinding;
2181 0 : mPosition = aSource.mPosition;
2182 0 : mFloats = aSource.mFloats;
2183 0 : mBreakType = aSource.mBreakType;
2184 0 : mBreakBefore = aSource.mBreakBefore;
2185 0 : mBreakAfter = aSource.mBreakAfter;
2186 0 : mOverflowX = aSource.mOverflowX;
2187 0 : mOverflowY = aSource.mOverflowY;
2188 0 : mResize = aSource.mResize;
2189 0 : mClipFlags = aSource.mClipFlags;
2190 0 : mClip = aSource.mClip;
2191 0 : mOpacity = aSource.mOpacity;
2192 0 : mOrient = aSource.mOrient;
2193 :
2194 : /* Copy over the transformation information. */
2195 0 : mSpecifiedTransform = aSource.mSpecifiedTransform;
2196 :
2197 : /* Copy over transform origin. */
2198 0 : mTransformOrigin[0] = aSource.mTransformOrigin[0];
2199 0 : mTransformOrigin[1] = aSource.mTransformOrigin[1];
2200 0 : mTransformOrigin[2] = aSource.mTransformOrigin[2];
2201 0 : mPerspectiveOrigin[0] = aSource.mPerspectiveOrigin[0];
2202 0 : mPerspectiveOrigin[1] = aSource.mPerspectiveOrigin[1];
2203 0 : mChildPerspective = aSource.mChildPerspective;
2204 0 : mBackfaceVisibility = aSource.mBackfaceVisibility;
2205 0 : mTransformStyle = aSource.mTransformStyle;
2206 0 : }
2207 :
2208 0 : nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
2209 : {
2210 0 : nsChangeHint hint = nsChangeHint(0);
2211 :
2212 0 : if (!EqualURIs(mBinding, aOther.mBinding)
2213 : || mPosition != aOther.mPosition
2214 : || mDisplay != aOther.mDisplay
2215 : || (mFloats == NS_STYLE_FLOAT_NONE) != (aOther.mFloats == NS_STYLE_FLOAT_NONE)
2216 : || mOverflowX != aOther.mOverflowX
2217 : || mOverflowY != aOther.mOverflowY
2218 : || mResize != aOther.mResize)
2219 0 : NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
2220 :
2221 0 : if (mFloats != aOther.mFloats) {
2222 : // Changing which side we float on doesn't affect descendants directly
2223 : NS_UpdateHint(hint,
2224 : NS_SubtractHint(nsChangeHint_ReflowFrame,
2225 : NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics,
2226 0 : nsChangeHint_NeedDirtyReflow)));
2227 : }
2228 :
2229 : // XXX the following is conservative, for now: changing float breaking shouldn't
2230 : // necessarily require a repaint, reflow should suffice.
2231 0 : if (mBreakType != aOther.mBreakType
2232 : || mBreakBefore != aOther.mBreakBefore
2233 : || mBreakAfter != aOther.mBreakAfter
2234 : || mAppearance != aOther.mAppearance
2235 : || mOrient != aOther.mOrient
2236 0 : || mClipFlags != aOther.mClipFlags || !mClip.IsEqualInterior(aOther.mClip))
2237 0 : NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_ReflowFrame, nsChangeHint_RepaintFrame));
2238 :
2239 0 : if (mOpacity != aOther.mOpacity) {
2240 0 : NS_UpdateHint(hint, nsChangeHint_UpdateOpacityLayer);
2241 : }
2242 :
2243 : /* If we've added or removed the transform property, we need to reconstruct the frame to add
2244 : * or remove the view object, and also to handle abs-pos and fixed-pos containers.
2245 : */
2246 0 : if (HasTransform() != aOther.HasTransform()) {
2247 0 : NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
2248 : }
2249 0 : else if (HasTransform()) {
2250 : /* Otherwise, if we've kept the property lying around and we already had a
2251 : * transform, we need to see whether or not we've changed the transform.
2252 : * If so, we need to recompute its overflow rect (which probably changed
2253 : * if the transform changed) and to redraw within the bounds of that new
2254 : * overflow rect.
2255 : */
2256 0 : if (!mSpecifiedTransform != !aOther.mSpecifiedTransform ||
2257 : (mSpecifiedTransform &&
2258 0 : *mSpecifiedTransform != *aOther.mSpecifiedTransform)) {
2259 : NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_UpdateOverflow,
2260 0 : nsChangeHint_UpdateTransformLayer));
2261 : }
2262 :
2263 : const nsChangeHint kUpdateOverflowAndRepaintHint =
2264 0 : NS_CombineHint(nsChangeHint_UpdateOverflow, nsChangeHint_RepaintFrame);
2265 0 : for (PRUint8 index = 0; index < 3; ++index)
2266 0 : if (mTransformOrigin[index] != aOther.mTransformOrigin[index]) {
2267 0 : NS_UpdateHint(hint, kUpdateOverflowAndRepaintHint);
2268 0 : break;
2269 : }
2270 :
2271 0 : for (PRUint8 index = 0; index < 2; ++index)
2272 0 : if (mPerspectiveOrigin[index] != aOther.mPerspectiveOrigin[index]) {
2273 0 : NS_UpdateHint(hint, kUpdateOverflowAndRepaintHint);
2274 0 : break;
2275 : }
2276 :
2277 0 : if (mChildPerspective != aOther.mChildPerspective ||
2278 : mTransformStyle != aOther.mTransformStyle)
2279 0 : NS_UpdateHint(hint, kUpdateOverflowAndRepaintHint);
2280 :
2281 0 : if (mBackfaceVisibility != aOther.mBackfaceVisibility)
2282 0 : NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
2283 : }
2284 :
2285 : // Note: Our current behavior for handling changes to the
2286 : // transition-duration, transition-delay, and transition-timing-function
2287 : // properties is to do nothing. In other words, the transition
2288 : // property that matters is what it is when the transition begins, and
2289 : // we don't stop a transition later because the transition property
2290 : // changed.
2291 : // We do handle changes to transition-property, but we don't need to
2292 : // bother with anything here, since the transition manager is notified
2293 : // of any style context change anyway.
2294 :
2295 : // Note: Likewise, for animation-*, the animation manager gets
2296 : // notified about every new style context constructed, and it uses
2297 : // that opportunity to handle dynamic changes appropriately.
2298 :
2299 0 : return hint;
2300 : }
2301 :
2302 : #ifdef DEBUG
2303 : /* static */
2304 0 : nsChangeHint nsStyleDisplay::MaxDifference()
2305 : {
2306 : // All the parts of FRAMECHANGE are present above in CalcDifference.
2307 : return nsChangeHint(NS_STYLE_HINT_FRAMECHANGE |
2308 : nsChangeHint_UpdateOpacityLayer |
2309 : nsChangeHint_UpdateTransformLayer |
2310 0 : nsChangeHint_UpdateOverflow);
2311 : }
2312 : #endif
2313 :
2314 : // --------------------
2315 : // nsStyleVisibility
2316 : //
2317 :
2318 0 : nsStyleVisibility::nsStyleVisibility(nsPresContext* aPresContext)
2319 : {
2320 0 : MOZ_COUNT_CTOR(nsStyleVisibility);
2321 0 : PRUint32 bidiOptions = aPresContext->GetBidi();
2322 0 : if (GET_BIDI_OPTION_DIRECTION(bidiOptions) == IBMBIDI_TEXTDIRECTION_RTL)
2323 0 : mDirection = NS_STYLE_DIRECTION_RTL;
2324 : else
2325 0 : mDirection = NS_STYLE_DIRECTION_LTR;
2326 :
2327 0 : mVisible = NS_STYLE_VISIBILITY_VISIBLE;
2328 0 : mPointerEvents = NS_STYLE_POINTER_EVENTS_AUTO;
2329 0 : }
2330 :
2331 0 : nsStyleVisibility::nsStyleVisibility(const nsStyleVisibility& aSource)
2332 : {
2333 0 : MOZ_COUNT_CTOR(nsStyleVisibility);
2334 0 : mDirection = aSource.mDirection;
2335 0 : mVisible = aSource.mVisible;
2336 0 : mPointerEvents = aSource.mPointerEvents;
2337 0 : }
2338 :
2339 0 : nsChangeHint nsStyleVisibility::CalcDifference(const nsStyleVisibility& aOther) const
2340 : {
2341 0 : nsChangeHint hint = nsChangeHint(0);
2342 :
2343 0 : if (mDirection != aOther.mDirection) {
2344 0 : NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
2345 0 : } else if (mVisible != aOther.mVisible) {
2346 0 : if ((NS_STYLE_VISIBILITY_COLLAPSE == mVisible) ||
2347 : (NS_STYLE_VISIBILITY_COLLAPSE == aOther.mVisible)) {
2348 0 : NS_UpdateHint(hint, NS_STYLE_HINT_REFLOW);
2349 : } else {
2350 0 : NS_UpdateHint(hint, NS_STYLE_HINT_VISUAL);
2351 : }
2352 : }
2353 0 : return hint;
2354 : }
2355 :
2356 : #ifdef DEBUG
2357 : /* static */
2358 0 : nsChangeHint nsStyleVisibility::MaxDifference()
2359 : {
2360 0 : return NS_STYLE_HINT_FRAMECHANGE;
2361 : }
2362 : #endif
2363 :
2364 0 : nsStyleContentData::~nsStyleContentData()
2365 : {
2366 0 : NS_ABORT_IF_FALSE(!mImageTracked,
2367 : "nsStyleContentData being destroyed while still tracking image!");
2368 0 : if (mType == eStyleContentType_Image) {
2369 0 : NS_IF_RELEASE(mContent.mImage);
2370 0 : } else if (mType == eStyleContentType_Counter ||
2371 : mType == eStyleContentType_Counters) {
2372 0 : mContent.mCounters->Release();
2373 0 : } else if (mContent.mString) {
2374 0 : NS_Free(mContent.mString);
2375 : }
2376 0 : }
2377 :
2378 0 : nsStyleContentData& nsStyleContentData::operator=(const nsStyleContentData& aOther)
2379 : {
2380 0 : if (this == &aOther)
2381 0 : return *this;
2382 0 : this->~nsStyleContentData();
2383 0 : new (this) nsStyleContentData();
2384 :
2385 0 : mType = aOther.mType;
2386 0 : if (mType == eStyleContentType_Image) {
2387 0 : mContent.mImage = aOther.mContent.mImage;
2388 0 : NS_IF_ADDREF(mContent.mImage);
2389 0 : } else if (mType == eStyleContentType_Counter ||
2390 : mType == eStyleContentType_Counters) {
2391 0 : mContent.mCounters = aOther.mContent.mCounters;
2392 0 : mContent.mCounters->AddRef();
2393 0 : } else if (aOther.mContent.mString) {
2394 0 : mContent.mString = NS_strdup(aOther.mContent.mString);
2395 : } else {
2396 0 : mContent.mString = nsnull;
2397 : }
2398 0 : return *this;
2399 : }
2400 :
2401 0 : bool nsStyleContentData::operator==(const nsStyleContentData& aOther) const
2402 : {
2403 0 : if (mType != aOther.mType)
2404 0 : return false;
2405 0 : if (mType == eStyleContentType_Image) {
2406 0 : if (!mContent.mImage || !aOther.mContent.mImage)
2407 0 : return mContent.mImage == aOther.mContent.mImage;
2408 : bool eq;
2409 0 : nsCOMPtr<nsIURI> thisURI, otherURI;
2410 0 : mContent.mImage->GetURI(getter_AddRefs(thisURI));
2411 0 : aOther.mContent.mImage->GetURI(getter_AddRefs(otherURI));
2412 0 : return thisURI == otherURI || // handles null==null
2413 0 : (thisURI && otherURI &&
2414 0 : NS_SUCCEEDED(thisURI->Equals(otherURI, &eq)) &&
2415 0 : eq);
2416 : }
2417 0 : if (mType == eStyleContentType_Counter ||
2418 : mType == eStyleContentType_Counters)
2419 0 : return *mContent.mCounters == *aOther.mContent.mCounters;
2420 0 : return safe_strcmp(mContent.mString, aOther.mContent.mString) == 0;
2421 : }
2422 :
2423 : void
2424 0 : nsStyleContentData::TrackImage(nsPresContext* aContext)
2425 : {
2426 : // Sanity
2427 0 : NS_ABORT_IF_FALSE(!mImageTracked, "Already tracking image!");
2428 0 : NS_ABORT_IF_FALSE(mType == eStyleContentType_Image,
2429 : "Tryingto do image tracking on non-image!");
2430 0 : NS_ABORT_IF_FALSE(mContent.mImage,
2431 : "Can't track image when there isn't one!");
2432 :
2433 : // Register the image with the document
2434 0 : nsIDocument* doc = aContext->Document();
2435 0 : if (doc)
2436 0 : doc->AddImage(mContent.mImage);
2437 :
2438 : // Mark state
2439 : #ifdef DEBUG
2440 0 : mImageTracked = true;
2441 : #endif
2442 0 : }
2443 :
2444 : void
2445 0 : nsStyleContentData::UntrackImage(nsPresContext* aContext)
2446 : {
2447 : // Sanity
2448 0 : NS_ABORT_IF_FALSE(mImageTracked, "Image not tracked!");
2449 0 : NS_ABORT_IF_FALSE(mType == eStyleContentType_Image,
2450 : "Trying to do image tracking on non-image!");
2451 0 : NS_ABORT_IF_FALSE(mContent.mImage,
2452 : "Can't untrack image when there isn't one!");
2453 :
2454 : // Unregister the image with the document
2455 0 : nsIDocument* doc = aContext->Document();
2456 0 : if (doc)
2457 0 : doc->RemoveImage(mContent.mImage);
2458 :
2459 : // Mark state
2460 : #ifdef DEBUG
2461 0 : mImageTracked = false;
2462 : #endif
2463 0 : }
2464 :
2465 :
2466 : //-----------------------
2467 : // nsStyleContent
2468 : //
2469 :
2470 0 : nsStyleContent::nsStyleContent(void)
2471 : : mMarkerOffset(),
2472 : mContents(nsnull),
2473 : mIncrements(nsnull),
2474 : mResets(nsnull),
2475 : mContentCount(0),
2476 : mIncrementCount(0),
2477 0 : mResetCount(0)
2478 : {
2479 0 : MOZ_COUNT_CTOR(nsStyleContent);
2480 0 : mMarkerOffset.SetAutoValue();
2481 0 : }
2482 :
2483 0 : nsStyleContent::~nsStyleContent(void)
2484 : {
2485 0 : MOZ_COUNT_DTOR(nsStyleContent);
2486 0 : DELETE_ARRAY_IF(mContents);
2487 0 : DELETE_ARRAY_IF(mIncrements);
2488 0 : DELETE_ARRAY_IF(mResets);
2489 0 : }
2490 :
2491 : void
2492 0 : nsStyleContent::Destroy(nsPresContext* aContext)
2493 : {
2494 : // Unregister any images we might have with the document.
2495 0 : for (PRUint32 i = 0; i < mContentCount; ++i) {
2496 0 : if ((mContents[i].mType == eStyleContentType_Image) &&
2497 0 : mContents[i].mContent.mImage) {
2498 0 : mContents[i].UntrackImage(aContext);
2499 : }
2500 : }
2501 :
2502 0 : this->~nsStyleContent();
2503 0 : aContext->FreeToShell(sizeof(nsStyleContent), this);
2504 0 : }
2505 :
2506 0 : nsStyleContent::nsStyleContent(const nsStyleContent& aSource)
2507 : :mMarkerOffset(),
2508 : mContents(nsnull),
2509 : mIncrements(nsnull),
2510 : mResets(nsnull),
2511 : mContentCount(0),
2512 : mIncrementCount(0),
2513 0 : mResetCount(0)
2514 :
2515 : {
2516 0 : MOZ_COUNT_CTOR(nsStyleContent);
2517 0 : mMarkerOffset = aSource.mMarkerOffset;
2518 :
2519 : PRUint32 index;
2520 0 : if (NS_SUCCEEDED(AllocateContents(aSource.ContentCount()))) {
2521 0 : for (index = 0; index < mContentCount; index++) {
2522 0 : ContentAt(index) = aSource.ContentAt(index);
2523 : }
2524 : }
2525 :
2526 0 : if (NS_SUCCEEDED(AllocateCounterIncrements(aSource.CounterIncrementCount()))) {
2527 0 : for (index = 0; index < mIncrementCount; index++) {
2528 0 : const nsStyleCounterData *data = aSource.GetCounterIncrementAt(index);
2529 0 : mIncrements[index].mCounter = data->mCounter;
2530 0 : mIncrements[index].mValue = data->mValue;
2531 : }
2532 : }
2533 :
2534 0 : if (NS_SUCCEEDED(AllocateCounterResets(aSource.CounterResetCount()))) {
2535 0 : for (index = 0; index < mResetCount; index++) {
2536 0 : const nsStyleCounterData *data = aSource.GetCounterResetAt(index);
2537 0 : mResets[index].mCounter = data->mCounter;
2538 0 : mResets[index].mValue = data->mValue;
2539 : }
2540 : }
2541 0 : }
2542 :
2543 0 : nsChangeHint nsStyleContent::CalcDifference(const nsStyleContent& aOther) const
2544 : {
2545 : // In ReResolveStyleContext we assume that if there's no existing
2546 : // ::before or ::after and we don't have to restyle children of the
2547 : // node then we can't end up with a ::before or ::after due to the
2548 : // restyle of the node itself. That's not quite true, but the only
2549 : // exception to the above is when the 'content' property of the node
2550 : // changes and the pseudo-element inherits the changed value. Since
2551 : // the code here triggers a frame change on the node in that case,
2552 : // the optimization in ReResolveStyleContext is ok. But if we ever
2553 : // change this code to not reconstruct frames on changes to the
2554 : // 'content' property, then we will need to revisit the optimization
2555 : // in ReResolveStyleContext.
2556 :
2557 0 : if (mContentCount != aOther.mContentCount ||
2558 : mIncrementCount != aOther.mIncrementCount ||
2559 : mResetCount != aOther.mResetCount) {
2560 0 : return NS_STYLE_HINT_FRAMECHANGE;
2561 : }
2562 :
2563 0 : PRUint32 ix = mContentCount;
2564 0 : while (0 < ix--) {
2565 0 : if (mContents[ix] != aOther.mContents[ix]) {
2566 : // Unfortunately we need to reframe here; a simple reflow
2567 : // will not pick up different text or different image URLs,
2568 : // since we set all that up in the CSSFrameConstructor
2569 0 : return NS_STYLE_HINT_FRAMECHANGE;
2570 : }
2571 : }
2572 0 : ix = mIncrementCount;
2573 0 : while (0 < ix--) {
2574 0 : if ((mIncrements[ix].mValue != aOther.mIncrements[ix].mValue) ||
2575 0 : (mIncrements[ix].mCounter != aOther.mIncrements[ix].mCounter)) {
2576 0 : return NS_STYLE_HINT_FRAMECHANGE;
2577 : }
2578 : }
2579 0 : ix = mResetCount;
2580 0 : while (0 < ix--) {
2581 0 : if ((mResets[ix].mValue != aOther.mResets[ix].mValue) ||
2582 0 : (mResets[ix].mCounter != aOther.mResets[ix].mCounter)) {
2583 0 : return NS_STYLE_HINT_FRAMECHANGE;
2584 : }
2585 : }
2586 0 : if (mMarkerOffset != aOther.mMarkerOffset) {
2587 0 : return NS_STYLE_HINT_REFLOW;
2588 : }
2589 0 : return NS_STYLE_HINT_NONE;
2590 : }
2591 :
2592 : #ifdef DEBUG
2593 : /* static */
2594 0 : nsChangeHint nsStyleContent::MaxDifference()
2595 : {
2596 0 : return NS_STYLE_HINT_FRAMECHANGE;
2597 : }
2598 : #endif
2599 :
2600 0 : nsresult nsStyleContent::AllocateContents(PRUint32 aCount)
2601 : {
2602 : // We need to run the destructors of the elements of mContents, so we
2603 : // delete and reallocate even if aCount == mContentCount. (If
2604 : // nsStyleContentData had its members private and managed their
2605 : // ownership on setting, we wouldn't need this, but that seems
2606 : // unnecessary at this point.)
2607 0 : DELETE_ARRAY_IF(mContents);
2608 0 : if (aCount) {
2609 0 : mContents = new nsStyleContentData[aCount];
2610 0 : if (! mContents) {
2611 0 : mContentCount = 0;
2612 0 : return NS_ERROR_OUT_OF_MEMORY;
2613 : }
2614 : }
2615 0 : mContentCount = aCount;
2616 0 : return NS_OK;
2617 : }
2618 :
2619 : // ---------------------
2620 : // nsStyleQuotes
2621 : //
2622 :
2623 0 : nsStyleQuotes::nsStyleQuotes(void)
2624 : : mQuotesCount(0),
2625 0 : mQuotes(nsnull)
2626 : {
2627 0 : MOZ_COUNT_CTOR(nsStyleQuotes);
2628 0 : SetInitial();
2629 0 : }
2630 :
2631 0 : nsStyleQuotes::~nsStyleQuotes(void)
2632 : {
2633 0 : MOZ_COUNT_DTOR(nsStyleQuotes);
2634 0 : DELETE_ARRAY_IF(mQuotes);
2635 0 : }
2636 :
2637 0 : nsStyleQuotes::nsStyleQuotes(const nsStyleQuotes& aSource)
2638 : : mQuotesCount(0),
2639 0 : mQuotes(nsnull)
2640 : {
2641 0 : MOZ_COUNT_CTOR(nsStyleQuotes);
2642 0 : CopyFrom(aSource);
2643 0 : }
2644 :
2645 : void
2646 0 : nsStyleQuotes::SetInitial()
2647 : {
2648 : // The initial value for quotes is the en-US typographic convention:
2649 : // outermost are LEFT and RIGHT DOUBLE QUOTATION MARK, alternating
2650 : // with LEFT and RIGHT SINGLE QUOTATION MARK.
2651 : static const PRUnichar initialQuotes[8] = {
2652 : 0x201C, 0, 0x201D, 0, 0x2018, 0, 0x2019, 0
2653 : };
2654 :
2655 0 : if (NS_SUCCEEDED(AllocateQuotes(2))) {
2656 : SetQuotesAt(0,
2657 0 : nsDependentString(&initialQuotes[0], 1),
2658 0 : nsDependentString(&initialQuotes[2], 1));
2659 : SetQuotesAt(1,
2660 0 : nsDependentString(&initialQuotes[4], 1),
2661 0 : nsDependentString(&initialQuotes[6], 1));
2662 : }
2663 0 : }
2664 :
2665 : void
2666 0 : nsStyleQuotes::CopyFrom(const nsStyleQuotes& aSource)
2667 : {
2668 0 : if (NS_SUCCEEDED(AllocateQuotes(aSource.QuotesCount()))) {
2669 0 : PRUint32 count = (mQuotesCount * 2);
2670 0 : for (PRUint32 index = 0; index < count; index += 2) {
2671 0 : aSource.GetQuotesAt(index, mQuotes[index], mQuotes[index + 1]);
2672 : }
2673 : }
2674 0 : }
2675 :
2676 0 : nsChangeHint nsStyleQuotes::CalcDifference(const nsStyleQuotes& aOther) const
2677 : {
2678 : // If the quotes implementation is ever going to change we might not need
2679 : // a framechange here and a reflow should be sufficient. See bug 35768.
2680 0 : if (mQuotesCount == aOther.mQuotesCount) {
2681 0 : PRUint32 ix = (mQuotesCount * 2);
2682 0 : while (0 < ix--) {
2683 0 : if (mQuotes[ix] != aOther.mQuotes[ix]) {
2684 0 : return NS_STYLE_HINT_FRAMECHANGE;
2685 : }
2686 : }
2687 :
2688 0 : return NS_STYLE_HINT_NONE;
2689 : }
2690 0 : return NS_STYLE_HINT_FRAMECHANGE;
2691 : }
2692 :
2693 : #ifdef DEBUG
2694 : /* static */
2695 0 : nsChangeHint nsStyleQuotes::MaxDifference()
2696 : {
2697 0 : return NS_STYLE_HINT_FRAMECHANGE;
2698 : }
2699 : #endif
2700 :
2701 : // --------------------
2702 : // nsStyleTextReset
2703 : //
2704 :
2705 0 : nsStyleTextReset::nsStyleTextReset(void)
2706 : {
2707 0 : MOZ_COUNT_CTOR(nsStyleTextReset);
2708 0 : mVerticalAlign.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE, eStyleUnit_Enumerated);
2709 0 : mTextBlink = NS_STYLE_TEXT_BLINK_NONE;
2710 0 : mTextDecorationLine = NS_STYLE_TEXT_DECORATION_LINE_NONE;
2711 0 : mTextDecorationColor = NS_RGB(0,0,0);
2712 : mTextDecorationStyle =
2713 0 : NS_STYLE_TEXT_DECORATION_STYLE_SOLID | BORDER_COLOR_FOREGROUND;
2714 0 : mUnicodeBidi = NS_STYLE_UNICODE_BIDI_NORMAL;
2715 0 : }
2716 :
2717 0 : nsStyleTextReset::nsStyleTextReset(const nsStyleTextReset& aSource)
2718 : {
2719 0 : MOZ_COUNT_CTOR(nsStyleTextReset);
2720 0 : *this = aSource;
2721 0 : }
2722 :
2723 0 : nsStyleTextReset::~nsStyleTextReset(void)
2724 : {
2725 0 : MOZ_COUNT_DTOR(nsStyleTextReset);
2726 0 : }
2727 :
2728 0 : nsChangeHint nsStyleTextReset::CalcDifference(const nsStyleTextReset& aOther) const
2729 : {
2730 0 : if (mVerticalAlign == aOther.mVerticalAlign
2731 : && mUnicodeBidi == aOther.mUnicodeBidi) {
2732 : // Reflow for blink changes
2733 0 : if (mTextBlink != aOther.mTextBlink) {
2734 0 : return NS_STYLE_HINT_REFLOW;
2735 : }
2736 :
2737 0 : PRUint8 lineStyle = GetDecorationStyle();
2738 0 : PRUint8 otherLineStyle = aOther.GetDecorationStyle();
2739 0 : if (mTextDecorationLine != aOther.mTextDecorationLine ||
2740 : lineStyle != otherLineStyle) {
2741 : // Reflow for decoration line style changes only to or from double or
2742 : // wave because that may cause overflow area changes
2743 0 : if (lineStyle == NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE ||
2744 : lineStyle == NS_STYLE_TEXT_DECORATION_STYLE_WAVY ||
2745 : otherLineStyle == NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE ||
2746 : otherLineStyle == NS_STYLE_TEXT_DECORATION_STYLE_WAVY) {
2747 0 : return NS_STYLE_HINT_REFLOW;
2748 : }
2749 : // Repaint for other style decoration lines because they must be in
2750 : // default overflow rect
2751 0 : return NS_STYLE_HINT_VISUAL;
2752 : }
2753 :
2754 : // Repaint for decoration color changes
2755 : nscolor decColor, otherDecColor;
2756 : bool isFG, otherIsFG;
2757 0 : GetDecorationColor(decColor, isFG);
2758 0 : aOther.GetDecorationColor(otherDecColor, otherIsFG);
2759 0 : if (isFG != otherIsFG || (!isFG && decColor != otherDecColor)) {
2760 0 : return NS_STYLE_HINT_VISUAL;
2761 : }
2762 :
2763 0 : if (mTextOverflow != aOther.mTextOverflow) {
2764 0 : return NS_STYLE_HINT_VISUAL;
2765 : }
2766 0 : return NS_STYLE_HINT_NONE;
2767 : }
2768 0 : return NS_STYLE_HINT_REFLOW;
2769 : }
2770 :
2771 : #ifdef DEBUG
2772 : /* static */
2773 0 : nsChangeHint nsStyleTextReset::MaxDifference()
2774 : {
2775 0 : return NS_STYLE_HINT_REFLOW;
2776 : }
2777 : #endif
2778 :
2779 : // Allowed to return one of NS_STYLE_HINT_NONE, NS_STYLE_HINT_REFLOW
2780 : // or NS_STYLE_HINT_VISUAL. Currently we just return NONE or REFLOW, though.
2781 : // XXXbz can this not return a more specific hint? If that's ever
2782 : // changed, nsStyleBorder::CalcDifference will need changing too.
2783 : static nsChangeHint
2784 0 : CalcShadowDifference(nsCSSShadowArray* lhs,
2785 : nsCSSShadowArray* rhs)
2786 : {
2787 0 : if (lhs == rhs)
2788 0 : return NS_STYLE_HINT_NONE;
2789 :
2790 0 : if (!lhs || !rhs || lhs->Length() != rhs->Length())
2791 0 : return NS_STYLE_HINT_REFLOW;
2792 :
2793 0 : for (PRUint32 i = 0; i < lhs->Length(); ++i) {
2794 0 : if (*lhs->ShadowAt(i) != *rhs->ShadowAt(i))
2795 0 : return NS_STYLE_HINT_REFLOW;
2796 : }
2797 0 : return NS_STYLE_HINT_NONE;
2798 : }
2799 :
2800 : // --------------------
2801 : // nsStyleText
2802 : //
2803 :
2804 0 : nsStyleText::nsStyleText(void)
2805 : {
2806 0 : MOZ_COUNT_CTOR(nsStyleText);
2807 0 : mTextAlign = NS_STYLE_TEXT_ALIGN_DEFAULT;
2808 0 : mTextAlignLast = NS_STYLE_TEXT_ALIGN_AUTO;
2809 0 : mTextTransform = NS_STYLE_TEXT_TRANSFORM_NONE;
2810 0 : mWhiteSpace = NS_STYLE_WHITESPACE_NORMAL;
2811 0 : mWordWrap = NS_STYLE_WORDWRAP_NORMAL;
2812 0 : mHyphens = NS_STYLE_HYPHENS_MANUAL;
2813 0 : mTextSizeAdjust = NS_STYLE_TEXT_SIZE_ADJUST_AUTO;
2814 :
2815 0 : mLetterSpacing.SetNormalValue();
2816 0 : mLineHeight.SetNormalValue();
2817 0 : mTextIndent.SetCoordValue(0);
2818 0 : mWordSpacing = 0;
2819 :
2820 0 : mTextShadow = nsnull;
2821 0 : mTabSize = NS_STYLE_TABSIZE_INITIAL;
2822 0 : }
2823 :
2824 0 : nsStyleText::nsStyleText(const nsStyleText& aSource)
2825 : : mTextAlign(aSource.mTextAlign),
2826 : mTextAlignLast(aSource.mTextAlignLast),
2827 : mTextTransform(aSource.mTextTransform),
2828 : mWhiteSpace(aSource.mWhiteSpace),
2829 : mWordWrap(aSource.mWordWrap),
2830 : mHyphens(aSource.mHyphens),
2831 : mTextSizeAdjust(aSource.mTextSizeAdjust),
2832 : mTabSize(aSource.mTabSize),
2833 : mLetterSpacing(aSource.mLetterSpacing),
2834 : mLineHeight(aSource.mLineHeight),
2835 : mTextIndent(aSource.mTextIndent),
2836 : mWordSpacing(aSource.mWordSpacing),
2837 0 : mTextShadow(aSource.mTextShadow)
2838 : {
2839 0 : MOZ_COUNT_CTOR(nsStyleText);
2840 0 : }
2841 :
2842 0 : nsStyleText::~nsStyleText(void)
2843 : {
2844 0 : MOZ_COUNT_DTOR(nsStyleText);
2845 0 : }
2846 :
2847 0 : nsChangeHint nsStyleText::CalcDifference(const nsStyleText& aOther) const
2848 : {
2849 0 : if (NewlineIsSignificant() != aOther.NewlineIsSignificant()) {
2850 : // This may require construction of suppressed text frames
2851 0 : return NS_STYLE_HINT_FRAMECHANGE;
2852 : }
2853 :
2854 0 : if ((mTextAlign != aOther.mTextAlign) ||
2855 : (mTextAlignLast != aOther.mTextAlignLast) ||
2856 : (mTextTransform != aOther.mTextTransform) ||
2857 : (mWhiteSpace != aOther.mWhiteSpace) ||
2858 : (mWordWrap != aOther.mWordWrap) ||
2859 : (mHyphens != aOther.mHyphens) ||
2860 : (mTextSizeAdjust != aOther.mTextSizeAdjust) ||
2861 0 : (mLetterSpacing != aOther.mLetterSpacing) ||
2862 0 : (mLineHeight != aOther.mLineHeight) ||
2863 0 : (mTextIndent != aOther.mTextIndent) ||
2864 : (mWordSpacing != aOther.mWordSpacing) ||
2865 : (mTabSize != aOther.mTabSize))
2866 0 : return NS_STYLE_HINT_REFLOW;
2867 :
2868 0 : return CalcShadowDifference(mTextShadow, aOther.mTextShadow);
2869 : }
2870 :
2871 : #ifdef DEBUG
2872 : /* static */
2873 0 : nsChangeHint nsStyleText::MaxDifference()
2874 : {
2875 0 : return NS_STYLE_HINT_FRAMECHANGE;
2876 : }
2877 : #endif
2878 :
2879 : //-----------------------
2880 : // nsStyleUserInterface
2881 : //
2882 :
2883 0 : nsCursorImage::nsCursorImage()
2884 : : mHaveHotspot(false)
2885 : , mHotspotX(0.0f)
2886 0 : , mHotspotY(0.0f)
2887 : {
2888 0 : }
2889 :
2890 0 : nsCursorImage::nsCursorImage(const nsCursorImage& aOther)
2891 : : mHaveHotspot(aOther.mHaveHotspot)
2892 : , mHotspotX(aOther.mHotspotX)
2893 0 : , mHotspotY(aOther.mHotspotY)
2894 : {
2895 0 : SetImage(aOther.GetImage());
2896 0 : }
2897 :
2898 0 : nsCursorImage::~nsCursorImage()
2899 : {
2900 0 : SetImage(nsnull);
2901 0 : }
2902 :
2903 : nsCursorImage&
2904 0 : nsCursorImage::operator=(const nsCursorImage& aOther)
2905 : {
2906 0 : if (this != &aOther) {
2907 0 : mHaveHotspot = aOther.mHaveHotspot;
2908 0 : mHotspotX = aOther.mHotspotX;
2909 0 : mHotspotY = aOther.mHotspotY;
2910 0 : SetImage(aOther.GetImage());
2911 : }
2912 :
2913 0 : return *this;
2914 : }
2915 :
2916 0 : nsStyleUserInterface::nsStyleUserInterface(void)
2917 : {
2918 0 : MOZ_COUNT_CTOR(nsStyleUserInterface);
2919 0 : mUserInput = NS_STYLE_USER_INPUT_AUTO;
2920 0 : mUserModify = NS_STYLE_USER_MODIFY_READ_ONLY;
2921 0 : mUserFocus = NS_STYLE_USER_FOCUS_NONE;
2922 :
2923 0 : mCursor = NS_STYLE_CURSOR_AUTO; // fix for bugzilla bug 51113
2924 :
2925 0 : mCursorArrayLength = 0;
2926 0 : mCursorArray = nsnull;
2927 0 : }
2928 :
2929 0 : nsStyleUserInterface::nsStyleUserInterface(const nsStyleUserInterface& aSource) :
2930 : mUserInput(aSource.mUserInput),
2931 : mUserModify(aSource.mUserModify),
2932 : mUserFocus(aSource.mUserFocus),
2933 0 : mCursor(aSource.mCursor)
2934 : {
2935 0 : MOZ_COUNT_CTOR(nsStyleUserInterface);
2936 0 : CopyCursorArrayFrom(aSource);
2937 0 : }
2938 :
2939 0 : nsStyleUserInterface::~nsStyleUserInterface(void)
2940 : {
2941 0 : MOZ_COUNT_DTOR(nsStyleUserInterface);
2942 0 : delete [] mCursorArray;
2943 0 : }
2944 :
2945 0 : nsChangeHint nsStyleUserInterface::CalcDifference(const nsStyleUserInterface& aOther) const
2946 : {
2947 0 : nsChangeHint hint = nsChangeHint(0);
2948 0 : if (mCursor != aOther.mCursor)
2949 0 : NS_UpdateHint(hint, nsChangeHint_UpdateCursor);
2950 :
2951 : // We could do better. But it wouldn't be worth it, URL-specified cursors are
2952 : // rare.
2953 0 : if (mCursorArrayLength > 0 || aOther.mCursorArrayLength > 0)
2954 0 : NS_UpdateHint(hint, nsChangeHint_UpdateCursor);
2955 :
2956 0 : if (mUserModify != aOther.mUserModify)
2957 0 : NS_UpdateHint(hint, NS_STYLE_HINT_VISUAL);
2958 :
2959 0 : if ((mUserInput != aOther.mUserInput) &&
2960 : ((NS_STYLE_USER_INPUT_NONE == mUserInput) ||
2961 : (NS_STYLE_USER_INPUT_NONE == aOther.mUserInput))) {
2962 0 : NS_UpdateHint(hint, NS_STYLE_HINT_FRAMECHANGE);
2963 : }
2964 :
2965 : // ignore mUserFocus
2966 :
2967 0 : return hint;
2968 : }
2969 :
2970 : #ifdef DEBUG
2971 : /* static */
2972 0 : nsChangeHint nsStyleUserInterface::MaxDifference()
2973 : {
2974 0 : return nsChangeHint(nsChangeHint_UpdateCursor | NS_STYLE_HINT_FRAMECHANGE);
2975 : }
2976 : #endif
2977 :
2978 : void
2979 0 : nsStyleUserInterface::CopyCursorArrayFrom(const nsStyleUserInterface& aSource)
2980 : {
2981 0 : mCursorArray = nsnull;
2982 0 : mCursorArrayLength = 0;
2983 0 : if (aSource.mCursorArrayLength) {
2984 0 : mCursorArray = new nsCursorImage[aSource.mCursorArrayLength];
2985 0 : if (mCursorArray) {
2986 0 : mCursorArrayLength = aSource.mCursorArrayLength;
2987 0 : for (PRUint32 i = 0; i < mCursorArrayLength; ++i)
2988 0 : mCursorArray[i] = aSource.mCursorArray[i];
2989 : }
2990 : }
2991 0 : }
2992 :
2993 : //-----------------------
2994 : // nsStyleUIReset
2995 : //
2996 :
2997 0 : nsStyleUIReset::nsStyleUIReset(void)
2998 : {
2999 0 : MOZ_COUNT_CTOR(nsStyleUIReset);
3000 0 : mUserSelect = NS_STYLE_USER_SELECT_AUTO;
3001 0 : mForceBrokenImageIcon = 0;
3002 0 : mIMEMode = NS_STYLE_IME_MODE_AUTO;
3003 0 : mWindowShadow = NS_STYLE_WINDOW_SHADOW_DEFAULT;
3004 0 : }
3005 :
3006 0 : nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset& aSource)
3007 : {
3008 0 : MOZ_COUNT_CTOR(nsStyleUIReset);
3009 0 : mUserSelect = aSource.mUserSelect;
3010 0 : mForceBrokenImageIcon = aSource.mForceBrokenImageIcon;
3011 0 : mIMEMode = aSource.mIMEMode;
3012 0 : mWindowShadow = aSource.mWindowShadow;
3013 0 : }
3014 :
3015 0 : nsStyleUIReset::~nsStyleUIReset(void)
3016 : {
3017 0 : MOZ_COUNT_DTOR(nsStyleUIReset);
3018 0 : }
3019 :
3020 0 : nsChangeHint nsStyleUIReset::CalcDifference(const nsStyleUIReset& aOther) const
3021 : {
3022 : // ignore mIMEMode
3023 0 : if (mForceBrokenImageIcon != aOther.mForceBrokenImageIcon)
3024 0 : return NS_STYLE_HINT_FRAMECHANGE;
3025 0 : if (mWindowShadow != aOther.mWindowShadow) {
3026 : // We really need just an nsChangeHint_SyncFrameView, except
3027 : // on an ancestor of the frame, so we get that by doing a
3028 : // reflow.
3029 0 : return NS_STYLE_HINT_REFLOW;
3030 : }
3031 0 : if (mUserSelect != aOther.mUserSelect)
3032 0 : return NS_STYLE_HINT_VISUAL;
3033 0 : return NS_STYLE_HINT_NONE;
3034 : }
3035 :
3036 : #ifdef DEBUG
3037 : /* static */
3038 0 : nsChangeHint nsStyleUIReset::MaxDifference()
3039 : {
3040 0 : return NS_STYLE_HINT_FRAMECHANGE;
3041 : }
3042 : #endif
3043 :
|