Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/style/nsStyleCoord.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
/* representation of length values in computed style data */
8
9
#include "mozilla/HashFunctions.h"
10
#include "mozilla/PodOperations.h"
11
12
// nsStyleCoord.h must not be the first header in a unified source file,
13
// otherwise it may not build with MSVC due to a bug in our STL wrapper.
14
// See bug 1331102.
15
#include "nsStyleCoord.h"
16
17
using namespace mozilla;
18
19
nsStyleCoord::nsStyleCoord(nsStyleUnit aUnit)
20
  : mUnit(aUnit)
21
0
{
22
0
  NS_ASSERTION(aUnit < eStyleUnit_Percent, "not a valueless unit");
23
0
  if (aUnit >= eStyleUnit_Percent) {
24
0
    mUnit = eStyleUnit_Null;
25
0
  }
26
0
  mValue.mInt = 0;
27
0
}
28
29
nsStyleCoord::nsStyleCoord(int32_t aValue, nsStyleUnit aUnit)
30
  : mUnit(aUnit)
31
0
{
32
0
  //if you want to pass in eStyleUnit_Coord, don't. instead, use the
33
0
  //constructor just above this one... MMP
34
0
  NS_ASSERTION((aUnit == eStyleUnit_Enumerated) ||
35
0
               (aUnit == eStyleUnit_Integer), "not an int value");
36
0
  if ((aUnit == eStyleUnit_Enumerated) ||
37
0
      (aUnit == eStyleUnit_Integer)) {
38
0
    mValue.mInt = aValue;
39
0
  }
40
0
  else {
41
0
    mUnit = eStyleUnit_Null;
42
0
    mValue.mInt = 0;
43
0
  }
44
0
}
45
46
nsStyleCoord::nsStyleCoord(float aValue, nsStyleUnit aUnit)
47
  : mUnit(aUnit)
48
0
{
49
0
  if (aUnit < eStyleUnit_Percent || aUnit >= eStyleUnit_Coord) {
50
0
    MOZ_ASSERT_UNREACHABLE("not a float value");
51
0
    mUnit = eStyleUnit_Null;
52
0
    mValue.mInt = 0;
53
0
  } else {
54
0
    mValue.mFloat = aValue;
55
0
  }
56
0
}
57
58
bool nsStyleCoord::operator==(const nsStyleCoord& aOther) const
59
0
{
60
0
  if (mUnit != aOther.mUnit) {
61
0
    return false;
62
0
  }
63
0
  switch (mUnit) {
64
0
    case eStyleUnit_Null:
65
0
    case eStyleUnit_Normal:
66
0
    case eStyleUnit_Auto:
67
0
    case eStyleUnit_None:
68
0
      return true;
69
0
    case eStyleUnit_Percent:
70
0
    case eStyleUnit_Factor:
71
0
    case eStyleUnit_Degree:
72
0
    case eStyleUnit_Grad:
73
0
    case eStyleUnit_Radian:
74
0
    case eStyleUnit_Turn:
75
0
    case eStyleUnit_FlexFraction:
76
0
      return mValue.mFloat == aOther.mValue.mFloat;
77
0
    case eStyleUnit_Coord:
78
0
    case eStyleUnit_Integer:
79
0
    case eStyleUnit_Enumerated:
80
0
      return mValue.mInt == aOther.mValue.mInt;
81
0
    case eStyleUnit_Calc:
82
0
      return *this->GetCalcValue() == *aOther.GetCalcValue();
83
0
  }
84
0
  MOZ_ASSERT(false, "unexpected unit");
85
0
  return false;
86
0
}
87
88
void nsStyleCoord::Reset()
89
0
{
90
0
  Reset(mUnit, mValue);
91
0
}
92
93
void nsStyleCoord::SetCoordValue(nscoord aValue)
94
0
{
95
0
  Reset();
96
0
  mUnit = eStyleUnit_Coord;
97
0
  mValue.mInt = aValue;
98
0
}
99
100
void nsStyleCoord::SetIntValue(int32_t aValue, nsStyleUnit aUnit)
101
0
{
102
0
  NS_ASSERTION((aUnit == eStyleUnit_Enumerated) ||
103
0
               (aUnit == eStyleUnit_Integer), "not an int value");
104
0
  Reset();
105
0
  if ((aUnit == eStyleUnit_Enumerated) ||
106
0
      (aUnit == eStyleUnit_Integer)) {
107
0
    mUnit = aUnit;
108
0
    mValue.mInt = aValue;
109
0
  }
110
0
}
111
112
void nsStyleCoord::SetPercentValue(float aValue)
113
0
{
114
0
  Reset();
115
0
  mUnit = eStyleUnit_Percent;
116
0
  mValue.mFloat = aValue;
117
0
}
118
119
void nsStyleCoord::SetFactorValue(float aValue)
120
0
{
121
0
  Reset();
122
0
  mUnit = eStyleUnit_Factor;
123
0
  mValue.mFloat = aValue;
124
0
}
125
126
void nsStyleCoord::SetAngleValue(float aValue, nsStyleUnit aUnit)
127
0
{
128
0
  Reset();
129
0
  if (aUnit == eStyleUnit_Degree ||
130
0
      aUnit == eStyleUnit_Grad ||
131
0
      aUnit == eStyleUnit_Radian ||
132
0
      aUnit == eStyleUnit_Turn) {
133
0
    mUnit = aUnit;
134
0
    mValue.mFloat = aValue;
135
0
  } else {
136
0
    MOZ_ASSERT_UNREACHABLE("not an angle value");
137
0
  }
138
0
}
139
140
void nsStyleCoord::SetFlexFractionValue(float aValue)
141
0
{
142
0
  Reset();
143
0
  mUnit = eStyleUnit_FlexFraction;
144
0
  mValue.mFloat = aValue;
145
0
}
146
147
void nsStyleCoord::SetCalcValue(Calc* aValue)
148
0
{
149
0
  Reset();
150
0
  mUnit = eStyleUnit_Calc;
151
0
  mValue.mPointer = aValue;
152
0
  aValue->AddRef();
153
0
}
154
155
void nsStyleCoord::SetNormalValue()
156
0
{
157
0
  Reset();
158
0
  mUnit = eStyleUnit_Normal;
159
0
  mValue.mInt = 0;
160
0
}
161
162
void nsStyleCoord::SetAutoValue()
163
0
{
164
0
  Reset();
165
0
  mUnit = eStyleUnit_Auto;
166
0
  mValue.mInt = 0;
167
0
}
168
169
void nsStyleCoord::SetNoneValue()
170
0
{
171
0
  Reset();
172
0
  mUnit = eStyleUnit_None;
173
0
  mValue.mInt = 0;
174
0
}
175
176
// accessors that are not inlined
177
178
double
179
nsStyleCoord::GetAngleValueInDegrees() const
180
0
{
181
0
  return GetAngleValueInRadians() * (180.0 / M_PI);
182
0
}
183
184
double
185
nsStyleCoord::GetAngleValueInRadians() const
186
0
{
187
0
  double angle = mValue.mFloat;
188
0
189
0
  switch (GetUnit()) {
190
0
  case eStyleUnit_Radian: return angle;
191
0
  case eStyleUnit_Turn:   return angle * 2 * M_PI;
192
0
  case eStyleUnit_Degree: return angle * M_PI / 180.0;
193
0
  case eStyleUnit_Grad:   return angle * M_PI / 200.0;
194
0
195
0
  default:
196
0
    MOZ_ASSERT_UNREACHABLE("unrecognized angular unit");
197
0
    return 0.0;
198
0
  }
199
0
}
200
201
nscoord
202
nsStyleCoord::ComputeComputedCalc(nscoord aPercentageBasis) const
203
0
{
204
0
  Calc* calc = GetCalcValue();
205
0
  return calc->mLength +
206
0
         NSToCoordFloorClamped(aPercentageBasis * calc->mPercent);
207
0
}
208
209
nscoord
210
nsStyleCoord::ComputeCoordPercentCalc(nscoord aPercentageBasis) const
211
0
{
212
0
  switch (GetUnit()) {
213
0
    case eStyleUnit_Coord:
214
0
      return GetCoordValue();
215
0
    case eStyleUnit_Percent:
216
0
      return NSToCoordFloorClamped(aPercentageBasis * GetPercentValue());
217
0
    case eStyleUnit_Calc:
218
0
      return ComputeComputedCalc(aPercentageBasis);
219
0
    default:
220
0
      MOZ_ASSERT_UNREACHABLE("Unexpected unit!");
221
0
      return 0;
222
0
  }
223
0
}
224
225
nsStyleSides::nsStyleSides()
226
0
{
227
0
  NS_FOR_CSS_SIDES(i) {
228
0
    mUnits[i] = eStyleUnit_Null;
229
0
  }
230
0
  mozilla::PodArrayZero(mValues);
231
0
}
232
233
nsStyleSides::nsStyleSides(const nsStyleSides& aOther)
234
0
{
235
0
  NS_FOR_CSS_SIDES(i) {
236
0
    mUnits[i] = eStyleUnit_Null;
237
0
  }
238
0
  *this = aOther;
239
0
}
240
241
nsStyleSides::~nsStyleSides()
242
0
{
243
0
  Reset();
244
0
}
245
246
nsStyleSides&
247
nsStyleSides::operator=(const nsStyleSides& aCopy)
248
0
{
249
0
  if (this != &aCopy) {
250
0
    NS_FOR_CSS_SIDES(i) {
251
0
      nsStyleCoord::SetValue(mUnits[i], mValues[i],
252
0
                             aCopy.mUnits[i], aCopy.mValues[i]);
253
0
    }
254
0
  }
255
0
  return *this;
256
0
}
257
258
bool nsStyleSides::operator==(const nsStyleSides& aOther) const
259
0
{
260
0
  NS_FOR_CSS_SIDES(i) {
261
0
    if (nsStyleCoord(mValues[i], (nsStyleUnit)mUnits[i]) !=
262
0
        nsStyleCoord(aOther.mValues[i], (nsStyleUnit)aOther.mUnits[i])) {
263
0
      return false;
264
0
    }
265
0
  }
266
0
  return true;
267
0
}
268
269
void nsStyleSides::Reset()
270
0
{
271
0
  NS_FOR_CSS_SIDES(i) {
272
0
    nsStyleCoord::Reset(mUnits[i], mValues[i]);
273
0
  }
274
0
}
275
276
nsStyleCorners::nsStyleCorners()
277
0
{
278
0
  NS_FOR_CSS_HALF_CORNERS(i) {
279
0
    mUnits[i] = eStyleUnit_Null;
280
0
  }
281
0
  mozilla::PodArrayZero(mValues);
282
0
}
283
284
nsStyleCorners::nsStyleCorners(const nsStyleCorners& aOther)
285
0
{
286
0
  NS_FOR_CSS_HALF_CORNERS(i) {
287
0
    mUnits[i] = eStyleUnit_Null;
288
0
  }
289
0
  *this = aOther;
290
0
}
291
292
nsStyleCorners::~nsStyleCorners()
293
0
{
294
0
  Reset();
295
0
}
296
297
nsStyleCorners&
298
nsStyleCorners::operator=(const nsStyleCorners& aCopy)
299
0
{
300
0
  if (this != &aCopy) {
301
0
    NS_FOR_CSS_HALF_CORNERS(i) {
302
0
      nsStyleCoord::SetValue(mUnits[i], mValues[i],
303
0
                             aCopy.mUnits[i], aCopy.mValues[i]);
304
0
    }
305
0
  }
306
0
  return *this;
307
0
}
308
309
bool
310
nsStyleCorners::operator==(const nsStyleCorners& aOther) const
311
0
{
312
0
  NS_FOR_CSS_HALF_CORNERS(i) {
313
0
    if (nsStyleCoord(mValues[i], (nsStyleUnit)mUnits[i]) !=
314
0
        nsStyleCoord(aOther.mValues[i], (nsStyleUnit)aOther.mUnits[i])) {
315
0
      return false;
316
0
    }
317
0
  }
318
0
  return true;
319
0
}
320
321
void nsStyleCorners::Reset()
322
0
{
323
0
  NS_FOR_CSS_HALF_CORNERS(i) {
324
0
    nsStyleCoord::Reset(mUnits[i], mValues[i]);
325
0
  }
326
0
}
327
328
// Validation of SideIsVertical.
329
#define CASE(side, result)                                                    \
330
  static_assert(SideIsVertical(side) == result,                               \
331
                "SideIsVertical is wrong")
332
CASE(eSideTop,    false);
333
CASE(eSideRight,  true);
334
CASE(eSideBottom, false);
335
CASE(eSideLeft,   true);
336
#undef CASE
337
338
// Validation of HalfCornerIsX.
339
#define CASE(corner, result)                                                  \
340
  static_assert(HalfCornerIsX(corner) == result,                              \
341
                "HalfCornerIsX is wrong")
342
CASE(eCornerTopLeftX,     true);
343
CASE(eCornerTopLeftY,     false);
344
CASE(eCornerTopRightX,    true);
345
CASE(eCornerTopRightY,    false);
346
CASE(eCornerBottomRightX, true);
347
CASE(eCornerBottomRightY, false);
348
CASE(eCornerBottomLeftX,  true);
349
CASE(eCornerBottomLeftY,  false);
350
#undef CASE
351
352
// Validation of HalfToFullCorner.
353
#define CASE(corner, result)                                                  \
354
  static_assert(HalfToFullCorner(corner) == result,                           \
355
                "HalfToFullCorner is wrong")
356
CASE(eCornerTopLeftX,     eCornerTopLeft);
357
CASE(eCornerTopLeftY,     eCornerTopLeft);
358
CASE(eCornerTopRightX,    eCornerTopRight);
359
CASE(eCornerTopRightY,    eCornerTopRight);
360
CASE(eCornerBottomRightX, eCornerBottomRight);
361
CASE(eCornerBottomRightY, eCornerBottomRight);
362
CASE(eCornerBottomLeftX,  eCornerBottomLeft);
363
CASE(eCornerBottomLeftY,  eCornerBottomLeft);
364
#undef CASE
365
366
// Validation of FullToHalfCorner.
367
#define CASE(corner, vert, result)                                            \
368
  static_assert(FullToHalfCorner(corner, vert) == result,                     \
369
                "FullToHalfCorner is wrong")
370
CASE(eCornerTopLeft,     false, eCornerTopLeftX);
371
CASE(eCornerTopLeft,     true,  eCornerTopLeftY);
372
CASE(eCornerTopRight,    false, eCornerTopRightX);
373
CASE(eCornerTopRight,    true,  eCornerTopRightY);
374
CASE(eCornerBottomRight, false, eCornerBottomRightX);
375
CASE(eCornerBottomRight, true,  eCornerBottomRightY);
376
CASE(eCornerBottomLeft,  false, eCornerBottomLeftX);
377
CASE(eCornerBottomLeft,  true,  eCornerBottomLeftY);
378
#undef CASE
379
380
// Validation of SideToFullCorner.
381
#define CASE(side, second, result)                                            \
382
  static_assert(SideToFullCorner(side, second) == result,                     \
383
                "SideToFullCorner is wrong")
384
CASE(eSideTop,    false, eCornerTopLeft);
385
CASE(eSideTop,    true,  eCornerTopRight);
386
387
CASE(eSideRight,  false, eCornerTopRight);
388
CASE(eSideRight,  true,  eCornerBottomRight);
389
390
CASE(eSideBottom, false, eCornerBottomRight);
391
CASE(eSideBottom, true,  eCornerBottomLeft);
392
393
CASE(eSideLeft,   false, eCornerBottomLeft);
394
CASE(eSideLeft,   true,  eCornerTopLeft);
395
#undef CASE
396
397
// Validation of SideToHalfCorner.
398
#define CASE(side, second, parallel, result)                                  \
399
  static_assert(SideToHalfCorner(side, second, parallel) == result,           \
400
                "SideToHalfCorner is wrong")
401
CASE(eSideTop,    false, true,  eCornerTopLeftX);
402
CASE(eSideTop,    false, false, eCornerTopLeftY);
403
CASE(eSideTop,    true,  true,  eCornerTopRightX);
404
CASE(eSideTop,    true,  false, eCornerTopRightY);
405
406
CASE(eSideRight,  false, false, eCornerTopRightX);
407
CASE(eSideRight,  false, true,  eCornerTopRightY);
408
CASE(eSideRight,  true,  false, eCornerBottomRightX);
409
CASE(eSideRight,  true,  true,  eCornerBottomRightY);
410
411
CASE(eSideBottom, false, true,  eCornerBottomRightX);
412
CASE(eSideBottom, false, false, eCornerBottomRightY);
413
CASE(eSideBottom, true,  true,  eCornerBottomLeftX);
414
CASE(eSideBottom, true,  false, eCornerBottomLeftY);
415
416
CASE(eSideLeft,   false, false, eCornerBottomLeftX);
417
CASE(eSideLeft,   false, true,  eCornerBottomLeftY);
418
CASE(eSideLeft,   true,  false, eCornerTopLeftX);
419
CASE(eSideLeft,   true,  true,  eCornerTopLeftY);
420
#undef CASE