/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__ |