OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org> | 2 * Copyright (C) 2004, 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org> |
3 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> | 3 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> |
4 * Copyright (C) 2007 Apple Inc. All rights reserved. | 4 * Copyright (C) 2007 Apple Inc. All rights reserved. |
5 * Copyright (C) Research In Motion Limited 2011. All rights reserved. | 5 * Copyright (C) Research In Motion Limited 2011. All rights reserved. |
6 * | 6 * |
7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 } | 46 } |
47 ASSERT_NOT_REACHED(); | 47 ASSERT_NOT_REACHED(); |
48 return 0; | 48 return 0; |
49 } | 49 } |
50 | 50 |
51 static float convertValueFromPercentageToUserUnits(const SVGLength& value, const
FloatSize& viewportSize) | 51 static float convertValueFromPercentageToUserUnits(const SVGLength& value, const
FloatSize& viewportSize) |
52 { | 52 { |
53 return CSSPrimitiveValue::clampToCSSLengthRange(value.scaleByPercentage(dime
nsionForLengthMode(value.unitMode(), viewportSize))); | 53 return CSSPrimitiveValue::clampToCSSLengthRange(value.scaleByPercentage(dime
nsionForLengthMode(value.unitMode(), viewportSize))); |
54 } | 54 } |
55 | 55 |
| 56 static const ComputedStyle* computedStyleForLengthResolving(const SVGElement* co
ntext) |
| 57 { |
| 58 if (!context) |
| 59 return 0; |
| 60 |
| 61 const ContainerNode* currentContext = context; |
| 62 do { |
| 63 if (currentContext->layoutObject()) |
| 64 return currentContext->layoutObject()->style(); |
| 65 currentContext = currentContext->parentNode(); |
| 66 } while (currentContext); |
| 67 |
| 68 // There must be at least a LayoutSVGRoot renderer, carrying a style. |
| 69 ASSERT_NOT_REACHED(); |
| 70 return 0; |
| 71 } |
| 72 |
| 73 static const ComputedStyle* rootElementStyle(const Node* context) |
| 74 { |
| 75 if (!context) |
| 76 return 0; |
| 77 |
| 78 const Document& document = context->document(); |
| 79 Node* documentElement = document.documentElement(); |
| 80 const ComputedStyle* documentStyle = document.computedStyle(); |
| 81 const ComputedStyle* style = documentElement && context != documentElement ?
documentElement->computedStyle() : documentStyle; |
| 82 if (!style) |
| 83 style = documentStyle; |
| 84 return style; |
| 85 } |
| 86 |
| 87 static float convertValueFromUserUnitsToEMS(const ComputedStyle* style, float va
lue) |
| 88 { |
| 89 if (!style) |
| 90 return 0; |
| 91 float fontSize = style->specifiedFontSize(); |
| 92 if (!fontSize) |
| 93 return 0; |
| 94 return value / fontSize; |
| 95 } |
| 96 |
| 97 static float convertValueFromEMSToUserUnits(const ComputedStyle* style, float va
lue) |
| 98 { |
| 99 if (!style) |
| 100 return 0; |
| 101 return value * style->specifiedFontSize(); |
| 102 } |
| 103 |
56 SVGLengthContext::SVGLengthContext(const SVGElement* context) | 104 SVGLengthContext::SVGLengthContext(const SVGElement* context) |
57 : m_context(context) | 105 : m_context(context) |
58 { | 106 { |
59 } | 107 } |
60 | 108 |
61 FloatRect SVGLengthContext::resolveRectangle(const SVGElement* context, SVGUnitT
ypes::SVGUnitType type, const FloatRect& viewport, const SVGLength& x, const SVG
Length& y, const SVGLength& width, const SVGLength& height) | 109 FloatRect SVGLengthContext::resolveRectangle(const SVGElement* context, SVGUnitT
ypes::SVGUnitType type, const FloatRect& viewport, const SVGLength& x, const SVG
Length& y, const SVGLength& width, const SVGLength& height) |
62 { | 110 { |
63 ASSERT(type != SVGUnitTypes::SVG_UNIT_TYPE_UNKNOWN); | 111 ASSERT(type != SVGUnitTypes::SVG_UNIT_TYPE_UNKNOWN); |
64 if (type != SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE && !viewport.isEmpty(
)) { | 112 if (type != SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE && !viewport.isEmpty(
)) { |
65 const FloatSize& viewportSize = viewport.size(); | 113 const FloatSize& viewportSize = viewport.size(); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 userUnits = value; | 190 userUnits = value; |
143 break; | 191 break; |
144 case LengthTypePercentage: { | 192 case LengthTypePercentage: { |
145 FloatSize viewportSize; | 193 FloatSize viewportSize; |
146 if (!determineViewport(viewportSize)) | 194 if (!determineViewport(viewportSize)) |
147 return 0; | 195 return 0; |
148 userUnits = value * dimensionForLengthMode(mode, viewportSize) / 100; | 196 userUnits = value * dimensionForLengthMode(mode, viewportSize) / 100; |
149 break; | 197 break; |
150 } | 198 } |
151 case LengthTypeEMS: | 199 case LengthTypeEMS: |
152 userUnits = convertValueFromEMSToUserUnits(value); | 200 userUnits = convertValueFromEMSToUserUnits(computedStyleForLengthResolvi
ng(m_context), value); |
153 break; | 201 break; |
154 case LengthTypeEXS: | 202 case LengthTypeEXS: |
155 userUnits = convertValueFromEXSToUserUnits(value); | 203 userUnits = convertValueFromEXSToUserUnits(value); |
156 break; | 204 break; |
157 case LengthTypeCM: | 205 case LengthTypeCM: |
158 userUnits = value * cssPixelsPerCentimeter; | 206 userUnits = value * cssPixelsPerCentimeter; |
159 break; | 207 break; |
160 case LengthTypeMM: | 208 case LengthTypeMM: |
161 userUnits = value * cssPixelsPerMillimeter; | 209 userUnits = value * cssPixelsPerMillimeter; |
162 break; | 210 break; |
163 case LengthTypeIN: | 211 case LengthTypeIN: |
164 userUnits = value * cssPixelsPerInch; | 212 userUnits = value * cssPixelsPerInch; |
165 break; | 213 break; |
166 case LengthTypePT: | 214 case LengthTypePT: |
167 userUnits = value * cssPixelsPerPoint; | 215 userUnits = value * cssPixelsPerPoint; |
168 break; | 216 break; |
169 case LengthTypePC: | 217 case LengthTypePC: |
170 userUnits = value * cssPixelsPerPica; | 218 userUnits = value * cssPixelsPerPica; |
171 break; | 219 break; |
172 case LengthTypeREMS: | 220 case LengthTypeREMS: |
173 userUnits = convertValueFromREMSToUserUnits(value); | 221 userUnits = convertValueFromEMSToUserUnits(rootElementStyle(m_context),
value); |
174 break; | 222 break; |
175 default: | 223 default: |
176 ASSERT_NOT_REACHED(); | 224 ASSERT_NOT_REACHED(); |
177 break; | 225 break; |
178 } | 226 } |
179 | 227 |
180 // Since we mix css <length> values with svg's length values we need to | 228 // Since we mix css <length> values with svg's length values we need to |
181 // clamp values to the narrowest range, otherwise it can result in | 229 // clamp values to the narrowest range, otherwise it can result in |
182 // rendering issues. | 230 // rendering issues. |
183 return CSSPrimitiveValue::clampToCSSLengthRange(userUnits); | 231 return CSSPrimitiveValue::clampToCSSLengthRange(userUnits); |
184 } | 232 } |
185 | 233 |
186 float SVGLengthContext::convertValueFromUserUnits(float value, SVGLengthMode mod
e, SVGLengthType toUnit) const | 234 float SVGLengthContext::convertValueFromUserUnits(float value, SVGLengthMode mod
e, SVGLengthType toUnit) const |
187 { | 235 { |
188 switch (toUnit) { | 236 switch (toUnit) { |
189 case LengthTypeUnknown: | 237 case LengthTypeUnknown: |
190 return 0; | 238 return 0; |
191 case LengthTypeNumber: | 239 case LengthTypeNumber: |
192 return value; | 240 return value; |
193 case LengthTypePercentage: { | 241 case LengthTypePercentage: { |
194 FloatSize viewportSize; | 242 FloatSize viewportSize; |
195 if (!determineViewport(viewportSize)) | 243 if (!determineViewport(viewportSize)) |
196 return 0; | 244 return 0; |
197 // LengthTypePercentage is represented with 100% = 100.0. | 245 // LengthTypePercentage is represented with 100% = 100.0. |
198 // Good for accuracy but could eventually be changed. | 246 // Good for accuracy but could eventually be changed. |
199 return value * 100 / dimensionForLengthMode(mode, viewportSize); | 247 return value * 100 / dimensionForLengthMode(mode, viewportSize); |
200 } | 248 } |
201 case LengthTypeEMS: | 249 case LengthTypeEMS: |
202 return convertValueFromUserUnitsToEMS(value); | 250 return convertValueFromUserUnitsToEMS(computedStyleForLengthResolving(m_
context), value); |
203 case LengthTypeEXS: | 251 case LengthTypeEXS: |
204 return convertValueFromUserUnitsToEXS(value); | 252 return convertValueFromUserUnitsToEXS(value); |
205 case LengthTypeREMS: | 253 case LengthTypeREMS: |
206 return convertValueFromUserUnitsToREMS(value); | 254 return convertValueFromUserUnitsToEMS(rootElementStyle(m_context), value
); |
207 case LengthTypePX: | 255 case LengthTypePX: |
208 return value; | 256 return value; |
209 case LengthTypeCM: | 257 case LengthTypeCM: |
210 return value / cssPixelsPerCentimeter; | 258 return value / cssPixelsPerCentimeter; |
211 case LengthTypeMM: | 259 case LengthTypeMM: |
212 return value / cssPixelsPerMillimeter; | 260 return value / cssPixelsPerMillimeter; |
213 case LengthTypeIN: | 261 case LengthTypeIN: |
214 return value / cssPixelsPerInch; | 262 return value / cssPixelsPerInch; |
215 case LengthTypePT: | 263 case LengthTypePT: |
216 return value / cssPixelsPerPoint; | 264 return value / cssPixelsPerPoint; |
217 case LengthTypePC: | 265 case LengthTypePC: |
218 return value / cssPixelsPerPica; | 266 return value / cssPixelsPerPica; |
219 } | 267 } |
220 | 268 |
221 ASSERT_NOT_REACHED(); | 269 ASSERT_NOT_REACHED(); |
222 return 0; | 270 return 0; |
223 } | 271 } |
224 | 272 |
225 static inline const ComputedStyle* computedStyleForLengthResolving(const SVGElem
ent* context) | |
226 { | |
227 if (!context) | |
228 return 0; | |
229 | |
230 const ContainerNode* currentContext = context; | |
231 do { | |
232 if (currentContext->layoutObject()) | |
233 return currentContext->layoutObject()->style(); | |
234 currentContext = currentContext->parentNode(); | |
235 } while (currentContext); | |
236 | |
237 // There must be at least a LayoutSVGRoot renderer, carrying a style. | |
238 ASSERT_NOT_REACHED(); | |
239 return 0; | |
240 } | |
241 | |
242 float SVGLengthContext::convertValueFromUserUnitsToEMS(float value) const | |
243 { | |
244 const ComputedStyle* style = computedStyleForLengthResolving(m_context); | |
245 if (!style) | |
246 return 0; | |
247 | |
248 float fontSize = style->specifiedFontSize(); | |
249 if (!fontSize) | |
250 return 0; | |
251 | |
252 return value / fontSize; | |
253 } | |
254 | |
255 float SVGLengthContext::convertValueFromEMSToUserUnits(float value) const | |
256 { | |
257 const ComputedStyle* style = computedStyleForLengthResolving(m_context); | |
258 if (!style) | |
259 return 0; | |
260 return value * style->specifiedFontSize(); | |
261 } | |
262 | |
263 float SVGLengthContext::convertValueFromUserUnitsToREMS(float value) const | |
264 { | |
265 if (!m_context) | |
266 return 0; | |
267 | |
268 const ComputedStyle* style = 0; | |
269 const Document& document = m_context->document(); | |
270 Node* documentElement = document.documentElement(); | |
271 const ComputedStyle* documentStyle = document.computedStyle(); | |
272 style = documentElement && (static_cast<const Node*>(m_context.get()) != doc
umentElement) ? documentElement->computedStyle() : documentStyle; | |
273 if (!style) | |
274 style = documentStyle; | |
275 | |
276 if (!style) | |
277 return 0; | |
278 | |
279 float fontSize = style->specifiedFontSize(); | |
280 if (!fontSize) | |
281 return 0; | |
282 | |
283 return value / fontSize; | |
284 } | |
285 | |
286 float SVGLengthContext::convertValueFromREMSToUserUnits(float value) const | |
287 { | |
288 if (!m_context) | |
289 return 0; | |
290 | |
291 const ComputedStyle* style = 0; | |
292 const Document& document = m_context->document(); | |
293 Node* documentElement = document.documentElement(); | |
294 const ComputedStyle* documentStyle = document.computedStyle(); | |
295 style = documentElement && (static_cast<const Node*>(m_context.get()) != doc
umentElement) ? documentElement->computedStyle() : documentStyle; | |
296 if (!style) | |
297 style = documentStyle; | |
298 | |
299 if (!style) | |
300 return 0; | |
301 | |
302 return value * style->specifiedFontSize(); | |
303 } | |
304 | |
305 float SVGLengthContext::convertValueFromUserUnitsToEXS(float value) const | 273 float SVGLengthContext::convertValueFromUserUnitsToEXS(float value) const |
306 { | 274 { |
307 const ComputedStyle* style = computedStyleForLengthResolving(m_context); | 275 const ComputedStyle* style = computedStyleForLengthResolving(m_context); |
308 if (!style) | 276 if (!style) |
309 return 0; | 277 return 0; |
310 | 278 |
311 // Use of ceil allows a pixel match to the W3Cs expected output of coords-un
its-03-b.svg | 279 // Use of ceil allows a pixel match to the W3Cs expected output of coords-un
its-03-b.svg |
312 // if this causes problems in real world cases maybe it would be best to rem
ove this | 280 // if this causes problems in real world cases maybe it would be best to rem
ove this |
313 float xHeight = ceilf(style->fontMetrics().xHeight()); | 281 float xHeight = ceilf(style->fontMetrics().xHeight()); |
314 if (!xHeight) | 282 if (!xHeight) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 | 314 |
347 const SVGSVGElement& svg = toSVGSVGElement(*viewportElement); | 315 const SVGSVGElement& svg = toSVGSVGElement(*viewportElement); |
348 viewportSize = svg.currentViewBoxRect().size(); | 316 viewportSize = svg.currentViewBoxRect().size(); |
349 if (viewportSize.isEmpty()) | 317 if (viewportSize.isEmpty()) |
350 viewportSize = svg.currentViewportSize(); | 318 viewportSize = svg.currentViewportSize(); |
351 | 319 |
352 return true; | 320 return true; |
353 } | 321 } |
354 | 322 |
355 } | 323 } |
OLD | NEW |