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 :
799 0 : mColumnRuleWidth = (aPresContext->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM];
800 0 : mColumnRuleStyle = NS_STYLE_BORDER_STYLE_NONE;
801 0 : mColumnRuleColor = NS_RGB(0, 0, 0);
802 0 : mColumnRuleColorIsForeground = true;
803 :
804 0 : mTwipsPerPixel = aPresContext->AppUnitsPerDevPixel();
805 0 : }
806 :
807 0 : nsStyleColumn::~nsStyleColumn()
808 : {
809 0 : MOZ_COUNT_DTOR(nsStyleColumn);
810 0 : }
811 :
812 0 : nsStyleColumn::nsStyleColumn(const nsStyleColumn& aSource)
813 : {
814 0 : MOZ_COUNT_CTOR(nsStyleColumn);
815 0 : memcpy((nsStyleColumn*)this, &aSource, sizeof(nsStyleColumn));
816 0 : }
817 :
818 0 : nsChangeHint nsStyleColumn::CalcDifference(const nsStyleColumn& aOther) const
819 : {
820 0 : if ((mColumnWidth.GetUnit() == eStyleUnit_Auto)
821 0 : != (aOther.mColumnWidth.GetUnit() == eStyleUnit_Auto) ||
822 : mColumnCount != aOther.mColumnCount)
823 : // We force column count changes to do a reframe, because it's tricky to handle
824 : // some edge cases where the column count gets smaller and content overflows.
825 : // XXX not ideal
826 0 : return NS_STYLE_HINT_FRAMECHANGE;
827 :
828 0 : if (mColumnWidth != aOther.mColumnWidth ||
829 0 : mColumnGap != aOther.mColumnGap)
830 0 : return NS_STYLE_HINT_REFLOW;
831 :
832 0 : if (GetComputedColumnRuleWidth() != aOther.GetComputedColumnRuleWidth() ||
833 : mColumnRuleStyle != aOther.mColumnRuleStyle ||
834 : mColumnRuleColor != aOther.mColumnRuleColor ||
835 : mColumnRuleColorIsForeground != aOther.mColumnRuleColorIsForeground)
836 0 : return NS_STYLE_HINT_VISUAL;
837 :
838 0 : return NS_STYLE_HINT_NONE;
839 : }
840 :
841 : #ifdef DEBUG
842 : /* static */
843 0 : nsChangeHint nsStyleColumn::MaxDifference()
844 : {
845 0 : return NS_STYLE_HINT_FRAMECHANGE;
846 : }
847 : #endif
848 :
849 : // --------------------
850 : // nsStyleSVG
851 : //
852 0 : nsStyleSVG::nsStyleSVG()
853 : {
854 0 : MOZ_COUNT_CTOR(nsStyleSVG);
855 0 : mFill.mType = eStyleSVGPaintType_Color;
856 0 : mFill.mPaint.mColor = NS_RGB(0,0,0);
857 0 : mFill.mFallbackColor = NS_RGB(0,0,0);
858 0 : mStroke.mType = eStyleSVGPaintType_None;
859 0 : mStroke.mPaint.mColor = NS_RGB(0,0,0);
860 0 : mStroke.mFallbackColor = NS_RGB(0,0,0);
861 0 : mStrokeDasharray = nsnull;
862 :
863 0 : mStrokeDashoffset.SetCoordValue(0);
864 0 : mStrokeWidth.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1));
865 :
866 0 : mFillOpacity = 1.0f;
867 0 : mStrokeMiterlimit = 4.0f;
868 0 : mStrokeOpacity = 1.0f;
869 :
870 0 : mStrokeDasharrayLength = 0;
871 0 : mClipRule = NS_STYLE_FILL_RULE_NONZERO;
872 0 : mColorInterpolation = NS_STYLE_COLOR_INTERPOLATION_SRGB;
873 0 : mColorInterpolationFilters = NS_STYLE_COLOR_INTERPOLATION_LINEARRGB;
874 0 : mFillRule = NS_STYLE_FILL_RULE_NONZERO;
875 0 : mImageRendering = NS_STYLE_IMAGE_RENDERING_AUTO;
876 0 : mShapeRendering = NS_STYLE_SHAPE_RENDERING_AUTO;
877 0 : mStrokeLinecap = NS_STYLE_STROKE_LINECAP_BUTT;
878 0 : mStrokeLinejoin = NS_STYLE_STROKE_LINEJOIN_MITER;
879 0 : mTextAnchor = NS_STYLE_TEXT_ANCHOR_START;
880 0 : mTextRendering = NS_STYLE_TEXT_RENDERING_AUTO;
881 0 : }
882 :
883 0 : nsStyleSVG::~nsStyleSVG()
884 : {
885 0 : MOZ_COUNT_DTOR(nsStyleSVG);
886 0 : delete [] mStrokeDasharray;
887 0 : }
888 :
889 0 : nsStyleSVG::nsStyleSVG(const nsStyleSVG& aSource)
890 : {
891 0 : MOZ_COUNT_CTOR(nsStyleSVG);
892 0 : mFill = aSource.mFill;
893 0 : mStroke = aSource.mStroke;
894 :
895 0 : mMarkerEnd = aSource.mMarkerEnd;
896 0 : mMarkerMid = aSource.mMarkerMid;
897 0 : mMarkerStart = aSource.mMarkerStart;
898 :
899 0 : mStrokeDasharrayLength = aSource.mStrokeDasharrayLength;
900 0 : if (aSource.mStrokeDasharray) {
901 0 : mStrokeDasharray = new nsStyleCoord[mStrokeDasharrayLength];
902 0 : if (mStrokeDasharray)
903 : memcpy(mStrokeDasharray,
904 : aSource.mStrokeDasharray,
905 0 : mStrokeDasharrayLength * sizeof(nsStyleCoord));
906 : else
907 0 : mStrokeDasharrayLength = 0;
908 : } else {
909 0 : mStrokeDasharray = nsnull;
910 : }
911 :
912 0 : mStrokeDashoffset = aSource.mStrokeDashoffset;
913 0 : mStrokeWidth = aSource.mStrokeWidth;
914 :
915 0 : mFillOpacity = aSource.mFillOpacity;
916 0 : mStrokeMiterlimit = aSource.mStrokeMiterlimit;
917 0 : mStrokeOpacity = aSource.mStrokeOpacity;
918 :
919 0 : mClipRule = aSource.mClipRule;
920 0 : mColorInterpolation = aSource.mColorInterpolation;
921 0 : mColorInterpolationFilters = aSource.mColorInterpolationFilters;
922 0 : mFillRule = aSource.mFillRule;
923 0 : mImageRendering = aSource.mImageRendering;
924 0 : mShapeRendering = aSource.mShapeRendering;
925 0 : mStrokeLinecap = aSource.mStrokeLinecap;
926 0 : mStrokeLinejoin = aSource.mStrokeLinejoin;
927 0 : mTextAnchor = aSource.mTextAnchor;
928 0 : mTextRendering = aSource.mTextRendering;
929 0 : }
930 :
931 0 : static bool PaintURIChanged(const nsStyleSVGPaint& aPaint1,
932 : const nsStyleSVGPaint& aPaint2)
933 : {
934 0 : if (aPaint1.mType != aPaint2.mType) {
935 : return aPaint1.mType == eStyleSVGPaintType_Server ||
936 0 : aPaint2.mType == eStyleSVGPaintType_Server;
937 : }
938 : return aPaint1.mType == eStyleSVGPaintType_Server &&
939 0 : !EqualURIs(aPaint1.mPaint.mPaintServer, aPaint2.mPaint.mPaintServer);
940 : }
941 :
942 0 : nsChangeHint nsStyleSVG::CalcDifference(const nsStyleSVG& aOther) const
943 : {
944 0 : nsChangeHint hint = nsChangeHint(0);
945 :
946 0 : if (mTextRendering != aOther.mTextRendering) {
947 0 : NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
948 : // May be needed for non-svg frames
949 0 : NS_UpdateHint(hint, nsChangeHint_ReflowFrame);
950 : }
951 :
952 0 : if (!EqualURIs(mMarkerEnd, aOther.mMarkerEnd) ||
953 0 : !EqualURIs(mMarkerMid, aOther.mMarkerMid) ||
954 0 : !EqualURIs(mMarkerStart, aOther.mMarkerStart)) {
955 0 : NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
956 0 : NS_UpdateHint(hint, nsChangeHint_UpdateEffects);
957 0 : return hint;
958 : }
959 :
960 0 : if (mFill != aOther.mFill ||
961 0 : mStroke != aOther.mStroke) {
962 0 : NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
963 0 : if (PaintURIChanged(mFill, aOther.mFill) ||
964 0 : PaintURIChanged(mStroke, aOther.mStroke)) {
965 0 : NS_UpdateHint(hint, nsChangeHint_UpdateEffects);
966 : }
967 : // Nothing more to do, below we can only set "repaint"
968 0 : return hint;
969 : }
970 :
971 0 : if ( mStrokeDashoffset != aOther.mStrokeDashoffset ||
972 0 : mStrokeWidth != aOther.mStrokeWidth ||
973 :
974 : mFillOpacity != aOther.mFillOpacity ||
975 : mStrokeMiterlimit != aOther.mStrokeMiterlimit ||
976 : mStrokeOpacity != aOther.mStrokeOpacity ||
977 :
978 : mClipRule != aOther.mClipRule ||
979 : mColorInterpolation != aOther.mColorInterpolation ||
980 : mColorInterpolationFilters != aOther.mColorInterpolationFilters ||
981 : mFillRule != aOther.mFillRule ||
982 : mImageRendering != aOther.mImageRendering ||
983 : mShapeRendering != aOther.mShapeRendering ||
984 : mStrokeDasharrayLength != aOther.mStrokeDasharrayLength ||
985 : mStrokeLinecap != aOther.mStrokeLinecap ||
986 : mStrokeLinejoin != aOther.mStrokeLinejoin ||
987 : mTextAnchor != aOther.mTextAnchor) {
988 0 : NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
989 0 : return hint;
990 : }
991 :
992 : // length of stroke dasharrays are the same (tested above) - check entries
993 0 : for (PRUint32 i=0; i<mStrokeDasharrayLength; i++)
994 0 : if (mStrokeDasharray[i] != aOther.mStrokeDasharray[i]) {
995 0 : NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
996 0 : return hint;
997 : }
998 :
999 0 : return hint;
1000 : }
1001 :
1002 : #ifdef DEBUG
1003 : /* static */
1004 0 : nsChangeHint nsStyleSVG::MaxDifference()
1005 : {
1006 : return NS_CombineHint(NS_CombineHint(nsChangeHint_UpdateEffects,
1007 : nsChangeHint_ReflowFrame),
1008 0 : nsChangeHint_RepaintFrame);
1009 : }
1010 : #endif
1011 :
1012 : // --------------------
1013 : // nsStyleSVGReset
1014 : //
1015 0 : nsStyleSVGReset::nsStyleSVGReset()
1016 : {
1017 0 : MOZ_COUNT_CTOR(nsStyleSVGReset);
1018 0 : mStopColor = NS_RGB(0,0,0);
1019 0 : mFloodColor = NS_RGB(0,0,0);
1020 0 : mLightingColor = NS_RGB(255,255,255);
1021 0 : mClipPath = nsnull;
1022 0 : mFilter = nsnull;
1023 0 : mMask = nsnull;
1024 0 : mStopOpacity = 1.0f;
1025 0 : mFloodOpacity = 1.0f;
1026 0 : mDominantBaseline = NS_STYLE_DOMINANT_BASELINE_AUTO;
1027 0 : }
1028 :
1029 0 : nsStyleSVGReset::~nsStyleSVGReset()
1030 : {
1031 0 : MOZ_COUNT_DTOR(nsStyleSVGReset);
1032 0 : }
1033 :
1034 0 : nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset& aSource)
1035 : {
1036 0 : MOZ_COUNT_CTOR(nsStyleSVGReset);
1037 0 : mStopColor = aSource.mStopColor;
1038 0 : mFloodColor = aSource.mFloodColor;
1039 0 : mLightingColor = aSource.mLightingColor;
1040 0 : mClipPath = aSource.mClipPath;
1041 0 : mFilter = aSource.mFilter;
1042 0 : mMask = aSource.mMask;
1043 0 : mStopOpacity = aSource.mStopOpacity;
1044 0 : mFloodOpacity = aSource.mFloodOpacity;
1045 0 : mDominantBaseline = aSource.mDominantBaseline;
1046 0 : }
1047 :
1048 0 : nsChangeHint nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aOther) const
1049 : {
1050 0 : nsChangeHint hint = nsChangeHint(0);
1051 :
1052 0 : if (!EqualURIs(mClipPath, aOther.mClipPath) ||
1053 0 : !EqualURIs(mFilter, aOther.mFilter) ||
1054 0 : !EqualURIs(mMask, aOther.mMask)) {
1055 0 : NS_UpdateHint(hint, nsChangeHint_UpdateEffects);
1056 0 : NS_UpdateHint(hint, nsChangeHint_ReflowFrame);
1057 0 : NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
1058 0 : } else if (mStopColor != aOther.mStopColor ||
1059 : mFloodColor != aOther.mFloodColor ||
1060 : mLightingColor != aOther.mLightingColor ||
1061 : mStopOpacity != aOther.mStopOpacity ||
1062 : mFloodOpacity != aOther.mFloodOpacity ||
1063 : mDominantBaseline != aOther.mDominantBaseline)
1064 0 : NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
1065 :
1066 0 : return hint;
1067 : }
1068 :
1069 : #ifdef DEBUG
1070 : /* static */
1071 0 : nsChangeHint nsStyleSVGReset::MaxDifference()
1072 : {
1073 : return NS_CombineHint(NS_CombineHint(nsChangeHint_UpdateEffects,
1074 : nsChangeHint_ReflowFrame),
1075 0 : nsChangeHint_RepaintFrame);
1076 : }
1077 : #endif
1078 :
1079 : // nsStyleSVGPaint implementation
1080 0 : nsStyleSVGPaint::~nsStyleSVGPaint()
1081 : {
1082 0 : if (mType == eStyleSVGPaintType_Server) {
1083 0 : NS_IF_RELEASE(mPaint.mPaintServer);
1084 : }
1085 0 : }
1086 :
1087 : void
1088 0 : nsStyleSVGPaint::SetType(nsStyleSVGPaintType aType)
1089 : {
1090 0 : if (mType == eStyleSVGPaintType_Server) {
1091 0 : this->~nsStyleSVGPaint();
1092 0 : new (this) nsStyleSVGPaint();
1093 : }
1094 0 : mType = aType;
1095 0 : }
1096 :
1097 0 : nsStyleSVGPaint& nsStyleSVGPaint::operator=(const nsStyleSVGPaint& aOther)
1098 : {
1099 0 : if (this == &aOther)
1100 0 : return *this;
1101 :
1102 0 : SetType(aOther.mType);
1103 :
1104 0 : mFallbackColor = aOther.mFallbackColor;
1105 0 : if (mType == eStyleSVGPaintType_Server) {
1106 0 : mPaint.mPaintServer = aOther.mPaint.mPaintServer;
1107 0 : NS_IF_ADDREF(mPaint.mPaintServer);
1108 : } else {
1109 0 : mPaint.mColor = aOther.mPaint.mColor;
1110 : }
1111 0 : return *this;
1112 : }
1113 :
1114 0 : bool nsStyleSVGPaint::operator==(const nsStyleSVGPaint& aOther) const
1115 : {
1116 0 : if (mType != aOther.mType)
1117 0 : return false;
1118 0 : if (mType == eStyleSVGPaintType_Server)
1119 0 : return EqualURIs(mPaint.mPaintServer, aOther.mPaint.mPaintServer) &&
1120 0 : mFallbackColor == aOther.mFallbackColor;
1121 0 : if (mType == eStyleSVGPaintType_None)
1122 0 : return true;
1123 0 : return mPaint.mColor == aOther.mPaint.mColor;
1124 : }
1125 :
1126 :
1127 : // --------------------
1128 : // nsStylePosition
1129 : //
1130 0 : nsStylePosition::nsStylePosition(void)
1131 : {
1132 0 : MOZ_COUNT_CTOR(nsStylePosition);
1133 : // positioning values not inherited
1134 0 : nsStyleCoord autoCoord(eStyleUnit_Auto);
1135 0 : mOffset.SetLeft(autoCoord);
1136 0 : mOffset.SetTop(autoCoord);
1137 0 : mOffset.SetRight(autoCoord);
1138 0 : mOffset.SetBottom(autoCoord);
1139 0 : mWidth.SetAutoValue();
1140 0 : mMinWidth.SetCoordValue(0);
1141 0 : mMaxWidth.SetNoneValue();
1142 0 : mHeight.SetAutoValue();
1143 0 : mMinHeight.SetCoordValue(0);
1144 0 : mMaxHeight.SetNoneValue();
1145 0 : mBoxSizing = NS_STYLE_BOX_SIZING_CONTENT;
1146 0 : mZIndex.SetAutoValue();
1147 0 : }
1148 :
1149 0 : nsStylePosition::~nsStylePosition(void)
1150 : {
1151 0 : MOZ_COUNT_DTOR(nsStylePosition);
1152 0 : }
1153 :
1154 0 : nsStylePosition::nsStylePosition(const nsStylePosition& aSource)
1155 : {
1156 0 : MOZ_COUNT_CTOR(nsStylePosition);
1157 0 : memcpy((nsStylePosition*)this, &aSource, sizeof(nsStylePosition));
1158 0 : }
1159 :
1160 0 : nsChangeHint nsStylePosition::CalcDifference(const nsStylePosition& aOther) const
1161 : {
1162 : nsChangeHint hint =
1163 0 : (mZIndex == aOther.mZIndex) ? NS_STYLE_HINT_NONE : nsChangeHint_RepaintFrame;
1164 :
1165 0 : if (mBoxSizing != aOther.mBoxSizing) {
1166 : // Can affect both widths and heights; just a bad scene.
1167 0 : return NS_CombineHint(hint, nsChangeHint_ReflowFrame);
1168 : }
1169 :
1170 0 : if (mHeight != aOther.mHeight ||
1171 0 : mMinHeight != aOther.mMinHeight ||
1172 0 : mMaxHeight != aOther.mMaxHeight) {
1173 : // Height changes can affect descendant intrinsic sizes due to replaced
1174 : // elements with percentage heights in descendants which also have
1175 : // percentage heights. And due to our not-so-great computation of mVResize
1176 : // in nsHTMLReflowState, they do need to force reflow of the whole subtree.
1177 : // XXXbz due to XUL caching heights as well, height changes also need to
1178 : // clear ancestor intrinsics!
1179 0 : return NS_CombineHint(hint, nsChangeHint_ReflowFrame);
1180 : }
1181 :
1182 0 : if ((mWidth == aOther.mWidth) &&
1183 0 : (mMinWidth == aOther.mMinWidth) &&
1184 0 : (mMaxWidth == aOther.mMaxWidth)) {
1185 0 : if (mOffset == aOther.mOffset) {
1186 0 : return hint;
1187 : } else {
1188 : // Offset changes only affect positioned content, and can't affect any
1189 : // intrinsic widths. They also don't need to force reflow of
1190 : // descendants.
1191 0 : return NS_CombineHint(hint, nsChangeHint_NeedReflow);
1192 : }
1193 : }
1194 :
1195 : // None of our width differences can affect descendant intrinsic
1196 : // sizes and none of them need to force children to reflow.
1197 : return
1198 : NS_CombineHint(hint,
1199 : NS_SubtractHint(nsChangeHint_ReflowFrame,
1200 : NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics,
1201 0 : nsChangeHint_NeedDirtyReflow)));
1202 : }
1203 :
1204 : #ifdef DEBUG
1205 : /* static */
1206 0 : nsChangeHint nsStylePosition::MaxDifference()
1207 : {
1208 0 : return NS_STYLE_HINT_REFLOW;
1209 : }
1210 : #endif
1211 :
1212 : /* static */ bool
1213 0 : nsStylePosition::WidthCoordDependsOnContainer(const nsStyleCoord &aCoord)
1214 : {
1215 0 : return aCoord.GetUnit() == eStyleUnit_Auto ||
1216 0 : aCoord.HasPercent() ||
1217 0 : (aCoord.GetUnit() == eStyleUnit_Enumerated &&
1218 0 : (aCoord.GetIntValue() == NS_STYLE_WIDTH_FIT_CONTENT ||
1219 0 : aCoord.GetIntValue() == NS_STYLE_WIDTH_AVAILABLE));
1220 : }
1221 :
1222 : // --------------------
1223 : // nsStyleTable
1224 : //
1225 :
1226 0 : nsStyleTable::nsStyleTable()
1227 : {
1228 0 : MOZ_COUNT_CTOR(nsStyleTable);
1229 : // values not inherited
1230 0 : mLayoutStrategy = NS_STYLE_TABLE_LAYOUT_AUTO;
1231 0 : mCols = NS_STYLE_TABLE_COLS_NONE;
1232 0 : mFrame = NS_STYLE_TABLE_FRAME_NONE;
1233 0 : mRules = NS_STYLE_TABLE_RULES_NONE;
1234 0 : mSpan = 1;
1235 0 : }
1236 :
1237 0 : nsStyleTable::~nsStyleTable(void)
1238 : {
1239 0 : MOZ_COUNT_DTOR(nsStyleTable);
1240 0 : }
1241 :
1242 0 : nsStyleTable::nsStyleTable(const nsStyleTable& aSource)
1243 : {
1244 0 : MOZ_COUNT_CTOR(nsStyleTable);
1245 0 : memcpy((nsStyleTable*)this, &aSource, sizeof(nsStyleTable));
1246 0 : }
1247 :
1248 0 : nsChangeHint nsStyleTable::CalcDifference(const nsStyleTable& aOther) const
1249 : {
1250 : // Changes in mRules may require reframing (if border-collapse stuff changes, for example).
1251 0 : if (mRules != aOther.mRules || mSpan != aOther.mSpan ||
1252 : mLayoutStrategy != aOther.mLayoutStrategy)
1253 0 : return NS_STYLE_HINT_FRAMECHANGE;
1254 0 : if (mFrame != aOther.mFrame || mCols != aOther.mCols)
1255 0 : return NS_STYLE_HINT_REFLOW;
1256 0 : return NS_STYLE_HINT_NONE;
1257 : }
1258 :
1259 : #ifdef DEBUG
1260 : /* static */
1261 0 : nsChangeHint nsStyleTable::MaxDifference()
1262 : {
1263 0 : return NS_STYLE_HINT_FRAMECHANGE;
1264 : }
1265 : #endif
1266 :
1267 : // -----------------------
1268 : // nsStyleTableBorder
1269 :
1270 0 : nsStyleTableBorder::nsStyleTableBorder(nsPresContext* aPresContext)
1271 : {
1272 0 : MOZ_COUNT_CTOR(nsStyleTableBorder);
1273 0 : mBorderCollapse = NS_STYLE_BORDER_SEPARATE;
1274 :
1275 0 : nsCompatibility compatMode = eCompatibility_FullStandards;
1276 0 : if (aPresContext)
1277 0 : compatMode = aPresContext->CompatibilityMode();
1278 : mEmptyCells = (compatMode == eCompatibility_NavQuirks)
1279 : ? NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND
1280 0 : : NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
1281 0 : mCaptionSide = NS_STYLE_CAPTION_SIDE_TOP;
1282 0 : mBorderSpacingX = 0;
1283 0 : mBorderSpacingY = 0;
1284 0 : }
1285 :
1286 0 : nsStyleTableBorder::~nsStyleTableBorder(void)
1287 : {
1288 0 : MOZ_COUNT_DTOR(nsStyleTableBorder);
1289 0 : }
1290 :
1291 0 : nsStyleTableBorder::nsStyleTableBorder(const nsStyleTableBorder& aSource)
1292 : {
1293 0 : MOZ_COUNT_CTOR(nsStyleTableBorder);
1294 0 : memcpy((nsStyleTableBorder*)this, &aSource, sizeof(nsStyleTableBorder));
1295 0 : }
1296 :
1297 0 : nsChangeHint nsStyleTableBorder::CalcDifference(const nsStyleTableBorder& aOther) const
1298 : {
1299 : // Border-collapse changes need a reframe, because we use a different frame
1300 : // class for table cells in the collapsed border model. This is used to
1301 : // conserve memory when using the separated border model (collapsed borders
1302 : // require extra state to be stored).
1303 0 : if (mBorderCollapse != aOther.mBorderCollapse) {
1304 0 : return NS_STYLE_HINT_FRAMECHANGE;
1305 : }
1306 :
1307 0 : if ((mCaptionSide == aOther.mCaptionSide) &&
1308 : (mBorderSpacingX == aOther.mBorderSpacingX) &&
1309 : (mBorderSpacingY == aOther.mBorderSpacingY)) {
1310 0 : if (mEmptyCells == aOther.mEmptyCells)
1311 0 : return NS_STYLE_HINT_NONE;
1312 0 : return NS_STYLE_HINT_VISUAL;
1313 : }
1314 : else
1315 0 : return NS_STYLE_HINT_REFLOW;
1316 : }
1317 :
1318 : #ifdef DEBUG
1319 : /* static */
1320 0 : nsChangeHint nsStyleTableBorder::MaxDifference()
1321 : {
1322 0 : return NS_STYLE_HINT_FRAMECHANGE;
1323 : }
1324 : #endif
1325 :
1326 : // --------------------
1327 : // nsStyleColor
1328 : //
1329 :
1330 0 : nsStyleColor::nsStyleColor(nsPresContext* aPresContext)
1331 : {
1332 0 : MOZ_COUNT_CTOR(nsStyleColor);
1333 0 : mColor = aPresContext->DefaultColor();
1334 0 : }
1335 :
1336 0 : nsStyleColor::nsStyleColor(const nsStyleColor& aSource)
1337 : {
1338 0 : MOZ_COUNT_CTOR(nsStyleColor);
1339 0 : mColor = aSource.mColor;
1340 0 : }
1341 :
1342 0 : nsChangeHint nsStyleColor::CalcDifference(const nsStyleColor& aOther) const
1343 : {
1344 0 : if (mColor == aOther.mColor)
1345 0 : return NS_STYLE_HINT_NONE;
1346 0 : return NS_STYLE_HINT_VISUAL;
1347 : }
1348 :
1349 : #ifdef DEBUG
1350 : /* static */
1351 0 : nsChangeHint nsStyleColor::MaxDifference()
1352 : {
1353 0 : return NS_STYLE_HINT_VISUAL;
1354 : }
1355 : #endif
1356 :
1357 : // --------------------
1358 : // nsStyleGradient
1359 : //
1360 : bool
1361 0 : nsStyleGradient::operator==(const nsStyleGradient& aOther) const
1362 : {
1363 0 : NS_ABORT_IF_FALSE(mSize == NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER ||
1364 : mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR,
1365 : "incorrect combination of shape and size");
1366 0 : NS_ABORT_IF_FALSE(aOther.mSize == NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER ||
1367 : aOther.mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR,
1368 : "incorrect combination of shape and size");
1369 :
1370 0 : if (mShape != aOther.mShape ||
1371 : mSize != aOther.mSize ||
1372 : mRepeating != aOther.mRepeating ||
1373 : mToCorner != aOther.mToCorner ||
1374 0 : mBgPosX != aOther.mBgPosX ||
1375 0 : mBgPosY != aOther.mBgPosY ||
1376 0 : mAngle != aOther.mAngle)
1377 0 : return false;
1378 :
1379 0 : if (mStops.Length() != aOther.mStops.Length())
1380 0 : return false;
1381 :
1382 0 : for (PRUint32 i = 0; i < mStops.Length(); i++) {
1383 0 : if (mStops[i].mLocation != aOther.mStops[i].mLocation ||
1384 0 : mStops[i].mColor != aOther.mStops[i].mColor)
1385 0 : return false;
1386 : }
1387 :
1388 0 : return true;
1389 : }
1390 :
1391 0 : nsStyleGradient::nsStyleGradient(void)
1392 : : mShape(NS_STYLE_GRADIENT_SHAPE_LINEAR)
1393 : , mSize(NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER)
1394 : , mRepeating(false)
1395 0 : , mToCorner(false)
1396 : {
1397 0 : }
1398 :
1399 : bool
1400 0 : nsStyleGradient::IsOpaque()
1401 : {
1402 0 : for (PRUint32 i = 0; i < mStops.Length(); i++) {
1403 0 : if (NS_GET_A(mStops[i].mColor) < 255)
1404 0 : return false;
1405 : }
1406 0 : return true;
1407 : }
1408 :
1409 : // --------------------
1410 : // nsStyleImage
1411 : //
1412 :
1413 0 : nsStyleImage::nsStyleImage()
1414 : : mType(eStyleImageType_Null)
1415 : , mCropRect(nsnull)
1416 : #ifdef DEBUG
1417 0 : , mImageTracked(false)
1418 : #endif
1419 : {
1420 0 : MOZ_COUNT_CTOR(nsStyleImage);
1421 0 : }
1422 :
1423 0 : nsStyleImage::~nsStyleImage()
1424 : {
1425 0 : MOZ_COUNT_DTOR(nsStyleImage);
1426 0 : if (mType != eStyleImageType_Null)
1427 0 : SetNull();
1428 0 : }
1429 :
1430 0 : nsStyleImage::nsStyleImage(const nsStyleImage& aOther)
1431 : : mType(eStyleImageType_Null)
1432 : , mCropRect(nsnull)
1433 : #ifdef DEBUG
1434 0 : , mImageTracked(false)
1435 : #endif
1436 : {
1437 : // We need our own copy constructor because we don't want
1438 : // to copy the reference count
1439 0 : MOZ_COUNT_CTOR(nsStyleImage);
1440 0 : DoCopy(aOther);
1441 0 : }
1442 :
1443 : nsStyleImage&
1444 0 : nsStyleImage::operator=(const nsStyleImage& aOther)
1445 : {
1446 0 : if (this != &aOther)
1447 0 : DoCopy(aOther);
1448 :
1449 0 : return *this;
1450 : }
1451 :
1452 : void
1453 0 : nsStyleImage::DoCopy(const nsStyleImage& aOther)
1454 : {
1455 0 : SetNull();
1456 :
1457 0 : if (aOther.mType == eStyleImageType_Image)
1458 0 : SetImageData(aOther.mImage);
1459 0 : else if (aOther.mType == eStyleImageType_Gradient)
1460 0 : SetGradientData(aOther.mGradient);
1461 0 : else if (aOther.mType == eStyleImageType_Element)
1462 0 : SetElementId(aOther.mElementId);
1463 :
1464 0 : SetCropRect(aOther.mCropRect);
1465 0 : }
1466 :
1467 : void
1468 0 : nsStyleImage::SetNull()
1469 : {
1470 0 : NS_ABORT_IF_FALSE(!mImageTracked,
1471 : "Calling SetNull() with image tracked!");
1472 :
1473 0 : if (mType == eStyleImageType_Gradient)
1474 0 : mGradient->Release();
1475 0 : else if (mType == eStyleImageType_Image)
1476 0 : NS_RELEASE(mImage);
1477 0 : else if (mType == eStyleImageType_Element)
1478 0 : NS_Free(mElementId);
1479 :
1480 0 : mType = eStyleImageType_Null;
1481 0 : mCropRect = nsnull;
1482 0 : }
1483 :
1484 : void
1485 0 : nsStyleImage::SetImageData(imgIRequest* aImage)
1486 : {
1487 0 : NS_ABORT_IF_FALSE(!mImageTracked,
1488 : "Setting a new image without untracking the old one!");
1489 :
1490 0 : NS_IF_ADDREF(aImage);
1491 :
1492 0 : if (mType != eStyleImageType_Null)
1493 0 : SetNull();
1494 :
1495 0 : if (aImage) {
1496 0 : mImage = aImage;
1497 0 : mType = eStyleImageType_Image;
1498 : }
1499 0 : }
1500 :
1501 : void
1502 0 : nsStyleImage::TrackImage(nsPresContext* aContext)
1503 : {
1504 : // Sanity
1505 0 : NS_ABORT_IF_FALSE(!mImageTracked, "Already tracking image!");
1506 0 : NS_ABORT_IF_FALSE(mType == eStyleImageType_Image,
1507 : "Can't track image when there isn't one!");
1508 :
1509 : // Register the image with the document
1510 0 : nsIDocument* doc = aContext->Document();
1511 0 : if (doc)
1512 0 : doc->AddImage(mImage);
1513 :
1514 : // Mark state
1515 : #ifdef DEBUG
1516 0 : mImageTracked = true;
1517 : #endif
1518 0 : }
1519 :
1520 : void
1521 0 : nsStyleImage::UntrackImage(nsPresContext* aContext)
1522 : {
1523 : // Sanity
1524 0 : NS_ABORT_IF_FALSE(mImageTracked, "Image not tracked!");
1525 0 : NS_ABORT_IF_FALSE(mType == eStyleImageType_Image,
1526 : "Can't untrack image when there isn't one!");
1527 :
1528 : // Unregister the image with the document
1529 0 : nsIDocument* doc = aContext->Document();
1530 0 : if (doc)
1531 0 : doc->RemoveImage(mImage);
1532 :
1533 : // Mark state
1534 : #ifdef DEBUG
1535 0 : mImageTracked = false;
1536 : #endif
1537 0 : }
1538 :
1539 : void
1540 0 : nsStyleImage::SetGradientData(nsStyleGradient* aGradient)
1541 : {
1542 0 : if (aGradient)
1543 0 : aGradient->AddRef();
1544 :
1545 0 : if (mType != eStyleImageType_Null)
1546 0 : SetNull();
1547 :
1548 0 : if (aGradient) {
1549 0 : mGradient = aGradient;
1550 0 : mType = eStyleImageType_Gradient;
1551 : }
1552 0 : }
1553 :
1554 : void
1555 0 : nsStyleImage::SetElementId(const PRUnichar* aElementId)
1556 : {
1557 0 : if (mType != eStyleImageType_Null)
1558 0 : SetNull();
1559 :
1560 0 : if (aElementId) {
1561 0 : mElementId = NS_strdup(aElementId);
1562 0 : mType = eStyleImageType_Element;
1563 : }
1564 0 : }
1565 :
1566 : void
1567 0 : nsStyleImage::SetCropRect(nsStyleSides* aCropRect)
1568 : {
1569 0 : if (aCropRect) {
1570 0 : mCropRect = new nsStyleSides(*aCropRect);
1571 : // There is really not much we can do if 'new' fails
1572 : } else {
1573 0 : mCropRect = nsnull;
1574 : }
1575 0 : }
1576 :
1577 : static PRInt32
1578 0 : ConvertToPixelCoord(const nsStyleCoord& aCoord, PRInt32 aPercentScale)
1579 : {
1580 : double pixelValue;
1581 0 : switch (aCoord.GetUnit()) {
1582 : case eStyleUnit_Percent:
1583 0 : pixelValue = aCoord.GetPercentValue() * aPercentScale;
1584 0 : break;
1585 : case eStyleUnit_Factor:
1586 0 : pixelValue = aCoord.GetFactorValue();
1587 0 : break;
1588 : default:
1589 0 : NS_NOTREACHED("unexpected unit for image crop rect");
1590 0 : return 0;
1591 : }
1592 0 : NS_ABORT_IF_FALSE(pixelValue >= 0, "we ensured non-negative while parsing");
1593 0 : pixelValue = NS_MIN(pixelValue, double(PR_INT32_MAX)); // avoid overflow
1594 0 : return NS_lround(pixelValue);
1595 : }
1596 :
1597 : bool
1598 0 : nsStyleImage::ComputeActualCropRect(nsIntRect& aActualCropRect,
1599 : bool* aIsEntireImage) const
1600 : {
1601 0 : if (mType != eStyleImageType_Image)
1602 0 : return false;
1603 :
1604 0 : nsCOMPtr<imgIContainer> imageContainer;
1605 0 : mImage->GetImage(getter_AddRefs(imageContainer));
1606 0 : if (!imageContainer)
1607 0 : return false;
1608 :
1609 0 : nsIntSize imageSize;
1610 0 : imageContainer->GetWidth(&imageSize.width);
1611 0 : imageContainer->GetHeight(&imageSize.height);
1612 0 : if (imageSize.width <= 0 || imageSize.height <= 0)
1613 0 : return false;
1614 :
1615 0 : PRInt32 left = ConvertToPixelCoord(mCropRect->GetLeft(), imageSize.width);
1616 0 : PRInt32 top = ConvertToPixelCoord(mCropRect->GetTop(), imageSize.height);
1617 0 : PRInt32 right = ConvertToPixelCoord(mCropRect->GetRight(), imageSize.width);
1618 0 : PRInt32 bottom = ConvertToPixelCoord(mCropRect->GetBottom(), imageSize.height);
1619 :
1620 : // IntersectRect() returns an empty rect if we get negative width or height
1621 0 : nsIntRect cropRect(left, top, right - left, bottom - top);
1622 0 : nsIntRect imageRect(nsIntPoint(0, 0), imageSize);
1623 0 : aActualCropRect.IntersectRect(imageRect, cropRect);
1624 :
1625 0 : if (aIsEntireImage)
1626 0 : *aIsEntireImage = aActualCropRect.IsEqualInterior(imageRect);
1627 0 : return true;
1628 : }
1629 :
1630 : nsresult
1631 0 : nsStyleImage::RequestDecode() const
1632 : {
1633 0 : if ((mType == eStyleImageType_Image) && mImage)
1634 0 : return mImage->RequestDecode();
1635 0 : return NS_OK;
1636 : }
1637 :
1638 : bool
1639 0 : nsStyleImage::IsOpaque() const
1640 : {
1641 0 : if (!IsComplete())
1642 0 : return false;
1643 :
1644 0 : if (mType == eStyleImageType_Gradient)
1645 0 : return mGradient->IsOpaque();
1646 :
1647 0 : if (mType == eStyleImageType_Element)
1648 0 : return false;
1649 :
1650 0 : NS_ABORT_IF_FALSE(mType == eStyleImageType_Image, "unexpected image type");
1651 :
1652 0 : nsCOMPtr<imgIContainer> imageContainer;
1653 0 : mImage->GetImage(getter_AddRefs(imageContainer));
1654 0 : NS_ABORT_IF_FALSE(imageContainer, "IsComplete() said image container is ready");
1655 :
1656 : // Check if the crop region of the current image frame is opaque
1657 : bool isOpaque;
1658 0 : if (NS_SUCCEEDED(imageContainer->GetCurrentFrameIsOpaque(&isOpaque)) &&
1659 : isOpaque) {
1660 0 : if (!mCropRect)
1661 0 : return true;
1662 :
1663 : // Must make sure if mCropRect contains at least a pixel.
1664 : // XXX Is this optimization worth it? Maybe I should just return false.
1665 0 : nsIntRect actualCropRect;
1666 0 : bool rv = ComputeActualCropRect(actualCropRect);
1667 0 : NS_ASSERTION(rv, "ComputeActualCropRect() can not fail here");
1668 0 : return rv && !actualCropRect.IsEmpty();
1669 : }
1670 :
1671 0 : return false;
1672 : }
1673 :
1674 : bool
1675 0 : nsStyleImage::IsComplete() const
1676 : {
1677 0 : switch (mType) {
1678 : case eStyleImageType_Null:
1679 0 : return false;
1680 : case eStyleImageType_Gradient:
1681 : case eStyleImageType_Element:
1682 0 : return true;
1683 : case eStyleImageType_Image:
1684 : {
1685 0 : PRUint32 status = imgIRequest::STATUS_ERROR;
1686 0 : return NS_SUCCEEDED(mImage->GetImageStatus(&status)) &&
1687 : (status & imgIRequest::STATUS_SIZE_AVAILABLE) &&
1688 0 : (status & imgIRequest::STATUS_FRAME_COMPLETE);
1689 : }
1690 : default:
1691 0 : NS_NOTREACHED("unexpected image type");
1692 0 : return false;
1693 : }
1694 : }
1695 :
1696 : static inline bool
1697 0 : EqualRects(const nsStyleSides* aRect1, const nsStyleSides* aRect2)
1698 : {
1699 : return aRect1 == aRect2 || /* handles null== null, and optimize */
1700 0 : (aRect1 && aRect2 && *aRect1 == *aRect2);
1701 : }
1702 :
1703 : bool
1704 0 : nsStyleImage::operator==(const nsStyleImage& aOther) const
1705 : {
1706 0 : if (mType != aOther.mType)
1707 0 : return false;
1708 :
1709 0 : if (!EqualRects(mCropRect, aOther.mCropRect))
1710 0 : return false;
1711 :
1712 0 : if (mType == eStyleImageType_Image)
1713 0 : return EqualImages(mImage, aOther.mImage);
1714 :
1715 0 : if (mType == eStyleImageType_Gradient)
1716 0 : return *mGradient == *aOther.mGradient;
1717 :
1718 0 : if (mType == eStyleImageType_Element)
1719 0 : return NS_strcmp(mElementId, aOther.mElementId) == 0;
1720 :
1721 0 : return true;
1722 : }
1723 :
1724 : // --------------------
1725 : // nsStyleBackground
1726 : //
1727 :
1728 0 : nsStyleBackground::nsStyleBackground()
1729 : : mAttachmentCount(1)
1730 : , mClipCount(1)
1731 : , mOriginCount(1)
1732 : , mRepeatCount(1)
1733 : , mPositionCount(1)
1734 : , mImageCount(1)
1735 : , mSizeCount(1)
1736 : , mBackgroundColor(NS_RGBA(0, 0, 0, 0))
1737 0 : , mBackgroundInlinePolicy(NS_STYLE_BG_INLINE_POLICY_CONTINUOUS)
1738 : {
1739 0 : MOZ_COUNT_CTOR(nsStyleBackground);
1740 0 : Layer *onlyLayer = mLayers.AppendElement();
1741 0 : NS_ASSERTION(onlyLayer, "auto array must have room for 1 element");
1742 0 : onlyLayer->SetInitialValues();
1743 0 : }
1744 :
1745 0 : nsStyleBackground::nsStyleBackground(const nsStyleBackground& aSource)
1746 : : mAttachmentCount(aSource.mAttachmentCount)
1747 : , mClipCount(aSource.mClipCount)
1748 : , mOriginCount(aSource.mOriginCount)
1749 : , mRepeatCount(aSource.mRepeatCount)
1750 : , mPositionCount(aSource.mPositionCount)
1751 : , mImageCount(aSource.mImageCount)
1752 : , mSizeCount(aSource.mSizeCount)
1753 : , mLayers(aSource.mLayers) // deep copy
1754 : , mBackgroundColor(aSource.mBackgroundColor)
1755 0 : , mBackgroundInlinePolicy(aSource.mBackgroundInlinePolicy)
1756 : {
1757 0 : MOZ_COUNT_CTOR(nsStyleBackground);
1758 : // If the deep copy of mLayers failed, truncate the counts.
1759 0 : PRUint32 count = mLayers.Length();
1760 0 : if (count != aSource.mLayers.Length()) {
1761 0 : NS_WARNING("truncating counts due to out-of-memory");
1762 0 : mAttachmentCount = NS_MAX(mAttachmentCount, count);
1763 0 : mClipCount = NS_MAX(mClipCount, count);
1764 0 : mOriginCount = NS_MAX(mOriginCount, count);
1765 0 : mRepeatCount = NS_MAX(mRepeatCount, count);
1766 0 : mPositionCount = NS_MAX(mPositionCount, count);
1767 0 : mImageCount = NS_MAX(mImageCount, count);
1768 0 : mSizeCount = NS_MAX(mSizeCount, count);
1769 : }
1770 0 : }
1771 :
1772 0 : nsStyleBackground::~nsStyleBackground()
1773 : {
1774 0 : MOZ_COUNT_DTOR(nsStyleBackground);
1775 0 : }
1776 :
1777 : void
1778 0 : nsStyleBackground::Destroy(nsPresContext* aContext)
1779 : {
1780 : // Untrack all the images stored in our layers
1781 0 : for (PRUint32 i = 0; i < mImageCount; ++i)
1782 0 : mLayers[i].UntrackImages(aContext);
1783 :
1784 0 : this->~nsStyleBackground();
1785 0 : aContext->FreeToShell(sizeof(nsStyleBackground), this);
1786 0 : }
1787 :
1788 0 : nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther) const
1789 : {
1790 : const nsStyleBackground* moreLayers =
1791 0 : mImageCount > aOther.mImageCount ? this : &aOther;
1792 : const nsStyleBackground* lessLayers =
1793 0 : mImageCount > aOther.mImageCount ? &aOther : this;
1794 :
1795 0 : bool hasVisualDifference = false;
1796 :
1797 0 : NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, moreLayers) {
1798 0 : if (i < lessLayers->mImageCount) {
1799 0 : if (moreLayers->mLayers[i] != lessLayers->mLayers[i]) {
1800 0 : if ((moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element) ||
1801 0 : (lessLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element))
1802 0 : return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL);
1803 0 : hasVisualDifference = true;
1804 : }
1805 : } else {
1806 0 : if (moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element)
1807 0 : return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL);
1808 0 : hasVisualDifference = true;
1809 : }
1810 : }
1811 :
1812 0 : if (hasVisualDifference ||
1813 : mBackgroundColor != aOther.mBackgroundColor ||
1814 : mBackgroundInlinePolicy != aOther.mBackgroundInlinePolicy)
1815 0 : return NS_STYLE_HINT_VISUAL;
1816 :
1817 0 : return NS_STYLE_HINT_NONE;
1818 : }
1819 :
1820 : #ifdef DEBUG
1821 : /* static */
1822 0 : nsChangeHint nsStyleBackground::MaxDifference()
1823 : {
1824 0 : return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL);
1825 : }
1826 : #endif
1827 :
1828 0 : bool nsStyleBackground::HasFixedBackground() const
1829 : {
1830 0 : NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, this) {
1831 0 : const Layer &layer = mLayers[i];
1832 0 : if (layer.mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
1833 0 : !layer.mImage.IsEmpty()) {
1834 0 : return true;
1835 : }
1836 : }
1837 0 : return false;
1838 : }
1839 :
1840 0 : bool nsStyleBackground::IsTransparent() const
1841 : {
1842 0 : return BottomLayer().mImage.IsEmpty() &&
1843 : mImageCount == 1 &&
1844 0 : NS_GET_A(mBackgroundColor) == 0;
1845 : }
1846 :
1847 : void
1848 0 : nsStyleBackground::Position::SetInitialValues()
1849 : {
1850 : // Initial value is "0% 0%"
1851 0 : mXPosition.mPercent = 0.0f;
1852 0 : mXPosition.mLength = 0;
1853 0 : mXPosition.mHasPercent = true;
1854 0 : mYPosition.mPercent = 0.0f;
1855 0 : mYPosition.mLength = 0;
1856 0 : mYPosition.mHasPercent = true;
1857 0 : }
1858 :
1859 : bool
1860 0 : nsStyleBackground::Size::DependsOnFrameSize(const nsStyleImage& aImage) const
1861 : {
1862 0 : NS_ABORT_IF_FALSE(aImage.GetType() != eStyleImageType_Null,
1863 : "caller should have handled this");
1864 :
1865 : // If either dimension contains a non-zero percentage, rendering for that
1866 : // dimension straightforwardly depends on frame size.
1867 0 : if ((mWidthType == eLengthPercentage && mWidth.mPercent != 0.0f) ||
1868 : (mHeightType == eLengthPercentage && mHeight.mPercent != 0.0f)) {
1869 0 : return true;
1870 : }
1871 :
1872 : // So too for contain and cover.
1873 0 : if (mWidthType == eContain || mWidthType == eCover) {
1874 0 : return true;
1875 : }
1876 :
1877 : // If both dimensions are fixed lengths, there's no dependency.
1878 0 : if (mWidthType == eLengthPercentage && mHeightType == eLengthPercentage) {
1879 0 : return false;
1880 : }
1881 :
1882 0 : NS_ABORT_IF_FALSE((mWidthType == eLengthPercentage && mHeightType == eAuto) ||
1883 : (mWidthType == eAuto && mHeightType == eLengthPercentage) ||
1884 : (mWidthType == eAuto && mHeightType == eAuto),
1885 : "logic error");
1886 :
1887 0 : nsStyleImageType type = aImage.GetType();
1888 :
1889 : // Gradient rendering depends on frame size when auto is involved because
1890 : // gradients have no intrinsic ratio or dimensions, and therefore the relevant
1891 : // dimension is "treat[ed] as 100%".
1892 0 : if (type == eStyleImageType_Gradient) {
1893 0 : return true;
1894 : }
1895 :
1896 : // XXX Element rendering for auto or fixed length doesn't depend on frame size
1897 : // according to the spec. However, we don't implement the spec yet, so
1898 : // for now we bail and say element() plus auto affects ultimate size.
1899 0 : if (type == eStyleImageType_Element) {
1900 0 : return true;
1901 : }
1902 :
1903 0 : if (type == eStyleImageType_Image) {
1904 0 : nsCOMPtr<imgIContainer> imgContainer;
1905 0 : aImage.GetImageData()->GetImage(getter_AddRefs(imgContainer));
1906 0 : if (imgContainer) {
1907 0 : nsIntSize imageSize;
1908 0 : nsSize imageRatio;
1909 : bool hasWidth, hasHeight;
1910 : nsLayoutUtils::ComputeSizeForDrawing(imgContainer, imageSize, imageRatio,
1911 0 : hasWidth, hasHeight);
1912 :
1913 : // If the image has a fixed width and height, rendering never depends on
1914 : // the frame size.
1915 0 : if (hasWidth && hasHeight) {
1916 0 : return false;
1917 : }
1918 :
1919 : // If the image has an intrinsic ratio, rendering will depend on frame
1920 : // size when background-size is all auto.
1921 0 : if (imageRatio != nsSize(0, 0)) {
1922 0 : return mWidthType == mHeightType;
1923 : }
1924 :
1925 : // Otherwise, rendering depends on frame size when the image dimensions
1926 : // and background-size don't complement each other.
1927 0 : return !(hasWidth && mHeightType == eLengthPercentage) &&
1928 0 : !(hasHeight && mWidthType == eLengthPercentage);
1929 : }
1930 : } else {
1931 0 : NS_NOTREACHED("missed an enum value");
1932 : }
1933 :
1934 : // Passed the gauntlet: no dependency.
1935 0 : return false;
1936 : }
1937 :
1938 : void
1939 0 : nsStyleBackground::Size::SetInitialValues()
1940 : {
1941 0 : mWidthType = mHeightType = eAuto;
1942 0 : }
1943 :
1944 : bool
1945 0 : nsStyleBackground::Size::operator==(const Size& aOther) const
1946 : {
1947 0 : NS_ABORT_IF_FALSE(mWidthType < eDimensionType_COUNT,
1948 : "bad mWidthType for this");
1949 0 : NS_ABORT_IF_FALSE(mHeightType < eDimensionType_COUNT,
1950 : "bad mHeightType for this");
1951 0 : NS_ABORT_IF_FALSE(aOther.mWidthType < eDimensionType_COUNT,
1952 : "bad mWidthType for aOther");
1953 0 : NS_ABORT_IF_FALSE(aOther.mHeightType < eDimensionType_COUNT,
1954 : "bad mHeightType for aOther");
1955 :
1956 : return mWidthType == aOther.mWidthType &&
1957 : mHeightType == aOther.mHeightType &&
1958 0 : (mWidthType != eLengthPercentage || mWidth == aOther.mWidth) &&
1959 0 : (mHeightType != eLengthPercentage || mHeight == aOther.mHeight);
1960 : }
1961 :
1962 : void
1963 0 : nsStyleBackground::Repeat::SetInitialValues()
1964 : {
1965 0 : mXRepeat = NS_STYLE_BG_REPEAT_REPEAT;
1966 0 : mYRepeat = NS_STYLE_BG_REPEAT_REPEAT;
1967 0 : }
1968 :
1969 0 : nsStyleBackground::Layer::Layer()
1970 : {
1971 0 : }
1972 :
1973 0 : nsStyleBackground::Layer::~Layer()
1974 : {
1975 0 : }
1976 :
1977 : void
1978 0 : nsStyleBackground::Layer::SetInitialValues()
1979 : {
1980 0 : mAttachment = NS_STYLE_BG_ATTACHMENT_SCROLL;
1981 0 : mClip = NS_STYLE_BG_CLIP_BORDER;
1982 0 : mOrigin = NS_STYLE_BG_ORIGIN_PADDING;
1983 0 : mRepeat.SetInitialValues();
1984 0 : mPosition.SetInitialValues();
1985 0 : mSize.SetInitialValues();
1986 0 : mImage.SetNull();
1987 0 : }
1988 :
1989 : bool
1990 0 : nsStyleBackground::Layer::RenderingMightDependOnFrameSize() const
1991 : {
1992 : // Do we even have an image?
1993 0 : if (mImage.IsEmpty()) {
1994 0 : return false;
1995 : }
1996 :
1997 0 : return mPosition.DependsOnFrameSize() || mSize.DependsOnFrameSize(mImage);
1998 : }
1999 :
2000 : bool
2001 0 : nsStyleBackground::Layer::operator==(const Layer& aOther) const
2002 : {
2003 : return mAttachment == aOther.mAttachment &&
2004 : mClip == aOther.mClip &&
2005 : mOrigin == aOther.mOrigin &&
2006 0 : mRepeat == aOther.mRepeat &&
2007 0 : mPosition == aOther.mPosition &&
2008 0 : mSize == aOther.mSize &&
2009 0 : mImage == aOther.mImage;
2010 : }
2011 :
2012 : // --------------------
2013 : // nsStyleDisplay
2014 : //
2015 0 : void nsTimingFunction::AssignFromKeyword(PRInt32 aTimingFunctionType)
2016 : {
2017 0 : switch (aTimingFunctionType) {
2018 : case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START:
2019 0 : mType = StepStart;
2020 0 : mSteps = 1;
2021 0 : return;
2022 : case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END:
2023 0 : mType = StepEnd;
2024 0 : mSteps = 1;
2025 0 : return;
2026 : default:
2027 0 : mType = Function;
2028 : break;
2029 : }
2030 :
2031 : MOZ_STATIC_ASSERT(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE == 0 &&
2032 : NS_STYLE_TRANSITION_TIMING_FUNCTION_LINEAR == 1 &&
2033 : NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN == 2 &&
2034 : NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_OUT == 3 &&
2035 : NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN_OUT == 4,
2036 : "transition timing function constants not as expected");
2037 :
2038 : static const float timingFunctionValues[5][4] = {
2039 : { 0.25, 0.10, 0.25, 1.00 }, // ease
2040 : { 0.00, 0.00, 1.00, 1.00 }, // linear
2041 : { 0.42, 0.00, 1.00, 1.00 }, // ease-in
2042 : { 0.00, 0.00, 0.58, 1.00 }, // ease-out
2043 : { 0.42, 0.00, 0.58, 1.00 } // ease-in-out
2044 : };
2045 :
2046 0 : NS_ABORT_IF_FALSE(0 <= aTimingFunctionType && aTimingFunctionType < 5,
2047 : "keyword out of range");
2048 0 : mFunc.mX1 = timingFunctionValues[aTimingFunctionType][0];
2049 0 : mFunc.mY1 = timingFunctionValues[aTimingFunctionType][1];
2050 0 : mFunc.mX2 = timingFunctionValues[aTimingFunctionType][2];
2051 0 : mFunc.mY2 = timingFunctionValues[aTimingFunctionType][3];
2052 : }
2053 :
2054 0 : nsTransition::nsTransition(const nsTransition& aCopy)
2055 : : mTimingFunction(aCopy.mTimingFunction)
2056 : , mDuration(aCopy.mDuration)
2057 : , mDelay(aCopy.mDelay)
2058 : , mProperty(aCopy.mProperty)
2059 0 : , mUnknownProperty(aCopy.mUnknownProperty)
2060 : {
2061 0 : }
2062 :
2063 0 : void nsTransition::SetInitialValues()
2064 : {
2065 0 : mTimingFunction = nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE);
2066 0 : mDuration = 0.0;
2067 0 : mDelay = 0.0;
2068 0 : mProperty = eCSSPropertyExtra_all_properties;
2069 0 : }
2070 :
2071 0 : void nsTransition::SetUnknownProperty(const nsAString& aUnknownProperty)
2072 : {
2073 0 : NS_ASSERTION(nsCSSProps::LookupProperty(aUnknownProperty) ==
2074 : eCSSProperty_UNKNOWN,
2075 : "should be unknown property");
2076 0 : mProperty = eCSSProperty_UNKNOWN;
2077 0 : mUnknownProperty = do_GetAtom(aUnknownProperty);
2078 0 : }
2079 :
2080 0 : nsAnimation::nsAnimation(const nsAnimation& aCopy)
2081 : : mTimingFunction(aCopy.mTimingFunction)
2082 : , mDuration(aCopy.mDuration)
2083 : , mDelay(aCopy.mDelay)
2084 : , mName(aCopy.mName)
2085 : , mDirection(aCopy.mDirection)
2086 : , mFillMode(aCopy.mFillMode)
2087 : , mPlayState(aCopy.mPlayState)
2088 0 : , mIterationCount(aCopy.mIterationCount)
2089 : {
2090 0 : }
2091 :
2092 : void
2093 0 : nsAnimation::SetInitialValues()
2094 : {
2095 0 : mTimingFunction = nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE);
2096 0 : mDuration = 0.0;
2097 0 : mDelay = 0.0;
2098 0 : mName = EmptyString();
2099 0 : mDirection = NS_STYLE_ANIMATION_DIRECTION_NORMAL;
2100 0 : mFillMode = NS_STYLE_ANIMATION_FILL_MODE_NONE;
2101 0 : mPlayState = NS_STYLE_ANIMATION_PLAY_STATE_RUNNING;
2102 0 : mIterationCount = 1.0f;
2103 0 : }
2104 :
2105 0 : nsStyleDisplay::nsStyleDisplay()
2106 : {
2107 0 : MOZ_COUNT_CTOR(nsStyleDisplay);
2108 0 : mAppearance = NS_THEME_NONE;
2109 0 : mDisplay = NS_STYLE_DISPLAY_INLINE;
2110 0 : mOriginalDisplay = mDisplay;
2111 0 : mPosition = NS_STYLE_POSITION_STATIC;
2112 0 : mFloats = NS_STYLE_FLOAT_NONE;
2113 0 : mOriginalFloats = mFloats;
2114 0 : mBreakType = NS_STYLE_CLEAR_NONE;
2115 0 : mBreakBefore = false;
2116 0 : mBreakAfter = false;
2117 0 : mOverflowX = NS_STYLE_OVERFLOW_VISIBLE;
2118 0 : mOverflowY = NS_STYLE_OVERFLOW_VISIBLE;
2119 0 : mResize = NS_STYLE_RESIZE_NONE;
2120 0 : mClipFlags = NS_STYLE_CLIP_AUTO;
2121 0 : mClip.SetRect(0,0,0,0);
2122 0 : mOpacity = 1.0f;
2123 0 : mSpecifiedTransform = nsnull;
2124 0 : mTransformOrigin[0].SetPercentValue(0.5f); // Transform is centered on origin
2125 0 : mTransformOrigin[1].SetPercentValue(0.5f);
2126 0 : mTransformOrigin[2].SetCoordValue(0);
2127 0 : mPerspectiveOrigin[0].SetPercentValue(0.5f);
2128 0 : mPerspectiveOrigin[1].SetPercentValue(0.5f);
2129 0 : mChildPerspective.SetCoordValue(0);
2130 0 : mBackfaceVisibility = NS_STYLE_BACKFACE_VISIBILITY_VISIBLE;
2131 0 : mTransformStyle = NS_STYLE_TRANSFORM_STYLE_FLAT;
2132 0 : mOrient = NS_STYLE_ORIENT_HORIZONTAL;
2133 :
2134 0 : mTransitions.AppendElement();
2135 0 : NS_ABORT_IF_FALSE(mTransitions.Length() == 1,
2136 : "appending within auto buffer should never fail");
2137 0 : mTransitions[0].SetInitialValues();
2138 0 : mTransitionTimingFunctionCount = 1;
2139 0 : mTransitionDurationCount = 1;
2140 0 : mTransitionDelayCount = 1;
2141 0 : mTransitionPropertyCount = 1;
2142 :
2143 0 : mAnimations.AppendElement();
2144 0 : NS_ABORT_IF_FALSE(mAnimations.Length() == 1,
2145 : "appending within auto buffer should never fail");
2146 0 : mAnimations[0].SetInitialValues();
2147 0 : mAnimationTimingFunctionCount = 1;
2148 0 : mAnimationDurationCount = 1;
2149 0 : mAnimationDelayCount = 1;
2150 0 : mAnimationNameCount = 1;
2151 0 : mAnimationDirectionCount = 1;
2152 0 : mAnimationFillModeCount = 1;
2153 0 : mAnimationPlayStateCount = 1;
2154 0 : mAnimationIterationCountCount = 1;
2155 0 : }
2156 :
2157 0 : nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource)
2158 : : mTransitions(aSource.mTransitions)
2159 : , mTransitionTimingFunctionCount(aSource.mTransitionTimingFunctionCount)
2160 : , mTransitionDurationCount(aSource.mTransitionDurationCount)
2161 : , mTransitionDelayCount(aSource.mTransitionDelayCount)
2162 : , mTransitionPropertyCount(aSource.mTransitionPropertyCount)
2163 : , mAnimations(aSource.mAnimations)
2164 : , mAnimationTimingFunctionCount(aSource.mAnimationTimingFunctionCount)
2165 : , mAnimationDurationCount(aSource.mAnimationDurationCount)
2166 : , mAnimationDelayCount(aSource.mAnimationDelayCount)
2167 : , mAnimationNameCount(aSource.mAnimationNameCount)
2168 : , mAnimationDirectionCount(aSource.mAnimationDirectionCount)
2169 : , mAnimationFillModeCount(aSource.mAnimationFillModeCount)
2170 : , mAnimationPlayStateCount(aSource.mAnimationPlayStateCount)
2171 0 : , mAnimationIterationCountCount(aSource.mAnimationIterationCountCount)
2172 : {
2173 0 : MOZ_COUNT_CTOR(nsStyleDisplay);
2174 0 : mAppearance = aSource.mAppearance;
2175 0 : mDisplay = aSource.mDisplay;
2176 0 : mOriginalDisplay = aSource.mOriginalDisplay;
2177 0 : mOriginalFloats = aSource.mOriginalFloats;
2178 0 : mBinding = aSource.mBinding;
2179 0 : mPosition = aSource.mPosition;
2180 0 : mFloats = aSource.mFloats;
2181 0 : mBreakType = aSource.mBreakType;
2182 0 : mBreakBefore = aSource.mBreakBefore;
2183 0 : mBreakAfter = aSource.mBreakAfter;
2184 0 : mOverflowX = aSource.mOverflowX;
2185 0 : mOverflowY = aSource.mOverflowY;
2186 0 : mResize = aSource.mResize;
2187 0 : mClipFlags = aSource.mClipFlags;
2188 0 : mClip = aSource.mClip;
2189 0 : mOpacity = aSource.mOpacity;
2190 0 : mOrient = aSource.mOrient;
2191 :
2192 : /* Copy over the transformation information. */
2193 0 : mSpecifiedTransform = aSource.mSpecifiedTransform;
2194 :
2195 : /* Copy over transform origin. */
2196 0 : mTransformOrigin[0] = aSource.mTransformOrigin[0];
2197 0 : mTransformOrigin[1] = aSource.mTransformOrigin[1];
2198 0 : mTransformOrigin[2] = aSource.mTransformOrigin[2];
2199 0 : mPerspectiveOrigin[0] = aSource.mPerspectiveOrigin[0];
2200 0 : mPerspectiveOrigin[1] = aSource.mPerspectiveOrigin[1];
2201 0 : mChildPerspective = aSource.mChildPerspective;
2202 0 : mBackfaceVisibility = aSource.mBackfaceVisibility;
2203 0 : mTransformStyle = aSource.mTransformStyle;
2204 0 : }
2205 :
2206 0 : nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
2207 : {
2208 0 : nsChangeHint hint = nsChangeHint(0);
2209 :
2210 0 : if (!EqualURIs(mBinding, aOther.mBinding)
2211 : || mPosition != aOther.mPosition
2212 : || mDisplay != aOther.mDisplay
2213 : || (mFloats == NS_STYLE_FLOAT_NONE) != (aOther.mFloats == NS_STYLE_FLOAT_NONE)
2214 : || mOverflowX != aOther.mOverflowX
2215 : || mOverflowY != aOther.mOverflowY
2216 : || mResize != aOther.mResize)
2217 0 : NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
2218 :
2219 0 : if (mFloats != aOther.mFloats) {
2220 : // Changing which side we float on doesn't affect descendants directly
2221 : NS_UpdateHint(hint,
2222 : NS_SubtractHint(nsChangeHint_ReflowFrame,
2223 : NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics,
2224 0 : nsChangeHint_NeedDirtyReflow)));
2225 : }
2226 :
2227 : // XXX the following is conservative, for now: changing float breaking shouldn't
2228 : // necessarily require a repaint, reflow should suffice.
2229 0 : if (mBreakType != aOther.mBreakType
2230 : || mBreakBefore != aOther.mBreakBefore
2231 : || mBreakAfter != aOther.mBreakAfter
2232 : || mAppearance != aOther.mAppearance
2233 : || mOrient != aOther.mOrient
2234 0 : || mClipFlags != aOther.mClipFlags || !mClip.IsEqualInterior(aOther.mClip))
2235 0 : NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_ReflowFrame, nsChangeHint_RepaintFrame));
2236 :
2237 0 : if (mOpacity != aOther.mOpacity) {
2238 0 : NS_UpdateHint(hint, nsChangeHint_UpdateOpacityLayer);
2239 : }
2240 :
2241 : /* If we've added or removed the transform property, we need to reconstruct the frame to add
2242 : * or remove the view object, and also to handle abs-pos and fixed-pos containers.
2243 : */
2244 0 : if (HasTransform() != aOther.HasTransform()) {
2245 0 : NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
2246 : }
2247 0 : else if (HasTransform()) {
2248 : /* Otherwise, if we've kept the property lying around and we already had a
2249 : * transform, we need to see whether or not we've changed the transform.
2250 : * If so, we need to recompute its overflow rect (which probably changed
2251 : * if the transform changed) and to redraw within the bounds of that new
2252 : * overflow rect.
2253 : */
2254 0 : if (!mSpecifiedTransform != !aOther.mSpecifiedTransform ||
2255 : (mSpecifiedTransform &&
2256 0 : *mSpecifiedTransform != *aOther.mSpecifiedTransform)) {
2257 : NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_UpdateOverflow,
2258 0 : nsChangeHint_UpdateTransformLayer));
2259 : }
2260 :
2261 : const nsChangeHint kUpdateOverflowAndRepaintHint =
2262 0 : NS_CombineHint(nsChangeHint_UpdateOverflow, nsChangeHint_RepaintFrame);
2263 0 : for (PRUint8 index = 0; index < 3; ++index)
2264 0 : if (mTransformOrigin[index] != aOther.mTransformOrigin[index]) {
2265 0 : NS_UpdateHint(hint, kUpdateOverflowAndRepaintHint);
2266 0 : break;
2267 : }
2268 :
2269 0 : for (PRUint8 index = 0; index < 2; ++index)
2270 0 : if (mPerspectiveOrigin[index] != aOther.mPerspectiveOrigin[index]) {
2271 0 : NS_UpdateHint(hint, kUpdateOverflowAndRepaintHint);
2272 0 : break;
2273 : }
2274 :
2275 0 : if (mChildPerspective != aOther.mChildPerspective ||
2276 : mTransformStyle != aOther.mTransformStyle)
2277 0 : NS_UpdateHint(hint, kUpdateOverflowAndRepaintHint);
2278 :
2279 0 : if (mBackfaceVisibility != aOther.mBackfaceVisibility)
2280 0 : NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
2281 : }
2282 :
2283 : // Note: Our current behavior for handling changes to the
2284 : // transition-duration, transition-delay, and transition-timing-function
2285 : // properties is to do nothing. In other words, the transition
2286 : // property that matters is what it is when the transition begins, and
2287 : // we don't stop a transition later because the transition property
2288 : // changed.
2289 : // We do handle changes to transition-property, but we don't need to
2290 : // bother with anything here, since the transition manager is notified
2291 : // of any style context change anyway.
2292 :
2293 : // Note: Likewise, for animation-*, the animation manager gets
2294 : // notified about every new style context constructed, and it uses
2295 : // that opportunity to handle dynamic changes appropriately.
2296 :
2297 0 : return hint;
2298 : }
2299 :
2300 : #ifdef DEBUG
2301 : /* static */
2302 0 : nsChangeHint nsStyleDisplay::MaxDifference()
2303 : {
2304 : // All the parts of FRAMECHANGE are present above in CalcDifference.
2305 : return nsChangeHint(NS_STYLE_HINT_FRAMECHANGE |
2306 : nsChangeHint_UpdateOpacityLayer |
2307 : nsChangeHint_UpdateTransformLayer |
2308 0 : nsChangeHint_UpdateOverflow);
2309 : }
2310 : #endif
2311 :
2312 : // --------------------
2313 : // nsStyleVisibility
2314 : //
2315 :
2316 0 : nsStyleVisibility::nsStyleVisibility(nsPresContext* aPresContext)
2317 : {
2318 0 : MOZ_COUNT_CTOR(nsStyleVisibility);
2319 0 : PRUint32 bidiOptions = aPresContext->GetBidi();
2320 0 : if (GET_BIDI_OPTION_DIRECTION(bidiOptions) == IBMBIDI_TEXTDIRECTION_RTL)
2321 0 : mDirection = NS_STYLE_DIRECTION_RTL;
2322 : else
2323 0 : mDirection = NS_STYLE_DIRECTION_LTR;
2324 :
2325 0 : mVisible = NS_STYLE_VISIBILITY_VISIBLE;
2326 0 : mPointerEvents = NS_STYLE_POINTER_EVENTS_AUTO;
2327 0 : }
2328 :
2329 0 : nsStyleVisibility::nsStyleVisibility(const nsStyleVisibility& aSource)
2330 : {
2331 0 : MOZ_COUNT_CTOR(nsStyleVisibility);
2332 0 : mDirection = aSource.mDirection;
2333 0 : mVisible = aSource.mVisible;
2334 0 : mPointerEvents = aSource.mPointerEvents;
2335 0 : }
2336 :
2337 0 : nsChangeHint nsStyleVisibility::CalcDifference(const nsStyleVisibility& aOther) const
2338 : {
2339 0 : nsChangeHint hint = nsChangeHint(0);
2340 :
2341 0 : if (mDirection != aOther.mDirection) {
2342 0 : NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
2343 0 : } else if (mVisible != aOther.mVisible) {
2344 0 : if ((NS_STYLE_VISIBILITY_COLLAPSE == mVisible) ||
2345 : (NS_STYLE_VISIBILITY_COLLAPSE == aOther.mVisible)) {
2346 0 : NS_UpdateHint(hint, NS_STYLE_HINT_REFLOW);
2347 : } else {
2348 0 : NS_UpdateHint(hint, NS_STYLE_HINT_VISUAL);
2349 : }
2350 : }
2351 0 : return hint;
2352 : }
2353 :
2354 : #ifdef DEBUG
2355 : /* static */
2356 0 : nsChangeHint nsStyleVisibility::MaxDifference()
2357 : {
2358 0 : return NS_STYLE_HINT_FRAMECHANGE;
2359 : }
2360 : #endif
2361 :
2362 0 : nsStyleContentData::~nsStyleContentData()
2363 : {
2364 0 : NS_ABORT_IF_FALSE(!mImageTracked,
2365 : "nsStyleContentData being destroyed while still tracking image!");
2366 0 : if (mType == eStyleContentType_Image) {
2367 0 : NS_IF_RELEASE(mContent.mImage);
2368 0 : } else if (mType == eStyleContentType_Counter ||
2369 : mType == eStyleContentType_Counters) {
2370 0 : mContent.mCounters->Release();
2371 0 : } else if (mContent.mString) {
2372 0 : NS_Free(mContent.mString);
2373 : }
2374 0 : }
2375 :
2376 0 : nsStyleContentData& nsStyleContentData::operator=(const nsStyleContentData& aOther)
2377 : {
2378 0 : if (this == &aOther)
2379 0 : return *this;
2380 0 : this->~nsStyleContentData();
2381 0 : new (this) nsStyleContentData();
2382 :
2383 0 : mType = aOther.mType;
2384 0 : if (mType == eStyleContentType_Image) {
2385 0 : mContent.mImage = aOther.mContent.mImage;
2386 0 : NS_IF_ADDREF(mContent.mImage);
2387 0 : } else if (mType == eStyleContentType_Counter ||
2388 : mType == eStyleContentType_Counters) {
2389 0 : mContent.mCounters = aOther.mContent.mCounters;
2390 0 : mContent.mCounters->AddRef();
2391 0 : } else if (aOther.mContent.mString) {
2392 0 : mContent.mString = NS_strdup(aOther.mContent.mString);
2393 : } else {
2394 0 : mContent.mString = nsnull;
2395 : }
2396 0 : return *this;
2397 : }
2398 :
2399 0 : bool nsStyleContentData::operator==(const nsStyleContentData& aOther) const
2400 : {
2401 0 : if (mType != aOther.mType)
2402 0 : return false;
2403 0 : if (mType == eStyleContentType_Image) {
2404 0 : if (!mContent.mImage || !aOther.mContent.mImage)
2405 0 : return mContent.mImage == aOther.mContent.mImage;
2406 : bool eq;
2407 0 : nsCOMPtr<nsIURI> thisURI, otherURI;
2408 0 : mContent.mImage->GetURI(getter_AddRefs(thisURI));
2409 0 : aOther.mContent.mImage->GetURI(getter_AddRefs(otherURI));
2410 0 : return thisURI == otherURI || // handles null==null
2411 0 : (thisURI && otherURI &&
2412 0 : NS_SUCCEEDED(thisURI->Equals(otherURI, &eq)) &&
2413 0 : eq);
2414 : }
2415 0 : if (mType == eStyleContentType_Counter ||
2416 : mType == eStyleContentType_Counters)
2417 0 : return *mContent.mCounters == *aOther.mContent.mCounters;
2418 0 : return safe_strcmp(mContent.mString, aOther.mContent.mString) == 0;
2419 : }
2420 :
2421 : void
2422 0 : nsStyleContentData::TrackImage(nsPresContext* aContext)
2423 : {
2424 : // Sanity
2425 0 : NS_ABORT_IF_FALSE(!mImageTracked, "Already tracking image!");
2426 0 : NS_ABORT_IF_FALSE(mType == eStyleContentType_Image,
2427 : "Tryingto do image tracking on non-image!");
2428 0 : NS_ABORT_IF_FALSE(mContent.mImage,
2429 : "Can't track image when there isn't one!");
2430 :
2431 : // Register the image with the document
2432 0 : nsIDocument* doc = aContext->Document();
2433 0 : if (doc)
2434 0 : doc->AddImage(mContent.mImage);
2435 :
2436 : // Mark state
2437 : #ifdef DEBUG
2438 0 : mImageTracked = true;
2439 : #endif
2440 0 : }
2441 :
2442 : void
2443 0 : nsStyleContentData::UntrackImage(nsPresContext* aContext)
2444 : {
2445 : // Sanity
2446 0 : NS_ABORT_IF_FALSE(mImageTracked, "Image not tracked!");
2447 0 : NS_ABORT_IF_FALSE(mType == eStyleContentType_Image,
2448 : "Trying to do image tracking on non-image!");
2449 0 : NS_ABORT_IF_FALSE(mContent.mImage,
2450 : "Can't untrack image when there isn't one!");
2451 :
2452 : // Unregister the image with the document
2453 0 : nsIDocument* doc = aContext->Document();
2454 0 : if (doc)
2455 0 : doc->RemoveImage(mContent.mImage);
2456 :
2457 : // Mark state
2458 : #ifdef DEBUG
2459 0 : mImageTracked = false;
2460 : #endif
2461 0 : }
2462 :
2463 :
2464 : //-----------------------
2465 : // nsStyleContent
2466 : //
2467 :
2468 0 : nsStyleContent::nsStyleContent(void)
2469 : : mMarkerOffset(),
2470 : mContents(nsnull),
2471 : mIncrements(nsnull),
2472 : mResets(nsnull),
2473 : mContentCount(0),
2474 : mIncrementCount(0),
2475 0 : mResetCount(0)
2476 : {
2477 0 : MOZ_COUNT_CTOR(nsStyleContent);
2478 0 : mMarkerOffset.SetAutoValue();
2479 0 : }
2480 :
2481 0 : nsStyleContent::~nsStyleContent(void)
2482 : {
2483 0 : MOZ_COUNT_DTOR(nsStyleContent);
2484 0 : DELETE_ARRAY_IF(mContents);
2485 0 : DELETE_ARRAY_IF(mIncrements);
2486 0 : DELETE_ARRAY_IF(mResets);
2487 0 : }
2488 :
2489 : void
2490 0 : nsStyleContent::Destroy(nsPresContext* aContext)
2491 : {
2492 : // Unregister any images we might have with the document.
2493 0 : for (PRUint32 i = 0; i < mContentCount; ++i) {
2494 0 : if ((mContents[i].mType == eStyleContentType_Image) &&
2495 0 : mContents[i].mContent.mImage) {
2496 0 : mContents[i].UntrackImage(aContext);
2497 : }
2498 : }
2499 :
2500 0 : this->~nsStyleContent();
2501 0 : aContext->FreeToShell(sizeof(nsStyleContent), this);
2502 0 : }
2503 :
2504 0 : nsStyleContent::nsStyleContent(const nsStyleContent& aSource)
2505 : :mMarkerOffset(),
2506 : mContents(nsnull),
2507 : mIncrements(nsnull),
2508 : mResets(nsnull),
2509 : mContentCount(0),
2510 : mIncrementCount(0),
2511 0 : mResetCount(0)
2512 :
2513 : {
2514 0 : MOZ_COUNT_CTOR(nsStyleContent);
2515 0 : mMarkerOffset = aSource.mMarkerOffset;
2516 :
2517 : PRUint32 index;
2518 0 : if (NS_SUCCEEDED(AllocateContents(aSource.ContentCount()))) {
2519 0 : for (index = 0; index < mContentCount; index++) {
2520 0 : ContentAt(index) = aSource.ContentAt(index);
2521 : }
2522 : }
2523 :
2524 0 : if (NS_SUCCEEDED(AllocateCounterIncrements(aSource.CounterIncrementCount()))) {
2525 0 : for (index = 0; index < mIncrementCount; index++) {
2526 0 : const nsStyleCounterData *data = aSource.GetCounterIncrementAt(index);
2527 0 : mIncrements[index].mCounter = data->mCounter;
2528 0 : mIncrements[index].mValue = data->mValue;
2529 : }
2530 : }
2531 :
2532 0 : if (NS_SUCCEEDED(AllocateCounterResets(aSource.CounterResetCount()))) {
2533 0 : for (index = 0; index < mResetCount; index++) {
2534 0 : const nsStyleCounterData *data = aSource.GetCounterResetAt(index);
2535 0 : mResets[index].mCounter = data->mCounter;
2536 0 : mResets[index].mValue = data->mValue;
2537 : }
2538 : }
2539 0 : }
2540 :
2541 0 : nsChangeHint nsStyleContent::CalcDifference(const nsStyleContent& aOther) const
2542 : {
2543 : // In ReResolveStyleContext we assume that if there's no existing
2544 : // ::before or ::after and we don't have to restyle children of the
2545 : // node then we can't end up with a ::before or ::after due to the
2546 : // restyle of the node itself. That's not quite true, but the only
2547 : // exception to the above is when the 'content' property of the node
2548 : // changes and the pseudo-element inherits the changed value. Since
2549 : // the code here triggers a frame change on the node in that case,
2550 : // the optimization in ReResolveStyleContext is ok. But if we ever
2551 : // change this code to not reconstruct frames on changes to the
2552 : // 'content' property, then we will need to revisit the optimization
2553 : // in ReResolveStyleContext.
2554 :
2555 0 : if (mContentCount != aOther.mContentCount ||
2556 : mIncrementCount != aOther.mIncrementCount ||
2557 : mResetCount != aOther.mResetCount) {
2558 0 : return NS_STYLE_HINT_FRAMECHANGE;
2559 : }
2560 :
2561 0 : PRUint32 ix = mContentCount;
2562 0 : while (0 < ix--) {
2563 0 : if (mContents[ix] != aOther.mContents[ix]) {
2564 : // Unfortunately we need to reframe here; a simple reflow
2565 : // will not pick up different text or different image URLs,
2566 : // since we set all that up in the CSSFrameConstructor
2567 0 : return NS_STYLE_HINT_FRAMECHANGE;
2568 : }
2569 : }
2570 0 : ix = mIncrementCount;
2571 0 : while (0 < ix--) {
2572 0 : if ((mIncrements[ix].mValue != aOther.mIncrements[ix].mValue) ||
2573 0 : (mIncrements[ix].mCounter != aOther.mIncrements[ix].mCounter)) {
2574 0 : return NS_STYLE_HINT_FRAMECHANGE;
2575 : }
2576 : }
2577 0 : ix = mResetCount;
2578 0 : while (0 < ix--) {
2579 0 : if ((mResets[ix].mValue != aOther.mResets[ix].mValue) ||
2580 0 : (mResets[ix].mCounter != aOther.mResets[ix].mCounter)) {
2581 0 : return NS_STYLE_HINT_FRAMECHANGE;
2582 : }
2583 : }
2584 0 : if (mMarkerOffset != aOther.mMarkerOffset) {
2585 0 : return NS_STYLE_HINT_REFLOW;
2586 : }
2587 0 : return NS_STYLE_HINT_NONE;
2588 : }
2589 :
2590 : #ifdef DEBUG
2591 : /* static */
2592 0 : nsChangeHint nsStyleContent::MaxDifference()
2593 : {
2594 0 : return NS_STYLE_HINT_FRAMECHANGE;
2595 : }
2596 : #endif
2597 :
2598 0 : nsresult nsStyleContent::AllocateContents(PRUint32 aCount)
2599 : {
2600 : // We need to run the destructors of the elements of mContents, so we
2601 : // delete and reallocate even if aCount == mContentCount. (If
2602 : // nsStyleContentData had its members private and managed their
2603 : // ownership on setting, we wouldn't need this, but that seems
2604 : // unnecessary at this point.)
2605 0 : DELETE_ARRAY_IF(mContents);
2606 0 : if (aCount) {
2607 0 : mContents = new nsStyleContentData[aCount];
2608 0 : if (! mContents) {
2609 0 : mContentCount = 0;
2610 0 : return NS_ERROR_OUT_OF_MEMORY;
2611 : }
2612 : }
2613 0 : mContentCount = aCount;
2614 0 : return NS_OK;
2615 : }
2616 :
2617 : // ---------------------
2618 : // nsStyleQuotes
2619 : //
2620 :
2621 0 : nsStyleQuotes::nsStyleQuotes(void)
2622 : : mQuotesCount(0),
2623 0 : mQuotes(nsnull)
2624 : {
2625 0 : MOZ_COUNT_CTOR(nsStyleQuotes);
2626 0 : SetInitial();
2627 0 : }
2628 :
2629 0 : nsStyleQuotes::~nsStyleQuotes(void)
2630 : {
2631 0 : MOZ_COUNT_DTOR(nsStyleQuotes);
2632 0 : DELETE_ARRAY_IF(mQuotes);
2633 0 : }
2634 :
2635 0 : nsStyleQuotes::nsStyleQuotes(const nsStyleQuotes& aSource)
2636 : : mQuotesCount(0),
2637 0 : mQuotes(nsnull)
2638 : {
2639 0 : MOZ_COUNT_CTOR(nsStyleQuotes);
2640 0 : CopyFrom(aSource);
2641 0 : }
2642 :
2643 : void
2644 0 : nsStyleQuotes::SetInitial()
2645 : {
2646 : // The initial value for quotes is the en-US typographic convention:
2647 : // outermost are LEFT and RIGHT DOUBLE QUOTATION MARK, alternating
2648 : // with LEFT and RIGHT SINGLE QUOTATION MARK.
2649 : static const PRUnichar initialQuotes[8] = {
2650 : 0x201C, 0, 0x201D, 0, 0x2018, 0, 0x2019, 0
2651 : };
2652 :
2653 0 : if (NS_SUCCEEDED(AllocateQuotes(2))) {
2654 : SetQuotesAt(0,
2655 0 : nsDependentString(&initialQuotes[0], 1),
2656 0 : nsDependentString(&initialQuotes[2], 1));
2657 : SetQuotesAt(1,
2658 0 : nsDependentString(&initialQuotes[4], 1),
2659 0 : nsDependentString(&initialQuotes[6], 1));
2660 : }
2661 0 : }
2662 :
2663 : void
2664 0 : nsStyleQuotes::CopyFrom(const nsStyleQuotes& aSource)
2665 : {
2666 0 : if (NS_SUCCEEDED(AllocateQuotes(aSource.QuotesCount()))) {
2667 0 : PRUint32 count = (mQuotesCount * 2);
2668 0 : for (PRUint32 index = 0; index < count; index += 2) {
2669 0 : aSource.GetQuotesAt(index, mQuotes[index], mQuotes[index + 1]);
2670 : }
2671 : }
2672 0 : }
2673 :
2674 0 : nsChangeHint nsStyleQuotes::CalcDifference(const nsStyleQuotes& aOther) const
2675 : {
2676 : // If the quotes implementation is ever going to change we might not need
2677 : // a framechange here and a reflow should be sufficient. See bug 35768.
2678 0 : if (mQuotesCount == aOther.mQuotesCount) {
2679 0 : PRUint32 ix = (mQuotesCount * 2);
2680 0 : while (0 < ix--) {
2681 0 : if (mQuotes[ix] != aOther.mQuotes[ix]) {
2682 0 : return NS_STYLE_HINT_FRAMECHANGE;
2683 : }
2684 : }
2685 :
2686 0 : return NS_STYLE_HINT_NONE;
2687 : }
2688 0 : return NS_STYLE_HINT_FRAMECHANGE;
2689 : }
2690 :
2691 : #ifdef DEBUG
2692 : /* static */
2693 0 : nsChangeHint nsStyleQuotes::MaxDifference()
2694 : {
2695 0 : return NS_STYLE_HINT_FRAMECHANGE;
2696 : }
2697 : #endif
2698 :
2699 : // --------------------
2700 : // nsStyleTextReset
2701 : //
2702 :
2703 0 : nsStyleTextReset::nsStyleTextReset(void)
2704 : {
2705 0 : MOZ_COUNT_CTOR(nsStyleTextReset);
2706 0 : mVerticalAlign.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE, eStyleUnit_Enumerated);
2707 0 : mTextBlink = NS_STYLE_TEXT_BLINK_NONE;
2708 0 : mTextDecorationLine = NS_STYLE_TEXT_DECORATION_LINE_NONE;
2709 0 : mTextDecorationColor = NS_RGB(0,0,0);
2710 : mTextDecorationStyle =
2711 0 : NS_STYLE_TEXT_DECORATION_STYLE_SOLID | BORDER_COLOR_FOREGROUND;
2712 0 : mUnicodeBidi = NS_STYLE_UNICODE_BIDI_NORMAL;
2713 0 : }
2714 :
2715 0 : nsStyleTextReset::nsStyleTextReset(const nsStyleTextReset& aSource)
2716 : {
2717 0 : MOZ_COUNT_CTOR(nsStyleTextReset);
2718 0 : *this = aSource;
2719 0 : }
2720 :
2721 0 : nsStyleTextReset::~nsStyleTextReset(void)
2722 : {
2723 0 : MOZ_COUNT_DTOR(nsStyleTextReset);
2724 0 : }
2725 :
2726 0 : nsChangeHint nsStyleTextReset::CalcDifference(const nsStyleTextReset& aOther) const
2727 : {
2728 0 : if (mVerticalAlign == aOther.mVerticalAlign
2729 : && mUnicodeBidi == aOther.mUnicodeBidi) {
2730 : // Reflow for blink changes
2731 0 : if (mTextBlink != aOther.mTextBlink) {
2732 0 : return NS_STYLE_HINT_REFLOW;
2733 : }
2734 :
2735 0 : PRUint8 lineStyle = GetDecorationStyle();
2736 0 : PRUint8 otherLineStyle = aOther.GetDecorationStyle();
2737 0 : if (mTextDecorationLine != aOther.mTextDecorationLine ||
2738 : lineStyle != otherLineStyle) {
2739 : // Reflow for decoration line style changes only to or from double or
2740 : // wave because that may cause overflow area changes
2741 0 : if (lineStyle == NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE ||
2742 : lineStyle == NS_STYLE_TEXT_DECORATION_STYLE_WAVY ||
2743 : otherLineStyle == NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE ||
2744 : otherLineStyle == NS_STYLE_TEXT_DECORATION_STYLE_WAVY) {
2745 0 : return NS_STYLE_HINT_REFLOW;
2746 : }
2747 : // Repaint for other style decoration lines because they must be in
2748 : // default overflow rect
2749 0 : return NS_STYLE_HINT_VISUAL;
2750 : }
2751 :
2752 : // Repaint for decoration color changes
2753 : nscolor decColor, otherDecColor;
2754 : bool isFG, otherIsFG;
2755 0 : GetDecorationColor(decColor, isFG);
2756 0 : aOther.GetDecorationColor(otherDecColor, otherIsFG);
2757 0 : if (isFG != otherIsFG || (!isFG && decColor != otherDecColor)) {
2758 0 : return NS_STYLE_HINT_VISUAL;
2759 : }
2760 :
2761 0 : if (mTextOverflow != aOther.mTextOverflow) {
2762 0 : return NS_STYLE_HINT_VISUAL;
2763 : }
2764 0 : return NS_STYLE_HINT_NONE;
2765 : }
2766 0 : return NS_STYLE_HINT_REFLOW;
2767 : }
2768 :
2769 : #ifdef DEBUG
2770 : /* static */
2771 0 : nsChangeHint nsStyleTextReset::MaxDifference()
2772 : {
2773 0 : return NS_STYLE_HINT_REFLOW;
2774 : }
2775 : #endif
2776 :
2777 : // Allowed to return one of NS_STYLE_HINT_NONE, NS_STYLE_HINT_REFLOW
2778 : // or NS_STYLE_HINT_VISUAL. Currently we just return NONE or REFLOW, though.
2779 : // XXXbz can this not return a more specific hint? If that's ever
2780 : // changed, nsStyleBorder::CalcDifference will need changing too.
2781 : static nsChangeHint
2782 0 : CalcShadowDifference(nsCSSShadowArray* lhs,
2783 : nsCSSShadowArray* rhs)
2784 : {
2785 0 : if (lhs == rhs)
2786 0 : return NS_STYLE_HINT_NONE;
2787 :
2788 0 : if (!lhs || !rhs || lhs->Length() != rhs->Length())
2789 0 : return NS_STYLE_HINT_REFLOW;
2790 :
2791 0 : for (PRUint32 i = 0; i < lhs->Length(); ++i) {
2792 0 : if (*lhs->ShadowAt(i) != *rhs->ShadowAt(i))
2793 0 : return NS_STYLE_HINT_REFLOW;
2794 : }
2795 0 : return NS_STYLE_HINT_NONE;
2796 : }
2797 :
2798 : // --------------------
2799 : // nsStyleText
2800 : //
2801 :
2802 0 : nsStyleText::nsStyleText(void)
2803 : {
2804 0 : MOZ_COUNT_CTOR(nsStyleText);
2805 0 : mTextAlign = NS_STYLE_TEXT_ALIGN_DEFAULT;
2806 0 : mTextAlignLast = NS_STYLE_TEXT_ALIGN_AUTO;
2807 0 : mTextTransform = NS_STYLE_TEXT_TRANSFORM_NONE;
2808 0 : mWhiteSpace = NS_STYLE_WHITESPACE_NORMAL;
2809 0 : mWordWrap = NS_STYLE_WORDWRAP_NORMAL;
2810 0 : mHyphens = NS_STYLE_HYPHENS_MANUAL;
2811 0 : mTextSizeAdjust = NS_STYLE_TEXT_SIZE_ADJUST_AUTO;
2812 :
2813 0 : mLetterSpacing.SetNormalValue();
2814 0 : mLineHeight.SetNormalValue();
2815 0 : mTextIndent.SetCoordValue(0);
2816 0 : mWordSpacing = 0;
2817 :
2818 0 : mTextShadow = nsnull;
2819 0 : mTabSize = NS_STYLE_TABSIZE_INITIAL;
2820 0 : }
2821 :
2822 0 : nsStyleText::nsStyleText(const nsStyleText& aSource)
2823 : : mTextAlign(aSource.mTextAlign),
2824 : mTextAlignLast(aSource.mTextAlignLast),
2825 : mTextTransform(aSource.mTextTransform),
2826 : mWhiteSpace(aSource.mWhiteSpace),
2827 : mWordWrap(aSource.mWordWrap),
2828 : mHyphens(aSource.mHyphens),
2829 : mTextSizeAdjust(aSource.mTextSizeAdjust),
2830 : mTabSize(aSource.mTabSize),
2831 : mLetterSpacing(aSource.mLetterSpacing),
2832 : mLineHeight(aSource.mLineHeight),
2833 : mTextIndent(aSource.mTextIndent),
2834 : mWordSpacing(aSource.mWordSpacing),
2835 0 : mTextShadow(aSource.mTextShadow)
2836 : {
2837 0 : MOZ_COUNT_CTOR(nsStyleText);
2838 0 : }
2839 :
2840 0 : nsStyleText::~nsStyleText(void)
2841 : {
2842 0 : MOZ_COUNT_DTOR(nsStyleText);
2843 0 : }
2844 :
2845 0 : nsChangeHint nsStyleText::CalcDifference(const nsStyleText& aOther) const
2846 : {
2847 0 : if (NewlineIsSignificant() != aOther.NewlineIsSignificant()) {
2848 : // This may require construction of suppressed text frames
2849 0 : return NS_STYLE_HINT_FRAMECHANGE;
2850 : }
2851 :
2852 0 : if ((mTextAlign != aOther.mTextAlign) ||
2853 : (mTextAlignLast != aOther.mTextAlignLast) ||
2854 : (mTextTransform != aOther.mTextTransform) ||
2855 : (mWhiteSpace != aOther.mWhiteSpace) ||
2856 : (mWordWrap != aOther.mWordWrap) ||
2857 : (mHyphens != aOther.mHyphens) ||
2858 : (mTextSizeAdjust != aOther.mTextSizeAdjust) ||
2859 0 : (mLetterSpacing != aOther.mLetterSpacing) ||
2860 0 : (mLineHeight != aOther.mLineHeight) ||
2861 0 : (mTextIndent != aOther.mTextIndent) ||
2862 : (mWordSpacing != aOther.mWordSpacing) ||
2863 : (mTabSize != aOther.mTabSize))
2864 0 : return NS_STYLE_HINT_REFLOW;
2865 :
2866 0 : return CalcShadowDifference(mTextShadow, aOther.mTextShadow);
2867 : }
2868 :
2869 : #ifdef DEBUG
2870 : /* static */
2871 0 : nsChangeHint nsStyleText::MaxDifference()
2872 : {
2873 0 : return NS_STYLE_HINT_FRAMECHANGE;
2874 : }
2875 : #endif
2876 :
2877 : //-----------------------
2878 : // nsStyleUserInterface
2879 : //
2880 :
2881 0 : nsCursorImage::nsCursorImage()
2882 : : mHaveHotspot(false)
2883 : , mHotspotX(0.0f)
2884 0 : , mHotspotY(0.0f)
2885 : {
2886 0 : }
2887 :
2888 0 : nsCursorImage::nsCursorImage(const nsCursorImage& aOther)
2889 : : mHaveHotspot(aOther.mHaveHotspot)
2890 : , mHotspotX(aOther.mHotspotX)
2891 0 : , mHotspotY(aOther.mHotspotY)
2892 : {
2893 0 : SetImage(aOther.GetImage());
2894 0 : }
2895 :
2896 0 : nsCursorImage::~nsCursorImage()
2897 : {
2898 0 : SetImage(nsnull);
2899 0 : }
2900 :
2901 : nsCursorImage&
2902 0 : nsCursorImage::operator=(const nsCursorImage& aOther)
2903 : {
2904 0 : if (this != &aOther) {
2905 0 : mHaveHotspot = aOther.mHaveHotspot;
2906 0 : mHotspotX = aOther.mHotspotX;
2907 0 : mHotspotY = aOther.mHotspotY;
2908 0 : SetImage(aOther.GetImage());
2909 : }
2910 :
2911 0 : return *this;
2912 : }
2913 :
2914 0 : nsStyleUserInterface::nsStyleUserInterface(void)
2915 : {
2916 0 : MOZ_COUNT_CTOR(nsStyleUserInterface);
2917 0 : mUserInput = NS_STYLE_USER_INPUT_AUTO;
2918 0 : mUserModify = NS_STYLE_USER_MODIFY_READ_ONLY;
2919 0 : mUserFocus = NS_STYLE_USER_FOCUS_NONE;
2920 :
2921 0 : mCursor = NS_STYLE_CURSOR_AUTO; // fix for bugzilla bug 51113
2922 :
2923 0 : mCursorArrayLength = 0;
2924 0 : mCursorArray = nsnull;
2925 0 : }
2926 :
2927 0 : nsStyleUserInterface::nsStyleUserInterface(const nsStyleUserInterface& aSource) :
2928 : mUserInput(aSource.mUserInput),
2929 : mUserModify(aSource.mUserModify),
2930 : mUserFocus(aSource.mUserFocus),
2931 0 : mCursor(aSource.mCursor)
2932 : {
2933 0 : MOZ_COUNT_CTOR(nsStyleUserInterface);
2934 0 : CopyCursorArrayFrom(aSource);
2935 0 : }
2936 :
2937 0 : nsStyleUserInterface::~nsStyleUserInterface(void)
2938 : {
2939 0 : MOZ_COUNT_DTOR(nsStyleUserInterface);
2940 0 : delete [] mCursorArray;
2941 0 : }
2942 :
2943 0 : nsChangeHint nsStyleUserInterface::CalcDifference(const nsStyleUserInterface& aOther) const
2944 : {
2945 0 : nsChangeHint hint = nsChangeHint(0);
2946 0 : if (mCursor != aOther.mCursor)
2947 0 : NS_UpdateHint(hint, nsChangeHint_UpdateCursor);
2948 :
2949 : // We could do better. But it wouldn't be worth it, URL-specified cursors are
2950 : // rare.
2951 0 : if (mCursorArrayLength > 0 || aOther.mCursorArrayLength > 0)
2952 0 : NS_UpdateHint(hint, nsChangeHint_UpdateCursor);
2953 :
2954 0 : if (mUserModify != aOther.mUserModify)
2955 0 : NS_UpdateHint(hint, NS_STYLE_HINT_VISUAL);
2956 :
2957 0 : if ((mUserInput != aOther.mUserInput) &&
2958 : ((NS_STYLE_USER_INPUT_NONE == mUserInput) ||
2959 : (NS_STYLE_USER_INPUT_NONE == aOther.mUserInput))) {
2960 0 : NS_UpdateHint(hint, NS_STYLE_HINT_FRAMECHANGE);
2961 : }
2962 :
2963 : // ignore mUserFocus
2964 :
2965 0 : return hint;
2966 : }
2967 :
2968 : #ifdef DEBUG
2969 : /* static */
2970 0 : nsChangeHint nsStyleUserInterface::MaxDifference()
2971 : {
2972 0 : return nsChangeHint(nsChangeHint_UpdateCursor | NS_STYLE_HINT_FRAMECHANGE);
2973 : }
2974 : #endif
2975 :
2976 : void
2977 0 : nsStyleUserInterface::CopyCursorArrayFrom(const nsStyleUserInterface& aSource)
2978 : {
2979 0 : mCursorArray = nsnull;
2980 0 : mCursorArrayLength = 0;
2981 0 : if (aSource.mCursorArrayLength) {
2982 0 : mCursorArray = new nsCursorImage[aSource.mCursorArrayLength];
2983 0 : if (mCursorArray) {
2984 0 : mCursorArrayLength = aSource.mCursorArrayLength;
2985 0 : for (PRUint32 i = 0; i < mCursorArrayLength; ++i)
2986 0 : mCursorArray[i] = aSource.mCursorArray[i];
2987 : }
2988 : }
2989 0 : }
2990 :
2991 : //-----------------------
2992 : // nsStyleUIReset
2993 : //
2994 :
2995 0 : nsStyleUIReset::nsStyleUIReset(void)
2996 : {
2997 0 : MOZ_COUNT_CTOR(nsStyleUIReset);
2998 0 : mUserSelect = NS_STYLE_USER_SELECT_AUTO;
2999 0 : mForceBrokenImageIcon = 0;
3000 0 : mIMEMode = NS_STYLE_IME_MODE_AUTO;
3001 0 : mWindowShadow = NS_STYLE_WINDOW_SHADOW_DEFAULT;
3002 0 : }
3003 :
3004 0 : nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset& aSource)
3005 : {
3006 0 : MOZ_COUNT_CTOR(nsStyleUIReset);
3007 0 : mUserSelect = aSource.mUserSelect;
3008 0 : mForceBrokenImageIcon = aSource.mForceBrokenImageIcon;
3009 0 : mIMEMode = aSource.mIMEMode;
3010 0 : mWindowShadow = aSource.mWindowShadow;
3011 0 : }
3012 :
3013 0 : nsStyleUIReset::~nsStyleUIReset(void)
3014 : {
3015 0 : MOZ_COUNT_DTOR(nsStyleUIReset);
3016 0 : }
3017 :
3018 0 : nsChangeHint nsStyleUIReset::CalcDifference(const nsStyleUIReset& aOther) const
3019 : {
3020 : // ignore mIMEMode
3021 0 : if (mForceBrokenImageIcon != aOther.mForceBrokenImageIcon)
3022 0 : return NS_STYLE_HINT_FRAMECHANGE;
3023 0 : if (mWindowShadow != aOther.mWindowShadow) {
3024 : // We really need just an nsChangeHint_SyncFrameView, except
3025 : // on an ancestor of the frame, so we get that by doing a
3026 : // reflow.
3027 0 : return NS_STYLE_HINT_REFLOW;
3028 : }
3029 0 : if (mUserSelect != aOther.mUserSelect)
3030 0 : return NS_STYLE_HINT_VISUAL;
3031 0 : return NS_STYLE_HINT_NONE;
3032 : }
3033 :
3034 : #ifdef DEBUG
3035 : /* static */
3036 0 : nsChangeHint nsStyleUIReset::MaxDifference()
3037 : {
3038 0 : return NS_STYLE_HINT_FRAMECHANGE;
3039 : }
3040 : #endif
3041 :
|