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