Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/svg/SVGLength.h
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
#ifndef MOZILLA_SVGLENGTH_H__
8
#define MOZILLA_SVGLENGTH_H__
9
10
#include "nsDebug.h"
11
#include "nsMathUtils.h"
12
#include "mozilla/FloatingPoint.h"
13
#include "mozilla/dom/SVGLengthBinding.h"
14
15
class nsSVGElement;
16
17
namespace mozilla {
18
19
/**
20
 * This SVGLength class is currently used for SVGLength *list* attributes only.
21
 * The class that is currently used for <length> attributes is nsSVGLength2.
22
 *
23
 * The member mUnit should always be valid, but the member mValue may be
24
 * numeric_limits<float>::quiet_NaN() under one circumstances (see the comment
25
 * in SetValueAndUnit below). Even if mValue is valid, some methods may return
26
 * numeric_limits<float>::quiet_NaN() if they involve a unit conversion that
27
 * fails - see comments below.
28
 *
29
 * The DOM wrapper class for this class is DOMSVGLength.
30
 */
31
class SVGLength
32
{
33
public:
34
35
  SVGLength()
36
    : mValue(0.0f)
37
    , mUnit(dom::SVGLength_Binding::SVG_LENGTHTYPE_UNKNOWN) // caught by IsValid()
38
0
  {}
39
40
  SVGLength(float aValue, uint8_t aUnit)
41
    : mValue(aValue)
42
    , mUnit(aUnit)
43
0
  {
44
0
    NS_ASSERTION(IsValid(), "Constructed an invalid length");
45
0
  }
46
47
  SVGLength(const SVGLength &aOther)
48
    : mValue(aOther.mValue)
49
    , mUnit(aOther.mUnit)
50
0
  {}
51
52
0
  SVGLength& operator=(const SVGLength &rhs) {
53
0
    mValue = rhs.mValue;
54
0
    mUnit = rhs.mUnit;
55
0
    return *this;
56
0
  }
57
58
0
  bool operator==(const SVGLength &rhs) const {
59
0
    return mValue == rhs.mValue && mUnit == rhs.mUnit;
60
0
  }
61
62
  void GetValueAsString(nsAString& aValue) const;
63
64
  /**
65
   * This method returns true, unless there was a parse failure, in which
66
   * case it returns false (and the length is left unchanged).
67
   */
68
  bool SetValueFromString(const nsAString& aValue);
69
70
  /**
71
   * This will usually return a valid, finite number. There is one exception
72
   * though - see the comment in SetValueAndUnit().
73
   */
74
0
  float GetValueInCurrentUnits() const {
75
0
    return mValue;
76
0
  }
77
78
0
  uint8_t GetUnit() const {
79
0
    return mUnit;
80
0
  }
81
82
0
  void SetValueInCurrentUnits(float aValue) {
83
0
    mValue = aValue;
84
0
    NS_ASSERTION(IsValid(), "Set invalid SVGLength");
85
0
  }
86
87
0
  void SetValueAndUnit(float aValue, uint8_t aUnit) {
88
0
    mValue = aValue;
89
0
    mUnit = aUnit;
90
0
91
0
    // IsValid() should always be true, with one exception: if
92
0
    // SVGLengthListSMILType has to convert between unit types and the unit
93
0
    // conversion is undefined, it will end up passing in and setting
94
0
    // numeric_limits<float>::quiet_NaN(). Because of that we only check the
95
0
    // unit here, and allow mValue to be invalid. The painting code has to be
96
0
    // able to handle NaN anyway, since conversion to user units may fail in
97
0
    // general.
98
0
99
0
    NS_ASSERTION(IsValidUnitType(mUnit), "Set invalid SVGLength");
100
0
  }
101
102
  /**
103
   * If it's not possible to convert this length's value to user units, then
104
   * this method will return numeric_limits<float>::quiet_NaN().
105
   */
106
0
  float GetValueInUserUnits(const nsSVGElement *aElement, uint8_t aAxis) const {
107
0
    return mValue * GetUserUnitsPerUnit(aElement, aAxis);
108
0
  }
109
110
  /**
111
   * Get this length's value in the units specified.
112
   *
113
   * This method returns numeric_limits<float>::quiet_NaN() if it is not
114
   * possible to convert the value to the specified unit.
115
   */
116
  float GetValueInSpecifiedUnit(uint8_t aUnit,
117
                                const nsSVGElement *aElement,
118
                                uint8_t aAxis) const;
119
120
0
  bool IsPercentage() const {
121
0
    return mUnit == dom::SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE;
122
0
  }
123
124
0
  static bool IsValidUnitType(uint16_t unit) {
125
0
    return unit > dom::SVGLength_Binding::SVG_LENGTHTYPE_UNKNOWN &&
126
0
           unit <= dom::SVGLength_Binding::SVG_LENGTHTYPE_PC;
127
0
  }
128
129
  /**
130
   * Returns the number of user units per current unit.
131
   *
132
   * This method returns numeric_limits<float>::quiet_NaN() if the conversion
133
   * factor between the length's current unit and user units is undefined (see
134
   * the comments for GetUserUnitsPerInch and GetUserUnitsPerPercent).
135
   */
136
  float GetUserUnitsPerUnit(const nsSVGElement *aElement, uint8_t aAxis) const;
137
138
private:
139
140
#ifdef DEBUG
141
  bool IsValid() const {
142
    return IsFinite(mValue) && IsValidUnitType(mUnit);
143
  }
144
#endif
145
146
  /**
147
   * The conversion factor between user units (CSS px) and CSS inches is
148
   * constant: 96 px per inch.
149
   */
150
  static float GetUserUnitsPerInch()
151
0
  {
152
0
    return 96.0;
153
0
  }
154
155
  /**
156
   * The conversion factor between user units and percentage units depends on
157
   * aElement being non-null, and on aElement having a viewport element
158
   * ancestor with only appropriate SVG elements between aElement and that
159
   * ancestor. If that's not the case, then the conversion factor is undefined.
160
   *
161
   * This function returns a non-negative value if the conversion factor is
162
   * defined, otherwise it returns numeric_limits<float>::quiet_NaN().
163
   */
164
  static float GetUserUnitsPerPercent(const nsSVGElement *aElement, uint8_t aAxis);
165
166
  float mValue;
167
  uint8_t mUnit;
168
};
169
170
} // namespace mozilla
171
172
#endif // MOZILLA_SVGLENGTH_H__