Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/style/nsStyleStruct.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
/*
8
 * structs that contain the data provided by ComputedStyle, the
9
 * internal API for computed style data for an element
10
 */
11
12
#include "nsStyleStruct.h"
13
#include "nsStyleStructInlines.h"
14
#include "nsStyleConsts.h"
15
#include "nsStyleConsts.h"
16
#include "nsString.h"
17
#include "nsPresContext.h"
18
#include "nsIAppShellService.h"
19
#include "nsIWidget.h"
20
#include "nsCRTGlue.h"
21
#include "nsCSSProps.h"
22
#include "nsDeviceContext.h"
23
#include "nsStyleUtil.h"
24
25
#include "nsCOMPtr.h"
26
27
#include "nsBidiUtils.h"
28
#include "nsLayoutUtils.h"
29
30
#include "imgIRequest.h"
31
#include "imgIContainer.h"
32
#include "CounterStyleManager.h"
33
34
#include "mozilla/dom/AnimationEffectBinding.h" // for PlaybackDirection
35
#include "mozilla/dom/DocGroup.h"
36
#include "mozilla/dom/ImageTracker.h"
37
#include "mozilla/CORSMode.h"
38
#include "mozilla/ClearOnShutdown.h"
39
#include "mozilla/Likely.h"
40
#include "nsIURI.h"
41
#include "nsIDocument.h"
42
#include <algorithm>
43
#include "ImageLoader.h"
44
45
using namespace mozilla;
46
using namespace mozilla::dom;
47
48
/* static */ const int32_t nsStyleGridLine::kMinLine;
49
/* static */ const int32_t nsStyleGridLine::kMaxLine;
50
51
// We set the size limit of style structs to 504 bytes so that when they
52
// are allocated by Servo side with Arc, the total size doesn't exceed
53
// 512 bytes, which minimizes allocator slop.
54
static constexpr size_t kStyleStructSizeLimit = 504;
55
#define STYLE_STRUCT(name_) \
56
  static_assert(sizeof(nsStyle##name_) <= kStyleStructSizeLimit, \
57
                "nsStyle" #name_ " became larger than the size limit");
58
#include "nsStyleStructList.h"
59
#undef STYLE_STRUCT
60
61
static bool
62
DefinitelyEqualURIs(css::URLValueData* aURI1,
63
                    css::URLValueData* aURI2)
64
0
{
65
0
  return aURI1 == aURI2 ||
66
0
         (aURI1 && aURI2 && aURI1->DefinitelyEqualURIs(*aURI2));
67
0
}
68
69
static bool
70
DefinitelyEqualURIsAndPrincipal(css::URLValueData* aURI1,
71
                                css::URLValueData* aURI2)
72
0
{
73
0
  return aURI1 == aURI2 ||
74
0
         (aURI1 && aURI2 && aURI1->DefinitelyEqualURIsAndPrincipal(*aURI2));
75
0
}
76
77
static bool
78
DefinitelyEqualImages(nsStyleImageRequest* aRequest1,
79
                      nsStyleImageRequest* aRequest2)
80
0
{
81
0
  if (aRequest1 == aRequest2) {
82
0
    return true;
83
0
  }
84
0
85
0
  if (!aRequest1 || !aRequest2) {
86
0
    return false;
87
0
  }
88
0
89
0
  return aRequest1->DefinitelyEquals(*aRequest2);
90
0
}
91
92
static bool AreShadowArraysEqual(nsCSSShadowArray* lhs, nsCSSShadowArray* rhs);
93
94
// --------------------
95
// nsStyleFont
96
//
97
nsStyleFont::nsStyleFont(const nsStyleFont& aSrc)
98
  : mFont(aSrc.mFont)
99
  , mSize(aSrc.mSize)
100
  , mFontSizeFactor(aSrc.mFontSizeFactor)
101
  , mFontSizeOffset(aSrc.mFontSizeOffset)
102
  , mFontSizeKeyword(aSrc.mFontSizeKeyword)
103
  , mGenericID(aSrc.mGenericID)
104
  , mScriptLevel(aSrc.mScriptLevel)
105
  , mMathVariant(aSrc.mMathVariant)
106
  , mMathDisplay(aSrc.mMathDisplay)
107
  , mMinFontSizeRatio(aSrc.mMinFontSizeRatio)
108
  , mExplicitLanguage(aSrc.mExplicitLanguage)
109
  , mAllowZoom(aSrc.mAllowZoom)
110
  , mScriptUnconstrainedSize(aSrc.mScriptUnconstrainedSize)
111
  , mScriptMinSize(aSrc.mScriptMinSize)
112
  , mScriptSizeMultiplier(aSrc.mScriptSizeMultiplier)
113
  , mLanguage(aSrc.mLanguage)
114
0
{
115
0
  MOZ_COUNT_CTOR(nsStyleFont);
116
0
}
117
118
nsStyleFont::nsStyleFont(const nsPresContext* aContext)
119
  : mFont(*aContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID,
120
                                    nullptr))
121
  , mSize(ZoomText(aContext, mFont.size))
122
  , mFontSizeFactor(1.0)
123
  , mFontSizeOffset(0)
124
  , mFontSizeKeyword(NS_STYLE_FONT_SIZE_MEDIUM)
125
  , mGenericID(kGenericFont_NONE)
126
  , mScriptLevel(0)
127
  , mMathVariant(NS_MATHML_MATHVARIANT_NONE)
128
  , mMathDisplay(NS_MATHML_DISPLAYSTYLE_INLINE)
129
  , mMinFontSizeRatio(100) // 100%
130
  , mExplicitLanguage(false)
131
  , mAllowZoom(true)
132
  , mScriptUnconstrainedSize(mSize)
133
  , mScriptMinSize(nsPresContext::CSSTwipsToAppUnits(
134
      NS_POINTS_TO_TWIPS(NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT)))
135
  , mScriptSizeMultiplier(NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER)
136
  , mLanguage(GetLanguage(aContext))
137
0
{
138
0
  MOZ_COUNT_CTOR(nsStyleFont);
139
0
  MOZ_ASSERT(NS_IsMainThread());
140
0
  nscoord minimumFontSize = aContext->MinFontSize(mLanguage);
141
0
  if (minimumFontSize > 0 && !aContext->IsChrome()) {
142
0
    mFont.size = std::max(mSize, minimumFontSize);
143
0
  } else {
144
0
    mFont.size = mSize;
145
0
  }
146
0
}
147
148
nsChangeHint
149
nsStyleFont::CalcDifference(const nsStyleFont& aNewData) const
150
0
{
151
0
  MOZ_ASSERT(mAllowZoom == aNewData.mAllowZoom,
152
0
             "expected mAllowZoom to be the same on both nsStyleFonts");
153
0
  if (mSize != aNewData.mSize ||
154
0
      mLanguage != aNewData.mLanguage ||
155
0
      mExplicitLanguage != aNewData.mExplicitLanguage ||
156
0
      mMathVariant != aNewData.mMathVariant ||
157
0
      mMathDisplay != aNewData.mMathDisplay ||
158
0
      mMinFontSizeRatio != aNewData.mMinFontSizeRatio) {
159
0
    return NS_STYLE_HINT_REFLOW;
160
0
  }
161
0
162
0
  switch (mFont.CalcDifference(aNewData.mFont)) {
163
0
    case nsFont::MaxDifference::eLayoutAffecting:
164
0
      return NS_STYLE_HINT_REFLOW;
165
0
166
0
    case nsFont::MaxDifference::eVisual:
167
0
      return NS_STYLE_HINT_VISUAL;
168
0
169
0
    case nsFont::MaxDifference::eNone:
170
0
      break;
171
0
  }
172
0
173
0
  // XXX Should any of these cause a non-nsChangeHint_NeutralChange change?
174
0
  if (mGenericID != aNewData.mGenericID ||
175
0
      mScriptLevel != aNewData.mScriptLevel ||
176
0
      mScriptUnconstrainedSize != aNewData.mScriptUnconstrainedSize ||
177
0
      mScriptMinSize != aNewData.mScriptMinSize ||
178
0
      mScriptSizeMultiplier != aNewData.mScriptSizeMultiplier) {
179
0
    return nsChangeHint_NeutralChange;
180
0
  }
181
0
182
0
  return nsChangeHint(0);
183
0
}
184
185
/* static */ nscoord
186
nsStyleFont::ZoomText(const nsPresContext* aPresContext, nscoord aSize)
187
0
{
188
0
  // aSize can be negative (e.g.: calc(-1px)) so we can't assert that here.
189
0
  // The caller is expected deal with that.
190
0
  return NSToCoordTruncClamped(float(aSize) * aPresContext->EffectiveTextZoom());
191
0
}
192
193
/* static */ already_AddRefed<nsAtom>
194
nsStyleFont::GetLanguage(const nsPresContext* aPresContext)
195
0
{
196
0
  RefPtr<nsAtom> language = aPresContext->GetContentLanguage();
197
0
  if (!language) {
198
0
    // we didn't find a (usable) Content-Language, so we fall back
199
0
    // to whatever the presContext guessed from the charset
200
0
    // NOTE this should not be used elsewhere, because we want websites
201
0
    // to use UTF-8 with proper language tag, instead of relying on
202
0
    // deriving language from charset. See bug 1040668 comment 67.
203
0
    language = aPresContext->GetLanguageFromCharset();
204
0
  }
205
0
  return language.forget();
206
0
}
207
208
nsStyleMargin::nsStyleMargin(const nsPresContext* aContext)
209
0
{
210
0
  MOZ_COUNT_CTOR(nsStyleMargin);
211
0
  nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
212
0
  NS_FOR_CSS_SIDES(side) {
213
0
    mMargin.Set(side, zero);
214
0
  }
215
0
}
216
217
nsStyleMargin::nsStyleMargin(const nsStyleMargin& aSrc)
218
  : mMargin(aSrc.mMargin)
219
0
{
220
0
  MOZ_COUNT_CTOR(nsStyleMargin);
221
0
}
222
223
nsChangeHint
224
nsStyleMargin::CalcDifference(const nsStyleMargin& aNewData) const
225
0
{
226
0
  if (mMargin == aNewData.mMargin) {
227
0
    return nsChangeHint(0);
228
0
  }
229
0
  // Margin differences can't affect descendant intrinsic sizes and
230
0
  // don't need to force children to reflow.
231
0
  return nsChangeHint_NeedReflow |
232
0
         nsChangeHint_ReflowChangesSizeOrPosition |
233
0
         nsChangeHint_ClearAncestorIntrinsics;
234
0
}
235
236
nsStylePadding::nsStylePadding(const nsPresContext* aContext)
237
0
{
238
0
  MOZ_COUNT_CTOR(nsStylePadding);
239
0
  nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
240
0
  NS_FOR_CSS_SIDES(side) {
241
0
    mPadding.Set(side, zero);
242
0
  }
243
0
}
244
245
nsStylePadding::nsStylePadding(const nsStylePadding& aSrc)
246
  : mPadding(aSrc.mPadding)
247
0
{
248
0
  MOZ_COUNT_CTOR(nsStylePadding);
249
0
}
250
251
nsChangeHint
252
nsStylePadding::CalcDifference(const nsStylePadding& aNewData) const
253
0
{
254
0
  if (mPadding == aNewData.mPadding) {
255
0
    return nsChangeHint(0);
256
0
  }
257
0
  // Padding differences can't affect descendant intrinsic sizes, but do need
258
0
  // to force children to reflow so that we can reposition them, since their
259
0
  // offsets are from our frame bounds but our content rect's position within
260
0
  // those bounds is moving.
261
0
  // FIXME: It would be good to return a weaker hint here that doesn't
262
0
  // force reflow of all descendants, but the hint would need to force
263
0
  // reflow of the frame's children (see how
264
0
  // ReflowInput::InitResizeFlags initializes the inline-resize flag).
265
0
  return NS_STYLE_HINT_REFLOW & ~nsChangeHint_ClearDescendantIntrinsics;
266
0
}
267
268
nsStyleBorder::nsStyleBorder(const nsPresContext* aContext)
269
  : mBorderImageFill(NS_STYLE_BORDER_IMAGE_SLICE_NOFILL)
270
  , mBorderImageRepeatH(StyleBorderImageRepeat::Stretch)
271
  , mBorderImageRepeatV(StyleBorderImageRepeat::Stretch)
272
  , mFloatEdge(StyleFloatEdge::ContentBox)
273
  , mBoxDecorationBreak(StyleBoxDecorationBreak::Slice)
274
  , mBorderTopColor(StyleComplexColor::CurrentColor())
275
  , mBorderRightColor(StyleComplexColor::CurrentColor())
276
  , mBorderBottomColor(StyleComplexColor::CurrentColor())
277
  , mBorderLeftColor(StyleComplexColor::CurrentColor())
278
  , mComputedBorder(0, 0, 0, 0)
279
0
{
280
0
  MOZ_COUNT_CTOR(nsStyleBorder);
281
0
282
0
  NS_FOR_CSS_HALF_CORNERS (corner) {
283
0
    mBorderRadius.Set(corner, nsStyleCoord(0, nsStyleCoord::CoordConstructor));
284
0
  }
285
0
286
0
  nscoord medium =
287
0
    (StaticPresData::Get()->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM];
288
0
  NS_FOR_CSS_SIDES(side) {
289
0
    mBorderImageSlice.Set(side, nsStyleCoord(1.0f, eStyleUnit_Percent));
290
0
    mBorderImageWidth.Set(side, nsStyleCoord(1.0f, eStyleUnit_Factor));
291
0
    mBorderImageOutset.Set(side, nsStyleCoord(0.0f, eStyleUnit_Factor));
292
0
293
0
    mBorder.Side(side) = medium;
294
0
    mBorderStyle[side] = NS_STYLE_BORDER_STYLE_NONE;
295
0
  }
296
0
297
0
  mTwipsPerPixel = aContext->DevPixelsToAppUnits(1);
298
0
}
299
300
nsStyleBorder::nsStyleBorder(const nsStyleBorder& aSrc)
301
  : mBorderRadius(aSrc.mBorderRadius)
302
  , mBorderImageSource(aSrc.mBorderImageSource)
303
  , mBorderImageSlice(aSrc.mBorderImageSlice)
304
  , mBorderImageWidth(aSrc.mBorderImageWidth)
305
  , mBorderImageOutset(aSrc.mBorderImageOutset)
306
  , mBorderImageFill(aSrc.mBorderImageFill)
307
  , mBorderImageRepeatH(aSrc.mBorderImageRepeatH)
308
  , mBorderImageRepeatV(aSrc.mBorderImageRepeatV)
309
  , mFloatEdge(aSrc.mFloatEdge)
310
  , mBoxDecorationBreak(aSrc.mBoxDecorationBreak)
311
  , mBorderTopColor(aSrc.mBorderTopColor)
312
  , mBorderRightColor(aSrc.mBorderRightColor)
313
  , mBorderBottomColor(aSrc.mBorderBottomColor)
314
  , mBorderLeftColor(aSrc.mBorderLeftColor)
315
  , mComputedBorder(aSrc.mComputedBorder)
316
  , mBorder(aSrc.mBorder)
317
  , mTwipsPerPixel(aSrc.mTwipsPerPixel)
318
0
{
319
0
  MOZ_COUNT_CTOR(nsStyleBorder);
320
0
  NS_FOR_CSS_SIDES(side) {
321
0
    mBorderStyle[side] = aSrc.mBorderStyle[side];
322
0
  }
323
0
}
324
325
nsStyleBorder::~nsStyleBorder()
326
0
{
327
0
  MOZ_COUNT_DTOR(nsStyleBorder);
328
0
}
329
330
void
331
nsStyleBorder::FinishStyle(nsPresContext* aPresContext, const nsStyleBorder* aOldStyle)
332
0
{
333
0
  MOZ_ASSERT(NS_IsMainThread());
334
0
335
0
  mBorderImageSource.ResolveImage(
336
0
    aPresContext, aOldStyle ? &aOldStyle->mBorderImageSource : nullptr);
337
0
}
338
339
nsMargin
340
nsStyleBorder::GetImageOutset() const
341
0
{
342
0
  // We don't check whether there is a border-image (which is OK since
343
0
  // the initial values yields 0 outset) so that we don't have to
344
0
  // reflow to update overflow areas when an image loads.
345
0
  nsMargin outset;
346
0
  NS_FOR_CSS_SIDES(s) {
347
0
    nsStyleCoord coord = mBorderImageOutset.Get(s);
348
0
    nscoord value;
349
0
    switch (coord.GetUnit()) {
350
0
      case eStyleUnit_Coord:
351
0
        value = coord.GetCoordValue();
352
0
        break;
353
0
      case eStyleUnit_Factor:
354
0
        value = coord.GetFactorValue() * mComputedBorder.Side(s);
355
0
        break;
356
0
      default:
357
0
        MOZ_ASSERT_UNREACHABLE("unexpected CSS unit for image outset");
358
0
        value = 0;
359
0
        break;
360
0
    }
361
0
    outset.Side(s) = value;
362
0
  }
363
0
  return outset;
364
0
}
365
366
nsChangeHint
367
nsStyleBorder::CalcDifference(const nsStyleBorder& aNewData) const
368
0
{
369
0
  // FIXME: XXXbz: As in nsStylePadding::CalcDifference, many of these
370
0
  // differences should not need to clear descendant intrinsics.
371
0
  // FIXME: It would be good to return a weaker hint for the
372
0
  // GetComputedBorder() differences (and perhaps others) that doesn't
373
0
  // force reflow of all descendants, but the hint would need to force
374
0
  // reflow of the frame's children (see how
375
0
  // ReflowInput::InitResizeFlags initializes the inline-resize flag).
376
0
  if (mTwipsPerPixel != aNewData.mTwipsPerPixel ||
377
0
      GetComputedBorder() != aNewData.GetComputedBorder() ||
378
0
      mFloatEdge != aNewData.mFloatEdge ||
379
0
      mBorderImageOutset != aNewData.mBorderImageOutset ||
380
0
      mBoxDecorationBreak != aNewData.mBoxDecorationBreak) {
381
0
    return NS_STYLE_HINT_REFLOW;
382
0
  }
383
0
384
0
  NS_FOR_CSS_SIDES(ix) {
385
0
    // See the explanation in nsChangeHint.h of
386
0
    // nsChangeHint_BorderStyleNoneChange .
387
0
    // Furthermore, even though we know *this* side is 0 width, just
388
0
    // assume a repaint hint for some other change rather than bother
389
0
    // tracking this result through the rest of the function.
390
0
    if (HasVisibleStyle(ix) != aNewData.HasVisibleStyle(ix)) {
391
0
      return nsChangeHint_RepaintFrame |
392
0
             nsChangeHint_BorderStyleNoneChange;
393
0
    }
394
0
  }
395
0
396
0
  // Note that mBorderStyle stores not only the border style but also
397
0
  // color-related flags.  Given that we've already done an mComputedBorder
398
0
  // comparison, border-style differences can only lead to a repaint hint.  So
399
0
  // it's OK to just compare the values directly -- if either the actual
400
0
  // style or the color flags differ we want to repaint.
401
0
  NS_FOR_CSS_SIDES(ix) {
402
0
    if (mBorderStyle[ix] != aNewData.mBorderStyle[ix] ||
403
0
        BorderColorFor(ix) != aNewData.BorderColorFor(ix)) {
404
0
      return nsChangeHint_RepaintFrame;
405
0
    }
406
0
  }
407
0
408
0
  if (mBorderRadius != aNewData.mBorderRadius) {
409
0
    return nsChangeHint_RepaintFrame;
410
0
  }
411
0
412
0
  // Loading status of the border image can be accessed in main thread only
413
0
  // while CalcDifference might be executed on a background thread. As a
414
0
  // result, we have to check mBorderImage* fields even before border image was
415
0
  // actually loaded.
416
0
  if (!mBorderImageSource.IsEmpty() || !aNewData.mBorderImageSource.IsEmpty()) {
417
0
    if (mBorderImageSource  != aNewData.mBorderImageSource  ||
418
0
        mBorderImageRepeatH != aNewData.mBorderImageRepeatH ||
419
0
        mBorderImageRepeatV != aNewData.mBorderImageRepeatV ||
420
0
        mBorderImageSlice   != aNewData.mBorderImageSlice   ||
421
0
        mBorderImageFill    != aNewData.mBorderImageFill    ||
422
0
        mBorderImageWidth   != aNewData.mBorderImageWidth) {
423
0
      return nsChangeHint_RepaintFrame;
424
0
    }
425
0
  }
426
0
427
0
  // mBorder is the specified border value.  Changes to this don't
428
0
  // need any change processing, since we operate on the computed
429
0
  // border values instead.
430
0
  if (mBorder != aNewData.mBorder) {
431
0
    return nsChangeHint_NeutralChange;
432
0
  }
433
0
434
0
  // mBorderImage* fields are checked only when border-image is not 'none'.
435
0
  if (mBorderImageSource  != aNewData.mBorderImageSource  ||
436
0
      mBorderImageRepeatH != aNewData.mBorderImageRepeatH ||
437
0
      mBorderImageRepeatV != aNewData.mBorderImageRepeatV ||
438
0
      mBorderImageSlice   != aNewData.mBorderImageSlice   ||
439
0
      mBorderImageFill    != aNewData.mBorderImageFill    ||
440
0
      mBorderImageWidth   != aNewData.mBorderImageWidth) {
441
0
    return nsChangeHint_NeutralChange;
442
0
  }
443
0
444
0
  return nsChangeHint(0);
445
0
}
446
447
nsStyleOutline::nsStyleOutline(const nsPresContext* aContext)
448
  : mOutlineWidth((StaticPresData::Get()
449
                     ->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM])
450
  , mOutlineOffset(0)
451
  , mOutlineColor(StyleComplexColor::CurrentColor())
452
  , mOutlineStyle(NS_STYLE_BORDER_STYLE_NONE)
453
  , mActualOutlineWidth(0)
454
  , mTwipsPerPixel(aContext->DevPixelsToAppUnits(1))
455
0
{
456
0
  MOZ_COUNT_CTOR(nsStyleOutline);
457
0
  // spacing values not inherited
458
0
  nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
459
0
  NS_FOR_CSS_HALF_CORNERS(corner) {
460
0
    mOutlineRadius.Set(corner, zero);
461
0
  }
462
0
}
463
464
nsStyleOutline::nsStyleOutline(const nsStyleOutline& aSrc)
465
  : mOutlineRadius(aSrc.mOutlineRadius)
466
  , mOutlineWidth(aSrc.mOutlineWidth)
467
  , mOutlineOffset(aSrc.mOutlineOffset)
468
  , mOutlineColor(aSrc.mOutlineColor)
469
  , mOutlineStyle(aSrc.mOutlineStyle)
470
  , mActualOutlineWidth(aSrc.mActualOutlineWidth)
471
  , mTwipsPerPixel(aSrc.mTwipsPerPixel)
472
0
{
473
0
  MOZ_COUNT_CTOR(nsStyleOutline);
474
0
}
475
476
void
477
nsStyleOutline::RecalcData()
478
0
{
479
0
  if (NS_STYLE_BORDER_STYLE_NONE == mOutlineStyle) {
480
0
    mActualOutlineWidth = 0;
481
0
  } else {
482
0
    mActualOutlineWidth =
483
0
      NS_ROUND_BORDER_TO_PIXELS(mOutlineWidth, mTwipsPerPixel);
484
0
  }
485
0
}
486
487
nsChangeHint
488
nsStyleOutline::CalcDifference(const nsStyleOutline& aNewData) const
489
0
{
490
0
  if (mActualOutlineWidth != aNewData.mActualOutlineWidth ||
491
0
      (mActualOutlineWidth > 0 &&
492
0
       mOutlineOffset != aNewData.mOutlineOffset)) {
493
0
    return nsChangeHint_UpdateOverflow |
494
0
           nsChangeHint_SchedulePaint |
495
0
           nsChangeHint_RepaintFrame;
496
0
  }
497
0
498
0
  if (mOutlineStyle != aNewData.mOutlineStyle ||
499
0
      mOutlineColor != aNewData.mOutlineColor ||
500
0
      mOutlineRadius != aNewData.mOutlineRadius) {
501
0
    if (mActualOutlineWidth > 0) {
502
0
      return nsChangeHint_RepaintFrame;
503
0
    }
504
0
    return nsChangeHint_NeutralChange;
505
0
  }
506
0
507
0
  if (mOutlineWidth != aNewData.mOutlineWidth ||
508
0
      mOutlineOffset != aNewData.mOutlineOffset ||
509
0
      mTwipsPerPixel != aNewData.mTwipsPerPixel) {
510
0
    return nsChangeHint_NeutralChange;
511
0
  }
512
0
513
0
  return nsChangeHint(0);
514
0
}
515
516
// --------------------
517
// nsStyleList
518
//
519
nsStyleList::nsStyleList(const nsPresContext* aContext)
520
  : mListStylePosition(NS_STYLE_LIST_STYLE_POSITION_OUTSIDE)
521
0
{
522
0
  MOZ_COUNT_CTOR(nsStyleList);
523
0
  MOZ_ASSERT(NS_IsMainThread());
524
0
525
0
  mCounterStyle = CounterStyleManager::GetDiscStyle();
526
0
527
0
  if (!sInitialQuotes) {
528
0
    // The initial value for quotes is the en-US typographic convention:
529
0
    // outermost are LEFT and RIGHT DOUBLE QUOTATION MARK, alternating
530
0
    // with LEFT and RIGHT SINGLE QUOTATION MARK.
531
0
    static const char16_t initialQuotes[8] = {
532
0
      0x201C, 0, 0x201D, 0, 0x2018, 0, 0x2019, 0
533
0
    };
534
0
535
0
    sInitialQuotes = new nsStyleQuoteValues;
536
0
    sInitialQuotes->mQuotePairs.AppendElement(
537
0
        std::make_pair(nsDependentString(&initialQuotes[0], 1),
538
0
                       nsDependentString(&initialQuotes[2], 1)));
539
0
    sInitialQuotes->mQuotePairs.AppendElement(
540
0
        std::make_pair(nsDependentString(&initialQuotes[4], 1),
541
0
                       nsDependentString(&initialQuotes[6], 1)));
542
0
  }
543
0
544
0
  mQuotes = sInitialQuotes;
545
0
}
546
547
nsStyleList::~nsStyleList()
548
0
{
549
0
  MOZ_COUNT_DTOR(nsStyleList);
550
0
}
551
552
nsStyleList::nsStyleList(const nsStyleList& aSource)
553
  : mListStylePosition(aSource.mListStylePosition)
554
  , mListStyleImage(aSource.mListStyleImage)
555
  , mCounterStyle(aSource.mCounterStyle)
556
  , mQuotes(aSource.mQuotes)
557
  , mImageRegion(aSource.mImageRegion)
558
0
{
559
0
  MOZ_COUNT_CTOR(nsStyleList);
560
0
}
561
562
void
563
nsStyleList::FinishStyle(nsPresContext* aPresContext, const nsStyleList* aOldStyle)
564
0
{
565
0
  MOZ_ASSERT(NS_IsMainThread());
566
0
567
0
  if (mListStyleImage && !mListStyleImage->IsResolved()) {
568
0
    mListStyleImage->Resolve(
569
0
      aPresContext, aOldStyle ? aOldStyle->mListStyleImage.get() : nullptr);
570
0
  }
571
0
  mCounterStyle.Resolve(aPresContext->CounterStyleManager());
572
0
}
573
574
nsChangeHint
575
nsStyleList::CalcDifference(const nsStyleList& aNewData,
576
                            const nsStyleDisplay* aOldDisplay) const
577
0
{
578
0
  // If the quotes implementation is ever going to change we might not need
579
0
  // a framechange here and a reflow should be sufficient.  See bug 35768.
580
0
  if (mQuotes != aNewData.mQuotes &&
581
0
      (mQuotes || aNewData.mQuotes) &&
582
0
      GetQuotePairs() != aNewData.GetQuotePairs()) {
583
0
    return nsChangeHint_ReconstructFrame;
584
0
  }
585
0
  nsChangeHint hint = nsChangeHint(0);
586
0
  // Only elements whose display value is list-item can be affected by
587
0
  // list-style-position and list-style-type. If the old display struct
588
0
  // doesn't exist, assume it isn't affected by display value at all,
589
0
  // and thus these properties should not affect it either. This also
590
0
  // relies on that when the display value changes from something else
591
0
  // to list-item, that change itself would cause ReconstructFrame.
592
0
  if (aOldDisplay && aOldDisplay->mDisplay == StyleDisplay::ListItem) {
593
0
    if (mListStylePosition != aNewData.mListStylePosition) {
594
0
      return nsChangeHint_ReconstructFrame;
595
0
    }
596
0
    if (mCounterStyle != aNewData.mCounterStyle) {
597
0
      return NS_STYLE_HINT_REFLOW;
598
0
    }
599
0
  } else if (mListStylePosition != aNewData.mListStylePosition ||
600
0
             mCounterStyle != aNewData.mCounterStyle) {
601
0
    hint = nsChangeHint_NeutralChange;
602
0
  }
603
0
  // list-style-image and -moz-image-region may affect some XUL elements
604
0
  // regardless of display value, so we still need to check them.
605
0
  if (!DefinitelyEqualImages(mListStyleImage, aNewData.mListStyleImage)) {
606
0
    return NS_STYLE_HINT_REFLOW;
607
0
  }
608
0
  if (!mImageRegion.IsEqualInterior(aNewData.mImageRegion)) {
609
0
    if (mImageRegion.width != aNewData.mImageRegion.width ||
610
0
        mImageRegion.height != aNewData.mImageRegion.height) {
611
0
      return NS_STYLE_HINT_REFLOW;
612
0
    }
613
0
    return NS_STYLE_HINT_VISUAL;
614
0
  }
615
0
  return hint;
616
0
}
617
618
already_AddRefed<nsIURI>
619
nsStyleList::GetListStyleImageURI() const
620
0
{
621
0
  if (!mListStyleImage) {
622
0
    return nullptr;
623
0
  }
624
0
625
0
  nsCOMPtr<nsIURI> uri = mListStyleImage->GetImageURI();
626
0
  return uri.forget();
627
0
}
628
629
StaticRefPtr<nsStyleQuoteValues>
630
nsStyleList::sInitialQuotes;
631
632
633
// --------------------
634
// nsStyleXUL
635
//
636
nsStyleXUL::nsStyleXUL(const nsPresContext* aContext)
637
  : mBoxFlex(0.0f)
638
  , mBoxOrdinal(1)
639
  , mBoxAlign(StyleBoxAlign::Stretch)
640
  , mBoxDirection(StyleBoxDirection::Normal)
641
  , mBoxOrient(StyleBoxOrient::Horizontal)
642
  , mBoxPack(StyleBoxPack::Start)
643
  , mStackSizing(StyleStackSizing::StretchToFit)
644
0
{
645
0
  MOZ_COUNT_CTOR(nsStyleXUL);
646
0
}
647
648
nsStyleXUL::~nsStyleXUL()
649
0
{
650
0
  MOZ_COUNT_DTOR(nsStyleXUL);
651
0
}
652
653
nsStyleXUL::nsStyleXUL(const nsStyleXUL& aSource)
654
  : mBoxFlex(aSource.mBoxFlex)
655
  , mBoxOrdinal(aSource.mBoxOrdinal)
656
  , mBoxAlign(aSource.mBoxAlign)
657
  , mBoxDirection(aSource.mBoxDirection)
658
  , mBoxOrient(aSource.mBoxOrient)
659
  , mBoxPack(aSource.mBoxPack)
660
  , mStackSizing(aSource.mStackSizing)
661
0
{
662
0
  MOZ_COUNT_CTOR(nsStyleXUL);
663
0
}
664
665
nsChangeHint
666
nsStyleXUL::CalcDifference(const nsStyleXUL& aNewData) const
667
0
{
668
0
  if (mBoxAlign == aNewData.mBoxAlign &&
669
0
      mBoxDirection == aNewData.mBoxDirection &&
670
0
      mBoxFlex == aNewData.mBoxFlex &&
671
0
      mBoxOrient == aNewData.mBoxOrient &&
672
0
      mBoxPack == aNewData.mBoxPack &&
673
0
      mBoxOrdinal == aNewData.mBoxOrdinal &&
674
0
      mStackSizing == aNewData.mStackSizing) {
675
0
    return nsChangeHint(0);
676
0
  }
677
0
  if (mBoxOrdinal != aNewData.mBoxOrdinal) {
678
0
    return nsChangeHint_ReconstructFrame;
679
0
  }
680
0
  return NS_STYLE_HINT_REFLOW;
681
0
}
682
683
// --------------------
684
// nsStyleColumn
685
//
686
/* static */ const uint32_t nsStyleColumn::kMaxColumnCount;
687
/* static */ const uint32_t nsStyleColumn::kColumnCountAuto;
688
689
nsStyleColumn::nsStyleColumn(const nsPresContext* aContext)
690
  : mColumnWidth(eStyleUnit_Auto)
691
  , mColumnRuleColor(StyleComplexColor::CurrentColor())
692
  , mColumnRuleStyle(NS_STYLE_BORDER_STYLE_NONE)
693
  , mColumnRuleWidth((StaticPresData::Get()
694
                        ->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM])
695
  , mTwipsPerPixel(aContext->AppUnitsPerDevPixel())
696
0
{
697
0
  MOZ_COUNT_CTOR(nsStyleColumn);
698
0
}
699
700
nsStyleColumn::~nsStyleColumn()
701
0
{
702
0
  MOZ_COUNT_DTOR(nsStyleColumn);
703
0
}
704
705
nsStyleColumn::nsStyleColumn(const nsStyleColumn& aSource)
706
  : mColumnCount(aSource.mColumnCount)
707
  , mColumnWidth(aSource.mColumnWidth)
708
  , mColumnRuleColor(aSource.mColumnRuleColor)
709
  , mColumnRuleStyle(aSource.mColumnRuleStyle)
710
  , mColumnFill(aSource.mColumnFill)
711
  , mColumnSpan(aSource.mColumnSpan)
712
  , mColumnRuleWidth(aSource.mColumnRuleWidth)
713
  , mTwipsPerPixel(aSource.mTwipsPerPixel)
714
0
{
715
0
  MOZ_COUNT_CTOR(nsStyleColumn);
716
0
}
717
718
nsChangeHint
719
nsStyleColumn::CalcDifference(const nsStyleColumn& aNewData) const
720
0
{
721
0
  if ((mColumnWidth.GetUnit() == eStyleUnit_Auto)
722
0
      != (aNewData.mColumnWidth.GetUnit() == eStyleUnit_Auto) ||
723
0
      mColumnCount != aNewData.mColumnCount ||
724
0
      mColumnSpan != aNewData.mColumnSpan) {
725
0
    // We force column count changes to do a reframe, because it's tricky to handle
726
0
    // some edge cases where the column count gets smaller and content overflows.
727
0
    // XXX not ideal
728
0
    return nsChangeHint_ReconstructFrame;
729
0
  }
730
0
731
0
  if (mColumnWidth != aNewData.mColumnWidth ||
732
0
      mColumnFill != aNewData.mColumnFill) {
733
0
    return NS_STYLE_HINT_REFLOW;
734
0
  }
735
0
736
0
  if (GetComputedColumnRuleWidth() != aNewData.GetComputedColumnRuleWidth() ||
737
0
      mColumnRuleStyle != aNewData.mColumnRuleStyle ||
738
0
      mColumnRuleColor != aNewData.mColumnRuleColor) {
739
0
    return NS_STYLE_HINT_VISUAL;
740
0
  }
741
0
742
0
  // XXX Is it right that we never check mTwipsPerPixel to return a
743
0
  // non-nsChangeHint_NeutralChange hint?
744
0
  if (mColumnRuleWidth != aNewData.mColumnRuleWidth ||
745
0
      mTwipsPerPixel != aNewData.mTwipsPerPixel) {
746
0
    return nsChangeHint_NeutralChange;
747
0
  }
748
0
749
0
  return nsChangeHint(0);
750
0
}
751
752
// --------------------
753
// nsStyleSVG
754
//
755
nsStyleSVG::nsStyleSVG(const nsPresContext* aContext)
756
  : mFill(eStyleSVGPaintType_Color) // Will be initialized to NS_RGB(0, 0, 0)
757
  , mStroke(eStyleSVGPaintType_None)
758
  , mStrokeDashoffset(0, nsStyleCoord::CoordConstructor)
759
  , mStrokeWidth(nsPresContext::CSSPixelsToAppUnits(1), nsStyleCoord::CoordConstructor)
760
  , mFillOpacity(1.0f)
761
  , mStrokeMiterlimit(4.0f)
762
  , mStrokeOpacity(1.0f)
763
  , mClipRule(StyleFillRule::Nonzero)
764
  , mColorInterpolation(NS_STYLE_COLOR_INTERPOLATION_SRGB)
765
  , mColorInterpolationFilters(NS_STYLE_COLOR_INTERPOLATION_LINEARRGB)
766
  , mFillRule(StyleFillRule::Nonzero)
767
  , mPaintOrder(NS_STYLE_PAINT_ORDER_NORMAL)
768
  , mShapeRendering(NS_STYLE_SHAPE_RENDERING_AUTO)
769
  , mStrokeLinecap(NS_STYLE_STROKE_LINECAP_BUTT)
770
  , mStrokeLinejoin(NS_STYLE_STROKE_LINEJOIN_MITER)
771
  , mTextAnchor(NS_STYLE_TEXT_ANCHOR_START)
772
  , mContextPropsBits(0)
773
  , mContextFlags((eStyleSVGOpacitySource_Normal << FILL_OPACITY_SOURCE_SHIFT) |
774
                  (eStyleSVGOpacitySource_Normal << STROKE_OPACITY_SOURCE_SHIFT))
775
0
{
776
0
  MOZ_COUNT_CTOR(nsStyleSVG);
777
0
}
778
779
nsStyleSVG::~nsStyleSVG()
780
0
{
781
0
  MOZ_COUNT_DTOR(nsStyleSVG);
782
0
}
783
784
nsStyleSVG::nsStyleSVG(const nsStyleSVG& aSource)
785
  : mFill(aSource.mFill)
786
  , mStroke(aSource.mStroke)
787
  , mMarkerEnd(aSource.mMarkerEnd)
788
  , mMarkerMid(aSource.mMarkerMid)
789
  , mMarkerStart(aSource.mMarkerStart)
790
  , mStrokeDasharray(aSource.mStrokeDasharray)
791
  , mContextProps(aSource.mContextProps)
792
  , mStrokeDashoffset(aSource.mStrokeDashoffset)
793
  , mStrokeWidth(aSource.mStrokeWidth)
794
  , mFillOpacity(aSource.mFillOpacity)
795
  , mStrokeMiterlimit(aSource.mStrokeMiterlimit)
796
  , mStrokeOpacity(aSource.mStrokeOpacity)
797
  , mClipRule(aSource.mClipRule)
798
  , mColorInterpolation(aSource.mColorInterpolation)
799
  , mColorInterpolationFilters(aSource.mColorInterpolationFilters)
800
  , mFillRule(aSource.mFillRule)
801
  , mPaintOrder(aSource.mPaintOrder)
802
  , mShapeRendering(aSource.mShapeRendering)
803
  , mStrokeLinecap(aSource.mStrokeLinecap)
804
  , mStrokeLinejoin(aSource.mStrokeLinejoin)
805
  , mTextAnchor(aSource.mTextAnchor)
806
  , mContextPropsBits(aSource.mContextPropsBits)
807
  , mContextFlags(aSource.mContextFlags)
808
0
{
809
0
  MOZ_COUNT_CTOR(nsStyleSVG);
810
0
}
811
812
static bool
813
PaintURIChanged(const nsStyleSVGPaint& aPaint1, const nsStyleSVGPaint& aPaint2)
814
0
{
815
0
  if (aPaint1.Type() != aPaint2.Type()) {
816
0
    return aPaint1.Type() == eStyleSVGPaintType_Server ||
817
0
           aPaint2.Type() == eStyleSVGPaintType_Server;
818
0
  }
819
0
  return aPaint1.Type() == eStyleSVGPaintType_Server &&
820
0
         !DefinitelyEqualURIs(aPaint1.GetPaintServer(),
821
0
                              aPaint2.GetPaintServer());
822
0
}
823
824
nsChangeHint
825
nsStyleSVG::CalcDifference(const nsStyleSVG& aNewData) const
826
0
{
827
0
  nsChangeHint hint = nsChangeHint(0);
828
0
829
0
  if (!DefinitelyEqualURIs(mMarkerEnd, aNewData.mMarkerEnd) ||
830
0
      !DefinitelyEqualURIs(mMarkerMid, aNewData.mMarkerMid) ||
831
0
      !DefinitelyEqualURIs(mMarkerStart, aNewData.mMarkerStart)) {
832
0
    // Markers currently contribute to SVGGeometryFrame::mRect,
833
0
    // so we need a reflow as well as a repaint. No intrinsic sizes need
834
0
    // to change, so nsChangeHint_NeedReflow is sufficient.
835
0
    return nsChangeHint_UpdateEffects |
836
0
           nsChangeHint_NeedReflow |
837
0
           nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
838
0
           nsChangeHint_RepaintFrame;
839
0
  }
840
0
841
0
  if (mFill != aNewData.mFill ||
842
0
      mStroke != aNewData.mStroke ||
843
0
      mFillOpacity != aNewData.mFillOpacity ||
844
0
      mStrokeOpacity != aNewData.mStrokeOpacity) {
845
0
    hint |= nsChangeHint_RepaintFrame;
846
0
    if (HasStroke() != aNewData.HasStroke() ||
847
0
        (!HasStroke() && HasFill() != aNewData.HasFill())) {
848
0
      // Frame bounds and overflow rects depend on whether we "have" fill or
849
0
      // stroke. Whether we have stroke or not just changed, or else we have no
850
0
      // stroke (in which case whether we have fill or not is significant to frame
851
0
      // bounds) and whether we have fill or not just changed. In either case we
852
0
      // need to reflow so the frame rect is updated.
853
0
      // XXXperf this is a waste on non SVGGeometryFrames.
854
0
      hint |= nsChangeHint_NeedReflow |
855
0
              nsChangeHint_NeedDirtyReflow; // XXX remove me: bug 876085
856
0
    }
857
0
    if (PaintURIChanged(mFill, aNewData.mFill) ||
858
0
        PaintURIChanged(mStroke, aNewData.mStroke)) {
859
0
      hint |= nsChangeHint_UpdateEffects;
860
0
    }
861
0
  }
862
0
863
0
  // Stroke currently contributes to SVGGeometryFrame::mRect, so
864
0
  // we need a reflow here. No intrinsic sizes need to change, so
865
0
  // nsChangeHint_NeedReflow is sufficient.
866
0
  // Note that stroke-dashoffset does not affect SVGGeometryFrame::mRect.
867
0
  // text-anchor changes also require a reflow since it changes frames' rects.
868
0
  if (mStrokeWidth           != aNewData.mStrokeWidth           ||
869
0
      mStrokeMiterlimit      != aNewData.mStrokeMiterlimit      ||
870
0
      mStrokeLinecap         != aNewData.mStrokeLinecap         ||
871
0
      mStrokeLinejoin        != aNewData.mStrokeLinejoin        ||
872
0
      mTextAnchor            != aNewData.mTextAnchor) {
873
0
    return hint |
874
0
           nsChangeHint_NeedReflow |
875
0
           nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
876
0
           nsChangeHint_RepaintFrame;
877
0
  }
878
0
879
0
  if (hint & nsChangeHint_RepaintFrame) {
880
0
    return hint; // we don't add anything else below
881
0
  }
882
0
883
0
  if ( mStrokeDashoffset      != aNewData.mStrokeDashoffset      ||
884
0
       mClipRule              != aNewData.mClipRule              ||
885
0
       mColorInterpolation    != aNewData.mColorInterpolation    ||
886
0
       mColorInterpolationFilters != aNewData.mColorInterpolationFilters ||
887
0
       mFillRule              != aNewData.mFillRule              ||
888
0
       mPaintOrder            != aNewData.mPaintOrder            ||
889
0
       mShapeRendering        != aNewData.mShapeRendering        ||
890
0
       mStrokeDasharray       != aNewData.mStrokeDasharray       ||
891
0
       mContextFlags          != aNewData.mContextFlags          ||
892
0
       mContextPropsBits      != aNewData.mContextPropsBits) {
893
0
    return hint | nsChangeHint_RepaintFrame;
894
0
  }
895
0
896
0
  if (!hint) {
897
0
    if (mContextProps != aNewData.mContextProps) {
898
0
      hint = nsChangeHint_NeutralChange;
899
0
    }
900
0
  }
901
0
902
0
  return hint;
903
0
}
904
905
// --------------------
906
// StyleBasicShape
907
908
nsCSSKeyword
909
StyleBasicShape::GetShapeTypeName() const
910
0
{
911
0
  switch (mType) {
912
0
    case StyleBasicShapeType::Polygon:
913
0
      return eCSSKeyword_polygon;
914
0
    case StyleBasicShapeType::Circle:
915
0
      return eCSSKeyword_circle;
916
0
    case StyleBasicShapeType::Ellipse:
917
0
      return eCSSKeyword_ellipse;
918
0
    case StyleBasicShapeType::Inset:
919
0
      return eCSSKeyword_inset;
920
0
  }
921
0
  MOZ_ASSERT_UNREACHABLE("unexpected type");
922
0
  return eCSSKeyword_UNKNOWN;
923
0
}
924
925
// --------------------
926
// StyleShapeSource
927
StyleShapeSource::StyleShapeSource()
928
  : mBasicShape()
929
0
{
930
0
}
931
932
StyleShapeSource::StyleShapeSource(const StyleShapeSource& aSource)
933
0
{
934
0
  DoCopy(aSource);
935
0
}
936
937
StyleShapeSource::~StyleShapeSource()
938
0
{
939
0
  DoDestroy();
940
0
}
941
942
StyleShapeSource&
943
StyleShapeSource::operator=(const StyleShapeSource& aOther)
944
0
{
945
0
  if (this != &aOther) {
946
0
    DoCopy(aOther);
947
0
  }
948
0
949
0
  return *this;
950
0
}
951
952
bool
953
StyleShapeSource::operator==(const StyleShapeSource& aOther) const
954
0
{
955
0
  if (mType != aOther.mType) {
956
0
    return false;
957
0
  }
958
0
959
0
  switch (mType) {
960
0
    case StyleShapeSourceType::None:
961
0
      return true;
962
0
963
0
    case StyleShapeSourceType::URL:
964
0
    case StyleShapeSourceType::Image:
965
0
      return *mShapeImage == *aOther.mShapeImage;
966
0
967
0
    case StyleShapeSourceType::Shape:
968
0
      return *mBasicShape == *aOther.mBasicShape &&
969
0
        mReferenceBox == aOther.mReferenceBox;
970
0
971
0
    case StyleShapeSourceType::Box:
972
0
      return mReferenceBox == aOther.mReferenceBox;
973
0
974
0
    case StyleShapeSourceType::Path:
975
0
      return *mSVGPath == *aOther.mSVGPath;
976
0
  }
977
0
978
0
  MOZ_ASSERT_UNREACHABLE("Unexpected shape source type!");
979
0
  return true;
980
0
}
981
982
void
983
StyleShapeSource::SetURL(css::URLValue* aValue)
984
0
{
985
0
  MOZ_ASSERT(aValue);
986
0
  if (mType != StyleShapeSourceType::Image &&
987
0
      mType != StyleShapeSourceType::URL) {
988
0
    DoDestroy();
989
0
    new (&mShapeImage) UniquePtr<nsStyleImage>(new nsStyleImage());
990
0
  }
991
0
  mShapeImage->SetURLValue(do_AddRef(aValue));
992
0
  mType = StyleShapeSourceType::URL;
993
0
}
994
995
void
996
StyleShapeSource::SetShapeImage(UniquePtr<nsStyleImage> aShapeImage)
997
0
{
998
0
  MOZ_ASSERT(aShapeImage);
999
0
  DoDestroy();
1000
0
  new (&mShapeImage) UniquePtr<nsStyleImage>(std::move(aShapeImage));
1001
0
  mType = StyleShapeSourceType::Image;
1002
0
}
1003
1004
imgIRequest*
1005
StyleShapeSource::GetShapeImageData() const
1006
0
{
1007
0
  if (mType != StyleShapeSourceType::Image) {
1008
0
    return nullptr;
1009
0
  }
1010
0
  if (mShapeImage->GetType() != eStyleImageType_Image) {
1011
0
    return nullptr;
1012
0
  }
1013
0
  return mShapeImage->GetImageData();
1014
0
}
1015
1016
void
1017
StyleShapeSource::SetBasicShape(UniquePtr<StyleBasicShape> aBasicShape,
1018
                                StyleGeometryBox aReferenceBox)
1019
0
{
1020
0
  MOZ_ASSERT(aBasicShape);
1021
0
  DoDestroy();
1022
0
  new (&mBasicShape) UniquePtr<StyleBasicShape>(std::move(aBasicShape));
1023
0
  mReferenceBox = aReferenceBox;
1024
0
  mType = StyleShapeSourceType::Shape;
1025
0
}
1026
1027
void
1028
StyleShapeSource::SetPath(UniquePtr<StyleSVGPath> aPath)
1029
0
{
1030
0
  MOZ_ASSERT(aPath);
1031
0
  DoDestroy();
1032
0
  new (&mSVGPath) UniquePtr<StyleSVGPath>(std::move(aPath));
1033
0
  mType = StyleShapeSourceType::Path;
1034
0
}
1035
1036
void
1037
StyleShapeSource::SetReferenceBox(StyleGeometryBox aReferenceBox)
1038
0
{
1039
0
  DoDestroy();
1040
0
  mReferenceBox = aReferenceBox;
1041
0
  mType = StyleShapeSourceType::Box;
1042
0
}
1043
1044
void
1045
StyleShapeSource::DoCopy(const StyleShapeSource& aOther)
1046
{
1047
  switch (aOther.mType) {
1048
    case StyleShapeSourceType::None:
1049
      mReferenceBox = StyleGeometryBox::NoBox;
1050
      mType = StyleShapeSourceType::None;
1051
      break;
1052
1053
    case StyleShapeSourceType::URL:
1054
      SetURL(aOther.GetURL());
1055
      break;
1056
1057
    case StyleShapeSourceType::Image:
1058
      SetShapeImage(MakeUnique<nsStyleImage>(*aOther.GetShapeImage()));
1059
      break;
1060
1061
    case StyleShapeSourceType::Shape:
1062
      SetBasicShape(MakeUnique<StyleBasicShape>(*aOther.GetBasicShape()),
1063
                    aOther.GetReferenceBox());
1064
      break;
1065
1066
    case StyleShapeSourceType::Box:
1067
      SetReferenceBox(aOther.GetReferenceBox());
1068
      break;
1069
1070
    case StyleShapeSourceType::Path:
1071
      SetPath(MakeUnique<StyleSVGPath>(*aOther.GetPath()));
1072
      break;
1073
  }
1074
}
1075
1076
void
1077
StyleShapeSource::DoDestroy()
1078
0
{
1079
0
  switch (mType) {
1080
0
    case StyleShapeSourceType::Shape:
1081
0
      mBasicShape.~UniquePtr<StyleBasicShape>();
1082
0
      break;
1083
0
    case StyleShapeSourceType::Image:
1084
0
    case StyleShapeSourceType::URL:
1085
0
      mShapeImage.~UniquePtr<nsStyleImage>();
1086
0
      break;
1087
0
    case StyleShapeSourceType::Path:
1088
0
      mSVGPath.~UniquePtr<StyleSVGPath>();
1089
0
      break;
1090
0
    case StyleShapeSourceType::None:
1091
0
    case StyleShapeSourceType::Box:
1092
0
      // Not a union type, so do nothing.
1093
0
      break;
1094
0
  }
1095
0
  mType = StyleShapeSourceType::None;
1096
0
}
1097
1098
// --------------------
1099
// nsStyleFilter
1100
//
1101
nsStyleFilter::nsStyleFilter()
1102
  : mType(NS_STYLE_FILTER_NONE)
1103
  , mDropShadow(nullptr)
1104
0
{
1105
0
  MOZ_COUNT_CTOR(nsStyleFilter);
1106
0
}
1107
1108
nsStyleFilter::nsStyleFilter(const nsStyleFilter& aSource)
1109
  : mType(NS_STYLE_FILTER_NONE)
1110
  , mDropShadow(nullptr)
1111
0
{
1112
0
  MOZ_COUNT_CTOR(nsStyleFilter);
1113
0
  if (aSource.mType == NS_STYLE_FILTER_URL) {
1114
0
    SetURL(aSource.mURL);
1115
0
  } else if (aSource.mType == NS_STYLE_FILTER_DROP_SHADOW) {
1116
0
    SetDropShadow(aSource.mDropShadow);
1117
0
  } else if (aSource.mType != NS_STYLE_FILTER_NONE) {
1118
0
    SetFilterParameter(aSource.mFilterParameter, aSource.mType);
1119
0
  }
1120
0
}
1121
1122
nsStyleFilter::~nsStyleFilter()
1123
0
{
1124
0
  ReleaseRef();
1125
0
  MOZ_COUNT_DTOR(nsStyleFilter);
1126
0
}
1127
1128
nsStyleFilter&
1129
nsStyleFilter::operator=(const nsStyleFilter& aOther)
1130
0
{
1131
0
  if (this == &aOther) {
1132
0
    return *this;
1133
0
  }
1134
0
1135
0
  if (aOther.mType == NS_STYLE_FILTER_URL) {
1136
0
    SetURL(aOther.mURL);
1137
0
  } else if (aOther.mType == NS_STYLE_FILTER_DROP_SHADOW) {
1138
0
    SetDropShadow(aOther.mDropShadow);
1139
0
  } else if (aOther.mType != NS_STYLE_FILTER_NONE) {
1140
0
    SetFilterParameter(aOther.mFilterParameter, aOther.mType);
1141
0
  } else {
1142
0
    ReleaseRef();
1143
0
    mType = NS_STYLE_FILTER_NONE;
1144
0
  }
1145
0
1146
0
  return *this;
1147
0
}
1148
1149
bool
1150
nsStyleFilter::operator==(const nsStyleFilter& aOther) const
1151
0
{
1152
0
  if (mType != aOther.mType) {
1153
0
      return false;
1154
0
  }
1155
0
1156
0
  if (mType == NS_STYLE_FILTER_URL) {
1157
0
    return DefinitelyEqualURIs(mURL, aOther.mURL);
1158
0
  } else if (mType == NS_STYLE_FILTER_DROP_SHADOW) {
1159
0
    return *mDropShadow == *aOther.mDropShadow;
1160
0
  } else if (mType != NS_STYLE_FILTER_NONE) {
1161
0
    return mFilterParameter == aOther.mFilterParameter;
1162
0
  }
1163
0
1164
0
  return true;
1165
0
}
1166
1167
void
1168
nsStyleFilter::ReleaseRef()
1169
0
{
1170
0
  if (mType == NS_STYLE_FILTER_DROP_SHADOW) {
1171
0
    NS_ASSERTION(mDropShadow, "expected pointer");
1172
0
    mDropShadow->Release();
1173
0
  } else if (mType == NS_STYLE_FILTER_URL) {
1174
0
    NS_ASSERTION(mURL, "expected pointer");
1175
0
    mURL->Release();
1176
0
  }
1177
0
  mURL = nullptr;
1178
0
}
1179
1180
void
1181
nsStyleFilter::SetFilterParameter(const nsStyleCoord& aFilterParameter,
1182
                                  int32_t aType)
1183
0
{
1184
0
  ReleaseRef();
1185
0
  mFilterParameter = aFilterParameter;
1186
0
  mType = aType;
1187
0
}
1188
1189
bool
1190
nsStyleFilter::SetURL(css::URLValue* aURL)
1191
0
{
1192
0
  ReleaseRef();
1193
0
  mURL = aURL;
1194
0
  mURL->AddRef();
1195
0
  mType = NS_STYLE_FILTER_URL;
1196
0
  return true;
1197
0
}
1198
1199
void
1200
nsStyleFilter::SetDropShadow(nsCSSShadowArray* aDropShadow)
1201
0
{
1202
0
  NS_ASSERTION(aDropShadow, "expected pointer");
1203
0
  ReleaseRef();
1204
0
  mDropShadow = aDropShadow;
1205
0
  mDropShadow->AddRef();
1206
0
  mType = NS_STYLE_FILTER_DROP_SHADOW;
1207
0
}
1208
1209
// --------------------
1210
// nsStyleSVGReset
1211
//
1212
nsStyleSVGReset::nsStyleSVGReset(const nsPresContext* aContext)
1213
  : mMask(nsStyleImageLayers::LayerType::Mask)
1214
  , mStopColor(StyleComplexColor::Black())
1215
  , mFloodColor(StyleComplexColor::Black())
1216
  , mLightingColor(StyleComplexColor::White())
1217
  , mStopOpacity(1.0f)
1218
  , mFloodOpacity(1.0f)
1219
  , mDominantBaseline(NS_STYLE_DOMINANT_BASELINE_AUTO)
1220
  , mVectorEffect(NS_STYLE_VECTOR_EFFECT_NONE)
1221
  , mMaskType(NS_STYLE_MASK_TYPE_LUMINANCE)
1222
0
{
1223
0
  MOZ_COUNT_CTOR(nsStyleSVGReset);
1224
0
}
1225
1226
nsStyleSVGReset::~nsStyleSVGReset()
1227
0
{
1228
0
  MOZ_COUNT_DTOR(nsStyleSVGReset);
1229
0
}
1230
1231
nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset& aSource)
1232
  : mMask(aSource.mMask)
1233
  , mClipPath(aSource.mClipPath)
1234
  , mStopColor(aSource.mStopColor)
1235
  , mFloodColor(aSource.mFloodColor)
1236
  , mLightingColor(aSource.mLightingColor)
1237
  , mStopOpacity(aSource.mStopOpacity)
1238
  , mFloodOpacity(aSource.mFloodOpacity)
1239
  , mDominantBaseline(aSource.mDominantBaseline)
1240
  , mVectorEffect(aSource.mVectorEffect)
1241
  , mMaskType(aSource.mMaskType)
1242
0
{
1243
0
  MOZ_COUNT_CTOR(nsStyleSVGReset);
1244
0
}
1245
1246
void
1247
nsStyleSVGReset::FinishStyle(nsPresContext* aPresContext, const nsStyleSVGReset* aOldStyle)
1248
0
{
1249
0
  MOZ_ASSERT(NS_IsMainThread());
1250
0
1251
0
  NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, mMask) {
1252
0
    nsStyleImage& image = mMask.mLayers[i].mImage;
1253
0
    if (image.GetType() == eStyleImageType_Image) {
1254
0
      css::URLValueData* url = image.GetURLValue();
1255
0
      // If the url is a local ref, it must be a <mask-resource>, so we don't
1256
0
      // need to resolve the style image.
1257
0
      if (url->IsLocalRef()) {
1258
0
        continue;
1259
0
      }
1260
#if 0
1261
      // XXX The old style system also checks whether this is a reference to
1262
      // the current document with reference, but it doesn't seem to be a
1263
      // behavior mentioned anywhere, so we comment out the code for now.
1264
      nsIURI* docURI = aPresContext->Document()->GetDocumentURI();
1265
      if (url->EqualsExceptRef(docURI)) {
1266
        continue;
1267
      }
1268
#endif
1269
1270
0
      // Otherwise, we may need the image even if it has a reference, in case
1271
0
      // the referenced element isn't a valid SVG <mask> element.
1272
0
      const nsStyleImage* oldImage =
1273
0
        (aOldStyle && aOldStyle->mMask.mLayers.Length() > i)
1274
0
        ? &aOldStyle->mMask.mLayers[i].mImage
1275
0
        : nullptr;
1276
0
1277
0
      image.ResolveImage(aPresContext, oldImage);
1278
0
    }
1279
0
  }
1280
0
}
1281
1282
nsChangeHint
1283
nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aNewData) const
1284
0
{
1285
0
  nsChangeHint hint = nsChangeHint(0);
1286
0
1287
0
  if (mClipPath != aNewData.mClipPath) {
1288
0
    hint |= nsChangeHint_UpdateEffects |
1289
0
            nsChangeHint_RepaintFrame;
1290
0
    // clip-path changes require that we update the PreEffectsBBoxProperty,
1291
0
    // which is done during overflow computation.
1292
0
    hint |= nsChangeHint_UpdateOverflow;
1293
0
  }
1294
0
1295
0
  if (mDominantBaseline != aNewData.mDominantBaseline) {
1296
0
    // XXXjwatt: why NS_STYLE_HINT_REFLOW? Isn't that excessive?
1297
0
    hint |= NS_STYLE_HINT_REFLOW;
1298
0
  } else if (mVectorEffect  != aNewData.mVectorEffect) {
1299
0
    // Stroke currently affects SVGGeometryFrame::mRect, and
1300
0
    // vector-effect affect stroke. As a result we need to reflow if
1301
0
    // vector-effect changes in order to have SVGGeometryFrame::
1302
0
    // ReflowSVG called to update its mRect. No intrinsic sizes need
1303
0
    // to change so nsChangeHint_NeedReflow is sufficient.
1304
0
    hint |= nsChangeHint_NeedReflow |
1305
0
            nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
1306
0
            nsChangeHint_RepaintFrame;
1307
0
  } else if (mStopColor     != aNewData.mStopColor     ||
1308
0
             mFloodColor    != aNewData.mFloodColor    ||
1309
0
             mLightingColor != aNewData.mLightingColor ||
1310
0
             mStopOpacity   != aNewData.mStopOpacity   ||
1311
0
             mFloodOpacity  != aNewData.mFloodOpacity  ||
1312
0
             mMaskType      != aNewData.mMaskType) {
1313
0
    hint |= nsChangeHint_RepaintFrame;
1314
0
  }
1315
0
1316
0
  hint |= mMask.CalcDifference(aNewData.mMask,
1317
0
                               nsStyleImageLayers::LayerType::Mask);
1318
0
1319
0
  return hint;
1320
0
}
1321
1322
bool
1323
nsStyleSVGReset::HasMask() const
1324
0
{
1325
0
  for (uint32_t i = 0; i < mMask.mImageCount; i++) {
1326
0
    if (!mMask.mLayers[i].mImage.IsEmpty()) {
1327
0
      return true;
1328
0
    }
1329
0
  }
1330
0
1331
0
  return false;
1332
0
}
1333
1334
// nsStyleSVGPaint implementation
1335
nsStyleSVGPaint::nsStyleSVGPaint(nsStyleSVGPaintType aType)
1336
  : mPaint(StyleComplexColor::Black())
1337
  , mType(aType)
1338
  , mFallbackType(eStyleSVGFallbackType_NotSet)
1339
  , mFallbackColor(StyleComplexColor::Black())
1340
0
{
1341
0
  MOZ_ASSERT(aType == nsStyleSVGPaintType(0) ||
1342
0
             aType == eStyleSVGPaintType_None ||
1343
0
             aType == eStyleSVGPaintType_Color);
1344
0
}
1345
1346
nsStyleSVGPaint::nsStyleSVGPaint(const nsStyleSVGPaint& aSource)
1347
  : nsStyleSVGPaint(nsStyleSVGPaintType(0))
1348
0
{
1349
0
  Assign(aSource);
1350
0
}
1351
1352
nsStyleSVGPaint::~nsStyleSVGPaint()
1353
0
{
1354
0
  Reset();
1355
0
}
1356
1357
void
1358
nsStyleSVGPaint::Reset()
1359
0
{
1360
0
  switch (mType) {
1361
0
    case eStyleSVGPaintType_None:
1362
0
      break;
1363
0
    case eStyleSVGPaintType_Color:
1364
0
      mPaint.mColor = StyleComplexColor::Black();
1365
0
      break;
1366
0
    case eStyleSVGPaintType_Server:
1367
0
      mPaint.mPaintServer->Release();
1368
0
      mPaint.mPaintServer = nullptr;
1369
0
      MOZ_FALLTHROUGH;
1370
0
    case eStyleSVGPaintType_ContextFill:
1371
0
    case eStyleSVGPaintType_ContextStroke:
1372
0
      mFallbackType = eStyleSVGFallbackType_NotSet;
1373
0
      mFallbackColor = StyleComplexColor::Black();
1374
0
      break;
1375
0
  }
1376
0
  mType = nsStyleSVGPaintType(0);
1377
0
}
1378
1379
nsStyleSVGPaint&
1380
nsStyleSVGPaint::operator=(const nsStyleSVGPaint& aOther)
1381
0
{
1382
0
  if (this != &aOther) {
1383
0
    Assign(aOther);
1384
0
  }
1385
0
  return *this;
1386
0
}
1387
1388
void
1389
nsStyleSVGPaint::Assign(const nsStyleSVGPaint& aOther)
1390
0
{
1391
0
  MOZ_ASSERT(aOther.mType != nsStyleSVGPaintType(0),
1392
0
             "shouldn't copy uninitialized nsStyleSVGPaint");
1393
0
1394
0
  switch (aOther.mType) {
1395
0
    case eStyleSVGPaintType_None:
1396
0
      SetNone();
1397
0
      break;
1398
0
    case eStyleSVGPaintType_Color:
1399
0
      SetColor(aOther.mPaint.mColor);
1400
0
      break;
1401
0
    case eStyleSVGPaintType_Server:
1402
0
      SetPaintServer(aOther.mPaint.mPaintServer,
1403
0
                     aOther.mFallbackType,
1404
0
                     aOther.mFallbackColor);
1405
0
      break;
1406
0
    case eStyleSVGPaintType_ContextFill:
1407
0
    case eStyleSVGPaintType_ContextStroke:
1408
0
      SetContextValue(aOther.mType,
1409
0
                      aOther.mFallbackType,
1410
0
                      aOther.mFallbackColor);
1411
0
      break;
1412
0
  }
1413
0
}
1414
1415
void
1416
nsStyleSVGPaint::SetNone()
1417
0
{
1418
0
  Reset();
1419
0
  mType = eStyleSVGPaintType_None;
1420
0
}
1421
1422
void
1423
nsStyleSVGPaint::SetContextValue(nsStyleSVGPaintType aType,
1424
                                 nsStyleSVGFallbackType aFallbackType,
1425
                                 StyleComplexColor aFallbackColor)
1426
0
{
1427
0
  MOZ_ASSERT(aType == eStyleSVGPaintType_ContextFill ||
1428
0
             aType == eStyleSVGPaintType_ContextStroke);
1429
0
  Reset();
1430
0
  mType = aType;
1431
0
  mFallbackType = aFallbackType;
1432
0
  mFallbackColor = aFallbackColor;
1433
0
}
1434
1435
void
1436
nsStyleSVGPaint::SetColor(StyleComplexColor aColor)
1437
0
{
1438
0
  Reset();
1439
0
  mType = eStyleSVGPaintType_Color;
1440
0
  mPaint.mColor = aColor;
1441
0
}
1442
1443
void
1444
nsStyleSVGPaint::SetPaintServer(css::URLValue* aPaintServer,
1445
                                nsStyleSVGFallbackType aFallbackType,
1446
                                StyleComplexColor aFallbackColor)
1447
0
{
1448
0
  MOZ_ASSERT(aPaintServer);
1449
0
  Reset();
1450
0
  mType = eStyleSVGPaintType_Server;
1451
0
  mPaint.mPaintServer = aPaintServer;
1452
0
  mPaint.mPaintServer->AddRef();
1453
0
  mFallbackType = aFallbackType;
1454
0
  mFallbackColor = aFallbackColor;
1455
0
}
1456
1457
bool nsStyleSVGPaint::operator==(const nsStyleSVGPaint& aOther) const
1458
0
{
1459
0
  if (mType != aOther.mType) {
1460
0
    return false;
1461
0
  }
1462
0
  switch (mType) {
1463
0
    case eStyleSVGPaintType_Color:
1464
0
      return mPaint.mColor == aOther.mPaint.mColor;
1465
0
    case eStyleSVGPaintType_Server:
1466
0
      return DefinitelyEqualURIs(mPaint.mPaintServer,
1467
0
                                 aOther.mPaint.mPaintServer) &&
1468
0
             mFallbackType == aOther.mFallbackType &&
1469
0
             mFallbackColor == aOther.mFallbackColor;
1470
0
    case eStyleSVGPaintType_ContextFill:
1471
0
    case eStyleSVGPaintType_ContextStroke:
1472
0
      return mFallbackType == aOther.mFallbackType &&
1473
0
             mFallbackColor == aOther.mFallbackColor;
1474
0
    default:
1475
0
      MOZ_ASSERT(mType == eStyleSVGPaintType_None,
1476
0
                 "Unexpected SVG paint type");
1477
0
      return true;
1478
0
  }
1479
0
}
1480
1481
// --------------------
1482
// nsStylePosition
1483
//
1484
nsStylePosition::nsStylePosition(const nsPresContext* aContext)
1485
  : mWidth(eStyleUnit_Auto)
1486
  , mMinWidth(eStyleUnit_Auto)
1487
  , mMaxWidth(eStyleUnit_None)
1488
  , mHeight(eStyleUnit_Auto)
1489
  , mMinHeight(eStyleUnit_Auto)
1490
  , mMaxHeight(eStyleUnit_None)
1491
  , mFlexBasis(eStyleUnit_Auto)
1492
  , mGridAutoColumnsMin(eStyleUnit_Auto)
1493
  , mGridAutoColumnsMax(eStyleUnit_Auto)
1494
  , mGridAutoRowsMin(eStyleUnit_Auto)
1495
  , mGridAutoRowsMax(eStyleUnit_Auto)
1496
  , mGridAutoFlow(NS_STYLE_GRID_AUTO_FLOW_ROW)
1497
  , mBoxSizing(StyleBoxSizing::Content)
1498
  , mAlignContent(NS_STYLE_ALIGN_NORMAL)
1499
  , mAlignItems(NS_STYLE_ALIGN_NORMAL)
1500
  , mAlignSelf(NS_STYLE_ALIGN_AUTO)
1501
  , mJustifyContent(NS_STYLE_JUSTIFY_NORMAL)
1502
  , mSpecifiedJustifyItems(NS_STYLE_JUSTIFY_LEGACY)
1503
  , mJustifyItems(NS_STYLE_JUSTIFY_NORMAL)
1504
  , mJustifySelf(NS_STYLE_JUSTIFY_AUTO)
1505
  , mFlexDirection(NS_STYLE_FLEX_DIRECTION_ROW)
1506
  , mFlexWrap(NS_STYLE_FLEX_WRAP_NOWRAP)
1507
  , mObjectFit(NS_STYLE_OBJECT_FIT_FILL)
1508
  , mOrder(NS_STYLE_ORDER_INITIAL)
1509
  , mFlexGrow(0.0f)
1510
  , mFlexShrink(1.0f)
1511
  , mZIndex(eStyleUnit_Auto)
1512
  , mColumnGap(eStyleUnit_Normal)
1513
  , mRowGap(eStyleUnit_Normal)
1514
0
{
1515
0
  MOZ_COUNT_CTOR(nsStylePosition);
1516
0
1517
0
  // positioning values not inherited
1518
0
1519
0
  mObjectPosition.SetInitialPercentValues(0.5f);
1520
0
1521
0
  nsStyleCoord  autoCoord(eStyleUnit_Auto);
1522
0
  NS_FOR_CSS_SIDES(side) {
1523
0
    mOffset.Set(side, autoCoord);
1524
0
  }
1525
0
1526
0
  // The initial value of grid-auto-columns and grid-auto-rows is 'auto',
1527
0
  // which computes to 'minmax(auto, auto)'.
1528
0
1529
0
  // Other members get their default constructors
1530
0
  // which initialize them to representations of their respective initial value.
1531
0
  // mGridTemplateAreas: nullptr for 'none'
1532
0
  // mGridTemplate{Rows,Columns}: false and empty arrays for 'none'
1533
0
  // mGrid{Column,Row}{Start,End}: false/0/empty values for 'auto'
1534
0
}
1535
1536
nsStylePosition::~nsStylePosition()
1537
0
{
1538
0
  MOZ_COUNT_DTOR(nsStylePosition);
1539
0
}
1540
1541
nsStylePosition::nsStylePosition(const nsStylePosition& aSource)
1542
  : mObjectPosition(aSource.mObjectPosition)
1543
  , mOffset(aSource.mOffset)
1544
  , mWidth(aSource.mWidth)
1545
  , mMinWidth(aSource.mMinWidth)
1546
  , mMaxWidth(aSource.mMaxWidth)
1547
  , mHeight(aSource.mHeight)
1548
  , mMinHeight(aSource.mMinHeight)
1549
  , mMaxHeight(aSource.mMaxHeight)
1550
  , mFlexBasis(aSource.mFlexBasis)
1551
  , mGridAutoColumnsMin(aSource.mGridAutoColumnsMin)
1552
  , mGridAutoColumnsMax(aSource.mGridAutoColumnsMax)
1553
  , mGridAutoRowsMin(aSource.mGridAutoRowsMin)
1554
  , mGridAutoRowsMax(aSource.mGridAutoRowsMax)
1555
  , mGridAutoFlow(aSource.mGridAutoFlow)
1556
  , mBoxSizing(aSource.mBoxSizing)
1557
  , mAlignContent(aSource.mAlignContent)
1558
  , mAlignItems(aSource.mAlignItems)
1559
  , mAlignSelf(aSource.mAlignSelf)
1560
  , mJustifyContent(aSource.mJustifyContent)
1561
  , mSpecifiedJustifyItems(aSource.mSpecifiedJustifyItems)
1562
  , mJustifyItems(aSource.mJustifyItems)
1563
  , mJustifySelf(aSource.mJustifySelf)
1564
  , mFlexDirection(aSource.mFlexDirection)
1565
  , mFlexWrap(aSource.mFlexWrap)
1566
  , mObjectFit(aSource.mObjectFit)
1567
  , mOrder(aSource.mOrder)
1568
  , mFlexGrow(aSource.mFlexGrow)
1569
  , mFlexShrink(aSource.mFlexShrink)
1570
  , mZIndex(aSource.mZIndex)
1571
  , mGridTemplateAreas(aSource.mGridTemplateAreas)
1572
  , mGridColumnStart(aSource.mGridColumnStart)
1573
  , mGridColumnEnd(aSource.mGridColumnEnd)
1574
  , mGridRowStart(aSource.mGridRowStart)
1575
  , mGridRowEnd(aSource.mGridRowEnd)
1576
  , mColumnGap(aSource.mColumnGap)
1577
  , mRowGap(aSource.mRowGap)
1578
0
{
1579
0
  MOZ_COUNT_CTOR(nsStylePosition);
1580
0
1581
0
  if (aSource.mGridTemplateColumns) {
1582
0
    mGridTemplateColumns =
1583
0
      MakeUnique<nsStyleGridTemplate>(*aSource.mGridTemplateColumns);
1584
0
  }
1585
0
  if (aSource.mGridTemplateRows) {
1586
0
    mGridTemplateRows =
1587
0
      MakeUnique<nsStyleGridTemplate>(*aSource.mGridTemplateRows);
1588
0
  }
1589
0
}
1590
1591
static bool
1592
IsAutonessEqual(const nsStyleSides& aSides1, const nsStyleSides& aSides2)
1593
0
{
1594
0
  NS_FOR_CSS_SIDES(side) {
1595
0
    if ((aSides1.GetUnit(side) == eStyleUnit_Auto) !=
1596
0
        (aSides2.GetUnit(side) == eStyleUnit_Auto)) {
1597
0
      return false;
1598
0
    }
1599
0
  }
1600
0
  return true;
1601
0
}
1602
1603
static bool
1604
IsGridTemplateEqual(const UniquePtr<nsStyleGridTemplate>& aOldData,
1605
                    const UniquePtr<nsStyleGridTemplate>& aNewData)
1606
0
{
1607
0
  if (aOldData == aNewData) {
1608
0
    return true;
1609
0
  }
1610
0
  if (!aOldData || !aNewData) {
1611
0
    return false;
1612
0
  }
1613
0
  return *aOldData == *aNewData;
1614
0
}
1615
1616
nsChangeHint
1617
nsStylePosition::CalcDifference(const nsStylePosition& aNewData,
1618
                                const nsStyleVisibility* aOldStyleVisibility) const
1619
0
{
1620
0
  nsChangeHint hint = nsChangeHint(0);
1621
0
1622
0
  // Changes to "z-index" require a repaint.
1623
0
  if (mZIndex != aNewData.mZIndex) {
1624
0
    hint |= nsChangeHint_RepaintFrame;
1625
0
  }
1626
0
1627
0
  // Changes to "object-fit" & "object-position" require a repaint.  They
1628
0
  // may also require a reflow, if we have a nsSubDocumentFrame, so that we
1629
0
  // can adjust the size & position of the subdocument.
1630
0
  if (mObjectFit != aNewData.mObjectFit ||
1631
0
      mObjectPosition != aNewData.mObjectPosition) {
1632
0
    hint |= nsChangeHint_RepaintFrame |
1633
0
            nsChangeHint_NeedReflow;
1634
0
  }
1635
0
1636
0
  if (mOrder != aNewData.mOrder) {
1637
0
    // "order" impacts both layout order and stacking order, so we need both a
1638
0
    // reflow and a repaint when it changes.  (Technically, we only need a
1639
0
    // reflow if we're in a multi-line flexbox (which we can't be sure about,
1640
0
    // since that's determined by styling on our parent) -- there, "order" can
1641
0
    // affect which flex line we end up on, & hence can affect our sizing by
1642
0
    // changing the group of flex items we're competing with for space.)
1643
0
    return hint |
1644
0
           nsChangeHint_RepaintFrame |
1645
0
           nsChangeHint_AllReflowHints;
1646
0
  }
1647
0
1648
0
  if (mBoxSizing != aNewData.mBoxSizing) {
1649
0
    // Can affect both widths and heights; just a bad scene.
1650
0
    return hint |
1651
0
           nsChangeHint_AllReflowHints;
1652
0
  }
1653
0
1654
0
  // Properties that apply to flex items:
1655
0
  // XXXdholbert These should probably be more targeted (bug 819536)
1656
0
  if (mAlignSelf != aNewData.mAlignSelf ||
1657
0
      mFlexBasis != aNewData.mFlexBasis ||
1658
0
      mFlexGrow != aNewData.mFlexGrow ||
1659
0
      mFlexShrink != aNewData.mFlexShrink) {
1660
0
    return hint |
1661
0
           nsChangeHint_AllReflowHints;
1662
0
  }
1663
0
1664
0
  // Properties that apply to flex containers:
1665
0
  // - flex-direction can swap a flex container between vertical & horizontal.
1666
0
  // - align-items can change the sizing of a flex container & the positioning
1667
0
  //   of its children.
1668
0
  // - flex-wrap changes whether a flex container's children are wrapped, which
1669
0
  //   impacts their sizing/positioning and hence impacts the container's size.
1670
0
  if (mAlignItems != aNewData.mAlignItems ||
1671
0
      mFlexDirection != aNewData.mFlexDirection ||
1672
0
      mFlexWrap != aNewData.mFlexWrap) {
1673
0
    return hint |
1674
0
           nsChangeHint_AllReflowHints;
1675
0
  }
1676
0
1677
0
  // Properties that apply to grid containers:
1678
0
  // FIXME: only for grid containers
1679
0
  // (ie. 'display: grid' or 'display: inline-grid')
1680
0
  if (!IsGridTemplateEqual(mGridTemplateColumns,
1681
0
                           aNewData.mGridTemplateColumns) ||
1682
0
      !IsGridTemplateEqual(mGridTemplateRows,
1683
0
                           aNewData.mGridTemplateRows) ||
1684
0
      mGridTemplateAreas != aNewData.mGridTemplateAreas ||
1685
0
      mGridAutoColumnsMin != aNewData.mGridAutoColumnsMin ||
1686
0
      mGridAutoColumnsMax != aNewData.mGridAutoColumnsMax ||
1687
0
      mGridAutoRowsMin != aNewData.mGridAutoRowsMin ||
1688
0
      mGridAutoRowsMax != aNewData.mGridAutoRowsMax ||
1689
0
      mGridAutoFlow != aNewData.mGridAutoFlow) {
1690
0
    return hint |
1691
0
           nsChangeHint_AllReflowHints;
1692
0
  }
1693
0
1694
0
  // Properties that apply to grid items:
1695
0
  // FIXME: only for grid items
1696
0
  // (ie. parent frame is 'display: grid' or 'display: inline-grid')
1697
0
  if (mGridColumnStart != aNewData.mGridColumnStart ||
1698
0
      mGridColumnEnd != aNewData.mGridColumnEnd ||
1699
0
      mGridRowStart != aNewData.mGridRowStart ||
1700
0
      mGridRowEnd != aNewData.mGridRowEnd ||
1701
0
      mColumnGap != aNewData.mColumnGap ||
1702
0
      mRowGap != aNewData.mRowGap) {
1703
0
    return hint |
1704
0
           nsChangeHint_AllReflowHints;
1705
0
  }
1706
0
1707
0
  // Changing 'justify-content/items/self' might affect the positioning,
1708
0
  // but it won't affect any sizing.
1709
0
  if (mJustifyContent != aNewData.mJustifyContent ||
1710
0
      mJustifyItems != aNewData.mJustifyItems ||
1711
0
      mJustifySelf != aNewData.mJustifySelf) {
1712
0
    hint |= nsChangeHint_NeedReflow;
1713
0
  }
1714
0
1715
0
  // No need to do anything if mSpecifiedJustifyItems changes, as long as
1716
0
  // mJustifyItems (tested above) is unchanged.
1717
0
  if (mSpecifiedJustifyItems != aNewData.mSpecifiedJustifyItems) {
1718
0
    hint |= nsChangeHint_NeutralChange;
1719
0
  }
1720
0
1721
0
  // 'align-content' doesn't apply to a single-line flexbox but we don't know
1722
0
  // if we're a flex container at this point so we can't optimize for that.
1723
0
  if (mAlignContent != aNewData.mAlignContent) {
1724
0
    hint |= nsChangeHint_NeedReflow;
1725
0
  }
1726
0
1727
0
  bool widthChanged = mWidth != aNewData.mWidth ||
1728
0
                      mMinWidth != aNewData.mMinWidth ||
1729
0
                      mMaxWidth != aNewData.mMaxWidth;
1730
0
  bool heightChanged = mHeight != aNewData.mHeight ||
1731
0
                       mMinHeight != aNewData.mMinHeight ||
1732
0
                       mMaxHeight != aNewData.mMaxHeight;
1733
0
1734
0
  // If aOldStyleVisibility is null, we don't need to bother with any of
1735
0
  // these tests, since we know that the element never had its
1736
0
  // nsStyleVisibility accessed, which means it couldn't have done
1737
0
  // layout.
1738
0
  // Note that we pass an nsStyleVisibility here because we don't want
1739
0
  // to cause a new struct to be computed during
1740
0
  // ComputedStyle::CalcStyleDifference, which can lead to incorrect
1741
0
  // style data.
1742
0
  // It doesn't matter whether we're looking at the old or new
1743
0
  // visibility struct, since a change between vertical and horizontal
1744
0
  // writing-mode will cause a reframe, and it's easier to pass the old.
1745
0
  if (aOldStyleVisibility) {
1746
0
    bool isVertical = WritingMode(aOldStyleVisibility).IsVertical();
1747
0
    if (isVertical ? widthChanged : heightChanged) {
1748
0
      hint |= nsChangeHint_ReflowHintsForBSizeChange;
1749
0
    }
1750
0
1751
0
    if (isVertical ? heightChanged : widthChanged) {
1752
0
      hint |= nsChangeHint_ReflowHintsForISizeChange;
1753
0
    }
1754
0
  } else {
1755
0
    if (widthChanged || heightChanged) {
1756
0
      hint |= nsChangeHint_NeutralChange;
1757
0
    }
1758
0
  }
1759
0
1760
0
  // If any of the offsets have changed, then return the respective hints
1761
0
  // so that we would hopefully be able to avoid reflowing.
1762
0
  // Note that it is possible that we'll need to reflow when processing
1763
0
  // restyles, but we don't have enough information to make a good decision
1764
0
  // right now.
1765
0
  // Don't try to handle changes between "auto" and non-auto efficiently;
1766
0
  // that's tricky to do and will hardly ever be able to avoid a reflow.
1767
0
  if (mOffset != aNewData.mOffset) {
1768
0
    if (IsAutonessEqual(mOffset, aNewData.mOffset)) {
1769
0
      hint |= nsChangeHint_RecomputePosition |
1770
0
              nsChangeHint_UpdateParentOverflow;
1771
0
    } else {
1772
0
      hint |= nsChangeHint_AllReflowHints;
1773
0
    }
1774
0
  }
1775
0
  return hint;
1776
0
}
1777
1778
/* static */ bool
1779
nsStylePosition::WidthCoordDependsOnContainer(const nsStyleCoord &aCoord)
1780
0
{
1781
0
  return aCoord.HasPercent() ||
1782
0
         (aCoord.GetUnit() == eStyleUnit_Enumerated &&
1783
0
          (aCoord.GetIntValue() == NS_STYLE_WIDTH_FIT_CONTENT ||
1784
0
           aCoord.GetIntValue() == NS_STYLE_WIDTH_AVAILABLE));
1785
0
}
1786
1787
uint8_t
1788
nsStylePosition::UsedAlignSelf(ComputedStyle* aParent) const
1789
0
{
1790
0
  if (mAlignSelf != NS_STYLE_ALIGN_AUTO) {
1791
0
    return mAlignSelf;
1792
0
  }
1793
0
  if (MOZ_LIKELY(aParent)) {
1794
0
    auto parentAlignItems = aParent->StylePosition()->mAlignItems;
1795
0
    MOZ_ASSERT(!(parentAlignItems & NS_STYLE_ALIGN_LEGACY),
1796
0
               "align-items can't have 'legacy'");
1797
0
    return parentAlignItems;
1798
0
  }
1799
0
  return NS_STYLE_ALIGN_NORMAL;
1800
0
}
1801
1802
uint8_t
1803
nsStylePosition::UsedJustifySelf(ComputedStyle* aParent) const
1804
0
{
1805
0
  if (mJustifySelf != NS_STYLE_JUSTIFY_AUTO) {
1806
0
    return mJustifySelf;
1807
0
  }
1808
0
  if (MOZ_LIKELY(aParent)) {
1809
0
    auto inheritedJustifyItems = aParent->StylePosition()->mJustifyItems;
1810
0
    return inheritedJustifyItems & ~NS_STYLE_JUSTIFY_LEGACY;
1811
0
  }
1812
0
  return NS_STYLE_JUSTIFY_NORMAL;
1813
0
}
1814
1815
static StaticAutoPtr<nsStyleGridTemplate> sDefaultGridTemplate;
1816
1817
static const nsStyleGridTemplate&
1818
DefaultGridTemplate()
1819
0
{
1820
0
  if (!sDefaultGridTemplate) {
1821
0
    sDefaultGridTemplate = new nsStyleGridTemplate;
1822
0
    ClearOnShutdown(&sDefaultGridTemplate);
1823
0
  }
1824
0
  return *sDefaultGridTemplate;
1825
0
}
1826
1827
const nsStyleGridTemplate&
1828
nsStylePosition::GridTemplateColumns() const
1829
0
{
1830
0
  return mGridTemplateColumns ? *mGridTemplateColumns : DefaultGridTemplate();
1831
0
}
1832
1833
const nsStyleGridTemplate&
1834
nsStylePosition::GridTemplateRows() const
1835
0
{
1836
0
  return mGridTemplateRows ? *mGridTemplateRows : DefaultGridTemplate();
1837
0
}
1838
1839
// --------------------
1840
// nsStyleTable
1841
//
1842
1843
nsStyleTable::nsStyleTable(const nsPresContext* aContext)
1844
  : mLayoutStrategy(NS_STYLE_TABLE_LAYOUT_AUTO)
1845
  , mSpan(1)
1846
0
{
1847
0
  MOZ_COUNT_CTOR(nsStyleTable);
1848
0
}
1849
1850
nsStyleTable::~nsStyleTable()
1851
0
{
1852
0
  MOZ_COUNT_DTOR(nsStyleTable);
1853
0
}
1854
1855
nsStyleTable::nsStyleTable(const nsStyleTable& aSource)
1856
  : mLayoutStrategy(aSource.mLayoutStrategy)
1857
  , mSpan(aSource.mSpan)
1858
0
{
1859
0
  MOZ_COUNT_CTOR(nsStyleTable);
1860
0
}
1861
1862
nsChangeHint
1863
nsStyleTable::CalcDifference(const nsStyleTable& aNewData) const
1864
0
{
1865
0
  if (mSpan != aNewData.mSpan ||
1866
0
      mLayoutStrategy != aNewData.mLayoutStrategy) {
1867
0
    return nsChangeHint_ReconstructFrame;
1868
0
  }
1869
0
  return nsChangeHint(0);
1870
0
}
1871
1872
// -----------------------
1873
// nsStyleTableBorder
1874
1875
nsStyleTableBorder::nsStyleTableBorder(const nsPresContext* aContext)
1876
  : mBorderSpacingCol(0)
1877
  , mBorderSpacingRow(0)
1878
  , mBorderCollapse(NS_STYLE_BORDER_SEPARATE)
1879
  , mCaptionSide(NS_STYLE_CAPTION_SIDE_TOP)
1880
  , mEmptyCells(NS_STYLE_TABLE_EMPTY_CELLS_SHOW)
1881
0
{
1882
0
  MOZ_COUNT_CTOR(nsStyleTableBorder);
1883
0
}
1884
1885
nsStyleTableBorder::~nsStyleTableBorder()
1886
0
{
1887
0
  MOZ_COUNT_DTOR(nsStyleTableBorder);
1888
0
}
1889
1890
nsStyleTableBorder::nsStyleTableBorder(const nsStyleTableBorder& aSource)
1891
  : mBorderSpacingCol(aSource.mBorderSpacingCol)
1892
  , mBorderSpacingRow(aSource.mBorderSpacingRow)
1893
  , mBorderCollapse(aSource.mBorderCollapse)
1894
  , mCaptionSide(aSource.mCaptionSide)
1895
  , mEmptyCells(aSource.mEmptyCells)
1896
0
{
1897
0
  MOZ_COUNT_CTOR(nsStyleTableBorder);
1898
0
}
1899
1900
nsChangeHint
1901
nsStyleTableBorder::CalcDifference(const nsStyleTableBorder& aNewData) const
1902
0
{
1903
0
  // Border-collapse changes need a reframe, because we use a different frame
1904
0
  // class for table cells in the collapsed border model.  This is used to
1905
0
  // conserve memory when using the separated border model (collapsed borders
1906
0
  // require extra state to be stored).
1907
0
  if (mBorderCollapse != aNewData.mBorderCollapse) {
1908
0
    return nsChangeHint_ReconstructFrame;
1909
0
  }
1910
0
1911
0
  if ((mCaptionSide == aNewData.mCaptionSide) &&
1912
0
      (mBorderSpacingCol == aNewData.mBorderSpacingCol) &&
1913
0
      (mBorderSpacingRow == aNewData.mBorderSpacingRow)) {
1914
0
    if (mEmptyCells == aNewData.mEmptyCells) {
1915
0
      return nsChangeHint(0);
1916
0
    }
1917
0
    return NS_STYLE_HINT_VISUAL;
1918
0
  } else {
1919
0
    return NS_STYLE_HINT_REFLOW;
1920
0
  }
1921
0
}
1922
1923
// --------------------
1924
// nsStyleColor
1925
//
1926
1927
nsStyleColor::nsStyleColor(const nsPresContext* aContext)
1928
  : mColor(aContext->DefaultColor())
1929
0
{
1930
0
  MOZ_COUNT_CTOR(nsStyleColor);
1931
0
}
1932
1933
nsStyleColor::nsStyleColor(const nsStyleColor& aSource)
1934
  : mColor(aSource.mColor)
1935
0
{
1936
0
  MOZ_COUNT_CTOR(nsStyleColor);
1937
0
}
1938
1939
nsChangeHint
1940
nsStyleColor::CalcDifference(const nsStyleColor& aNewData) const
1941
0
{
1942
0
  if (mColor == aNewData.mColor) {
1943
0
    return nsChangeHint(0);
1944
0
  }
1945
0
  return nsChangeHint_RepaintFrame;
1946
0
}
1947
1948
// --------------------
1949
// nsStyleGradient
1950
//
1951
bool
1952
nsStyleGradient::operator==(const nsStyleGradient& aOther) const
1953
0
{
1954
0
  MOZ_ASSERT(mSize == NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER ||
1955
0
             mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR,
1956
0
             "incorrect combination of shape and size");
1957
0
  MOZ_ASSERT(aOther.mSize == NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER ||
1958
0
             aOther.mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR,
1959
0
             "incorrect combination of shape and size");
1960
0
1961
0
  if (mShape != aOther.mShape ||
1962
0
      mSize != aOther.mSize ||
1963
0
      mRepeating != aOther.mRepeating ||
1964
0
      mLegacySyntax != aOther.mLegacySyntax ||
1965
0
      mMozLegacySyntax != aOther.mMozLegacySyntax ||
1966
0
      mBgPosX != aOther.mBgPosX ||
1967
0
      mBgPosY != aOther.mBgPosY ||
1968
0
      mAngle != aOther.mAngle ||
1969
0
      mRadiusX != aOther.mRadiusX ||
1970
0
      mRadiusY != aOther.mRadiusY) {
1971
0
    return false;
1972
0
  }
1973
0
1974
0
  if (mStops.Length() != aOther.mStops.Length()) {
1975
0
    return false;
1976
0
  }
1977
0
1978
0
  for (uint32_t i = 0; i < mStops.Length(); i++) {
1979
0
    const auto& stop1 = mStops[i];
1980
0
    const auto& stop2 = aOther.mStops[i];
1981
0
    if (stop1.mLocation != stop2.mLocation ||
1982
0
        stop1.mIsInterpolationHint != stop2.mIsInterpolationHint ||
1983
0
        (!stop1.mIsInterpolationHint && stop1.mColor != stop2.mColor)) {
1984
0
      return false;
1985
0
    }
1986
0
  }
1987
0
1988
0
  return true;
1989
0
}
1990
1991
nsStyleGradient::nsStyleGradient()
1992
  : mShape(NS_STYLE_GRADIENT_SHAPE_LINEAR)
1993
  , mSize(NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER)
1994
  , mRepeating(false)
1995
  , mLegacySyntax(false)
1996
  , mMozLegacySyntax(false)
1997
0
{
1998
0
}
1999
2000
bool
2001
nsStyleGradient::IsOpaque()
2002
0
{
2003
0
  for (uint32_t i = 0; i < mStops.Length(); i++) {
2004
0
    if (mStops[i].mColor.MaybeTransparent()) {
2005
0
      // We don't know the foreground color here, so if it's being used
2006
0
      // we must assume it might be transparent.
2007
0
      return false;
2008
0
    }
2009
0
  }
2010
0
  return true;
2011
0
}
2012
2013
bool
2014
nsStyleGradient::HasCalc()
2015
0
{
2016
0
  for (uint32_t i = 0; i < mStops.Length(); i++) {
2017
0
    if (mStops[i].mLocation.IsCalcUnit()) {
2018
0
      return true;
2019
0
    }
2020
0
  }
2021
0
  return mBgPosX.IsCalcUnit() || mBgPosY.IsCalcUnit() || mAngle.IsCalcUnit() ||
2022
0
         mRadiusX.IsCalcUnit() || mRadiusY.IsCalcUnit();
2023
0
}
2024
2025
2026
// --------------------
2027
// nsStyleImageRequest
2028
2029
/**
2030
 * Runnable to release the nsStyleImageRequest's mRequestProxy,
2031
 * mImageValue and mImageTracker on the main thread, and to perform
2032
 * any necessary unlocking and untracking of the image.
2033
 */
2034
class StyleImageRequestCleanupTask : public mozilla::Runnable
2035
{
2036
public:
2037
  typedef nsStyleImageRequest::Mode Mode;
2038
2039
  StyleImageRequestCleanupTask(Mode aModeFlags,
2040
                               already_AddRefed<imgRequestProxy> aRequestProxy,
2041
                               already_AddRefed<css::ImageValue> aImageValue,
2042
                               already_AddRefed<ImageTracker> aImageTracker)
2043
    : mozilla::Runnable("StyleImageRequestCleanupTask")
2044
    , mModeFlags(aModeFlags)
2045
    , mRequestProxy(aRequestProxy)
2046
    , mImageValue(aImageValue)
2047
    , mImageTracker(aImageTracker)
2048
0
  {
2049
0
  }
2050
2051
  NS_IMETHOD Run() final
2052
0
  {
2053
0
    MOZ_ASSERT(!mRequestProxy || NS_IsMainThread(),
2054
0
               "If mRequestProxy is non-null, we need to run on main thread!");
2055
0
2056
0
    if (!mRequestProxy) {
2057
0
      return NS_OK;
2058
0
    }
2059
0
2060
0
    if (mModeFlags & Mode::Track) {
2061
0
      MOZ_ASSERT(mImageTracker);
2062
0
      mImageTracker->Remove(mRequestProxy);
2063
0
    } else {
2064
0
      mRequestProxy->UnlockImage();
2065
0
    }
2066
0
2067
0
    if (mModeFlags & Mode::Discard) {
2068
0
      mRequestProxy->RequestDiscard();
2069
0
    }
2070
0
2071
0
    return NS_OK;
2072
0
  }
2073
2074
protected:
2075
  virtual ~StyleImageRequestCleanupTask()
2076
0
  {
2077
0
    MOZ_ASSERT(mImageValue->mRequests.Count() == 0 || NS_IsMainThread(),
2078
0
               "If mImageValue has any mRequests, we need to run on main "
2079
0
               "thread to release ImageValues!");
2080
0
    MOZ_ASSERT((!mRequestProxy && !mImageTracker) || NS_IsMainThread(),
2081
0
               "mRequestProxy and mImageTracker's destructor need to run "
2082
0
               "on the main thread!");
2083
0
  }
2084
2085
private:
2086
  Mode mModeFlags;
2087
  // Since we always dispatch this runnable to the main thread, these will be
2088
  // released on the main thread when the runnable itself is released.
2089
  RefPtr<imgRequestProxy> mRequestProxy;
2090
  RefPtr<css::ImageValue> mImageValue;
2091
  RefPtr<ImageTracker> mImageTracker;
2092
};
2093
2094
nsStyleImageRequest::nsStyleImageRequest(Mode aModeFlags,
2095
                                         css::ImageValue* aImageValue)
2096
  : mImageValue(aImageValue)
2097
  , mModeFlags(aModeFlags)
2098
  , mResolved(false)
2099
0
{
2100
0
}
2101
2102
nsStyleImageRequest::~nsStyleImageRequest()
2103
0
{
2104
0
  // We may or may not be being destroyed on the main thread.  To clean
2105
0
  // up, we must untrack and unlock the image (depending on mModeFlags),
2106
0
  // and release mRequestProxy and mImageValue, all on the main thread.
2107
0
  {
2108
0
    RefPtr<StyleImageRequestCleanupTask> task =
2109
0
        new StyleImageRequestCleanupTask(mModeFlags,
2110
0
                                         mRequestProxy.forget(),
2111
0
                                         mImageValue.forget(),
2112
0
                                         mImageTracker.forget());
2113
0
    if (NS_IsMainThread()) {
2114
0
      task->Run();
2115
0
    } else {
2116
0
      if (mDocGroup) {
2117
0
        mDocGroup->Dispatch(TaskCategory::Other, task.forget());
2118
0
      } else {
2119
0
        // if Resolve was not called at some point, mDocGroup is not set.
2120
0
        SystemGroup::Dispatch(TaskCategory::Other, task.forget());
2121
0
      }
2122
0
    }
2123
0
  }
2124
0
2125
0
  MOZ_ASSERT(!mRequestProxy);
2126
0
  MOZ_ASSERT(!mImageValue);
2127
0
  MOZ_ASSERT(!mImageTracker);
2128
0
}
2129
2130
bool
2131
nsStyleImageRequest::Resolve(
2132
  nsPresContext* aPresContext,
2133
  const nsStyleImageRequest* aOldImageRequest)
2134
0
{
2135
0
  MOZ_ASSERT(NS_IsMainThread());
2136
0
  MOZ_ASSERT(!IsResolved(), "already resolved");
2137
0
  MOZ_ASSERT(aPresContext);
2138
0
2139
0
  mResolved = true;
2140
0
2141
0
  nsIDocument* doc = aPresContext->Document();
2142
0
  nsIURI* docURI = doc->GetDocumentURI();
2143
0
  if (GetImageValue()->HasRef()) {
2144
0
    bool isEqualExceptRef = false;
2145
0
    RefPtr<nsIURI> imageURI = GetImageURI();
2146
0
    if (!imageURI) {
2147
0
      return false;
2148
0
    }
2149
0
2150
0
    if (NS_SUCCEEDED(imageURI->EqualsExceptRef(docURI, &isEqualExceptRef)) &&
2151
0
        isEqualExceptRef) {
2152
0
      // Prevent loading an internal resource.
2153
0
      return true;
2154
0
    }
2155
0
  }
2156
0
2157
0
  // TODO(emilio, bug 1440442): This is a hackaround to avoid flickering due the
2158
0
  // lack of non-http image caching in imagelib (bug 1406134), which causes
2159
0
  // stuff like bug 1439285. Cleanest fix if that doesn't get fixed is bug
2160
0
  // 1440305, but that seems too risky, and a lot of work to do before 60.
2161
0
  //
2162
0
  // Once that's fixed, the "old style" argument to FinishStyle can go away.
2163
0
  if (aPresContext->IsChrome() && aOldImageRequest &&
2164
0
      aOldImageRequest->IsResolved() && DefinitelyEquals(*aOldImageRequest)) {
2165
0
    MOZ_ASSERT(aOldImageRequest->mDocGroup == doc->GetDocGroup());
2166
0
    MOZ_ASSERT(mModeFlags == aOldImageRequest->mModeFlags);
2167
0
2168
0
    mDocGroup = aOldImageRequest->mDocGroup;
2169
0
    mImageValue = aOldImageRequest->mImageValue;
2170
0
    mRequestProxy = aOldImageRequest->mRequestProxy;
2171
0
  } else {
2172
0
    mDocGroup = doc->GetDocGroup();
2173
0
    mImageValue->Initialize(doc);
2174
0
    imgRequestProxy* request = mImageValue->mRequests.GetWeak(doc);
2175
0
    if (aPresContext->IsDynamic()) {
2176
0
      mRequestProxy = request;
2177
0
    } else if (request) {
2178
0
      request->GetStaticRequest(doc, getter_AddRefs(mRequestProxy));
2179
0
    }
2180
0
  }
2181
0
2182
0
  if (!mRequestProxy) {
2183
0
    // The URL resolution or image load failed.
2184
0
    return false;
2185
0
  }
2186
0
2187
0
  if (mModeFlags & Mode::Track) {
2188
0
    mImageTracker = doc->ImageTracker();
2189
0
  }
2190
0
2191
0
  MaybeTrackAndLock();
2192
0
  return true;
2193
0
}
2194
2195
void
2196
nsStyleImageRequest::MaybeTrackAndLock()
2197
0
{
2198
0
  MOZ_ASSERT(NS_IsMainThread());
2199
0
  MOZ_ASSERT(IsResolved());
2200
0
  MOZ_ASSERT(mRequestProxy);
2201
0
2202
0
  if (mModeFlags & Mode::Track) {
2203
0
    MOZ_ASSERT(mImageTracker);
2204
0
    mImageTracker->Add(mRequestProxy);
2205
0
  } else {
2206
0
    MOZ_ASSERT(!mImageTracker);
2207
0
    mRequestProxy->LockImage();
2208
0
  }
2209
0
}
2210
2211
bool
2212
nsStyleImageRequest::DefinitelyEquals(const nsStyleImageRequest& aOther) const
2213
0
{
2214
0
  return DefinitelyEqualURIs(mImageValue, aOther.mImageValue);
2215
0
}
2216
2217
// --------------------
2218
// CachedBorderImageData
2219
//
2220
void
2221
CachedBorderImageData::SetCachedSVGViewportSize(
2222
  const mozilla::Maybe<nsSize>& aSVGViewportSize)
2223
0
{
2224
0
  mCachedSVGViewportSize = aSVGViewportSize;
2225
0
}
2226
2227
const mozilla::Maybe<nsSize>&
2228
CachedBorderImageData::GetCachedSVGViewportSize()
2229
0
{
2230
0
  return mCachedSVGViewportSize;
2231
0
}
2232
2233
struct PurgeCachedImagesTask : mozilla::Runnable
2234
{
2235
0
  PurgeCachedImagesTask() : mozilla::Runnable("PurgeCachedImagesTask") {}
2236
  NS_IMETHOD Run() final
2237
0
  {
2238
0
    mSubImages.Clear();
2239
0
    return NS_OK;
2240
0
  }
2241
2242
  nsCOMArray<imgIContainer> mSubImages;
2243
};
2244
2245
void
2246
CachedBorderImageData::PurgeCachedImages()
2247
0
{
2248
0
  if (ServoStyleSet::IsInServoTraversal()) {
2249
0
    RefPtr<PurgeCachedImagesTask> task = new PurgeCachedImagesTask();
2250
0
    task->mSubImages.SwapElements(mSubImages);
2251
0
    // This will run the task immediately if we're already on the main thread,
2252
0
    // but that is fine.
2253
0
    NS_DispatchToMainThread(task.forget());
2254
0
  } else {
2255
0
    mSubImages.Clear();
2256
0
  }
2257
0
}
2258
2259
void
2260
CachedBorderImageData::SetSubImage(uint8_t aIndex, imgIContainer* aSubImage)
2261
0
{
2262
0
  mSubImages.ReplaceObjectAt(aSubImage, aIndex);
2263
0
}
2264
2265
imgIContainer*
2266
CachedBorderImageData::GetSubImage(uint8_t aIndex)
2267
0
{
2268
0
  imgIContainer* subImage = nullptr;
2269
0
  if (aIndex < mSubImages.Count())
2270
0
    subImage = mSubImages[aIndex];
2271
0
  return subImage;
2272
0
}
2273
2274
// --------------------
2275
// nsStyleImage
2276
//
2277
2278
nsStyleImage::nsStyleImage()
2279
  : mType(eStyleImageType_Null)
2280
  , mImage(nullptr)
2281
  , mCropRect(nullptr)
2282
0
{
2283
0
  MOZ_COUNT_CTOR(nsStyleImage);
2284
0
}
2285
2286
nsStyleImage::~nsStyleImage()
2287
0
{
2288
0
  MOZ_COUNT_DTOR(nsStyleImage);
2289
0
  if (mType != eStyleImageType_Null) {
2290
0
    SetNull();
2291
0
  }
2292
0
}
2293
2294
nsStyleImage::nsStyleImage(const nsStyleImage& aOther)
2295
  : mType(eStyleImageType_Null)
2296
  , mCropRect(nullptr)
2297
0
{
2298
0
  // We need our own copy constructor because we don't want
2299
0
  // to copy the reference count
2300
0
  MOZ_COUNT_CTOR(nsStyleImage);
2301
0
  DoCopy(aOther);
2302
0
}
2303
2304
nsStyleImage&
2305
nsStyleImage::operator=(const nsStyleImage& aOther)
2306
0
{
2307
0
  if (this != &aOther) {
2308
0
    DoCopy(aOther);
2309
0
  }
2310
0
2311
0
  return *this;
2312
0
}
2313
2314
void
2315
nsStyleImage::DoCopy(const nsStyleImage& aOther)
2316
0
{
2317
0
  SetNull();
2318
0
2319
0
  if (aOther.mType == eStyleImageType_Image) {
2320
0
    SetImageRequest(do_AddRef(aOther.mImage));
2321
0
  } else if (aOther.mType == eStyleImageType_Gradient) {
2322
0
    SetGradientData(aOther.mGradient);
2323
0
  } else if (aOther.mType == eStyleImageType_Element) {
2324
0
    SetElementId(do_AddRef(aOther.mElementId));
2325
0
  } else if (aOther.mType == eStyleImageType_URL) {
2326
0
    SetURLValue(do_AddRef(aOther.mURLValue));
2327
0
  }
2328
0
2329
0
  UniquePtr<nsStyleSides> cropRectCopy;
2330
0
  if (aOther.mCropRect) {
2331
0
    cropRectCopy = MakeUnique<nsStyleSides>(*aOther.mCropRect.get());
2332
0
  }
2333
0
  SetCropRect(std::move(cropRectCopy));
2334
0
}
2335
2336
void
2337
nsStyleImage::SetNull()
2338
0
{
2339
0
  if (mType == eStyleImageType_Gradient) {
2340
0
    mGradient->Release();
2341
0
  } else if (mType == eStyleImageType_Image) {
2342
0
    NS_RELEASE(mImage);
2343
0
  } else if (mType == eStyleImageType_Element) {
2344
0
    NS_RELEASE(mElementId);
2345
0
  } else if (mType == eStyleImageType_URL) {
2346
0
    NS_RELEASE(mURLValue);
2347
0
  }
2348
0
2349
0
  mType = eStyleImageType_Null;
2350
0
  mCropRect = nullptr;
2351
0
}
2352
2353
void
2354
nsStyleImage::SetImageRequest(already_AddRefed<nsStyleImageRequest> aImage)
2355
0
{
2356
0
  RefPtr<nsStyleImageRequest> image = aImage;
2357
0
2358
0
  if (mType != eStyleImageType_Null) {
2359
0
    SetNull();
2360
0
  }
2361
0
2362
0
  if (image) {
2363
0
    mImage = image.forget().take();
2364
0
    mType = eStyleImageType_Image;
2365
0
  }
2366
0
  if (mCachedBIData) {
2367
0
    mCachedBIData->PurgeCachedImages();
2368
0
  }
2369
0
}
2370
2371
void
2372
nsStyleImage::SetGradientData(nsStyleGradient* aGradient)
2373
0
{
2374
0
  if (aGradient) {
2375
0
    aGradient->AddRef();
2376
0
  }
2377
0
2378
0
  if (mType != eStyleImageType_Null) {
2379
0
    SetNull();
2380
0
  }
2381
0
2382
0
  if (aGradient) {
2383
0
    mGradient = aGradient;
2384
0
    mType = eStyleImageType_Gradient;
2385
0
  }
2386
0
}
2387
2388
void
2389
nsStyleImage::SetElementId(already_AddRefed<nsAtom> aElementId)
2390
0
{
2391
0
  if (mType != eStyleImageType_Null) {
2392
0
    SetNull();
2393
0
  }
2394
0
2395
0
  if (RefPtr<nsAtom> atom = aElementId) {
2396
0
    mElementId = atom.forget().take();
2397
0
    mType = eStyleImageType_Element;
2398
0
  }
2399
0
}
2400
2401
void
2402
nsStyleImage::SetCropRect(UniquePtr<nsStyleSides> aCropRect)
2403
0
{
2404
0
    mCropRect = std::move(aCropRect);
2405
0
}
2406
2407
void
2408
nsStyleImage::SetURLValue(already_AddRefed<URLValue> aValue)
2409
0
{
2410
0
  RefPtr<URLValue> value = aValue;
2411
0
2412
0
  if (mType != eStyleImageType_Null) {
2413
0
    SetNull();
2414
0
  }
2415
0
2416
0
  if (value) {
2417
0
    mURLValue = value.forget().take();
2418
0
    mType = eStyleImageType_URL;
2419
0
  }
2420
0
}
2421
2422
static int32_t
2423
ConvertToPixelCoord(const nsStyleCoord& aCoord, int32_t aPercentScale)
2424
0
{
2425
0
  double pixelValue;
2426
0
  switch (aCoord.GetUnit()) {
2427
0
    case eStyleUnit_Percent:
2428
0
      pixelValue = aCoord.GetPercentValue() * aPercentScale;
2429
0
      break;
2430
0
    case eStyleUnit_Factor:
2431
0
      pixelValue = aCoord.GetFactorValue();
2432
0
      break;
2433
0
    default:
2434
0
      MOZ_ASSERT_UNREACHABLE("unexpected unit for image crop rect");
2435
0
      return 0;
2436
0
  }
2437
0
  MOZ_ASSERT(pixelValue >= 0, "we ensured non-negative while parsing");
2438
0
  pixelValue = std::min(pixelValue, double(INT32_MAX)); // avoid overflow
2439
0
  return NS_lround(pixelValue);
2440
0
}
2441
2442
already_AddRefed<nsIURI>
2443
nsStyleImageRequest::GetImageURI() const
2444
0
{
2445
0
  nsCOMPtr<nsIURI> uri;
2446
0
2447
0
  if (mRequestProxy) {
2448
0
    mRequestProxy->GetURI(getter_AddRefs(uri));
2449
0
    if (uri) {
2450
0
      return uri.forget();
2451
0
    }
2452
0
  }
2453
0
2454
0
  // If we had some problem resolving the mRequestProxy, use the URL stored
2455
0
  // in the mImageValue.
2456
0
  if (!mImageValue) {
2457
0
    return nullptr;
2458
0
  }
2459
0
2460
0
  uri = mImageValue->GetURI();
2461
0
  return uri.forget();
2462
0
}
2463
2464
bool
2465
nsStyleImage::ComputeActualCropRect(nsIntRect& aActualCropRect,
2466
                                    bool* aIsEntireImage) const
2467
0
{
2468
0
  MOZ_ASSERT(mType == eStyleImageType_Image,
2469
0
             "This function is designed to be used only when mType"
2470
0
             "is eStyleImageType_Image.");
2471
0
2472
0
  imgRequestProxy* req = GetImageData();
2473
0
  if (!req) {
2474
0
    return false;
2475
0
  }
2476
0
2477
0
  nsCOMPtr<imgIContainer> imageContainer;
2478
0
  req->GetImage(getter_AddRefs(imageContainer));
2479
0
  if (!imageContainer) {
2480
0
    return false;
2481
0
  }
2482
0
2483
0
  nsIntSize imageSize;
2484
0
  imageContainer->GetWidth(&imageSize.width);
2485
0
  imageContainer->GetHeight(&imageSize.height);
2486
0
  if (imageSize.width <= 0 || imageSize.height <= 0) {
2487
0
    return false;
2488
0
  }
2489
0
2490
0
  int32_t left   = ConvertToPixelCoord(mCropRect->GetLeft(),   imageSize.width);
2491
0
  int32_t top    = ConvertToPixelCoord(mCropRect->GetTop(),    imageSize.height);
2492
0
  int32_t right  = ConvertToPixelCoord(mCropRect->GetRight(),  imageSize.width);
2493
0
  int32_t bottom = ConvertToPixelCoord(mCropRect->GetBottom(), imageSize.height);
2494
0
2495
0
  // IntersectRect() returns an empty rect if we get negative width or height
2496
0
  nsIntRect cropRect(left, top, right - left, bottom - top);
2497
0
  nsIntRect imageRect(nsIntPoint(0, 0), imageSize);
2498
0
  aActualCropRect.IntersectRect(imageRect, cropRect);
2499
0
2500
0
  if (aIsEntireImage) {
2501
0
    *aIsEntireImage = aActualCropRect.IsEqualInterior(imageRect);
2502
0
  }
2503
0
  return true;
2504
0
}
2505
2506
bool
2507
nsStyleImage::StartDecoding() const
2508
0
{
2509
0
  if (mType == eStyleImageType_Image) {
2510
0
    imgRequestProxy* req = GetImageData();
2511
0
    if (!req) {
2512
0
      return false;
2513
0
    }
2514
0
    return req->StartDecodingWithResult(imgIContainer::FLAG_ASYNC_NOTIFY);
2515
0
  }
2516
0
  // null image types always return false from IsComplete, so we do the same here.
2517
0
  return mType != eStyleImageType_Null ? true : false;
2518
0
}
2519
2520
bool
2521
nsStyleImage::IsOpaque() const
2522
0
{
2523
0
  if (!IsComplete()) {
2524
0
    return false;
2525
0
  }
2526
0
2527
0
  if (mType == eStyleImageType_Gradient) {
2528
0
    return mGradient->IsOpaque();
2529
0
  }
2530
0
2531
0
  if (mType == eStyleImageType_Element || mType == eStyleImageType_URL) {
2532
0
    return false;
2533
0
  }
2534
0
2535
0
  MOZ_ASSERT(mType == eStyleImageType_Image, "unexpected image type");
2536
0
  MOZ_ASSERT(GetImageData(), "should've returned earlier above");
2537
0
2538
0
  nsCOMPtr<imgIContainer> imageContainer;
2539
0
  GetImageData()->GetImage(getter_AddRefs(imageContainer));
2540
0
  MOZ_ASSERT(imageContainer, "IsComplete() said image container is ready");
2541
0
2542
0
  // Check if the crop region of the image is opaque.
2543
0
  if (imageContainer->WillDrawOpaqueNow()) {
2544
0
    if (!mCropRect) {
2545
0
      return true;
2546
0
    }
2547
0
2548
0
    // Must make sure if mCropRect contains at least a pixel.
2549
0
    // XXX Is this optimization worth it? Maybe I should just return false.
2550
0
    nsIntRect actualCropRect;
2551
0
    return ComputeActualCropRect(actualCropRect) && !actualCropRect.IsEmpty();
2552
0
  }
2553
0
2554
0
  return false;
2555
0
}
2556
2557
bool
2558
nsStyleImage::IsComplete() const
2559
0
{
2560
0
  switch (mType) {
2561
0
    case eStyleImageType_Null:
2562
0
      return false;
2563
0
    case eStyleImageType_Gradient:
2564
0
    case eStyleImageType_Element:
2565
0
    case eStyleImageType_URL:
2566
0
      return true;
2567
0
    case eStyleImageType_Image: {
2568
0
      if (!IsResolved()) {
2569
0
        return false;
2570
0
      }
2571
0
      imgRequestProxy* req = GetImageData();
2572
0
      if (!req) {
2573
0
        return false;
2574
0
      }
2575
0
      uint32_t status = imgIRequest::STATUS_ERROR;
2576
0
      return NS_SUCCEEDED(req->GetImageStatus(&status)) &&
2577
0
             (status & imgIRequest::STATUS_SIZE_AVAILABLE) &&
2578
0
             (status & imgIRequest::STATUS_FRAME_COMPLETE);
2579
0
    }
2580
0
    default:
2581
0
      MOZ_ASSERT_UNREACHABLE("unexpected image type");
2582
0
      return false;
2583
0
  }
2584
0
}
2585
2586
bool
2587
nsStyleImage::IsLoaded() const
2588
0
{
2589
0
  switch (mType) {
2590
0
    case eStyleImageType_Null:
2591
0
      return false;
2592
0
    case eStyleImageType_Gradient:
2593
0
    case eStyleImageType_Element:
2594
0
    case eStyleImageType_URL:
2595
0
      return true;
2596
0
    case eStyleImageType_Image: {
2597
0
      imgRequestProxy* req = GetImageData();
2598
0
      if (!req) {
2599
0
        return false;
2600
0
      }
2601
0
      uint32_t status = imgIRequest::STATUS_ERROR;
2602
0
      return NS_SUCCEEDED(req->GetImageStatus(&status)) &&
2603
0
             !(status & imgIRequest::STATUS_ERROR) &&
2604
0
             (status & imgIRequest::STATUS_LOAD_COMPLETE);
2605
0
    }
2606
0
    default:
2607
0
      MOZ_ASSERT_UNREACHABLE("unexpected image type");
2608
0
      return false;
2609
0
  }
2610
0
}
2611
2612
static inline bool
2613
EqualRects(const UniquePtr<nsStyleSides>& aRect1, const UniquePtr<nsStyleSides>& aRect2)
2614
0
{
2615
0
  return aRect1 == aRect2 || /* handles null== null, and optimize */
2616
0
         (aRect1 && aRect2 && *aRect1 == *aRect2);
2617
0
}
2618
2619
bool
2620
nsStyleImage::operator==(const nsStyleImage& aOther) const
2621
0
{
2622
0
  if (mType != aOther.mType) {
2623
0
    return false;
2624
0
  }
2625
0
2626
0
  if (!EqualRects(mCropRect, aOther.mCropRect)) {
2627
0
    return false;
2628
0
  }
2629
0
2630
0
  if (mType == eStyleImageType_Image) {
2631
0
    return DefinitelyEqualImages(mImage, aOther.mImage);
2632
0
  }
2633
0
2634
0
  if (mType == eStyleImageType_Gradient) {
2635
0
    return *mGradient == *aOther.mGradient;
2636
0
  }
2637
0
2638
0
  if (mType == eStyleImageType_Element) {
2639
0
    return mElementId == aOther.mElementId;
2640
0
  }
2641
0
2642
0
  if (mType == eStyleImageType_URL) {
2643
0
    return DefinitelyEqualURIs(mURLValue, aOther.mURLValue);
2644
0
  }
2645
0
2646
0
  return true;
2647
0
}
2648
2649
void
2650
nsStyleImage::PurgeCacheForViewportChange(
2651
  const mozilla::Maybe<nsSize>& aSVGViewportSize,
2652
  const bool aHasIntrinsicRatio) const
2653
0
{
2654
0
  EnsureCachedBIData();
2655
0
2656
0
  // If we're redrawing with a different viewport-size than we used for our
2657
0
  // cached subimages, then we can't trust that our subimages are valid;
2658
0
  // any percent sizes/positions in our SVG doc may be different now. Purge!
2659
0
  // (We don't have to purge if the SVG document has an intrinsic ratio,
2660
0
  // though, because the actual size of elements in SVG documant's coordinate
2661
0
  // axis are fixed in this case.)
2662
0
  if (aSVGViewportSize != mCachedBIData->GetCachedSVGViewportSize() &&
2663
0
      !aHasIntrinsicRatio) {
2664
0
    mCachedBIData->PurgeCachedImages();
2665
0
    mCachedBIData->SetCachedSVGViewportSize(aSVGViewportSize);
2666
0
  }
2667
0
}
2668
2669
already_AddRefed<nsIURI>
2670
nsStyleImage::GetImageURI() const
2671
0
{
2672
0
  if (mType != eStyleImageType_Image) {
2673
0
    return nullptr;
2674
0
  }
2675
0
2676
0
  nsCOMPtr<nsIURI> uri = mImage->GetImageURI();
2677
0
  return uri.forget();
2678
0
}
2679
2680
css::URLValueData*
2681
nsStyleImage::GetURLValue() const
2682
0
{
2683
0
  if (mType == eStyleImageType_Image) {
2684
0
    return mImage->GetImageValue();
2685
0
  } else if (mType == eStyleImageType_URL) {
2686
0
    return mURLValue;
2687
0
  }
2688
0
2689
0
  return nullptr;
2690
0
}
2691
2692
// --------------------
2693
// nsStyleImageLayers
2694
//
2695
2696
const nsCSSPropertyID nsStyleImageLayers::kBackgroundLayerTable[] = {
2697
  eCSSProperty_background,                // shorthand
2698
  eCSSProperty_background_color,          // color
2699
  eCSSProperty_background_image,          // image
2700
  eCSSProperty_background_repeat,         // repeat
2701
  eCSSProperty_background_position_x,     // positionX
2702
  eCSSProperty_background_position_y,     // positionY
2703
  eCSSProperty_background_clip,           // clip
2704
  eCSSProperty_background_origin,         // origin
2705
  eCSSProperty_background_size,           // size
2706
  eCSSProperty_background_attachment,     // attachment
2707
  eCSSProperty_UNKNOWN,                   // maskMode
2708
  eCSSProperty_UNKNOWN                    // composite
2709
};
2710
2711
const nsCSSPropertyID nsStyleImageLayers::kMaskLayerTable[] = {
2712
  eCSSProperty_mask,                      // shorthand
2713
  eCSSProperty_UNKNOWN,                   // color
2714
  eCSSProperty_mask_image,                // image
2715
  eCSSProperty_mask_repeat,               // repeat
2716
  eCSSProperty_mask_position_x,           // positionX
2717
  eCSSProperty_mask_position_y,           // positionY
2718
  eCSSProperty_mask_clip,                 // clip
2719
  eCSSProperty_mask_origin,               // origin
2720
  eCSSProperty_mask_size,                 // size
2721
  eCSSProperty_UNKNOWN,                   // attachment
2722
  eCSSProperty_mask_mode,                 // maskMode
2723
  eCSSProperty_mask_composite             // composite
2724
};
2725
2726
nsStyleImageLayers::nsStyleImageLayers(nsStyleImageLayers::LayerType aType)
2727
  : mAttachmentCount(1)
2728
  , mClipCount(1)
2729
  , mOriginCount(1)
2730
  , mRepeatCount(1)
2731
  , mPositionXCount(1)
2732
  , mPositionYCount(1)
2733
  , mImageCount(1)
2734
  , mSizeCount(1)
2735
  , mMaskModeCount(1)
2736
  , mBlendModeCount(1)
2737
  , mCompositeCount(1)
2738
  , mLayers(nsStyleAutoArray<Layer>::WITH_SINGLE_INITIAL_ELEMENT)
2739
0
{
2740
0
  MOZ_COUNT_CTOR(nsStyleImageLayers);
2741
0
2742
0
  // Ensure first layer is initialized as specified layer type
2743
0
  mLayers[0].Initialize(aType);
2744
0
}
2745
2746
nsStyleImageLayers::nsStyleImageLayers(const nsStyleImageLayers &aSource)
2747
  : mAttachmentCount(aSource.mAttachmentCount)
2748
  , mClipCount(aSource.mClipCount)
2749
  , mOriginCount(aSource.mOriginCount)
2750
  , mRepeatCount(aSource.mRepeatCount)
2751
  , mPositionXCount(aSource.mPositionXCount)
2752
  , mPositionYCount(aSource.mPositionYCount)
2753
  , mImageCount(aSource.mImageCount)
2754
  , mSizeCount(aSource.mSizeCount)
2755
  , mMaskModeCount(aSource.mMaskModeCount)
2756
  , mBlendModeCount(aSource.mBlendModeCount)
2757
  , mCompositeCount(aSource.mCompositeCount)
2758
  , mLayers(aSource.mLayers) // deep copy
2759
0
{
2760
0
  MOZ_COUNT_CTOR(nsStyleImageLayers);
2761
0
  // If the deep copy of mLayers failed, truncate the counts.
2762
0
  uint32_t count = mLayers.Length();
2763
0
  if (count != aSource.mLayers.Length()) {
2764
0
    NS_WARNING("truncating counts due to out-of-memory");
2765
0
    mAttachmentCount = std::max(mAttachmentCount, count);
2766
0
    mClipCount = std::max(mClipCount, count);
2767
0
    mOriginCount = std::max(mOriginCount, count);
2768
0
    mRepeatCount = std::max(mRepeatCount, count);
2769
0
    mPositionXCount = std::max(mPositionXCount, count);
2770
0
    mPositionYCount = std::max(mPositionYCount, count);
2771
0
    mImageCount = std::max(mImageCount, count);
2772
0
    mSizeCount = std::max(mSizeCount, count);
2773
0
    mMaskModeCount = std::max(mMaskModeCount, count);
2774
0
    mBlendModeCount = std::max(mBlendModeCount, count);
2775
0
    mCompositeCount = std::max(mCompositeCount, count);
2776
0
  }
2777
0
}
2778
2779
nsChangeHint
2780
nsStyleImageLayers::CalcDifference(const nsStyleImageLayers& aNewLayers,
2781
                                   nsStyleImageLayers::LayerType aType) const
2782
0
{
2783
0
  nsChangeHint hint = nsChangeHint(0);
2784
0
2785
0
  const nsStyleImageLayers& moreLayers =
2786
0
    mImageCount > aNewLayers.mImageCount ?
2787
0
      *this : aNewLayers;
2788
0
  const nsStyleImageLayers& lessLayers =
2789
0
    mImageCount > aNewLayers.mImageCount ?
2790
0
      aNewLayers : *this;
2791
0
2792
0
  NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, moreLayers) {
2793
0
    if (i < lessLayers.mImageCount) {
2794
0
      nsChangeHint layerDifference =
2795
0
        moreLayers.mLayers[i].CalcDifference(lessLayers.mLayers[i]);
2796
0
      hint |= layerDifference;
2797
0
      if (layerDifference &&
2798
0
          ((moreLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element) ||
2799
0
           (lessLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element))) {
2800
0
        hint |= nsChangeHint_UpdateEffects | nsChangeHint_RepaintFrame;
2801
0
      }
2802
0
    } else {
2803
0
      hint |= nsChangeHint_RepaintFrame;
2804
0
      if (moreLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element) {
2805
0
        hint |= nsChangeHint_UpdateEffects | nsChangeHint_RepaintFrame;
2806
0
      }
2807
0
    }
2808
0
  }
2809
0
2810
0
  if (aType == nsStyleImageLayers::LayerType::Mask &&
2811
0
      mImageCount != aNewLayers.mImageCount) {
2812
0
    hint |= nsChangeHint_UpdateEffects;
2813
0
  }
2814
0
2815
0
  if (hint) {
2816
0
    return hint;
2817
0
  }
2818
0
2819
0
  if (mAttachmentCount != aNewLayers.mAttachmentCount ||
2820
0
      mBlendModeCount != aNewLayers.mBlendModeCount ||
2821
0
      mClipCount != aNewLayers.mClipCount ||
2822
0
      mCompositeCount != aNewLayers.mCompositeCount ||
2823
0
      mMaskModeCount != aNewLayers.mMaskModeCount ||
2824
0
      mOriginCount != aNewLayers.mOriginCount ||
2825
0
      mRepeatCount != aNewLayers.mRepeatCount ||
2826
0
      mPositionXCount != aNewLayers.mPositionXCount ||
2827
0
      mPositionYCount != aNewLayers.mPositionYCount ||
2828
0
      mSizeCount != aNewLayers.mSizeCount) {
2829
0
    hint |= nsChangeHint_NeutralChange;
2830
0
  }
2831
0
2832
0
  return hint;
2833
0
}
2834
2835
nsStyleImageLayers&
2836
nsStyleImageLayers::operator=(const nsStyleImageLayers& aOther)
2837
0
{
2838
0
  mAttachmentCount = aOther.mAttachmentCount;
2839
0
  mClipCount = aOther.mClipCount;
2840
0
  mOriginCount = aOther.mOriginCount;
2841
0
  mRepeatCount = aOther.mRepeatCount;
2842
0
  mPositionXCount = aOther.mPositionXCount;
2843
0
  mPositionYCount = aOther.mPositionYCount;
2844
0
  mImageCount = aOther.mImageCount;
2845
0
  mSizeCount = aOther.mSizeCount;
2846
0
  mMaskModeCount = aOther.mMaskModeCount;
2847
0
  mBlendModeCount = aOther.mBlendModeCount;
2848
0
  mCompositeCount = aOther.mCompositeCount;
2849
0
  mLayers = aOther.mLayers;
2850
0
2851
0
  uint32_t count = mLayers.Length();
2852
0
  if (count != aOther.mLayers.Length()) {
2853
0
    NS_WARNING("truncating counts due to out-of-memory");
2854
0
    mAttachmentCount = std::max(mAttachmentCount, count);
2855
0
    mClipCount = std::max(mClipCount, count);
2856
0
    mOriginCount = std::max(mOriginCount, count);
2857
0
    mRepeatCount = std::max(mRepeatCount, count);
2858
0
    mPositionXCount = std::max(mPositionXCount, count);
2859
0
    mPositionYCount = std::max(mPositionYCount, count);
2860
0
    mImageCount = std::max(mImageCount, count);
2861
0
    mSizeCount = std::max(mSizeCount, count);
2862
0
    mMaskModeCount = std::max(mMaskModeCount, count);
2863
0
    mBlendModeCount = std::max(mBlendModeCount, count);
2864
0
    mCompositeCount = std::max(mCompositeCount, count);
2865
0
  }
2866
0
2867
0
  return *this;
2868
0
}
2869
2870
nsStyleImageLayers&
2871
nsStyleImageLayers::operator=(nsStyleImageLayers&& aOther)
2872
0
{
2873
0
  mAttachmentCount = aOther.mAttachmentCount;
2874
0
  mClipCount = aOther.mClipCount;
2875
0
  mOriginCount = aOther.mOriginCount;
2876
0
  mRepeatCount = aOther.mRepeatCount;
2877
0
  mPositionXCount = aOther.mPositionXCount;
2878
0
  mPositionYCount = aOther.mPositionYCount;
2879
0
  mImageCount = aOther.mImageCount;
2880
0
  mSizeCount = aOther.mSizeCount;
2881
0
  mMaskModeCount = aOther.mMaskModeCount;
2882
0
  mBlendModeCount = aOther.mBlendModeCount;
2883
0
  mCompositeCount = aOther.mCompositeCount;
2884
0
  mLayers = std::move(aOther.mLayers);
2885
0
2886
0
  uint32_t count = mLayers.Length();
2887
0
  if (count != aOther.mLayers.Length()) {
2888
0
    NS_WARNING("truncating counts due to out-of-memory");
2889
0
    mAttachmentCount = std::max(mAttachmentCount, count);
2890
0
    mClipCount = std::max(mClipCount, count);
2891
0
    mOriginCount = std::max(mOriginCount, count);
2892
0
    mRepeatCount = std::max(mRepeatCount, count);
2893
0
    mPositionXCount = std::max(mPositionXCount, count);
2894
0
    mPositionYCount = std::max(mPositionYCount, count);
2895
0
    mImageCount = std::max(mImageCount, count);
2896
0
    mSizeCount = std::max(mSizeCount, count);
2897
0
    mMaskModeCount = std::max(mMaskModeCount, count);
2898
0
    mBlendModeCount = std::max(mBlendModeCount, count);
2899
0
    mCompositeCount = std::max(mCompositeCount, count);
2900
0
  }
2901
0
2902
0
  return *this;
2903
0
}
2904
2905
bool nsStyleImageLayers::operator==(const nsStyleImageLayers& aOther) const
2906
0
{
2907
0
  if (mAttachmentCount != aOther.mAttachmentCount ||
2908
0
      mClipCount != aOther.mClipCount ||
2909
0
      mOriginCount != aOther.mOriginCount ||
2910
0
      mRepeatCount != aOther.mRepeatCount ||
2911
0
      mPositionXCount != aOther.mPositionXCount ||
2912
0
      mPositionYCount != aOther.mPositionYCount ||
2913
0
      mImageCount != aOther.mImageCount ||
2914
0
      mSizeCount != aOther.mSizeCount ||
2915
0
      mMaskModeCount != aOther.mMaskModeCount ||
2916
0
      mBlendModeCount != aOther.mBlendModeCount) {
2917
0
    return false;
2918
0
  }
2919
0
2920
0
  if (mLayers.Length() != aOther.mLayers.Length()) {
2921
0
    return false;
2922
0
  }
2923
0
2924
0
  for (uint32_t i = 0; i < mLayers.Length(); i++) {
2925
0
    if (mLayers[i].mPosition != aOther.mLayers[i].mPosition ||
2926
0
        !DefinitelyEqualURIs(mLayers[i].mImage.GetURLValue(),
2927
0
                             aOther.mLayers[i].mImage.GetURLValue()) ||
2928
0
        mLayers[i].mImage != aOther.mLayers[i].mImage ||
2929
0
        mLayers[i].mSize != aOther.mLayers[i].mSize ||
2930
0
        mLayers[i].mClip != aOther.mLayers[i].mClip ||
2931
0
        mLayers[i].mOrigin != aOther.mLayers[i].mOrigin ||
2932
0
        mLayers[i].mAttachment != aOther.mLayers[i].mAttachment ||
2933
0
        mLayers[i].mBlendMode != aOther.mLayers[i].mBlendMode ||
2934
0
        mLayers[i].mComposite != aOther.mLayers[i].mComposite ||
2935
0
        mLayers[i].mMaskMode != aOther.mLayers[i].mMaskMode ||
2936
0
        mLayers[i].mRepeat != aOther.mLayers[i].mRepeat) {
2937
0
      return false;
2938
0
    }
2939
0
  }
2940
0
2941
0
  return true;
2942
0
}
2943
2944
bool
2945
nsStyleImageLayers::IsInitialPositionForLayerType(Position aPosition, LayerType aType)
2946
0
{
2947
0
  if (aPosition.mXPosition.mPercent == 0.0f &&
2948
0
      aPosition.mXPosition.mLength == 0 &&
2949
0
      aPosition.mXPosition.mHasPercent &&
2950
0
      aPosition.mYPosition.mPercent == 0.0f &&
2951
0
      aPosition.mYPosition.mLength == 0 &&
2952
0
      aPosition.mYPosition.mHasPercent) {
2953
0
    return true;
2954
0
  }
2955
0
2956
0
  return false;
2957
0
}
2958
2959
void
2960
Position::SetInitialPercentValues(float aPercentVal)
2961
0
{
2962
0
  mXPosition.mPercent = aPercentVal;
2963
0
  mXPosition.mLength = 0;
2964
0
  mXPosition.mHasPercent = true;
2965
0
  mYPosition.mPercent = aPercentVal;
2966
0
  mYPosition.mLength = 0;
2967
0
  mYPosition.mHasPercent = true;
2968
0
}
2969
2970
void
2971
Position::SetInitialZeroValues()
2972
0
{
2973
0
  mXPosition.mPercent = 0;
2974
0
  mXPosition.mLength = 0;
2975
0
  mXPosition.mHasPercent = false;
2976
0
  mYPosition.mPercent = 0;
2977
0
  mYPosition.mLength = 0;
2978
0
  mYPosition.mHasPercent = false;
2979
0
}
2980
2981
bool
2982
nsStyleImageLayers::Size::DependsOnPositioningAreaSize(const nsStyleImage& aImage) const
2983
0
{
2984
0
  MOZ_ASSERT(aImage.GetType() != eStyleImageType_Null,
2985
0
             "caller should have handled this");
2986
0
2987
0
  // If either dimension contains a non-zero percentage, rendering for that
2988
0
  // dimension straightforwardly depends on frame size.
2989
0
  if ((mWidthType == eLengthPercentage && mWidth.mPercent != 0.0f) ||
2990
0
      (mHeightType == eLengthPercentage && mHeight.mPercent != 0.0f)) {
2991
0
    return true;
2992
0
  }
2993
0
2994
0
  // So too for contain and cover.
2995
0
  if (mWidthType == eContain || mWidthType == eCover) {
2996
0
    return true;
2997
0
  }
2998
0
2999
0
  // If both dimensions are fixed lengths, there's no dependency.
3000
0
  if (mWidthType == eLengthPercentage && mHeightType == eLengthPercentage) {
3001
0
    return false;
3002
0
  }
3003
0
3004
0
  MOZ_ASSERT((mWidthType == eLengthPercentage && mHeightType == eAuto) ||
3005
0
             (mWidthType == eAuto && mHeightType == eLengthPercentage) ||
3006
0
             (mWidthType == eAuto && mHeightType == eAuto),
3007
0
             "logic error");
3008
0
3009
0
  nsStyleImageType type = aImage.GetType();
3010
0
3011
0
  // Gradient rendering depends on frame size when auto is involved because
3012
0
  // gradients have no intrinsic ratio or dimensions, and therefore the relevant
3013
0
  // dimension is "treat[ed] as 100%".
3014
0
  if (type == eStyleImageType_Gradient) {
3015
0
    return true;
3016
0
  }
3017
0
3018
0
  // XXX Element rendering for auto or fixed length doesn't depend on frame size
3019
0
  //     according to the spec.  However, we don't implement the spec yet, so
3020
0
  //     for now we bail and say element() plus auto affects ultimate size.
3021
0
  if (type == eStyleImageType_Element) {
3022
0
    return true;
3023
0
  }
3024
0
3025
0
  if (type == eStyleImageType_Image) {
3026
0
    nsCOMPtr<imgIContainer> imgContainer;
3027
0
    if (imgRequestProxy* req = aImage.GetImageData()) {
3028
0
      req->GetImage(getter_AddRefs(imgContainer));
3029
0
    }
3030
0
    if (imgContainer) {
3031
0
      CSSIntSize imageSize;
3032
0
      nsSize imageRatio;
3033
0
      bool hasWidth, hasHeight;
3034
0
      nsLayoutUtils::ComputeSizeForDrawing(imgContainer, imageSize, imageRatio,
3035
0
                                           hasWidth, hasHeight);
3036
0
3037
0
      // If the image has a fixed width and height, rendering never depends on
3038
0
      // the frame size.
3039
0
      if (hasWidth && hasHeight) {
3040
0
        return false;
3041
0
      }
3042
0
3043
0
      // If the image has an intrinsic ratio, rendering will depend on frame
3044
0
      // size when background-size is all auto.
3045
0
      if (imageRatio != nsSize(0, 0)) {
3046
0
        return mWidthType == mHeightType;
3047
0
      }
3048
0
3049
0
      // Otherwise, rendering depends on frame size when the image dimensions
3050
0
      // and background-size don't complement each other.
3051
0
      return !(hasWidth && mHeightType == eLengthPercentage) &&
3052
0
             !(hasHeight && mWidthType == eLengthPercentage);
3053
0
    }
3054
0
  } else {
3055
0
    MOZ_ASSERT_UNREACHABLE("missed an enum value");
3056
0
  }
3057
0
3058
0
  // Passed the gauntlet: no dependency.
3059
0
  return false;
3060
0
}
3061
3062
void
3063
nsStyleImageLayers::Size::SetInitialValues()
3064
0
{
3065
0
  mWidthType = mHeightType = eAuto;
3066
0
}
3067
3068
bool
3069
nsStyleImageLayers::Size::operator==(const Size& aOther) const
3070
0
{
3071
0
  MOZ_ASSERT(mWidthType < eDimensionType_COUNT,
3072
0
             "bad mWidthType for this");
3073
0
  MOZ_ASSERT(mHeightType < eDimensionType_COUNT,
3074
0
             "bad mHeightType for this");
3075
0
  MOZ_ASSERT(aOther.mWidthType < eDimensionType_COUNT,
3076
0
             "bad mWidthType for aOther");
3077
0
  MOZ_ASSERT(aOther.mHeightType < eDimensionType_COUNT,
3078
0
             "bad mHeightType for aOther");
3079
0
3080
0
  return mWidthType == aOther.mWidthType &&
3081
0
         mHeightType == aOther.mHeightType &&
3082
0
         (mWidthType != eLengthPercentage || mWidth == aOther.mWidth) &&
3083
0
         (mHeightType != eLengthPercentage || mHeight == aOther.mHeight);
3084
0
}
3085
3086
nsStyleImageLayers::Layer::Layer()
3087
  : mClip(StyleGeometryBox::BorderBox)
3088
  , mAttachment(StyleImageLayerAttachment::Scroll)
3089
  , mBlendMode(NS_STYLE_BLEND_NORMAL)
3090
  , mComposite(NS_STYLE_MASK_COMPOSITE_ADD)
3091
  , mMaskMode(NS_STYLE_MASK_MODE_MATCH_SOURCE)
3092
0
{
3093
0
  mImage.SetNull();
3094
0
  mSize.SetInitialValues();
3095
0
}
3096
3097
nsStyleImageLayers::Layer::~Layer()
3098
0
{
3099
0
}
3100
3101
void
3102
nsStyleImageLayers::Layer::Initialize(nsStyleImageLayers::LayerType aType)
3103
0
{
3104
0
  mRepeat.SetInitialValues();
3105
0
3106
0
  mPosition.SetInitialPercentValues(0.0f);
3107
0
3108
0
  if (aType == LayerType::Background) {
3109
0
    mOrigin = StyleGeometryBox::PaddingBox;
3110
0
  } else {
3111
0
    MOZ_ASSERT(aType == LayerType::Mask, "unsupported layer type.");
3112
0
    mOrigin = StyleGeometryBox::BorderBox;
3113
0
  }
3114
0
}
3115
3116
bool
3117
nsStyleImageLayers::Layer::RenderingMightDependOnPositioningAreaSizeChange() const
3118
0
{
3119
0
  // Do we even have an image?
3120
0
  if (mImage.IsEmpty()) {
3121
0
    return false;
3122
0
  }
3123
0
3124
0
  return mPosition.DependsOnPositioningAreaSize() ||
3125
0
      mSize.DependsOnPositioningAreaSize(mImage) ||
3126
0
      mRepeat.DependsOnPositioningAreaSize();
3127
0
}
3128
3129
bool
3130
nsStyleImageLayers::Layer::operator==(const Layer& aOther) const
3131
0
{
3132
0
  return mAttachment == aOther.mAttachment &&
3133
0
         mClip == aOther.mClip &&
3134
0
         mOrigin == aOther.mOrigin &&
3135
0
         mRepeat == aOther.mRepeat &&
3136
0
         mBlendMode == aOther.mBlendMode &&
3137
0
         mPosition == aOther.mPosition &&
3138
0
         mSize == aOther.mSize &&
3139
0
         mImage == aOther.mImage &&
3140
0
         mMaskMode == aOther.mMaskMode &&
3141
0
         mComposite == aOther.mComposite;
3142
0
}
3143
3144
template <class ComputedValueItem>
3145
static void
3146
FillImageLayerList(
3147
    nsStyleAutoArray<nsStyleImageLayers::Layer>& aLayers,
3148
    ComputedValueItem nsStyleImageLayers::Layer::* aResultLocation,
3149
    uint32_t aItemCount, uint32_t aFillCount)
3150
0
{
3151
0
  MOZ_ASSERT(aFillCount <= aLayers.Length(), "unexpected array length");
3152
0
  for (uint32_t sourceLayer = 0, destLayer = aItemCount;
3153
0
       destLayer < aFillCount;
3154
0
       ++sourceLayer, ++destLayer) {
3155
0
    aLayers[destLayer].*aResultLocation =
3156
0
      aLayers[sourceLayer].*aResultLocation;
3157
0
  }
3158
0
}
Unexecuted instantiation: Unified_cpp_layout_style3.cpp:void FillImageLayerList<nsStyleImage>(nsStyleAutoArray<nsStyleImageLayers::Layer>&, nsStyleImage nsStyleImageLayers::Layer::*, unsigned int, unsigned int)
Unexecuted instantiation: Unified_cpp_layout_style3.cpp:void FillImageLayerList<nsStyleImageLayers::Repeat>(nsStyleAutoArray<nsStyleImageLayers::Layer>&, nsStyleImageLayers::Repeat nsStyleImageLayers::Layer::*, unsigned int, unsigned int)
Unexecuted instantiation: Unified_cpp_layout_style3.cpp:void FillImageLayerList<mozilla::StyleImageLayerAttachment>(nsStyleAutoArray<nsStyleImageLayers::Layer>&, mozilla::StyleImageLayerAttachment nsStyleImageLayers::Layer::*, unsigned int, unsigned int)
Unexecuted instantiation: Unified_cpp_layout_style3.cpp:void FillImageLayerList<mozilla::StyleGeometryBox>(nsStyleAutoArray<nsStyleImageLayers::Layer>&, mozilla::StyleGeometryBox nsStyleImageLayers::Layer::*, unsigned int, unsigned int)
Unexecuted instantiation: Unified_cpp_layout_style3.cpp:void FillImageLayerList<unsigned char>(nsStyleAutoArray<nsStyleImageLayers::Layer>&, unsigned char nsStyleImageLayers::Layer::*, unsigned int, unsigned int)
Unexecuted instantiation: Unified_cpp_layout_style3.cpp:void FillImageLayerList<nsStyleImageLayers::Size>(nsStyleAutoArray<nsStyleImageLayers::Layer>&, nsStyleImageLayers::Size nsStyleImageLayers::Layer::*, unsigned int, unsigned int)
3159
3160
// The same as FillImageLayerList, but for values stored in
3161
// layer.mPosition.*aResultLocation instead of layer.*aResultLocation.
3162
static void
3163
FillImageLayerPositionCoordList(
3164
    nsStyleAutoArray<nsStyleImageLayers::Layer>& aLayers,
3165
    Position::Coord
3166
        Position::* aResultLocation,
3167
    uint32_t aItemCount, uint32_t aFillCount)
3168
0
{
3169
0
  MOZ_ASSERT(aFillCount <= aLayers.Length(), "unexpected array length");
3170
0
  for (uint32_t sourceLayer = 0, destLayer = aItemCount;
3171
0
       destLayer < aFillCount;
3172
0
       ++sourceLayer, ++destLayer) {
3173
0
    aLayers[destLayer].mPosition.*aResultLocation =
3174
0
      aLayers[sourceLayer].mPosition.*aResultLocation;
3175
0
  }
3176
0
}
3177
3178
void
3179
nsStyleImageLayers::FillAllLayers(uint32_t aMaxItemCount)
3180
0
{
3181
0
  // Delete any extra items.  We need to keep layers in which any
3182
0
  // property was specified.
3183
0
  mLayers.TruncateLengthNonZero(aMaxItemCount);
3184
0
3185
0
  uint32_t fillCount = mImageCount;
3186
0
  FillImageLayerList(mLayers,
3187
0
                     &Layer::mImage,
3188
0
                     mImageCount, fillCount);
3189
0
  FillImageLayerList(mLayers,
3190
0
                     &Layer::mRepeat,
3191
0
                     mRepeatCount, fillCount);
3192
0
  FillImageLayerList(mLayers,
3193
0
                     &Layer::mAttachment,
3194
0
                     mAttachmentCount, fillCount);
3195
0
  FillImageLayerList(mLayers,
3196
0
                     &Layer::mClip,
3197
0
                     mClipCount, fillCount);
3198
0
  FillImageLayerList(mLayers,
3199
0
                     &Layer::mBlendMode,
3200
0
                     mBlendModeCount, fillCount);
3201
0
  FillImageLayerList(mLayers,
3202
0
                     &Layer::mOrigin,
3203
0
                     mOriginCount, fillCount);
3204
0
  FillImageLayerPositionCoordList(mLayers,
3205
0
                                  &Position::mXPosition,
3206
0
                                  mPositionXCount, fillCount);
3207
0
  FillImageLayerPositionCoordList(mLayers,
3208
0
                                  &Position::mYPosition,
3209
0
                                  mPositionYCount, fillCount);
3210
0
  FillImageLayerList(mLayers,
3211
0
                     &Layer::mSize,
3212
0
                     mSizeCount, fillCount);
3213
0
  FillImageLayerList(mLayers,
3214
0
                     &Layer::mMaskMode,
3215
0
                     mMaskModeCount, fillCount);
3216
0
  FillImageLayerList(mLayers,
3217
0
                     &Layer::mComposite,
3218
0
                     mCompositeCount, fillCount);
3219
0
}
3220
3221
nsChangeHint
3222
nsStyleImageLayers::Layer::CalcDifference(const nsStyleImageLayers::Layer& aNewLayer) const
3223
0
{
3224
0
  nsChangeHint hint = nsChangeHint(0);
3225
0
  if (!DefinitelyEqualURIs(mImage.GetURLValue(),
3226
0
                           aNewLayer.mImage.GetURLValue())) {
3227
0
    hint |= nsChangeHint_RepaintFrame | nsChangeHint_UpdateEffects;
3228
0
3229
0
    // If mImage links to an SVG mask, the URL in mImage must have a fragment.
3230
0
    // Not vice versa.
3231
0
    // Here are examples of URI contains a fragment, two of them link to an
3232
0
    // SVG mask:
3233
0
    //   mask:url(a.svg#maskID); // The fragment of this URI is an ID of a mask
3234
0
    //                           // element in a.svg.
3235
0
    //   mask:url(#localMaskID); // The fragment of this URI is an ID of a mask
3236
0
    //                           // element in local document.
3237
0
    //   mask:url(b.svg#viewBoxID); // The fragment of this URI is an ID of a
3238
0
    //                              // viewbox defined in b.svg.
3239
0
    // That is, if the URL in mImage has a fragment, it may link to an SVG
3240
0
    // mask; If not, it "must" not link to an SVG mask.
3241
0
    bool maybeSVGMask = false;
3242
0
    if (mImage.GetURLValue()) {
3243
0
      maybeSVGMask = mImage.GetURLValue()->MightHaveRef();
3244
0
    }
3245
0
3246
0
    if (!maybeSVGMask && aNewLayer.mImage.GetURLValue()) {
3247
0
      maybeSVGMask = aNewLayer.mImage.GetURLValue()->MightHaveRef();
3248
0
    }
3249
0
3250
0
    // Return nsChangeHint_UpdateOverflow if either URI might link to an SVG
3251
0
    // mask.
3252
0
    if (maybeSVGMask) {
3253
0
      // Mask changes require that we update the PreEffectsBBoxProperty,
3254
0
      // which is done during overflow computation.
3255
0
      hint |= nsChangeHint_UpdateOverflow;
3256
0
    }
3257
0
  } else if (mAttachment != aNewLayer.mAttachment ||
3258
0
             mClip != aNewLayer.mClip ||
3259
0
             mOrigin != aNewLayer.mOrigin ||
3260
0
             mRepeat != aNewLayer.mRepeat ||
3261
0
             mBlendMode != aNewLayer.mBlendMode ||
3262
0
             mSize != aNewLayer.mSize ||
3263
0
             mImage != aNewLayer.mImage ||
3264
0
             mMaskMode != aNewLayer.mMaskMode ||
3265
0
             mComposite != aNewLayer.mComposite) {
3266
0
    hint |= nsChangeHint_RepaintFrame;
3267
0
  }
3268
0
3269
0
  if (mPosition != aNewLayer.mPosition) {
3270
0
    hint |= nsChangeHint_UpdateBackgroundPosition;
3271
0
  }
3272
0
3273
0
  return hint;
3274
0
}
3275
3276
// --------------------
3277
// nsStyleBackground
3278
//
3279
3280
nsStyleBackground::nsStyleBackground(const nsPresContext* aContext)
3281
  : mImage(nsStyleImageLayers::LayerType::Background)
3282
  , mBackgroundColor(StyleComplexColor::Transparent())
3283
0
{
3284
0
  MOZ_COUNT_CTOR(nsStyleBackground);
3285
0
}
3286
3287
nsStyleBackground::nsStyleBackground(const nsStyleBackground& aSource)
3288
  : mImage(aSource.mImage)
3289
  , mBackgroundColor(aSource.mBackgroundColor)
3290
0
{
3291
0
  MOZ_COUNT_CTOR(nsStyleBackground);
3292
0
}
3293
3294
nsStyleBackground::~nsStyleBackground()
3295
0
{
3296
0
  MOZ_COUNT_DTOR(nsStyleBackground);
3297
0
}
3298
3299
void
3300
nsStyleBackground::FinishStyle(
3301
  nsPresContext* aPresContext, const nsStyleBackground* aOldStyle)
3302
0
{
3303
0
  MOZ_ASSERT(NS_IsMainThread());
3304
0
3305
0
  mImage.ResolveImages(aPresContext, aOldStyle ? &aOldStyle->mImage : nullptr);
3306
0
}
3307
3308
nsChangeHint
3309
nsStyleBackground::CalcDifference(const nsStyleBackground& aNewData) const
3310
0
{
3311
0
  nsChangeHint hint = nsChangeHint(0);
3312
0
  if (mBackgroundColor != aNewData.mBackgroundColor) {
3313
0
    hint |= nsChangeHint_RepaintFrame;
3314
0
  }
3315
0
3316
0
  hint |= mImage.CalcDifference(aNewData.mImage,
3317
0
                                nsStyleImageLayers::LayerType::Background);
3318
0
3319
0
  return hint;
3320
0
}
3321
3322
bool
3323
nsStyleBackground::HasFixedBackground(nsIFrame* aFrame) const
3324
0
{
3325
0
  NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, mImage) {
3326
0
    const nsStyleImageLayers::Layer &layer = mImage.mLayers[i];
3327
0
    if (layer.mAttachment == StyleImageLayerAttachment::Fixed &&
3328
0
        !layer.mImage.IsEmpty() &&
3329
0
        !nsLayoutUtils::IsTransformed(aFrame)) {
3330
0
      return true;
3331
0
    }
3332
0
  }
3333
0
  return false;
3334
0
}
3335
3336
nscolor
3337
nsStyleBackground::BackgroundColor(const nsIFrame* aFrame) const
3338
0
{
3339
0
  return mBackgroundColor.CalcColor(aFrame);
3340
0
}
3341
3342
nscolor
3343
nsStyleBackground::BackgroundColor(mozilla::ComputedStyle* aStyle) const
3344
0
{
3345
0
  return mBackgroundColor.CalcColor(aStyle);
3346
0
}
3347
3348
bool
3349
nsStyleBackground::IsTransparent(const nsIFrame* aFrame) const
3350
0
{
3351
0
  return IsTransparent(aFrame->Style());
3352
0
}
3353
3354
bool
3355
nsStyleBackground::IsTransparent(mozilla::ComputedStyle* aStyle) const
3356
0
{
3357
0
  return BottomLayer().mImage.IsEmpty() &&
3358
0
         mImage.mImageCount == 1 &&
3359
0
         NS_GET_A(BackgroundColor(aStyle)) == 0;
3360
0
}
3361
3362
void
3363
nsTimingFunction::AssignFromKeyword(int32_t aTimingFunctionType)
3364
0
{
3365
0
  switch (aTimingFunctionType) {
3366
0
    case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START:
3367
0
      mType = Type::StepStart;
3368
0
      mStepsOrFrames = 1;
3369
0
      return;
3370
0
    default:
3371
0
      MOZ_FALLTHROUGH_ASSERT("aTimingFunctionType must be a keyword value");
3372
0
    case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END:
3373
0
      mType = Type::StepEnd;
3374
0
      mStepsOrFrames = 1;
3375
0
      return;
3376
0
    case NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE:
3377
0
    case NS_STYLE_TRANSITION_TIMING_FUNCTION_LINEAR:
3378
0
    case NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN:
3379
0
    case NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_OUT:
3380
0
    case NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN_OUT:
3381
0
      mType = static_cast<Type>(aTimingFunctionType);
3382
0
      break;
3383
0
  }
3384
0
3385
0
  static_assert(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE == 0 &&
3386
0
                NS_STYLE_TRANSITION_TIMING_FUNCTION_LINEAR == 1 &&
3387
0
                NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN == 2 &&
3388
0
                NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_OUT == 3 &&
3389
0
                NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN_OUT == 4,
3390
0
                "transition timing function constants not as expected");
3391
0
3392
0
  static const float timingFunctionValues[5][4] = {
3393
0
    { 0.25f, 0.10f, 0.25f, 1.00f }, // ease
3394
0
    { 0.00f, 0.00f, 1.00f, 1.00f }, // linear
3395
0
    { 0.42f, 0.00f, 1.00f, 1.00f }, // ease-in
3396
0
    { 0.00f, 0.00f, 0.58f, 1.00f }, // ease-out
3397
0
    { 0.42f, 0.00f, 0.58f, 1.00f }  // ease-in-out
3398
0
  };
3399
0
3400
0
  MOZ_ASSERT(0 <= aTimingFunctionType && aTimingFunctionType < 5,
3401
0
             "keyword out of range");
3402
0
  mFunc.mX1 = timingFunctionValues[aTimingFunctionType][0];
3403
0
  mFunc.mY1 = timingFunctionValues[aTimingFunctionType][1];
3404
0
  mFunc.mX2 = timingFunctionValues[aTimingFunctionType][2];
3405
0
  mFunc.mY2 = timingFunctionValues[aTimingFunctionType][3];
3406
0
}
3407
3408
StyleTransition::StyleTransition(const StyleTransition& aCopy)
3409
  : mTimingFunction(aCopy.mTimingFunction)
3410
  , mDuration(aCopy.mDuration)
3411
  , mDelay(aCopy.mDelay)
3412
  , mProperty(aCopy.mProperty)
3413
  , mUnknownProperty(aCopy.mUnknownProperty)
3414
0
{
3415
0
}
3416
3417
void
3418
StyleTransition::SetInitialValues()
3419
0
{
3420
0
  mTimingFunction = nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE);
3421
0
  mDuration = 0.0;
3422
0
  mDelay = 0.0;
3423
0
  mProperty = eCSSPropertyExtra_all_properties;
3424
0
}
3425
3426
bool
3427
StyleTransition::operator==(const StyleTransition& aOther) const
3428
0
{
3429
0
  return mTimingFunction == aOther.mTimingFunction &&
3430
0
         mDuration == aOther.mDuration &&
3431
0
         mDelay == aOther.mDelay &&
3432
0
         mProperty == aOther.mProperty &&
3433
0
         (mProperty != eCSSProperty_UNKNOWN ||
3434
0
          mUnknownProperty == aOther.mUnknownProperty);
3435
0
}
3436
3437
StyleAnimation::StyleAnimation(const StyleAnimation& aCopy)
3438
  : mTimingFunction(aCopy.mTimingFunction)
3439
  , mDuration(aCopy.mDuration)
3440
  , mDelay(aCopy.mDelay)
3441
  , mName(aCopy.mName)
3442
  , mDirection(aCopy.mDirection)
3443
  , mFillMode(aCopy.mFillMode)
3444
  , mPlayState(aCopy.mPlayState)
3445
  , mIterationCount(aCopy.mIterationCount)
3446
0
{
3447
0
}
3448
3449
void
3450
StyleAnimation::SetInitialValues()
3451
0
{
3452
0
  mTimingFunction = nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE);
3453
0
  mDuration = 0.0;
3454
0
  mDelay = 0.0;
3455
0
  mName = nsGkAtoms::_empty;
3456
0
  mDirection = dom::PlaybackDirection::Normal;
3457
0
  mFillMode = dom::FillMode::None;
3458
0
  mPlayState = NS_STYLE_ANIMATION_PLAY_STATE_RUNNING;
3459
0
  mIterationCount = 1.0f;
3460
0
}
3461
3462
bool
3463
StyleAnimation::operator==(const StyleAnimation& aOther) const
3464
0
{
3465
0
  return mTimingFunction == aOther.mTimingFunction &&
3466
0
         mDuration == aOther.mDuration &&
3467
0
         mDelay == aOther.mDelay &&
3468
0
         mName == aOther.mName &&
3469
0
         mDirection == aOther.mDirection &&
3470
0
         mFillMode == aOther.mFillMode &&
3471
0
         mPlayState == aOther.mPlayState &&
3472
0
         mIterationCount == aOther.mIterationCount;
3473
0
}
3474
3475
// --------------------
3476
// nsStyleDisplay
3477
//
3478
nsStyleDisplay::nsStyleDisplay(const nsPresContext* aContext)
3479
  : mDisplay(StyleDisplay::Inline)
3480
  , mOriginalDisplay(StyleDisplay::Inline)
3481
  , mContain(NS_STYLE_CONTAIN_NONE)
3482
  , mAppearance(StyleAppearance::None)
3483
  , mPosition(NS_STYLE_POSITION_STATIC)
3484
  , mFloat(StyleFloat::None)
3485
  , mOriginalFloat(StyleFloat::None)
3486
  , mBreakType(StyleClear::None)
3487
  , mBreakInside(NS_STYLE_PAGE_BREAK_AUTO)
3488
  , mBreakBefore(false)
3489
  , mBreakAfter(false)
3490
  , mOverflowX(NS_STYLE_OVERFLOW_VISIBLE)
3491
  , mOverflowY(NS_STYLE_OVERFLOW_VISIBLE)
3492
  , mOverflowClipBoxBlock(NS_STYLE_OVERFLOW_CLIP_BOX_PADDING_BOX)
3493
  , mOverflowClipBoxInline(NS_STYLE_OVERFLOW_CLIP_BOX_PADDING_BOX)
3494
  , mResize(NS_STYLE_RESIZE_NONE)
3495
  , mOrient(StyleOrient::Inline)
3496
  , mIsolation(NS_STYLE_ISOLATION_AUTO)
3497
  , mTopLayer(NS_STYLE_TOP_LAYER_NONE)
3498
  , mWillChangeBitField(0)
3499
  , mTouchAction(NS_STYLE_TOUCH_ACTION_AUTO)
3500
  , mScrollBehavior(NS_STYLE_SCROLL_BEHAVIOR_AUTO)
3501
  , mOverscrollBehaviorX(StyleOverscrollBehavior::Auto)
3502
  , mOverscrollBehaviorY(StyleOverscrollBehavior::Auto)
3503
  , mScrollSnapTypeX(NS_STYLE_SCROLL_SNAP_TYPE_NONE)
3504
  , mScrollSnapTypeY(NS_STYLE_SCROLL_SNAP_TYPE_NONE)
3505
  , mScrollSnapPointsX(eStyleUnit_None)
3506
  , mScrollSnapPointsY(eStyleUnit_None)
3507
  , mBackfaceVisibility(NS_STYLE_BACKFACE_VISIBILITY_VISIBLE)
3508
  , mTransformStyle(NS_STYLE_TRANSFORM_STYLE_FLAT)
3509
  , mTransformBox(StyleGeometryBox::BorderBox)
3510
  , mTransformOrigin{ {0.5f, eStyleUnit_Percent}, // Transform is centered on origin
3511
                      {0.5f, eStyleUnit_Percent},
3512
                      {0, nsStyleCoord::CoordConstructor} }
3513
  , mChildPerspective(eStyleUnit_None)
3514
  , mPerspectiveOrigin{ {0.5f, eStyleUnit_Percent},
3515
                        {0.5f, eStyleUnit_Percent} }
3516
  , mVerticalAlign(NS_STYLE_VERTICAL_ALIGN_BASELINE, eStyleUnit_Enumerated)
3517
  , mTransitions(nsStyleAutoArray<StyleTransition>::WITH_SINGLE_INITIAL_ELEMENT)
3518
  , mTransitionTimingFunctionCount(1)
3519
  , mTransitionDurationCount(1)
3520
  , mTransitionDelayCount(1)
3521
  , mTransitionPropertyCount(1)
3522
  , mAnimations(nsStyleAutoArray<StyleAnimation>::WITH_SINGLE_INITIAL_ELEMENT)
3523
  , mAnimationTimingFunctionCount(1)
3524
  , mAnimationDurationCount(1)
3525
  , mAnimationDelayCount(1)
3526
  , mAnimationNameCount(1)
3527
  , mAnimationDirectionCount(1)
3528
  , mAnimationFillModeCount(1)
3529
  , mAnimationPlayStateCount(1)
3530
  , mAnimationIterationCountCount(1)
3531
  , mShapeMargin(0, nsStyleCoord::CoordConstructor)
3532
0
{
3533
0
  MOZ_COUNT_CTOR(nsStyleDisplay);
3534
0
3535
0
  // Initial value for mScrollSnapDestination is "0px 0px"
3536
0
  mScrollSnapDestination.SetInitialZeroValues();
3537
0
3538
0
  mTransitions[0].SetInitialValues();
3539
0
  mAnimations[0].SetInitialValues();
3540
0
}
3541
3542
nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource)
3543
  : mBinding(aSource.mBinding)
3544
  , mDisplay(aSource.mDisplay)
3545
  , mOriginalDisplay(aSource.mOriginalDisplay)
3546
  , mContain(aSource.mContain)
3547
  , mAppearance(aSource.mAppearance)
3548
  , mPosition(aSource.mPosition)
3549
  , mFloat(aSource.mFloat)
3550
  , mOriginalFloat(aSource.mOriginalFloat)
3551
  , mBreakType(aSource.mBreakType)
3552
  , mBreakInside(aSource.mBreakInside)
3553
  , mBreakBefore(aSource.mBreakBefore)
3554
  , mBreakAfter(aSource.mBreakAfter)
3555
  , mOverflowX(aSource.mOverflowX)
3556
  , mOverflowY(aSource.mOverflowY)
3557
  , mOverflowClipBoxBlock(aSource.mOverflowClipBoxBlock)
3558
  , mOverflowClipBoxInline(aSource.mOverflowClipBoxInline)
3559
  , mResize(aSource.mResize)
3560
  , mOrient(aSource.mOrient)
3561
  , mIsolation(aSource.mIsolation)
3562
  , mTopLayer(aSource.mTopLayer)
3563
  , mWillChangeBitField(aSource.mWillChangeBitField)
3564
  , mWillChange(aSource.mWillChange)
3565
  , mTouchAction(aSource.mTouchAction)
3566
  , mScrollBehavior(aSource.mScrollBehavior)
3567
  , mOverscrollBehaviorX(aSource.mOverscrollBehaviorX)
3568
  , mOverscrollBehaviorY(aSource.mOverscrollBehaviorY)
3569
  , mScrollSnapTypeX(aSource.mScrollSnapTypeX)
3570
  , mScrollSnapTypeY(aSource.mScrollSnapTypeY)
3571
  , mScrollSnapPointsX(aSource.mScrollSnapPointsX)
3572
  , mScrollSnapPointsY(aSource.mScrollSnapPointsY)
3573
  , mScrollSnapDestination(aSource.mScrollSnapDestination)
3574
  , mScrollSnapCoordinate(aSource.mScrollSnapCoordinate)
3575
  , mBackfaceVisibility(aSource.mBackfaceVisibility)
3576
  , mTransformStyle(aSource.mTransformStyle)
3577
  , mTransformBox(aSource.mTransformBox)
3578
  , mSpecifiedTransform(aSource.mSpecifiedTransform)
3579
  , mSpecifiedRotate(aSource.mSpecifiedRotate)
3580
  , mSpecifiedTranslate(aSource.mSpecifiedTranslate)
3581
  , mSpecifiedScale(aSource.mSpecifiedScale)
3582
  , mIndividualTransform(aSource.mIndividualTransform)
3583
  , mMotion(aSource.mMotion
3584
            ? MakeUnique<StyleMotion>(*aSource.mMotion)
3585
            : nullptr)
3586
  , mTransformOrigin{ aSource.mTransformOrigin[0],
3587
                      aSource.mTransformOrigin[1],
3588
                      aSource.mTransformOrigin[2] }
3589
  , mChildPerspective(aSource.mChildPerspective)
3590
  , mPerspectiveOrigin{ aSource.mPerspectiveOrigin[0],
3591
                        aSource.mPerspectiveOrigin[1] }
3592
  , mVerticalAlign(aSource.mVerticalAlign)
3593
  , mTransitions(aSource.mTransitions)
3594
  , mTransitionTimingFunctionCount(aSource.mTransitionTimingFunctionCount)
3595
  , mTransitionDurationCount(aSource.mTransitionDurationCount)
3596
  , mTransitionDelayCount(aSource.mTransitionDelayCount)
3597
  , mTransitionPropertyCount(aSource.mTransitionPropertyCount)
3598
  , mAnimations(aSource.mAnimations)
3599
  , mAnimationTimingFunctionCount(aSource.mAnimationTimingFunctionCount)
3600
  , mAnimationDurationCount(aSource.mAnimationDurationCount)
3601
  , mAnimationDelayCount(aSource.mAnimationDelayCount)
3602
  , mAnimationNameCount(aSource.mAnimationNameCount)
3603
  , mAnimationDirectionCount(aSource.mAnimationDirectionCount)
3604
  , mAnimationFillModeCount(aSource.mAnimationFillModeCount)
3605
  , mAnimationPlayStateCount(aSource.mAnimationPlayStateCount)
3606
  , mAnimationIterationCountCount(aSource.mAnimationIterationCountCount)
3607
  , mShapeImageThreshold(aSource.mShapeImageThreshold)
3608
  , mShapeMargin(aSource.mShapeMargin)
3609
  , mShapeOutside(aSource.mShapeOutside)
3610
0
{
3611
0
  MOZ_COUNT_CTOR(nsStyleDisplay);
3612
0
}
3613
3614
3615
static
3616
void ReleaseSharedListOnMainThread(const char* aName,
3617
                                   RefPtr<nsCSSValueSharedList>& aList)
3618
0
{
3619
0
  // We don't allow releasing nsCSSValues with refcounted data in the Servo
3620
0
  // traversal, since the refcounts aren't threadsafe. Since Servo may trigger
3621
0
  // the deallocation of style structs during styling, we need to handle it
3622
0
  // here.
3623
0
  if (aList && ServoStyleSet::IsInServoTraversal()) {
3624
0
    // The default behavior of NS_ReleaseOnMainThreadSystemGroup is to only
3625
0
    // proxy the release if we're not already on the main thread. This is a nice
3626
0
    // optimization for the cases we happen to be doing a sequential traversal
3627
0
    // (i.e. a single-core machine), but it trips our assertions which check
3628
0
    // whether we're in a Servo traversal, parallel or not. So we
3629
0
    // unconditionally proxy in debug builds.
3630
0
    bool alwaysProxy =
3631
#ifdef DEBUG
3632
      true;
3633
#else
3634
      false;
3635
0
#endif
3636
0
    NS_ReleaseOnMainThreadSystemGroup(aName, aList.forget(), alwaysProxy);
3637
0
  }
3638
0
}
3639
3640
nsStyleDisplay::~nsStyleDisplay()
3641
0
{
3642
0
  ReleaseSharedListOnMainThread("nsStyleDisplay::mSpecifiedTransform",
3643
0
                                mSpecifiedTransform);
3644
0
  ReleaseSharedListOnMainThread("nsStyleDisplay::mSpecifiedRotate",
3645
0
                                mSpecifiedRotate);
3646
0
  ReleaseSharedListOnMainThread("nsStyleDisplay::mSpecifiedTranslate",
3647
0
                                mSpecifiedTranslate);
3648
0
  ReleaseSharedListOnMainThread("nsStyleDisplay::mSpecifiedScale",
3649
0
                                mSpecifiedScale);
3650
0
  ReleaseSharedListOnMainThread("nsStyleDisplay::mIndividualTransform",
3651
0
                                mIndividualTransform);
3652
0
  MOZ_COUNT_DTOR(nsStyleDisplay);
3653
0
}
3654
3655
void
3656
nsStyleDisplay::FinishStyle(
3657
    nsPresContext* aPresContext, const nsStyleDisplay* aOldStyle)
3658
0
{
3659
0
  MOZ_ASSERT(NS_IsMainThread());
3660
0
3661
0
  if (mShapeOutside.GetType() == StyleShapeSourceType::Image) {
3662
0
    const UniquePtr<nsStyleImage>& shapeImage = mShapeOutside.GetShapeImage();
3663
0
    if (shapeImage) {
3664
0
      const nsStyleImage* oldShapeImage =
3665
0
        (aOldStyle &&
3666
0
         aOldStyle->mShapeOutside.GetType() == StyleShapeSourceType::Image)
3667
0
          ?  &*aOldStyle->mShapeOutside.GetShapeImage() : nullptr;
3668
0
      shapeImage->ResolveImage(aPresContext, oldShapeImage);
3669
0
    }
3670
0
  }
3671
0
3672
0
  GenerateCombinedIndividualTransform();
3673
0
}
3674
3675
static inline nsChangeHint
3676
CompareTransformValues(const RefPtr<nsCSSValueSharedList>& aList,
3677
                       const RefPtr<nsCSSValueSharedList>& aNewList)
3678
0
{
3679
0
  nsChangeHint result = nsChangeHint(0);
3680
0
3681
0
  // Note: If we add a new change hint for transform changes here, we have to
3682
0
  // modify KeyframeEffect::CalculateCumulativeChangeHint too!
3683
0
  if (!aList != !aNewList || (aList && *aList != *aNewList)) {
3684
0
    result |= nsChangeHint_UpdateTransformLayer;
3685
0
    if (aList && aNewList) {
3686
0
      result |= nsChangeHint_UpdatePostTransformOverflow;
3687
0
    } else {
3688
0
      result |= nsChangeHint_UpdateOverflow;
3689
0
    }
3690
0
  }
3691
0
3692
0
  return result;
3693
0
}
3694
3695
static inline nsChangeHint
3696
CompareMotionValues(const StyleMotion* aMotion,
3697
                    const StyleMotion* aNewMotion)
3698
0
{
3699
0
  nsChangeHint result = nsChangeHint(0);
3700
0
3701
0
  // TODO: Bug 1482737: This probably doesn't need to UpdateOverflow
3702
0
  // (or UpdateTransformLayer) if there's already a transform.
3703
0
  if (!aMotion != !aNewMotion ||
3704
0
      (aMotion && *aMotion != *aNewMotion)) {
3705
0
    // Set the same hints as what we use for transform because motion path is
3706
0
    // a kind of transform and will be combined with other transforms.
3707
0
    result |= nsChangeHint_UpdateTransformLayer;
3708
0
    if ((aMotion && aMotion->HasPath()) &&
3709
0
        (aNewMotion && aNewMotion->HasPath())) {
3710
0
      result |= nsChangeHint_UpdatePostTransformOverflow;
3711
0
    } else {
3712
0
      result |= nsChangeHint_UpdateOverflow;
3713
0
    }
3714
0
  }
3715
0
  return result;
3716
0
}
3717
3718
nsChangeHint
3719
nsStyleDisplay::CalcDifference(const nsStyleDisplay& aNewData) const
3720
0
{
3721
0
  nsChangeHint hint = nsChangeHint(0);
3722
0
3723
0
  if (!DefinitelyEqualURIsAndPrincipal(mBinding, aNewData.mBinding)
3724
0
      || mPosition != aNewData.mPosition
3725
0
      || mDisplay != aNewData.mDisplay
3726
0
      || mContain != aNewData.mContain
3727
0
      || (mFloat == StyleFloat::None) != (aNewData.mFloat == StyleFloat::None)
3728
0
      || mScrollBehavior != aNewData.mScrollBehavior
3729
0
      || mScrollSnapTypeX != aNewData.mScrollSnapTypeX
3730
0
      || mScrollSnapTypeY != aNewData.mScrollSnapTypeY
3731
0
      || mScrollSnapPointsX != aNewData.mScrollSnapPointsX
3732
0
      || mScrollSnapPointsY != aNewData.mScrollSnapPointsY
3733
0
      || mScrollSnapDestination != aNewData.mScrollSnapDestination
3734
0
      || mTopLayer != aNewData.mTopLayer
3735
0
      || mResize != aNewData.mResize) {
3736
0
    return nsChangeHint_ReconstructFrame;
3737
0
  }
3738
0
3739
0
  if ((mAppearance == StyleAppearance::Textfield &&
3740
0
       aNewData.mAppearance != StyleAppearance::Textfield) ||
3741
0
      (mAppearance != StyleAppearance::Textfield &&
3742
0
       aNewData.mAppearance == StyleAppearance::Textfield)) {
3743
0
    // This is for <input type=number> where we allow authors to specify a
3744
0
    // |-moz-appearance:textfield| to get a control without a spinner. (The
3745
0
    // spinner is present for |-moz-appearance:number-input| but also other
3746
0
    // values such as 'none'.) We need to reframe since we want to use
3747
0
    // nsTextControlFrame instead of nsNumberControlFrame if the author
3748
0
    // specifies 'textfield'.
3749
0
    return nsChangeHint_ReconstructFrame;
3750
0
  }
3751
0
3752
0
  if (mOverflowX != aNewData.mOverflowX
3753
0
      || mOverflowY != aNewData.mOverflowY) {
3754
0
    hint |= nsChangeHint_ScrollbarChange;
3755
0
  }
3756
0
3757
0
  /* Note: When mScrollBehavior, mScrollSnapTypeX, mScrollSnapTypeY,
3758
0
   * mScrollSnapPointsX, mScrollSnapPointsY, or mScrollSnapDestination are
3759
0
   * changed, nsChangeHint_NeutralChange is not sufficient to enter
3760
0
   * nsCSSFrameConstructor::PropagateScrollToViewport. By using the same hint
3761
0
   * as used when the overflow css property changes,
3762
0
   * nsChangeHint_ReconstructFrame, PropagateScrollToViewport will be called.
3763
0
   *
3764
0
   * The scroll-behavior css property is not expected to change often (the
3765
0
   * CSSOM-View DOM methods are likely to be used in those cases); however,
3766
0
   * if this does become common perhaps a faster-path might be worth while.
3767
0
   */
3768
0
3769
0
  if (mFloat != aNewData.mFloat) {
3770
0
    // Changing which side we're floating on (float:none was handled above).
3771
0
    hint |= nsChangeHint_ReflowHintsForFloatAreaChange;
3772
0
  }
3773
0
3774
0
  if (mShapeOutside != aNewData.mShapeOutside ||
3775
0
      mShapeMargin != aNewData.mShapeMargin ||
3776
0
      mShapeImageThreshold != aNewData.mShapeImageThreshold) {
3777
0
    if (aNewData.mFloat != StyleFloat::None) {
3778
0
      // If we are floating, and our shape-outside, shape-margin, or
3779
0
      // shape-image-threshold are changed, our descendants are not impacted,
3780
0
      // but our ancestor and siblings are.
3781
0
      //
3782
0
      // This is similar to a float-only change, but since the ISize of the
3783
0
      // float area changes arbitrarily along its block axis, more is required
3784
0
      // to get the siblings to adjust properly. Hinting overflow change is
3785
0
      // sufficient to trigger the correct calculation, but may be too
3786
0
      // heavyweight.
3787
0
3788
0
      // XXX What is the minimum hint to ensure mShapeInfo is regenerated in
3789
0
      // the next reflow?
3790
0
      hint |= nsChangeHint_ReflowHintsForFloatAreaChange |
3791
0
              nsChangeHint_ScrollbarChange;
3792
0
    } else {
3793
0
      // shape-outside or shape-margin or shape-image-threshold changed,
3794
0
      // but we don't need to reflow because we're not floating.
3795
0
      hint |= nsChangeHint_NeutralChange;
3796
0
    }
3797
0
  }
3798
0
3799
0
  if (mVerticalAlign != aNewData.mVerticalAlign) {
3800
0
    // XXX Can this just be AllReflowHints + RepaintFrame, and be included in
3801
0
    // the block below?
3802
0
    hint |= NS_STYLE_HINT_REFLOW;
3803
0
  }
3804
0
3805
0
  // XXX the following is conservative, for now: changing float breaking shouldn't
3806
0
  // necessarily require a repaint, reflow should suffice.
3807
0
  if (mBreakType != aNewData.mBreakType
3808
0
      || mBreakInside != aNewData.mBreakInside
3809
0
      || mBreakBefore != aNewData.mBreakBefore
3810
0
      || mBreakAfter != aNewData.mBreakAfter
3811
0
      || mAppearance != aNewData.mAppearance
3812
0
      || mOrient != aNewData.mOrient
3813
0
      || mOverflowClipBoxBlock != aNewData.mOverflowClipBoxBlock
3814
0
      || mOverflowClipBoxInline != aNewData.mOverflowClipBoxInline) {
3815
0
    hint |= nsChangeHint_AllReflowHints |
3816
0
            nsChangeHint_RepaintFrame;
3817
0
  }
3818
0
3819
0
  if (mIsolation != aNewData.mIsolation) {
3820
0
    hint |= nsChangeHint_RepaintFrame;
3821
0
  }
3822
0
3823
0
  /* If we've added or removed the transform property, we need to reconstruct the frame to add
3824
0
   * or remove the view object, and also to handle abs-pos and fixed-pos containers.
3825
0
   */
3826
0
  if (HasTransformStyle() != aNewData.HasTransformStyle()) {
3827
0
    hint |= nsChangeHint_ComprehensiveAddOrRemoveTransform;
3828
0
  } else {
3829
0
    /* Otherwise, if we've kept the property lying around and we already had a
3830
0
     * transform, we need to see whether or not we've changed the transform.
3831
0
     * If so, we need to recompute its overflow rect (which probably changed
3832
0
     * if the transform changed) and to redraw within the bounds of that new
3833
0
     * overflow rect.
3834
0
     *
3835
0
     * If the property isn't present in either style struct, we still do the
3836
0
     * comparisons but turn all the resulting change hints into
3837
0
     * nsChangeHint_NeutralChange.
3838
0
     */
3839
0
    nsChangeHint transformHint = nsChangeHint(0);
3840
0
3841
0
    transformHint |= CompareTransformValues(mSpecifiedTransform,
3842
0
                                            aNewData.mSpecifiedTransform);
3843
0
    transformHint |= CompareTransformValues(mSpecifiedRotate, aNewData.
3844
0
                                            mSpecifiedRotate);
3845
0
    transformHint |= CompareTransformValues(mSpecifiedTranslate,
3846
0
                                            aNewData.mSpecifiedTranslate);
3847
0
    transformHint |= CompareTransformValues(mSpecifiedScale,
3848
0
                                            aNewData.mSpecifiedScale);
3849
0
    transformHint |= CompareMotionValues(mMotion.get(), aNewData.mMotion.get());
3850
0
3851
0
    const nsChangeHint kUpdateOverflowAndRepaintHint =
3852
0
      nsChangeHint_UpdateOverflow | nsChangeHint_RepaintFrame;
3853
0
    for (uint8_t index = 0; index < 3; ++index) {
3854
0
      if (mTransformOrigin[index] != aNewData.mTransformOrigin[index]) {
3855
0
        transformHint |= nsChangeHint_UpdateTransformLayer |
3856
0
                         nsChangeHint_UpdatePostTransformOverflow;
3857
0
        break;
3858
0
      }
3859
0
    }
3860
0
3861
0
    for (uint8_t index = 0; index < 2; ++index) {
3862
0
      if (mPerspectiveOrigin[index] != aNewData.mPerspectiveOrigin[index]) {
3863
0
        transformHint |= kUpdateOverflowAndRepaintHint;
3864
0
        break;
3865
0
      }
3866
0
    }
3867
0
3868
0
    if (mTransformStyle != aNewData.mTransformStyle ||
3869
0
        mTransformBox != aNewData.mTransformBox) {
3870
0
      transformHint |= kUpdateOverflowAndRepaintHint;
3871
0
    }
3872
0
3873
0
    if (mBackfaceVisibility != aNewData.mBackfaceVisibility) {
3874
0
      transformHint |= nsChangeHint_RepaintFrame;
3875
0
    }
3876
0
3877
0
    if (transformHint) {
3878
0
      if (HasTransformStyle()) {
3879
0
        hint |= transformHint;
3880
0
      } else {
3881
0
        hint |= nsChangeHint_NeutralChange;
3882
0
      }
3883
0
    }
3884
0
  }
3885
0
3886
0
  if (HasPerspectiveStyle() != aNewData.HasPerspectiveStyle()) {
3887
0
    // A change from/to being a containing block for position:fixed.
3888
0
    hint |= nsChangeHint_UpdateContainingBlock |
3889
0
            nsChangeHint_UpdateOverflow |
3890
0
            nsChangeHint_RepaintFrame;
3891
0
  } else if (mChildPerspective != aNewData.mChildPerspective) {
3892
0
    hint |= nsChangeHint_UpdateOverflow |
3893
0
            nsChangeHint_RepaintFrame;
3894
0
  }
3895
0
3896
0
  // Note that the HasTransformStyle() != aNewData.HasTransformStyle()
3897
0
  // test above handles relevant changes in the
3898
0
  // NS_STYLE_WILL_CHANGE_TRANSFORM bit, which in turn handles frame
3899
0
  // reconstruction for changes in the containing block of
3900
0
  // fixed-positioned elements.
3901
0
  uint8_t willChangeBitsChanged =
3902
0
    mWillChangeBitField ^ aNewData.mWillChangeBitField;
3903
0
  if (willChangeBitsChanged & (NS_STYLE_WILL_CHANGE_STACKING_CONTEXT |
3904
0
                               NS_STYLE_WILL_CHANGE_SCROLL |
3905
0
                               NS_STYLE_WILL_CHANGE_OPACITY)) {
3906
0
    hint |= nsChangeHint_RepaintFrame;
3907
0
  }
3908
0
3909
0
  if (willChangeBitsChanged & NS_STYLE_WILL_CHANGE_FIXPOS_CB) {
3910
0
    hint |= nsChangeHint_UpdateContainingBlock;
3911
0
  }
3912
0
3913
0
  // If touch-action is changed, we need to regenerate the event regions on
3914
0
  // the layers and send it over to the compositor for APZ to handle.
3915
0
  if (mTouchAction != aNewData.mTouchAction) {
3916
0
    hint |= nsChangeHint_RepaintFrame;
3917
0
  }
3918
0
3919
0
  // If overscroll-behavior has changed, the changes are picked up
3920
0
  // during a repaint.
3921
0
  if (mOverscrollBehaviorX != aNewData.mOverscrollBehaviorX ||
3922
0
      mOverscrollBehaviorY != aNewData.mOverscrollBehaviorY) {
3923
0
    hint |= nsChangeHint_SchedulePaint;
3924
0
  }
3925
0
3926
0
  // Note:  Our current behavior for handling changes to the
3927
0
  // transition-duration, transition-delay, and transition-timing-function
3928
0
  // properties is to do nothing.  In other words, the transition
3929
0
  // property that matters is what it is when the transition begins, and
3930
0
  // we don't stop a transition later because the transition property
3931
0
  // changed.
3932
0
  // We do handle changes to transition-property, but we don't need to
3933
0
  // bother with anything here, since the transition manager is notified
3934
0
  // of any ComputedStyle change anyway.
3935
0
3936
0
  // Note: Likewise, for animation-*, the animation manager gets
3937
0
  // notified about every new ComputedStyle constructed, and it uses
3938
0
  // that opportunity to handle dynamic changes appropriately.
3939
0
3940
0
  // But we still need to return nsChangeHint_NeutralChange for these
3941
0
  // properties, since some data did change in the style struct.
3942
0
3943
0
  if (!hint &&
3944
0
      (mOriginalDisplay != aNewData.mOriginalDisplay ||
3945
0
       mOriginalFloat != aNewData.mOriginalFloat ||
3946
0
       mTransitions != aNewData.mTransitions ||
3947
0
       mTransitionTimingFunctionCount !=
3948
0
         aNewData.mTransitionTimingFunctionCount ||
3949
0
       mTransitionDurationCount != aNewData.mTransitionDurationCount ||
3950
0
       mTransitionDelayCount != aNewData.mTransitionDelayCount ||
3951
0
       mTransitionPropertyCount != aNewData.mTransitionPropertyCount ||
3952
0
       mAnimations != aNewData.mAnimations ||
3953
0
       mAnimationTimingFunctionCount != aNewData.mAnimationTimingFunctionCount ||
3954
0
       mAnimationDurationCount != aNewData.mAnimationDurationCount ||
3955
0
       mAnimationDelayCount != aNewData.mAnimationDelayCount ||
3956
0
       mAnimationNameCount != aNewData.mAnimationNameCount ||
3957
0
       mAnimationDirectionCount != aNewData.mAnimationDirectionCount ||
3958
0
       mAnimationFillModeCount != aNewData.mAnimationFillModeCount ||
3959
0
       mAnimationPlayStateCount != aNewData.mAnimationPlayStateCount ||
3960
0
       mAnimationIterationCountCount != aNewData.mAnimationIterationCountCount ||
3961
0
       mScrollSnapCoordinate != aNewData.mScrollSnapCoordinate)) {
3962
0
    hint |= nsChangeHint_NeutralChange;
3963
0
  }
3964
0
3965
0
  return hint;
3966
0
}
3967
3968
void
3969
nsStyleDisplay::GenerateCombinedIndividualTransform()
3970
0
{
3971
0
  // FIXME(emilio): This should probably be called from somewhere like what we
3972
0
  // do for image layers, instead of FinishStyle.
3973
0
  //
3974
0
  // This does and undoes the work a ton of times in Stylo.
3975
0
  mIndividualTransform = nullptr;
3976
0
3977
0
  // Follow the order defined in the spec to append transform functions.
3978
0
  // https://drafts.csswg.org/css-transforms-2/#ctm
3979
0
  AutoTArray<nsCSSValueSharedList*, 3> shareLists;
3980
0
  if (mSpecifiedTranslate) {
3981
0
    shareLists.AppendElement(mSpecifiedTranslate.get());
3982
0
  }
3983
0
  if (mSpecifiedRotate) {
3984
0
    shareLists.AppendElement(mSpecifiedRotate.get());
3985
0
  }
3986
0
  if (mSpecifiedScale) {
3987
0
    shareLists.AppendElement(mSpecifiedScale.get());
3988
0
  }
3989
0
3990
0
  if (shareLists.Length() == 0) {
3991
0
    return;
3992
0
  }
3993
0
  if (shareLists.Length() == 1) {
3994
0
    mIndividualTransform = shareLists[0];
3995
0
    return;
3996
0
  }
3997
0
3998
0
  // In common, we may have 3 transform functions:
3999
0
  // 1. one rotate function in mSpecifiedRotate,
4000
0
  // 2. one translate function in mSpecifiedTranslate,
4001
0
  // 3. one scale function in mSpecifiedScale.
4002
0
  AutoTArray<nsCSSValueList*, 3> valueLists;
4003
0
  for (auto list: shareLists) {
4004
0
    if (list) {
4005
0
      valueLists.AppendElement(list->mHead->Clone());
4006
0
    }
4007
0
  }
4008
0
4009
0
  // Check we have at least one list or else valueLists.Length() - 1 below will
4010
0
  // underflow.
4011
0
  MOZ_ASSERT(valueLists.Length());
4012
0
4013
0
  for (uint32_t i = 0; i < valueLists.Length() - 1; i++) {
4014
0
    valueLists[i]->mNext = valueLists[i + 1];
4015
0
  }
4016
0
4017
0
  mIndividualTransform = new nsCSSValueSharedList(valueLists[0]);
4018
0
}
4019
4020
// --------------------
4021
// nsStyleVisibility
4022
//
4023
4024
nsStyleVisibility::nsStyleVisibility(const nsPresContext* aContext)
4025
  : mDirection(aContext->GetBidi() == IBMBIDI_TEXTDIRECTION_RTL
4026
                 ? NS_STYLE_DIRECTION_RTL
4027
                 : NS_STYLE_DIRECTION_LTR)
4028
  , mVisible(NS_STYLE_VISIBILITY_VISIBLE)
4029
  , mImageRendering(NS_STYLE_IMAGE_RENDERING_AUTO)
4030
  , mWritingMode(NS_STYLE_WRITING_MODE_HORIZONTAL_TB)
4031
  , mTextOrientation(NS_STYLE_TEXT_ORIENTATION_MIXED)
4032
  , mColorAdjust(NS_STYLE_COLOR_ADJUST_ECONOMY)
4033
0
{
4034
0
  MOZ_COUNT_CTOR(nsStyleVisibility);
4035
0
}
4036
4037
nsStyleVisibility::nsStyleVisibility(const nsStyleVisibility& aSource)
4038
  : mImageOrientation(aSource.mImageOrientation)
4039
  , mDirection(aSource.mDirection)
4040
  , mVisible(aSource.mVisible)
4041
  , mImageRendering(aSource.mImageRendering)
4042
  , mWritingMode(aSource.mWritingMode)
4043
  , mTextOrientation(aSource.mTextOrientation)
4044
  , mColorAdjust(aSource.mColorAdjust)
4045
0
{
4046
0
  MOZ_COUNT_CTOR(nsStyleVisibility);
4047
0
}
4048
4049
nsChangeHint
4050
nsStyleVisibility::CalcDifference(const nsStyleVisibility& aNewData) const
4051
0
{
4052
0
  nsChangeHint hint = nsChangeHint(0);
4053
0
4054
0
  if (mDirection != aNewData.mDirection || mWritingMode != aNewData.mWritingMode) {
4055
0
    // It's important that a change in mWritingMode results in frame
4056
0
    // reconstruction, because it may affect intrinsic size (see
4057
0
    // nsSubDocumentFrame::GetIntrinsicISize/BSize).
4058
0
    // Also, the used writing-mode value is now a field on nsIFrame and some
4059
0
    // classes (e.g. table rows/cells) copy their value from an ancestor.
4060
0
    hint |= nsChangeHint_ReconstructFrame;
4061
0
  } else {
4062
0
    if ((mImageOrientation != aNewData.mImageOrientation)) {
4063
0
      hint |= nsChangeHint_AllReflowHints |
4064
0
              nsChangeHint_RepaintFrame;
4065
0
    }
4066
0
    if (mVisible != aNewData.mVisible) {
4067
0
      if (mVisible == NS_STYLE_VISIBILITY_VISIBLE ||
4068
0
          aNewData.mVisible == NS_STYLE_VISIBILITY_VISIBLE) {
4069
0
        hint |= nsChangeHint_VisibilityChange;
4070
0
      }
4071
0
      if ((NS_STYLE_VISIBILITY_COLLAPSE == mVisible) ||
4072
0
          (NS_STYLE_VISIBILITY_COLLAPSE == aNewData.mVisible)) {
4073
0
        hint |= NS_STYLE_HINT_REFLOW;
4074
0
      } else {
4075
0
        hint |= NS_STYLE_HINT_VISUAL;
4076
0
      }
4077
0
    }
4078
0
    if (mTextOrientation != aNewData.mTextOrientation) {
4079
0
      hint |= NS_STYLE_HINT_REFLOW;
4080
0
    }
4081
0
    if (mImageRendering != aNewData.mImageRendering) {
4082
0
      hint |= nsChangeHint_RepaintFrame;
4083
0
    }
4084
0
    if (mColorAdjust != aNewData.mColorAdjust) {
4085
0
      // color-adjust only affects media where dynamic changes can't happen.
4086
0
      hint |= nsChangeHint_NeutralChange;
4087
0
    }
4088
0
  }
4089
0
  return hint;
4090
0
}
4091
4092
nsStyleContentData::~nsStyleContentData()
4093
0
{
4094
0
  MOZ_COUNT_DTOR(nsStyleContentData);
4095
0
4096
0
  if (mType == StyleContentType::Image) {
4097
0
    // FIXME(emilio): Is this needed now that URLs are not main thread only?
4098
0
    NS_ReleaseOnMainThreadSystemGroup(
4099
0
      "nsStyleContentData::mContent.mImage", dont_AddRef(mContent.mImage));
4100
0
    mContent.mImage = nullptr;
4101
0
  } else if (mType == StyleContentType::Counter ||
4102
0
             mType == StyleContentType::Counters) {
4103
0
    mContent.mCounters->Release();
4104
0
  } else if (mType == StyleContentType::String) {
4105
0
    free(mContent.mString);
4106
0
  } else if (mType == StyleContentType::Attr) {
4107
0
    delete mContent.mAttr;
4108
0
  } else {
4109
0
    MOZ_ASSERT(mContent.mString == nullptr, "Leaking due to missing case");
4110
0
  }
4111
0
}
4112
4113
nsStyleContentData::nsStyleContentData(const nsStyleContentData& aOther)
4114
  : mType(aOther.mType)
4115
0
{
4116
0
  MOZ_COUNT_CTOR(nsStyleContentData);
4117
0
  switch (mType) {
4118
0
    case StyleContentType::Image:
4119
0
      mContent.mImage = aOther.mContent.mImage;
4120
0
      mContent.mImage->AddRef();
4121
0
      break;
4122
0
    case StyleContentType::Counter:
4123
0
    case StyleContentType::Counters:
4124
0
      mContent.mCounters = aOther.mContent.mCounters;
4125
0
      mContent.mCounters->AddRef();
4126
0
      break;
4127
0
    case StyleContentType::Attr:
4128
0
      mContent.mAttr = new nsStyleContentAttr(*aOther.mContent.mAttr);
4129
0
      break;
4130
0
    case StyleContentType::String:
4131
0
      mContent.mString = NS_xstrdup(aOther.mContent.mString);
4132
0
      break;
4133
0
    default:
4134
0
      MOZ_ASSERT(!aOther.mContent.mString);
4135
0
      mContent.mString = nullptr;
4136
0
  }
4137
0
}
4138
4139
bool
4140
nsStyleContentData::
4141
CounterFunction::operator==(const CounterFunction& aOther) const
4142
0
{
4143
0
  return mIdent == aOther.mIdent &&
4144
0
    mSeparator == aOther.mSeparator &&
4145
0
    mCounterStyle == aOther.mCounterStyle;
4146
0
}
4147
4148
nsStyleContentData&
4149
nsStyleContentData::operator=(const nsStyleContentData& aOther)
4150
0
{
4151
0
  if (this == &aOther) {
4152
0
    return *this;
4153
0
  }
4154
0
  this->~nsStyleContentData();
4155
0
  new (this) nsStyleContentData(aOther);
4156
0
4157
0
  return *this;
4158
0
}
4159
4160
bool
4161
nsStyleContentData::operator==(const nsStyleContentData& aOther) const
4162
0
{
4163
0
  if (mType != aOther.mType) {
4164
0
    return false;
4165
0
  }
4166
0
  if (mType == StyleContentType::Image) {
4167
0
    return DefinitelyEqualImages(mContent.mImage, aOther.mContent.mImage);
4168
0
  }
4169
0
  if (mType == StyleContentType::Attr) {
4170
0
    return *mContent.mAttr == *aOther.mContent.mAttr;
4171
0
  }
4172
0
  if (mType == StyleContentType::Counter ||
4173
0
      mType == StyleContentType::Counters) {
4174
0
    return *mContent.mCounters == *aOther.mContent.mCounters;
4175
0
  }
4176
0
  if (mType == StyleContentType::String) {
4177
0
    return NS_strcmp(mContent.mString, aOther.mContent.mString) == 0;
4178
0
  }
4179
0
  MOZ_ASSERT(!mContent.mString && !aOther.mContent.mString);
4180
0
  return true;
4181
0
}
4182
4183
void
4184
nsStyleContentData::Resolve(
4185
  nsPresContext* aPresContext, const nsStyleContentData* aOldStyle)
4186
0
{
4187
0
  switch (mType) {
4188
0
    case StyleContentType::Image:
4189
0
      if (!mContent.mImage->IsResolved()) {
4190
0
        const nsStyleImageRequest* oldRequest =
4191
0
          (aOldStyle && aOldStyle->mType == StyleContentType::Image)
4192
0
          ? aOldStyle->mContent.mImage : nullptr;
4193
0
        mContent.mImage->Resolve(aPresContext, oldRequest);
4194
0
      }
4195
0
      break;
4196
0
    case StyleContentType::Counter:
4197
0
    case StyleContentType::Counters: {
4198
0
      mContent.mCounters->
4199
0
        mCounterStyle.Resolve(aPresContext->CounterStyleManager());
4200
0
      break;
4201
0
    }
4202
0
    default:
4203
0
      break;
4204
0
  }
4205
0
}
4206
4207
4208
//-----------------------
4209
// nsStyleContent
4210
//
4211
4212
nsStyleContent::nsStyleContent(const nsPresContext* aContext)
4213
0
{
4214
0
  MOZ_COUNT_CTOR(nsStyleContent);
4215
0
}
4216
4217
nsStyleContent::~nsStyleContent()
4218
0
{
4219
0
  MOZ_COUNT_DTOR(nsStyleContent);
4220
0
}
4221
4222
void
4223
nsStyleContent::FinishStyle(nsPresContext* aPresContext, const nsStyleContent* aOldStyle)
4224
0
{
4225
0
  for (size_t i = 0; i < mContents.Length(); ++i) {
4226
0
    const nsStyleContentData* oldData =
4227
0
      (aOldStyle && aOldStyle->mContents.Length() > i)
4228
0
      ? &aOldStyle->mContents[i]
4229
0
      : nullptr;
4230
0
    mContents[i].Resolve(aPresContext, oldData);
4231
0
  }
4232
0
}
4233
4234
nsStyleContent::nsStyleContent(const nsStyleContent& aSource)
4235
  : mContents(aSource.mContents)
4236
  , mIncrements(aSource.mIncrements)
4237
  , mResets(aSource.mResets)
4238
0
{
4239
0
  MOZ_COUNT_CTOR(nsStyleContent);
4240
0
}
4241
4242
nsChangeHint
4243
nsStyleContent::CalcDifference(const nsStyleContent& aNewData) const
4244
0
{
4245
0
  // In ElementRestyler::Restyle we assume that if there's no existing
4246
0
  // ::before or ::after and we don't have to restyle children of the
4247
0
  // node then we can't end up with a ::before or ::after due to the
4248
0
  // restyle of the node itself.  That's not quite true, but the only
4249
0
  // exception to the above is when the 'content' property of the node
4250
0
  // changes and the pseudo-element inherits the changed value.  Since
4251
0
  // the code here triggers a frame change on the node in that case,
4252
0
  // the optimization in ElementRestyler::Restyle is ok.  But if we ever
4253
0
  // change this code to not reconstruct frames on changes to the
4254
0
  // 'content' property, then we will need to revisit the optimization
4255
0
  // in ElementRestyler::Restyle.
4256
0
4257
0
  // Unfortunately we need to reframe even if the content lengths are the same;
4258
0
  // a simple reflow will not pick up different text or different image URLs,
4259
0
  // since we set all that up in the CSSFrameConstructor
4260
0
  //
4261
0
  // Also note that we also rely on this to return ReconstructFrame when
4262
0
  // content changes to ensure that nsCounterUseNode wouldn't reference
4263
0
  // to stale counter stylex.
4264
0
  if (mContents != aNewData.mContents ||
4265
0
      mIncrements != aNewData.mIncrements ||
4266
0
      mResets != aNewData.mResets) {
4267
0
    return nsChangeHint_ReconstructFrame;
4268
0
  }
4269
0
4270
0
  return nsChangeHint(0);
4271
0
}
4272
4273
// --------------------
4274
// nsStyleTextReset
4275
//
4276
4277
nsStyleTextReset::nsStyleTextReset(const nsPresContext* aContext)
4278
  : mTextOverflow()
4279
  , mTextDecorationLine(NS_STYLE_TEXT_DECORATION_LINE_NONE)
4280
  , mTextDecorationStyle(NS_STYLE_TEXT_DECORATION_STYLE_SOLID)
4281
  , mUnicodeBidi(NS_STYLE_UNICODE_BIDI_NORMAL)
4282
  , mInitialLetterSink(0)
4283
  , mInitialLetterSize(0.0f)
4284
  , mTextDecorationColor(StyleComplexColor::CurrentColor())
4285
0
{
4286
0
  MOZ_COUNT_CTOR(nsStyleTextReset);
4287
0
}
4288
4289
nsStyleTextReset::nsStyleTextReset(const nsStyleTextReset& aSource)
4290
  : mTextOverflow(aSource.mTextOverflow)
4291
  , mTextDecorationLine(aSource.mTextDecorationLine)
4292
  , mTextDecorationStyle(aSource.mTextDecorationStyle)
4293
  , mUnicodeBidi(aSource.mUnicodeBidi)
4294
  , mInitialLetterSink(aSource.mInitialLetterSink)
4295
  , mInitialLetterSize(aSource.mInitialLetterSize)
4296
  , mTextDecorationColor(aSource.mTextDecorationColor)
4297
0
{
4298
0
  MOZ_COUNT_CTOR(nsStyleTextReset);
4299
0
}
4300
4301
nsStyleTextReset::~nsStyleTextReset()
4302
0
{
4303
0
  MOZ_COUNT_DTOR(nsStyleTextReset);
4304
0
}
4305
4306
nsChangeHint
4307
nsStyleTextReset::CalcDifference(const nsStyleTextReset& aNewData) const
4308
0
{
4309
0
  if (mUnicodeBidi != aNewData.mUnicodeBidi ||
4310
0
      mInitialLetterSink != aNewData.mInitialLetterSink ||
4311
0
      mInitialLetterSize != aNewData.mInitialLetterSize) {
4312
0
    return NS_STYLE_HINT_REFLOW;
4313
0
  }
4314
0
4315
0
  if (mTextDecorationLine != aNewData.mTextDecorationLine ||
4316
0
      mTextDecorationStyle != aNewData.mTextDecorationStyle) {
4317
0
    // Changes to our text-decoration line can impact our overflow area &
4318
0
    // also our descendants' overflow areas (particularly for text-frame
4319
0
    // descendants).  So, we update those areas & trigger a repaint.
4320
0
    return nsChangeHint_RepaintFrame |
4321
0
           nsChangeHint_UpdateSubtreeOverflow |
4322
0
           nsChangeHint_SchedulePaint;
4323
0
  }
4324
0
4325
0
  // Repaint for decoration color changes
4326
0
  if (mTextDecorationColor != aNewData.mTextDecorationColor) {
4327
0
    return nsChangeHint_RepaintFrame;
4328
0
  }
4329
0
4330
0
  if (mTextOverflow != aNewData.mTextOverflow) {
4331
0
    return nsChangeHint_RepaintFrame;
4332
0
  }
4333
0
4334
0
  return nsChangeHint(0);
4335
0
}
4336
4337
// Returns true if the given shadow-arrays are equal.
4338
static bool
4339
AreShadowArraysEqual(nsCSSShadowArray* lhs,
4340
                     nsCSSShadowArray* rhs)
4341
0
{
4342
0
  if (lhs == rhs) {
4343
0
    return true;
4344
0
  }
4345
0
4346
0
  if (!lhs || !rhs || lhs->Length() != rhs->Length()) {
4347
0
    return false;
4348
0
  }
4349
0
4350
0
  for (uint32_t i = 0; i < lhs->Length(); ++i) {
4351
0
    if (*lhs->ShadowAt(i) != *rhs->ShadowAt(i)) {
4352
0
      return false;
4353
0
    }
4354
0
  }
4355
0
  return true;
4356
0
}
4357
4358
// --------------------
4359
// nsStyleText
4360
//
4361
4362
nsStyleText::nsStyleText(const nsPresContext* aContext)
4363
  : mTextAlign(NS_STYLE_TEXT_ALIGN_START)
4364
  , mTextAlignLast(NS_STYLE_TEXT_ALIGN_AUTO)
4365
  , mTextAlignTrue(false)
4366
  , mTextAlignLastTrue(false)
4367
  , mTextJustify(StyleTextJustify::Auto)
4368
  , mTextTransform(NS_STYLE_TEXT_TRANSFORM_NONE)
4369
  , mWhiteSpace(StyleWhiteSpace::Normal)
4370
  , mWordBreak(NS_STYLE_WORDBREAK_NORMAL)
4371
  , mOverflowWrap(NS_STYLE_OVERFLOWWRAP_NORMAL)
4372
  , mHyphens(StyleHyphens::Manual)
4373
  , mRubyAlign(NS_STYLE_RUBY_ALIGN_SPACE_AROUND)
4374
  , mRubyPosition(NS_STYLE_RUBY_POSITION_OVER)
4375
  , mTextSizeAdjust(NS_STYLE_TEXT_SIZE_ADJUST_AUTO)
4376
  , mTextCombineUpright(NS_STYLE_TEXT_COMBINE_UPRIGHT_NONE)
4377
  , mControlCharacterVisibility(nsLayoutUtils::ControlCharVisibilityDefault())
4378
  , mTextEmphasisStyle(NS_STYLE_TEXT_EMPHASIS_STYLE_NONE)
4379
  , mTextRendering(NS_STYLE_TEXT_RENDERING_AUTO)
4380
  , mTextEmphasisColor(StyleComplexColor::CurrentColor())
4381
  , mWebkitTextFillColor(StyleComplexColor::CurrentColor())
4382
  , mWebkitTextStrokeColor(StyleComplexColor::CurrentColor())
4383
  , mTabSize(float(NS_STYLE_TABSIZE_INITIAL), eStyleUnit_Factor)
4384
  , mWordSpacing(0, nsStyleCoord::CoordConstructor)
4385
  , mLetterSpacing(eStyleUnit_Normal)
4386
  , mLineHeight(eStyleUnit_Normal)
4387
  , mTextIndent(0, nsStyleCoord::CoordConstructor)
4388
  , mWebkitTextStrokeWidth(0)
4389
  , mTextShadow(nullptr)
4390
0
{
4391
0
  MOZ_COUNT_CTOR(nsStyleText);
4392
0
  RefPtr<nsAtom> language = aContext->GetContentLanguage();
4393
0
  mTextEmphasisPosition = language &&
4394
0
    nsStyleUtil::MatchesLanguagePrefix(language, u"zh") ?
4395
0
    NS_STYLE_TEXT_EMPHASIS_POSITION_DEFAULT_ZH :
4396
0
    NS_STYLE_TEXT_EMPHASIS_POSITION_DEFAULT;
4397
0
}
4398
4399
nsStyleText::nsStyleText(const nsStyleText& aSource)
4400
  : mTextAlign(aSource.mTextAlign)
4401
  , mTextAlignLast(aSource.mTextAlignLast)
4402
  , mTextAlignTrue(false)
4403
  , mTextAlignLastTrue(false)
4404
  , mTextJustify(aSource.mTextJustify)
4405
  , mTextTransform(aSource.mTextTransform)
4406
  , mWhiteSpace(aSource.mWhiteSpace)
4407
  , mWordBreak(aSource.mWordBreak)
4408
  , mOverflowWrap(aSource.mOverflowWrap)
4409
  , mHyphens(aSource.mHyphens)
4410
  , mRubyAlign(aSource.mRubyAlign)
4411
  , mRubyPosition(aSource.mRubyPosition)
4412
  , mTextSizeAdjust(aSource.mTextSizeAdjust)
4413
  , mTextCombineUpright(aSource.mTextCombineUpright)
4414
  , mControlCharacterVisibility(aSource.mControlCharacterVisibility)
4415
  , mTextEmphasisPosition(aSource.mTextEmphasisPosition)
4416
  , mTextEmphasisStyle(aSource.mTextEmphasisStyle)
4417
  , mTextRendering(aSource.mTextRendering)
4418
  , mTextEmphasisColor(aSource.mTextEmphasisColor)
4419
  , mWebkitTextFillColor(aSource.mWebkitTextFillColor)
4420
  , mWebkitTextStrokeColor(aSource.mWebkitTextStrokeColor)
4421
  , mTabSize(aSource.mTabSize)
4422
  , mWordSpacing(aSource.mWordSpacing)
4423
  , mLetterSpacing(aSource.mLetterSpacing)
4424
  , mLineHeight(aSource.mLineHeight)
4425
  , mTextIndent(aSource.mTextIndent)
4426
  , mWebkitTextStrokeWidth(aSource.mWebkitTextStrokeWidth)
4427
  , mTextShadow(aSource.mTextShadow)
4428
  , mTextEmphasisStyleString(aSource.mTextEmphasisStyleString)
4429
0
{
4430
0
  MOZ_COUNT_CTOR(nsStyleText);
4431
0
}
4432
4433
nsStyleText::~nsStyleText()
4434
0
{
4435
0
  MOZ_COUNT_DTOR(nsStyleText);
4436
0
}
4437
4438
nsChangeHint
4439
nsStyleText::CalcDifference(const nsStyleText& aNewData) const
4440
0
{
4441
0
  if (WhiteSpaceOrNewlineIsSignificant() !=
4442
0
      aNewData.WhiteSpaceOrNewlineIsSignificant()) {
4443
0
    // This may require construction of suppressed text frames
4444
0
    return nsChangeHint_ReconstructFrame;
4445
0
  }
4446
0
4447
0
  if (mTextCombineUpright != aNewData.mTextCombineUpright ||
4448
0
      mControlCharacterVisibility != aNewData.mControlCharacterVisibility) {
4449
0
    return nsChangeHint_ReconstructFrame;
4450
0
  }
4451
0
4452
0
  if ((mTextAlign != aNewData.mTextAlign) ||
4453
0
      (mTextAlignLast != aNewData.mTextAlignLast) ||
4454
0
      (mTextAlignTrue != aNewData.mTextAlignTrue) ||
4455
0
      (mTextAlignLastTrue != aNewData.mTextAlignLastTrue) ||
4456
0
      (mTextTransform != aNewData.mTextTransform) ||
4457
0
      (mWhiteSpace != aNewData.mWhiteSpace) ||
4458
0
      (mWordBreak != aNewData.mWordBreak) ||
4459
0
      (mOverflowWrap != aNewData.mOverflowWrap) ||
4460
0
      (mHyphens != aNewData.mHyphens) ||
4461
0
      (mRubyAlign != aNewData.mRubyAlign) ||
4462
0
      (mRubyPosition != aNewData.mRubyPosition) ||
4463
0
      (mTextSizeAdjust != aNewData.mTextSizeAdjust) ||
4464
0
      (mLetterSpacing != aNewData.mLetterSpacing) ||
4465
0
      (mLineHeight != aNewData.mLineHeight) ||
4466
0
      (mTextIndent != aNewData.mTextIndent) ||
4467
0
      (mTextJustify != aNewData.mTextJustify) ||
4468
0
      (mWordSpacing != aNewData.mWordSpacing) ||
4469
0
      (mTabSize != aNewData.mTabSize)) {
4470
0
    return NS_STYLE_HINT_REFLOW;
4471
0
  }
4472
0
4473
0
  if (HasTextEmphasis() != aNewData.HasTextEmphasis() ||
4474
0
      (HasTextEmphasis() &&
4475
0
       mTextEmphasisPosition != aNewData.mTextEmphasisPosition)) {
4476
0
    // Text emphasis position change could affect line height calculation.
4477
0
    return nsChangeHint_AllReflowHints |
4478
0
           nsChangeHint_RepaintFrame;
4479
0
  }
4480
0
4481
0
  nsChangeHint hint = nsChangeHint(0);
4482
0
4483
0
  // text-rendering changes require a reflow since they change SVG
4484
0
  // frames' rects.
4485
0
  if (mTextRendering != aNewData.mTextRendering) {
4486
0
    hint |= nsChangeHint_NeedReflow |
4487
0
            nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
4488
0
            nsChangeHint_RepaintFrame;
4489
0
  }
4490
0
4491
0
  if (!AreShadowArraysEqual(mTextShadow, aNewData.mTextShadow) ||
4492
0
      mTextEmphasisStyle != aNewData.mTextEmphasisStyle ||
4493
0
      mTextEmphasisStyleString != aNewData.mTextEmphasisStyleString ||
4494
0
      mWebkitTextStrokeWidth != aNewData.mWebkitTextStrokeWidth) {
4495
0
    hint |= nsChangeHint_UpdateSubtreeOverflow |
4496
0
            nsChangeHint_SchedulePaint |
4497
0
            nsChangeHint_RepaintFrame;
4498
0
4499
0
    // We don't add any other hints below.
4500
0
    return hint;
4501
0
  }
4502
0
4503
0
  if (mTextEmphasisColor != aNewData.mTextEmphasisColor ||
4504
0
      mWebkitTextFillColor != aNewData.mWebkitTextFillColor ||
4505
0
      mWebkitTextStrokeColor != aNewData.mWebkitTextStrokeColor) {
4506
0
    hint |= nsChangeHint_SchedulePaint |
4507
0
            nsChangeHint_RepaintFrame;
4508
0
  }
4509
0
4510
0
  if (hint) {
4511
0
    return hint;
4512
0
  }
4513
0
4514
0
  if (mTextEmphasisPosition != aNewData.mTextEmphasisPosition) {
4515
0
    return nsChangeHint_NeutralChange;
4516
0
  }
4517
0
4518
0
  return nsChangeHint(0);
4519
0
}
4520
4521
LogicalSide
4522
nsStyleText::TextEmphasisSide(WritingMode aWM) const
4523
0
{
4524
0
  MOZ_ASSERT(
4525
0
    (!(mTextEmphasisPosition & NS_STYLE_TEXT_EMPHASIS_POSITION_LEFT) !=
4526
0
     !(mTextEmphasisPosition & NS_STYLE_TEXT_EMPHASIS_POSITION_RIGHT)) &&
4527
0
    (!(mTextEmphasisPosition & NS_STYLE_TEXT_EMPHASIS_POSITION_OVER) !=
4528
0
     !(mTextEmphasisPosition & NS_STYLE_TEXT_EMPHASIS_POSITION_UNDER)));
4529
0
  mozilla::Side side = aWM.IsVertical() ?
4530
0
    (mTextEmphasisPosition & NS_STYLE_TEXT_EMPHASIS_POSITION_LEFT
4531
0
     ? eSideLeft : eSideRight) :
4532
0
    (mTextEmphasisPosition & NS_STYLE_TEXT_EMPHASIS_POSITION_OVER
4533
0
     ? eSideTop : eSideBottom);
4534
0
  LogicalSide result = aWM.LogicalSideForPhysicalSide(side);
4535
0
  MOZ_ASSERT(IsBlock(result));
4536
0
  return result;
4537
0
}
4538
4539
//-----------------------
4540
// nsStyleUI
4541
//
4542
4543
nsCursorImage::nsCursorImage()
4544
  : mHaveHotspot(false)
4545
  , mHotspotX(0.0f)
4546
  , mHotspotY(0.0f)
4547
0
{
4548
0
}
4549
4550
nsCursorImage::nsCursorImage(const nsCursorImage& aOther)
4551
  : mHaveHotspot(aOther.mHaveHotspot)
4552
  , mHotspotX(aOther.mHotspotX)
4553
  , mHotspotY(aOther.mHotspotY)
4554
  , mImage(aOther.mImage)
4555
0
{
4556
0
}
4557
4558
nsCursorImage&
4559
nsCursorImage::operator=(const nsCursorImage& aOther)
4560
0
{
4561
0
  if (this != &aOther) {
4562
0
    mHaveHotspot = aOther.mHaveHotspot;
4563
0
    mHotspotX = aOther.mHotspotX;
4564
0
    mHotspotY = aOther.mHotspotY;
4565
0
    mImage = aOther.mImage;
4566
0
  }
4567
0
4568
0
  return *this;
4569
0
}
4570
4571
bool
4572
nsCursorImage::operator==(const nsCursorImage& aOther) const
4573
0
{
4574
0
  NS_ASSERTION(mHaveHotspot ||
4575
0
               (mHotspotX == 0 && mHotspotY == 0),
4576
0
               "expected mHotspot{X,Y} to be 0 when mHaveHotspot is false");
4577
0
  NS_ASSERTION(aOther.mHaveHotspot ||
4578
0
               (aOther.mHotspotX == 0 && aOther.mHotspotY == 0),
4579
0
               "expected mHotspot{X,Y} to be 0 when mHaveHotspot is false");
4580
0
  return mHaveHotspot == aOther.mHaveHotspot &&
4581
0
         mHotspotX == aOther.mHotspotX &&
4582
0
         mHotspotY == aOther.mHotspotY &&
4583
0
         DefinitelyEqualImages(mImage, aOther.mImage);
4584
0
}
4585
4586
nsStyleUI::nsStyleUI(const nsPresContext* aContext)
4587
  : mUserInput(StyleUserInput::Auto)
4588
  , mUserModify(StyleUserModify::ReadOnly)
4589
  , mUserFocus(StyleUserFocus::None)
4590
  , mPointerEvents(NS_STYLE_POINTER_EVENTS_AUTO)
4591
  , mCursor(NS_STYLE_CURSOR_AUTO)
4592
  , mCaretColor(StyleComplexColor::Auto())
4593
  , mScrollbarFaceColor(StyleComplexColor::Auto())
4594
  , mScrollbarTrackColor(StyleComplexColor::Auto())
4595
0
{
4596
0
  MOZ_COUNT_CTOR(nsStyleUI);
4597
0
}
4598
4599
nsStyleUI::nsStyleUI(const nsStyleUI& aSource)
4600
  : mUserInput(aSource.mUserInput)
4601
  , mUserModify(aSource.mUserModify)
4602
  , mUserFocus(aSource.mUserFocus)
4603
  , mPointerEvents(aSource.mPointerEvents)
4604
  , mCursor(aSource.mCursor)
4605
  , mCursorImages(aSource.mCursorImages)
4606
  , mCaretColor(aSource.mCaretColor)
4607
  , mScrollbarFaceColor(aSource.mScrollbarFaceColor)
4608
  , mScrollbarTrackColor(aSource.mScrollbarTrackColor)
4609
0
{
4610
0
  MOZ_COUNT_CTOR(nsStyleUI);
4611
0
}
4612
4613
nsStyleUI::~nsStyleUI()
4614
0
{
4615
0
  MOZ_COUNT_DTOR(nsStyleUI);
4616
0
}
4617
4618
void
4619
nsStyleUI::FinishStyle(nsPresContext* aPresContext,
4620
                       const nsStyleUI* aOldStyle)
4621
0
{
4622
0
  MOZ_ASSERT(NS_IsMainThread());
4623
0
4624
0
  for (size_t i = 0; i < mCursorImages.Length(); ++i) {
4625
0
    nsCursorImage& cursor = mCursorImages[i];
4626
0
4627
0
    if (cursor.mImage && !cursor.mImage->IsResolved()) {
4628
0
      const nsCursorImage* oldCursor =
4629
0
        (aOldStyle && aOldStyle->mCursorImages.Length() > i)
4630
0
        ? &aOldStyle->mCursorImages[i]
4631
0
        : nullptr;
4632
0
      cursor.mImage->Resolve(
4633
0
        aPresContext, oldCursor ? oldCursor->mImage.get() : nullptr);
4634
0
    }
4635
0
  }
4636
0
}
4637
4638
nsChangeHint
4639
nsStyleUI::CalcDifference(const nsStyleUI& aNewData) const
4640
0
{
4641
0
  nsChangeHint hint = nsChangeHint(0);
4642
0
  if (mCursor != aNewData.mCursor) {
4643
0
    hint |= nsChangeHint_UpdateCursor;
4644
0
  }
4645
0
4646
0
  // We could do better. But it wouldn't be worth it, URL-specified cursors are
4647
0
  // rare.
4648
0
  if (mCursorImages != aNewData.mCursorImages) {
4649
0
    hint |= nsChangeHint_UpdateCursor;
4650
0
  }
4651
0
4652
0
  if (mPointerEvents != aNewData.mPointerEvents) {
4653
0
    // SVGGeometryFrame's mRect depends on stroke _and_ on the value
4654
0
    // of pointer-events. See SVGGeometryFrame::ReflowSVG's use of
4655
0
    // GetHitTestFlags. (Only a reflow, no visual change.)
4656
0
    hint |= nsChangeHint_NeedReflow |
4657
0
            nsChangeHint_NeedDirtyReflow; // XXX remove me: bug 876085
4658
0
  }
4659
0
4660
0
  if (mUserModify != aNewData.mUserModify) {
4661
0
    hint |= NS_STYLE_HINT_VISUAL;
4662
0
  }
4663
0
4664
0
  if (mUserInput != aNewData.mUserInput) {
4665
0
    if (StyleUserInput::None == mUserInput ||
4666
0
        StyleUserInput::None == aNewData.mUserInput) {
4667
0
      hint |= nsChangeHint_ReconstructFrame;
4668
0
    } else {
4669
0
      hint |= nsChangeHint_NeutralChange;
4670
0
    }
4671
0
  }
4672
0
4673
0
  if (mUserFocus != aNewData.mUserFocus) {
4674
0
    hint |= nsChangeHint_NeutralChange;
4675
0
  }
4676
0
4677
0
  if (mCaretColor != aNewData.mCaretColor ||
4678
0
      mScrollbarFaceColor != aNewData.mScrollbarFaceColor ||
4679
0
      mScrollbarTrackColor != aNewData.mScrollbarTrackColor) {
4680
0
    hint |= nsChangeHint_RepaintFrame;
4681
0
  }
4682
0
4683
0
  return hint;
4684
0
}
4685
4686
//-----------------------
4687
// nsStyleUIReset
4688
//
4689
4690
nsStyleUIReset::nsStyleUIReset(const nsPresContext* aContext)
4691
  : mUserSelect(StyleUserSelect::Auto)
4692
  , mScrollbarWidth(StyleScrollbarWidth::Auto)
4693
  , mForceBrokenImageIcon(0)
4694
  , mIMEMode(NS_STYLE_IME_MODE_AUTO)
4695
  , mWindowDragging(StyleWindowDragging::Default)
4696
  , mWindowShadow(NS_STYLE_WINDOW_SHADOW_DEFAULT)
4697
  , mWindowOpacity(1.0)
4698
  , mSpecifiedWindowTransform(nullptr)
4699
  , mWindowTransformOrigin{ {0.5f, eStyleUnit_Percent}, // Transform is centered on origin
4700
                            {0.5f, eStyleUnit_Percent} }
4701
0
{
4702
0
  MOZ_COUNT_CTOR(nsStyleUIReset);
4703
0
}
4704
4705
nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset& aSource)
4706
  : mUserSelect(aSource.mUserSelect)
4707
  , mScrollbarWidth(aSource.mScrollbarWidth)
4708
  , mForceBrokenImageIcon(aSource.mForceBrokenImageIcon)
4709
  , mIMEMode(aSource.mIMEMode)
4710
  , mWindowDragging(aSource.mWindowDragging)
4711
  , mWindowShadow(aSource.mWindowShadow)
4712
  , mWindowOpacity(aSource.mWindowOpacity)
4713
  , mSpecifiedWindowTransform(aSource.mSpecifiedWindowTransform)
4714
  , mWindowTransformOrigin{ aSource.mWindowTransformOrigin[0],
4715
                            aSource.mWindowTransformOrigin[1] }
4716
0
{
4717
0
  MOZ_COUNT_CTOR(nsStyleUIReset);
4718
0
}
4719
4720
nsStyleUIReset::~nsStyleUIReset()
4721
0
{
4722
0
  MOZ_COUNT_DTOR(nsStyleUIReset);
4723
0
4724
0
  ReleaseSharedListOnMainThread("nsStyleUIReset::mSpecifiedWindowTransform",
4725
0
                                mSpecifiedWindowTransform);
4726
0
}
4727
4728
nsChangeHint
4729
nsStyleUIReset::CalcDifference(const nsStyleUIReset& aNewData) const
4730
0
{
4731
0
  nsChangeHint hint = nsChangeHint(0);
4732
0
4733
0
  if (mForceBrokenImageIcon != aNewData.mForceBrokenImageIcon) {
4734
0
    hint |= nsChangeHint_ReconstructFrame;
4735
0
  }
4736
0
  if (mScrollbarWidth != aNewData.mScrollbarWidth) {
4737
0
    // For scrollbar-width change, we need some special handling similar
4738
0
    // to overflow properties. Specifically, we may need to reconstruct
4739
0
    // the scrollbar or force reflow of the viewport scrollbar.
4740
0
    hint |= nsChangeHint_ScrollbarChange;
4741
0
  }
4742
0
  if (mWindowShadow != aNewData.mWindowShadow) {
4743
0
    // We really need just an nsChangeHint_SyncFrameView, except
4744
0
    // on an ancestor of the frame, so we get that by doing a
4745
0
    // reflow.
4746
0
    hint |= NS_STYLE_HINT_REFLOW;
4747
0
  }
4748
0
  if (mUserSelect != aNewData.mUserSelect) {
4749
0
    hint |= NS_STYLE_HINT_VISUAL;
4750
0
  }
4751
0
4752
0
  if (mWindowDragging != aNewData.mWindowDragging) {
4753
0
    hint |= nsChangeHint_SchedulePaint;
4754
0
  }
4755
0
4756
0
  if (mWindowOpacity != aNewData.mWindowOpacity ||
4757
0
      !mSpecifiedWindowTransform != !aNewData.mSpecifiedWindowTransform ||
4758
0
      (mSpecifiedWindowTransform &&
4759
0
       *mSpecifiedWindowTransform != *aNewData.mSpecifiedWindowTransform)) {
4760
0
    hint |= nsChangeHint_UpdateWidgetProperties;
4761
0
  } else {
4762
0
    for (uint8_t index = 0; index < 2; ++index) {
4763
0
      if (mWindowTransformOrigin[index] !=
4764
0
            aNewData.mWindowTransformOrigin[index]) {
4765
0
        hint |= nsChangeHint_UpdateWidgetProperties;
4766
0
        break;
4767
0
      }
4768
0
    }
4769
0
  }
4770
0
4771
0
  if (!hint &&
4772
0
      mIMEMode != aNewData.mIMEMode) {
4773
0
    hint |= nsChangeHint_NeutralChange;
4774
0
  }
4775
0
4776
0
  return hint;
4777
0
}
4778
4779
//-----------------------
4780
// nsStyleEffects
4781
//
4782
4783
nsStyleEffects::nsStyleEffects(const nsPresContext* aContext)
4784
  : mBoxShadow(nullptr)
4785
  , mClip(0, 0, 0, 0)
4786
  , mOpacity(1.0f)
4787
  , mClipFlags(NS_STYLE_CLIP_AUTO)
4788
  , mMixBlendMode(NS_STYLE_BLEND_NORMAL)
4789
0
{
4790
0
  MOZ_COUNT_CTOR(nsStyleEffects);
4791
0
}
4792
4793
nsStyleEffects::nsStyleEffects(const nsStyleEffects& aSource)
4794
  : mFilters(aSource.mFilters)
4795
  , mBoxShadow(aSource.mBoxShadow)
4796
  , mClip(aSource.mClip)
4797
  , mOpacity(aSource.mOpacity)
4798
  , mClipFlags(aSource.mClipFlags)
4799
  , mMixBlendMode(aSource.mMixBlendMode)
4800
0
{
4801
0
  MOZ_COUNT_CTOR(nsStyleEffects);
4802
0
}
4803
4804
nsStyleEffects::~nsStyleEffects()
4805
0
{
4806
0
  MOZ_COUNT_DTOR(nsStyleEffects);
4807
0
}
4808
4809
nsChangeHint
4810
nsStyleEffects::CalcDifference(const nsStyleEffects& aNewData) const
4811
0
{
4812
0
  nsChangeHint hint = nsChangeHint(0);
4813
0
4814
0
  if (!AreShadowArraysEqual(mBoxShadow, aNewData.mBoxShadow)) {
4815
0
    // Update overflow regions & trigger DLBI to be sure it's noticed.
4816
0
    // Also request a repaint, since it's possible that only the color
4817
0
    // of the shadow is changing (and UpdateOverflow/SchedulePaint won't
4818
0
    // repaint for that, since they won't know what needs invalidating.)
4819
0
    hint |= nsChangeHint_UpdateOverflow |
4820
0
            nsChangeHint_SchedulePaint |
4821
0
            nsChangeHint_RepaintFrame;
4822
0
  }
4823
0
4824
0
  if (mClipFlags != aNewData.mClipFlags) {
4825
0
    hint |= nsChangeHint_AllReflowHints |
4826
0
            nsChangeHint_RepaintFrame;
4827
0
  }
4828
0
4829
0
  if (!mClip.IsEqualInterior(aNewData.mClip)) {
4830
0
    // If the clip has changed, we just need to update overflow areas. DLBI
4831
0
    // will handle the invalidation.
4832
0
    hint |= nsChangeHint_UpdateOverflow |
4833
0
            nsChangeHint_SchedulePaint;
4834
0
  }
4835
0
4836
0
  if (mOpacity != aNewData.mOpacity) {
4837
0
    // If we're going from the optimized >=0.99 opacity value to 1.0 or back, then
4838
0
    // repaint the frame because DLBI will not catch the invalidation.  Otherwise,
4839
0
    // just update the opacity layer.
4840
0
    if ((mOpacity >= 0.99f && mOpacity < 1.0f && aNewData.mOpacity == 1.0f) ||
4841
0
        (aNewData.mOpacity >= 0.99f && aNewData.mOpacity < 1.0f && mOpacity == 1.0f)) {
4842
0
      hint |= nsChangeHint_RepaintFrame;
4843
0
    } else {
4844
0
      hint |= nsChangeHint_UpdateOpacityLayer;
4845
0
      if ((mOpacity == 1.0f) != (aNewData.mOpacity == 1.0f)) {
4846
0
        hint |= nsChangeHint_UpdateUsesOpacity;
4847
0
      }
4848
0
    }
4849
0
  }
4850
0
4851
0
  if (HasFilters() != aNewData.HasFilters()) {
4852
0
    // A change from/to being a containing block for position:fixed.
4853
0
    hint |= nsChangeHint_UpdateContainingBlock;
4854
0
  }
4855
0
4856
0
  if (mFilters != aNewData.mFilters) {
4857
0
    hint |= nsChangeHint_UpdateEffects |
4858
0
            nsChangeHint_RepaintFrame |
4859
0
            nsChangeHint_UpdateOverflow;
4860
0
  }
4861
0
4862
0
  if (mMixBlendMode != aNewData.mMixBlendMode) {
4863
0
    hint |= nsChangeHint_RepaintFrame;
4864
0
  }
4865
0
4866
0
  if (!hint &&
4867
0
      !mClip.IsEqualEdges(aNewData.mClip)) {
4868
0
    hint |= nsChangeHint_NeutralChange;
4869
0
  }
4870
0
4871
0
  return hint;
4872
0
}