Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1159)

Side by Side Diff: Source/core/dom/ViewportArguments.cpp

Issue 19555002: Translate viewport related meta tags into @viewport descriptors as suggested by the CSS Device Adap… (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) 5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org)
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserv ed. 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserv ed.
7 * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/) 7 * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/)
8 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) 8 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
9 * Copyright (C) 2012-2013 Intel Corporation. All rights reserved. 9 * Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
10 * 10 *
(...skipping 28 matching lines...) Expand all
39 { 39 {
40 if (value1 == ViewportArguments::ValueAuto) 40 if (value1 == ViewportArguments::ValueAuto)
41 return value2; 41 return value2;
42 42
43 if (value2 == ViewportArguments::ValueAuto) 43 if (value2 == ViewportArguments::ValueAuto)
44 return value1; 44 return value1;
45 45
46 return compare(value1, value2); 46 return compare(value1, value2);
47 } 47 }
48 48
49 static inline float clampLengthValue(float value) 49 PageScaleConstraints ViewportArguments::resolve(const FloatSize& initialViewport Size) const
50 { 50 {
51 ASSERT(value != ViewportArguments::ValueDeviceWidth); 51 float resultWidth = ViewportArguments::ValueAuto;
52 ASSERT(value != ViewportArguments::ValueDeviceHeight);
53
54 // Limits as defined in the css-device-adapt spec.
55 if (value != ViewportArguments::ValueAuto)
56 return min(float(10000), max(value, float(1)));
57 return value;
58 }
59
60 static inline float clampScaleValue(float value)
61 {
62 ASSERT(value != ViewportArguments::ValueDeviceWidth);
63 ASSERT(value != ViewportArguments::ValueDeviceHeight);
64
65 // Limits as defined in the css-device-adapt spec.
66 if (value != ViewportArguments::ValueAuto)
67 return min(float(10), max(value, float(0.1)));
68 return value;
69 }
70
71 PageScaleConstraints ViewportArguments::resolve(const FloatSize& initialViewport Size, int defaultWidth) const
72 {
73 float resultWidth = width;
74 float resultMaxWidth = maxWidth; 52 float resultMaxWidth = maxWidth;
75 float resultMinWidth = minWidth; 53 float resultMinWidth = minWidth;
76 float resultHeight = height; 54
55 float resultHeight = ViewportArguments::ValueAuto;
77 float resultMinHeight = minHeight; 56 float resultMinHeight = minHeight;
78 float resultMaxHeight = maxHeight; 57 float resultMaxHeight = maxHeight;
79 58
80 float resultZoom = zoom; 59 float resultZoom = zoom;
81 float resultMinZoom = minZoom; 60 float resultMinZoom = minZoom;
82 float resultMaxZoom = maxZoom; 61 float resultMaxZoom = maxZoom;
83 float resultUserZoom = userZoom; 62 float resultUserZoom = userZoom;
84 63
85 if (type == ViewportArguments::CSSDeviceAdaptation) { 64 // 1. Resolve min-zoom and max-zoom values.
65 if (resultMinZoom != ViewportArguments::ValueAuto && resultMaxZoom != Viewpo rtArguments::ValueAuto)
66 resultMaxZoom = max(resultMinZoom, resultMaxZoom);
86 67
87 // device-width/device-height not supported for @viewport. 68 // 2. Constrain zoom value to the [min-zoom, max-zoom] range.
88 ASSERT(resultMinWidth != ViewportArguments::ValueDeviceWidth); 69 if (resultZoom != ViewportArguments::ValueAuto)
89 ASSERT(resultMinWidth != ViewportArguments::ValueDeviceHeight); 70 resultZoom = compareIgnoringAuto(resultMinZoom, compareIgnoringAuto(resu ltMaxZoom, resultZoom, min), max);
90 ASSERT(resultMaxWidth != ViewportArguments::ValueDeviceWidth);
91 ASSERT(resultMaxWidth != ViewportArguments::ValueDeviceHeight);
92 ASSERT(resultMinHeight != ViewportArguments::ValueDeviceWidth);
93 ASSERT(resultMinHeight != ViewportArguments::ValueDeviceHeight);
94 ASSERT(resultMaxHeight != ViewportArguments::ValueDeviceWidth);
95 ASSERT(resultMaxHeight != ViewportArguments::ValueDeviceHeight);
96 71
97 // 1. Resolve min-zoom and max-zoom values. 72 float extendZoom = compareIgnoringAuto(resultZoom, resultMaxZoom, min);
98 if (resultMinZoom != ViewportArguments::ValueAuto && resultMaxZoom != Vi ewportArguments::ValueAuto)
99 resultMaxZoom = max(resultMinZoom, resultMaxZoom);
100 73
101 // 2. Constrain zoom value to the [min-zoom, max-zoom] range. 74 // 3. Resolve non-"auto" lengths to pixel lengths.
102 if (resultZoom != ViewportArguments::ValueAuto) 75 if (extendZoom == ViewportArguments::ValueAuto) {
103 resultZoom = compareIgnoringAuto(resultMinZoom, compareIgnoringAuto( resultMaxZoom, resultZoom, min), max); 76 if (resultMaxWidth == ViewportArguments::ValueExtendToZoom)
77 resultMaxWidth = ViewportArguments::ValueAuto;
104 78
105 float extendZoom = compareIgnoringAuto(resultZoom, resultMaxZoom, min); 79 if (resultMaxHeight == ViewportArguments::ValueExtendToZoom)
80 resultMaxHeight = ViewportArguments::ValueAuto;
106 81
107 if (extendZoom == ViewportArguments::ValueAuto) { 82 if (resultMinWidth == ViewportArguments::ValueExtendToZoom)
108 if (resultMaxWidth == ViewportArguments::ValueExtendToZoom) 83 resultMinWidth = resultMaxWidth;
109 resultMaxWidth = ViewportArguments::ValueAuto;
110 84
111 if (resultMaxHeight == ViewportArguments::ValueExtendToZoom) 85 if (resultMinHeight == ViewportArguments::ValueExtendToZoom)
112 resultMaxHeight = ViewportArguments::ValueAuto; 86 resultMinHeight = resultMaxHeight;
87 } else {
88 float extendWidth = initialViewportSize.width() / extendZoom;
89 float extendHeight = initialViewportSize.height() / extendZoom;
113 90
114 if (resultMinWidth == ViewportArguments::ValueExtendToZoom) 91 if (resultMaxWidth == ViewportArguments::ValueExtendToZoom)
115 resultMinWidth = resultMaxWidth; 92 resultMaxWidth = extendWidth;
116 93
117 if (resultMinHeight == ViewportArguments::ValueExtendToZoom) 94 if (resultMaxHeight == ViewportArguments::ValueExtendToZoom)
118 resultMinHeight = resultMaxHeight; 95 resultMaxHeight = extendHeight;
119 } else {
120 float extendWidth = initialViewportSize.width() / extendZoom;
121 float extendHeight = initialViewportSize.height() / extendZoom;
122 96
123 if (resultMaxWidth == ViewportArguments::ValueExtendToZoom) 97 if (resultMinWidth == ViewportArguments::ValueExtendToZoom)
124 resultMaxWidth = extendWidth; 98 resultMinWidth = compareIgnoringAuto(extendWidth, resultMaxWidth, ma x);
125 99
126 if (resultMaxHeight == ViewportArguments::ValueExtendToZoom) 100 if (resultMinHeight == ViewportArguments::ValueExtendToZoom)
127 resultMaxHeight = extendHeight; 101 resultMinHeight = compareIgnoringAuto(extendHeight, resultMaxHeight, max);
128
129 if (resultMinWidth == ViewportArguments::ValueExtendToZoom)
130 resultMinWidth = compareIgnoringAuto(extendWidth, resultMaxWidth , max);
131
132 if (resultMinHeight == ViewportArguments::ValueExtendToZoom)
133 resultMinHeight = compareIgnoringAuto(extendHeight, resultMaxHei ght, max);
134 }
135
136 // 4. Resolve initial width from min/max descriptors.
137 if (resultMinWidth != ViewportArguments::ValueAuto || resultMaxWidth != ViewportArguments::ValueAuto)
138 resultWidth = compareIgnoringAuto(resultMinWidth, compareIgnoringAut o(resultMaxWidth, initialViewportSize.width(), min), max);
139
140 // 5. Resolve initial height from min/max descriptors.
141 if (resultMinHeight != ViewportArguments::ValueAuto || resultMaxHeight ! = ViewportArguments::ValueAuto)
142 resultHeight = compareIgnoringAuto(resultMinHeight, compareIgnoringA uto(resultMaxHeight, initialViewportSize.height(), min), max);
143
144 // 6-7. Resolve width value.
145 if (resultWidth == ViewportArguments::ValueAuto) {
146 if (resultHeight == ViewportArguments::ValueAuto || !initialViewport Size .height())
147 resultWidth = initialViewportSize.width();
148 else
149 resultWidth = resultHeight * (initialViewportSize.width() / init ialViewportSize.height());
150 }
151
152 // 8. Resolve height value.
153 if (resultHeight == ViewportArguments::ValueAuto) {
154 if (!initialViewportSize.width())
155 resultHeight = initialViewportSize.height();
156 else
157 resultHeight = resultWidth * initialViewportSize.height() / init ialViewportSize.width();
158 }
159
160 PageScaleConstraints result;
161 result.minimumScale = resultMinZoom;
162 result.maximumScale = resultMaxZoom;
163 result.initialScale = resultZoom;
164 result.layoutSize.setWidth(resultWidth);
165 result.layoutSize.setHeight(resultHeight);
166 return result;
167 } 102 }
168 103
169 switch (static_cast<int>(resultWidth)) { 104 // 4. Resolve initial width from min/max descriptors.
170 case ViewportArguments::ValueDeviceWidth: 105 if (resultMinWidth != ViewportArguments::ValueAuto || resultMaxWidth != View portArguments::ValueAuto)
171 resultWidth = initialViewportSize.width(); 106 resultWidth = compareIgnoringAuto(resultMinWidth, compareIgnoringAuto(re sultMaxWidth, initialViewportSize.width(), min), max);
172 break; 107
173 case ViewportArguments::ValueDeviceHeight: 108 // 5. Resolve initial height from min/max descriptors.
174 resultWidth = initialViewportSize.height(); 109 if (resultMinHeight != ViewportArguments::ValueAuto || resultMaxHeight != Vi ewportArguments::ValueAuto)
175 break; 110 resultHeight = compareIgnoringAuto(resultMinHeight, compareIgnoringAuto( resultMaxHeight, initialViewportSize.height(), min), max);
111
112 // 6-7. Resolve width value.
113 if (resultWidth == ViewportArguments::ValueAuto) {
114 if (resultHeight == ViewportArguments::ValueAuto || !initialViewportSize .height())
115 resultWidth = initialViewportSize.width();
116 else
117 resultWidth = resultHeight * (initialViewportSize.width() / initialV iewportSize.height());
176 } 118 }
177 119
178 switch (static_cast<int>(resultHeight)) { 120 // 8. Resolve height value.
179 case ViewportArguments::ValueDeviceWidth: 121 if (resultHeight == ViewportArguments::ValueAuto) {
180 resultHeight = initialViewportSize.width(); 122 if (!initialViewportSize.width())
181 break; 123 resultHeight = initialViewportSize.height();
182 case ViewportArguments::ValueDeviceHeight: 124 else
183 resultHeight = initialViewportSize.height(); 125 resultHeight = resultWidth * (initialViewportSize.height() / initial ViewportSize.width());
184 break;
185 }
186
187 if (type != ViewportArguments::Implicit) {
188 // Clamp values to a valid range, but not for @viewport since is
189 // not mandated by the specification.
190 resultWidth = clampLengthValue(resultWidth);
191 resultHeight = clampLengthValue(resultHeight);
192 resultZoom = clampScaleValue(resultZoom);
193 resultMinZoom = clampScaleValue(resultMinZoom);
194 resultMaxZoom = clampScaleValue(resultMaxZoom);
195 } 126 }
196 127
197 PageScaleConstraints result; 128 PageScaleConstraints result;
198 129
199 // Resolve minimum-scale and maximum-scale values according to spec. 130 result.minimumScale = resultMinZoom;
200 if (resultMinZoom == ViewportArguments::ValueAuto) 131 result.maximumScale = resultMaxZoom;
201 result.minimumScale = float(0.25);
202 else
203 result.minimumScale = resultMinZoom;
204
205 if (resultMaxZoom == ViewportArguments::ValueAuto) {
206 result.maximumScale = float(5.0);
207 result.minimumScale = min(float(5.0), result.minimumScale);
208 } else
209 result.maximumScale = resultMaxZoom;
210 result.maximumScale = max(result.minimumScale, result.maximumScale);
211
212 // Resolve initial-scale value.
213 result.initialScale = resultZoom; 132 result.initialScale = resultZoom;
214 if (resultZoom == ViewportArguments::ValueAuto) {
215 result.initialScale = initialViewportSize.width() / defaultWidth;
216 if (resultWidth != ViewportArguments::ValueAuto && resultWidth > 0)
217 result.initialScale = initialViewportSize.width() / resultWidth;
218 if (resultHeight != ViewportArguments::ValueAuto && resultHeight > 0) {
219 // if 'auto', the initial-scale will be negative here and thus ignor ed.
220 result.initialScale = max<float>(result.initialScale, initialViewpor tSize.height() / resultHeight);
221 }
222 }
223
224 // Constrain initial-scale value to minimum-scale/maximum-scale range.
225 result.initialScale = min(result.maximumScale, max(result.minimumScale, resu lt.initialScale));
226
227 // Resolve width value.
228 if (resultWidth == ViewportArguments::ValueAuto) {
229 if (resultZoom == ViewportArguments::ValueAuto)
230 resultWidth = defaultWidth;
231 else if (resultHeight != ViewportArguments::ValueAuto)
232 resultWidth = resultHeight * (initialViewportSize.width() / initialV iewportSize.height());
233 else
234 resultWidth = initialViewportSize.width() / result.initialScale;
235 }
236
237 // Resolve height value.
238 if (resultHeight == ViewportArguments::ValueAuto)
239 resultHeight = resultWidth * (initialViewportSize.height() / initialView portSize.width());
240
241 if (type == ViewportArguments::ViewportMeta) {
242 // Extend width and height to fill the visual viewport for the resolved initial-scale.
243 resultWidth = max<float>(resultWidth, initialViewportSize.width() / resu lt.initialScale);
244 resultHeight = max<float>(resultHeight, initialViewportSize.height() / r esult.initialScale);
245 }
246
247 result.layoutSize.setWidth(resultWidth); 133 result.layoutSize.setWidth(resultWidth);
248 result.layoutSize.setHeight(resultHeight); 134 result.layoutSize.setHeight(resultHeight);
249 135
250 // If user-scalable = no, lock the min/max scale to the computed initial
251 // scale.
252 if (!resultUserZoom)
253 result.maximumScale = result.minimumScale = result.initialScale;
254
255 // Only set initialScale to a value if it was explicitly set.
256 if (resultZoom == ViewportArguments::ValueAuto)
257 result.initialScale = ViewportArguments::ValueAuto;
258
259 return result; 136 return result;
260 } 137 }
261 138
262 static float numericPrefix(const String& keyString, const String& valueString, D ocument* document, bool* ok = 0)
263 {
264 size_t parsedLength;
265 float value;
266 if (valueString.is8Bit())
267 value = charactersToFloat(valueString.characters8(), valueString.length( ), parsedLength);
268 else
269 value = charactersToFloat(valueString.characters16(), valueString.length (), parsedLength);
270 if (!parsedLength) {
271 reportViewportWarning(document, UnrecognizedViewportArgumentValueError, valueString, keyString);
272 if (ok)
273 *ok = false;
274 return 0;
275 }
276 if (parsedLength < valueString.length())
277 reportViewportWarning(document, TruncatedViewportArgumentValueError, val ueString, keyString);
278 if (ok)
279 *ok = true;
280 return value;
281 }
282
283 static float findSizeValue(const String& keyString, const String& valueString, D ocument* document)
284 {
285 // 1) Non-negative number values are translated to px lengths.
286 // 2) Negative number values are translated to auto.
287 // 3) device-width and device-height are used as keywords.
288 // 4) Other keywords and unknown values translate to 0.0.
289
290 if (equalIgnoringCase(valueString, "device-width"))
291 return ViewportArguments::ValueDeviceWidth;
292 if (equalIgnoringCase(valueString, "device-height"))
293 return ViewportArguments::ValueDeviceHeight;
294
295 float value = numericPrefix(keyString, valueString, document);
296
297 if (value < 0)
298 return ViewportArguments::ValueAuto;
299
300 return value;
301 }
302
303 static float findScaleValue(const String& keyString, const String& valueString, Document* document)
304 {
305 // 1) Non-negative number values are translated to <number> values.
306 // 2) Negative number values are translated to auto.
307 // 3) yes is translated to 1.0.
308 // 4) device-width and device-height are translated to 10.0.
309 // 5) no and unknown values are translated to 0.0
310
311 if (equalIgnoringCase(valueString, "yes"))
312 return 1;
313 if (equalIgnoringCase(valueString, "no"))
314 return 0;
315 if (equalIgnoringCase(valueString, "device-width"))
316 return 10;
317 if (equalIgnoringCase(valueString, "device-height"))
318 return 10;
319
320 float value = numericPrefix(keyString, valueString, document);
321
322 if (value < 0)
323 return ViewportArguments::ValueAuto;
324
325 if (value > 10.0)
326 reportViewportWarning(document, MaximumScaleTooLargeError, String(), Str ing());
327
328 return value;
329 }
330
331 static float findUserScalableValue(const String& keyString, const String& valueS tring, Document* document)
332 {
333 // yes and no are used as keywords.
334 // Numbers >= 1, numbers <= -1, device-width and device-height are mapped to yes.
335 // Numbers in the range <-1, 1>, and unknown values, are mapped to no.
336
337 if (equalIgnoringCase(valueString, "yes"))
338 return 1;
339 if (equalIgnoringCase(valueString, "no"))
340 return 0;
341 if (equalIgnoringCase(valueString, "device-width"))
342 return 1;
343 if (equalIgnoringCase(valueString, "device-height"))
344 return 1;
345
346 float value = numericPrefix(keyString, valueString, document);
347
348 if (fabs(value) < 1)
349 return 0;
350
351 return 1;
352 }
353
354 static float findTargetDensityDPIValue(const String& keyString, const String& va lueString, Document* document)
355 {
356 if (equalIgnoringCase(valueString, "device-dpi"))
357 return ViewportArguments::ValueDeviceDPI;
358 if (equalIgnoringCase(valueString, "low-dpi"))
359 return ViewportArguments::ValueLowDPI;
360 if (equalIgnoringCase(valueString, "medium-dpi"))
361 return ViewportArguments::ValueMediumDPI;
362 if (equalIgnoringCase(valueString, "high-dpi"))
363 return ViewportArguments::ValueHighDPI;
364
365 bool ok;
366 float value = numericPrefix(keyString, valueString, document, &ok);
367 if (!ok || value < 70 || value > 400)
368 return ViewportArguments::ValueAuto;
369
370 return value;
371 }
372
373 void setViewportFeature(const String& keyString, const String& valueString, Docu ment* document, void* data)
374 {
375 ViewportArguments* arguments = static_cast<ViewportArguments*>(data);
376
377 if (keyString == "width")
378 arguments->width = findSizeValue(keyString, valueString, document);
379 else if (keyString == "height")
380 arguments->height = findSizeValue(keyString, valueString, document);
381 else if (keyString == "initial-scale")
382 arguments->zoom = findScaleValue(keyString, valueString, document);
383 else if (keyString == "minimum-scale")
384 arguments->minZoom = findScaleValue(keyString, valueString, document);
385 else if (keyString == "maximum-scale")
386 arguments->maxZoom = findScaleValue(keyString, valueString, document);
387 else if (keyString == "user-scalable")
388 arguments->userZoom = findUserScalableValue(keyString, valueString, docu ment);
389 else if (keyString == "target-densitydpi") {
390 arguments->deprecatedTargetDensityDPI = findTargetDensityDPIValue(keyStr ing, valueString, document);
391 reportViewportWarning(document, TargetDensityDpiUnsupported, String(), S tring());
392 } else
393 reportViewportWarning(document, UnrecognizedViewportArgumentKeyError, ke yString, String());
394 }
395
396 static const char* viewportErrorMessageTemplate(ViewportErrorCode errorCode)
397 {
398 static const char* const errors[] = {
399 "Viewport argument key \"%replacement1\" not recognized and ignored.",
400 "Viewport argument value \"%replacement1\" for key \"%replacement2\" is invalid, and has been ignored.",
401 "Viewport argument value \"%replacement1\" for key \"%replacement2\" was truncated to its numeric prefix.",
402 "Viewport maximum-scale cannot be larger than 10.0. The maximum-scale wi ll be set to 10.0.",
403 "Viewport target-densitydpi is not supported.",
404 };
405
406 return errors[errorCode];
407 }
408
409 static MessageLevel viewportErrorMessageLevel(ViewportErrorCode errorCode)
410 {
411 switch (errorCode) {
412 case TruncatedViewportArgumentValueError:
413 case TargetDensityDpiUnsupported:
414 return WarningMessageLevel;
415 case UnrecognizedViewportArgumentKeyError:
416 case UnrecognizedViewportArgumentValueError:
417 case MaximumScaleTooLargeError:
418 return ErrorMessageLevel;
419 }
420
421 ASSERT_NOT_REACHED();
422 return ErrorMessageLevel;
423 }
424
425 void reportViewportWarning(Document* document, ViewportErrorCode errorCode, cons t String& replacement1, const String& replacement2)
426 {
427 Frame* frame = document->frame();
428 if (!frame)
429 return;
430
431 String message = viewportErrorMessageTemplate(errorCode);
432 if (!replacement1.isNull())
433 message.replace("%replacement1", replacement1);
434 if (!replacement2.isNull())
435 message.replace("%replacement2", replacement2);
436
437 if ((errorCode == UnrecognizedViewportArgumentValueError || errorCode == Tru ncatedViewportArgumentValueError) && replacement1.find(';') != WTF::notFound)
438 message.append(" Note that ';' is not a separator in viewport values. Th e list should be comma-separated.");
439
440 // FIXME: This message should be moved off the console once a solution to ht tps://bugs.webkit.org/show_bug.cgi?id=103274 exists.
441 document->addConsoleMessage(RenderingMessageSource, viewportErrorMessageLeve l(errorCode), message);
442 }
443
444 } // namespace WebCore 139 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698