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

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, 5 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 Intel Corporation. All rights reserved. 9 * Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
10 * 10 *
11 * This library is free software; you can redistribute it and/or 11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public 12 * modify it under the terms of the GNU Library General Public
13 * License as published by the Free Software Foundation; either 13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version. 14 * version 2 of the License, or (at your option) any later version.
15 * 15 *
16 * This library is distributed in the hope that it will be useful, 16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Library General Public License for more details. 19 * Library General Public License for more details.
(...skipping 10 matching lines...) Expand all
30 30
31 #include "core/dom/Document.h" 31 #include "core/dom/Document.h"
32 #include "wtf/text/WTFString.h" 32 #include "wtf/text/WTFString.h"
33 33
34 using namespace std; 34 using namespace std;
35 35
36 namespace WebCore { 36 namespace WebCore {
37 37
38 static const float& compareIgnoringAuto(const float& value1, const float& value2 , const float& (*compare) (const float&, const float&)) 38 static const float& compareIgnoringAuto(const float& value1, const float& value2 , const float& (*compare) (const float&, const float&))
39 { 39 {
40 ASSERT(value1 != ViewportArguments::ValueAuto || value2 != ViewportArguments ::ValueAuto);
41
42 if (value1 == ViewportArguments::ValueAuto) 40 if (value1 == ViewportArguments::ValueAuto)
43 return value2; 41 return value2;
44 42
45 if (value2 == ViewportArguments::ValueAuto) 43 if (value2 == ViewportArguments::ValueAuto)
46 return value1; 44 return value1;
47 45
48 return compare(value1, value2); 46 return compare(value1, value2);
49 } 47 }
50 48
51 static inline float clampLengthValue(float value) 49 PageScaleConstraints ViewportArguments::resolve(const FloatSize& initialViewport Size) const
52 { 50 {
53 ASSERT(value != ViewportArguments::ValueDeviceWidth); 51 float resultWidth = ViewportArguments::ValueAuto;
54 ASSERT(value != ViewportArguments::ValueDeviceHeight);
55
56 // Limits as defined in the css-device-adapt spec.
57 if (value != ViewportArguments::ValueAuto)
58 return min(float(10000), max(value, float(1)));
59 return value;
60 }
61
62 static inline float clampScaleValue(float value)
63 {
64 ASSERT(value != ViewportArguments::ValueDeviceWidth);
65 ASSERT(value != ViewportArguments::ValueDeviceHeight);
66
67 // Limits as defined in the css-device-adapt spec.
68 if (value != ViewportArguments::ValueAuto)
69 return min(float(10), max(value, float(0.1)));
70 return value;
71 }
72
73 PageScaleConstraints ViewportArguments::resolve(const FloatSize& initialViewport Size, const FloatSize& deviceSize, int defaultWidth) const
74 {
75 float resultWidth = width;
76 float resultMaxWidth = maxWidth; 52 float resultMaxWidth = maxWidth;
77 float resultMinWidth = minWidth; 53 float resultMinWidth = minWidth;
78 float resultHeight = height; 54
55 float resultHeight = ViewportArguments::ValueAuto;
79 float resultMinHeight = minHeight; 56 float resultMinHeight = minHeight;
80 float resultMaxHeight = maxHeight; 57 float resultMaxHeight = maxHeight;
58
81 float resultZoom = zoom; 59 float resultZoom = zoom;
82 float resultMinZoom = minZoom; 60 float resultMinZoom = minZoom;
83 float resultMaxZoom = maxZoom; 61 float resultMaxZoom = maxZoom;
84 float resultUserZoom = userZoom; 62 float resultUserZoom = userZoom;
85 63
86 switch (int(resultWidth)) { 64 // 1. Resolve min-zoom and max-zoom values.
87 case ViewportArguments::ValueDeviceWidth: 65 if (resultMinZoom != ViewportArguments::ValueAuto && resultMaxZoom != Viewpo rtArguments::ValueAuto)
88 resultWidth = deviceSize.width(); 66 resultMaxZoom = max(resultMinZoom, resultMaxZoom);
89 break; 67
90 case ViewportArguments::ValueDeviceHeight: 68 // 2. Constrain zoom value to the [min-zoom, max-zoom] range.
91 resultWidth = deviceSize.height(); 69 if (resultZoom != ViewportArguments::ValueAuto)
92 break; 70 resultZoom = compareIgnoringAuto(resultMinZoom, compareIgnoringAuto(resu ltMaxZoom, resultZoom, min), max);
71
72 float extendZoom = compareIgnoringAuto(resultZoom, resultMaxZoom, min);
73
74 // 3. Resolve non-"auto" lengths to pixel lengths.
75 if (extendZoom == ViewportArguments::ValueAuto) {
76 if (resultMaxWidth == ViewportArguments::ValueExtendToZoom)
77 resultMaxWidth = ViewportArguments::ValueAuto;
78
79 if (resultMaxHeight == ViewportArguments::ValueExtendToZoom)
80 resultMaxHeight = ViewportArguments::ValueAuto;
81
82 if (resultMinWidth == ViewportArguments::ValueExtendToZoom)
83 resultMinWidth = resultMaxWidth;
84
85 if (resultMinHeight == ViewportArguments::ValueExtendToZoom)
86 resultMinHeight = resultMaxHeight;
87 } else {
88 float extendWidth = initialViewportSize.width() / extendZoom;
89 float extendHeight = initialViewportSize.height() / extendZoom;
90
91 if (resultMaxWidth == ViewportArguments::ValueExtendToZoom)
92 resultMaxWidth = extendWidth;
93
94 if (resultMaxHeight == ViewportArguments::ValueExtendToZoom)
95 resultMaxHeight = extendHeight;
96
97 if (resultMinWidth == ViewportArguments::ValueExtendToZoom)
98 resultMinWidth = compareIgnoringAuto(extendWidth, resultMaxWidth, ma x);
99
100 if (resultMinHeight == ViewportArguments::ValueExtendToZoom)
101 resultMinHeight = compareIgnoringAuto(extendHeight, resultMaxHeight, max);
93 } 102 }
94 103
95 switch (int(resultHeight)) { 104 // 4. Resolve initial width from min/max descriptors.
96 case ViewportArguments::ValueDeviceWidth: 105 if (resultMinWidth != ViewportArguments::ValueAuto || resultMaxWidth != View portArguments::ValueAuto)
97 resultHeight = deviceSize.width(); 106 resultWidth = compareIgnoringAuto(resultMinWidth, compareIgnoringAuto(re sultMaxWidth, initialViewportSize.width(), min), max);
98 break; 107
99 case ViewportArguments::ValueDeviceHeight: 108
100 resultHeight = deviceSize.height(); 109 // 5. Resolve initial height from min/max descriptors.
101 break; 110 if (resultMinHeight != ViewportArguments::ValueAuto || resultMaxHeight != Vi ewportArguments::ValueAuto)
111 resultHeight = compareIgnoringAuto(resultMinHeight, compareIgnoringAuto( resultMaxHeight, initialViewportSize.height(), min), max);
112
113 // 6-7. Resolve width value.
114 if (resultWidth == ViewportArguments::ValueAuto) {
115 if (resultHeight == ViewportArguments::ValueAuto || !initialViewportSize .height())
116 resultWidth = initialViewportSize.width();
117 else
118 resultWidth = resultHeight * (initialViewportSize.width() / initialV iewportSize.height());
102 } 119 }
103 120
104 if (type == ViewportArguments::CSSDeviceAdaptation) { 121 // 8. Resolve height value.
105 122 if (resultHeight == ViewportArguments::ValueAuto) {
106 // device-width/device-height not supported for @viewport. 123 if (!initialViewportSize.width())
107 ASSERT(resultMinWidth != ViewportArguments::ValueDeviceWidth); 124 resultHeight = initialViewportSize.height();
108 ASSERT(resultMinWidth != ViewportArguments::ValueDeviceHeight); 125 else
109 ASSERT(resultMaxWidth != ViewportArguments::ValueDeviceWidth); 126 resultHeight = resultWidth * (initialViewportSize.height() / initial ViewportSize.width());
110 ASSERT(resultMaxWidth != ViewportArguments::ValueDeviceHeight);
111 ASSERT(resultMinHeight != ViewportArguments::ValueDeviceWidth);
112 ASSERT(resultMinHeight != ViewportArguments::ValueDeviceHeight);
113 ASSERT(resultMaxHeight != ViewportArguments::ValueDeviceWidth);
114 ASSERT(resultMaxHeight != ViewportArguments::ValueDeviceHeight);
115
116 if (resultMinWidth != ViewportArguments::ValueAuto || resultMaxWidth != ViewportArguments::ValueAuto)
117 resultWidth = compareIgnoringAuto(resultMinWidth, compareIgnoringAut o(resultMaxWidth, initialViewportSize.width(), min), max);
118
119 if (resultMinHeight != ViewportArguments::ValueAuto || resultMaxHeight ! = ViewportArguments::ValueAuto)
120 resultHeight = compareIgnoringAuto(resultMinHeight, compareIgnoringA uto(resultMaxHeight, initialViewportSize.height(), min), max);
121
122 if (resultMinZoom != ViewportArguments::ValueAuto && resultMaxZoom != Vi ewportArguments::ValueAuto)
123 resultMaxZoom = max(resultMinZoom, resultMaxZoom);
124
125 if (resultZoom != ViewportArguments::ValueAuto)
126 resultZoom = compareIgnoringAuto(resultMinZoom, compareIgnoringAuto( resultMaxZoom, resultZoom, min), max);
127
128 if (resultWidth == ViewportArguments::ValueAuto && (resultHeight == View portArguments::ValueAuto || !initialViewportSize.height()))
129 resultWidth = initialViewportSize.width();
130
131 if (resultWidth == ViewportArguments::ValueAuto) {
132 ASSERT(initialViewportSize.height()); // If height is 0, resultWidth should be resolved above.
133 resultWidth = resultHeight * initialViewportSize.width() / initialVi ewportSize.height();
134 }
135
136 if (resultHeight == ViewportArguments::ValueAuto) {
137 if (!initialViewportSize.width())
138 resultHeight = initialViewportSize.height();
139 else
140 resultHeight = resultWidth * initialViewportSize.height() / init ialViewportSize.width();
141 }
142 }
143
144 if (type != ViewportArguments::CSSDeviceAdaptation && type != ViewportArgume nts::Implicit) {
145 // Clamp values to a valid range, but not for @viewport since is
146 // not mandated by the specification.
147 resultWidth = clampLengthValue(resultWidth);
148 resultHeight = clampLengthValue(resultHeight);
149 resultZoom = clampScaleValue(resultZoom);
150 resultMinZoom = clampScaleValue(resultMinZoom);
151 resultMaxZoom = clampScaleValue(resultMaxZoom);
152 } 127 }
153 128
154 PageScaleConstraints result; 129 PageScaleConstraints result;
155 130
156 // Resolve minimum-scale and maximum-scale values according to spec. 131 result.minimumScale = resultMinZoom;
157 if (resultMinZoom == ViewportArguments::ValueAuto) 132 result.maximumScale = resultMaxZoom;
158 result.minimumScale = float(0.25);
159 else
160 result.minimumScale = resultMinZoom;
161
162 if (resultMaxZoom == ViewportArguments::ValueAuto) {
163 result.maximumScale = float(5.0);
164 result.minimumScale = min(float(5.0), result.minimumScale);
165 } else
166 result.maximumScale = resultMaxZoom;
167 result.maximumScale = max(result.minimumScale, result.maximumScale);
168
169 // Resolve initial-scale value.
170 result.initialScale = resultZoom; 133 result.initialScale = resultZoom;
171 if (resultZoom == ViewportArguments::ValueAuto) {
172 result.initialScale = initialViewportSize.width() / defaultWidth;
173 if (resultWidth != ViewportArguments::ValueAuto && resultWidth > 0)
174 result.initialScale = initialViewportSize.width() / resultWidth;
175 if (resultHeight != ViewportArguments::ValueAuto && resultHeight > 0) {
176 // if 'auto', the initial-scale will be negative here and thus ignor ed.
177 result.initialScale = max<float>(result.initialScale, initialViewpor tSize.height() / resultHeight);
178 }
179 }
180
181 // Constrain initial-scale value to minimum-scale/maximum-scale range.
182 result.initialScale = min(result.maximumScale, max(result.minimumScale, resu lt.initialScale));
183
184 // Resolve width value.
185 if (resultWidth == ViewportArguments::ValueAuto) {
186 if (resultZoom == ViewportArguments::ValueAuto)
187 resultWidth = defaultWidth;
188 else if (resultHeight != ViewportArguments::ValueAuto)
189 resultWidth = resultHeight * (initialViewportSize.width() / initialV iewportSize.height());
190 else
191 resultWidth = initialViewportSize.width() / result.initialScale;
192 }
193
194 // Resolve height value.
195 if (resultHeight == ViewportArguments::ValueAuto)
196 resultHeight = resultWidth * (initialViewportSize.height() / initialView portSize.width());
197
198 if (type == ViewportArguments::ViewportMeta) {
199 // Extend width and height to fill the visual viewport for the resolved initial-scale.
200 resultWidth = max<float>(resultWidth, initialViewportSize.width() / resu lt.initialScale);
201 resultHeight = max<float>(resultHeight, initialViewportSize.height() / r esult.initialScale);
202 }
203
204 result.layoutSize.setWidth(resultWidth); 134 result.layoutSize.setWidth(resultWidth);
205 result.layoutSize.setHeight(resultHeight); 135 result.layoutSize.setHeight(resultHeight);
206 136
207 // If user-scalable = no, lock the min/max scale to the computed initial
208 // scale.
209 if (!resultUserZoom)
210 result.maximumScale = result.minimumScale = result.initialScale;
211
212 // Only set initialScale to a value if it was explicitly set.
213 if (resultZoom == ViewportArguments::ValueAuto)
214 result.initialScale = ViewportArguments::ValueAuto;
215
216 return result; 137 return result;
217 } 138 }
218 139
219 static float numericPrefix(const String& keyString, const String& valueString, D ocument* document, bool* ok = 0)
220 {
221 size_t parsedLength;
222 float value;
223 if (valueString.is8Bit())
224 value = charactersToFloat(valueString.characters8(), valueString.length( ), parsedLength);
225 else
226 value = charactersToFloat(valueString.characters16(), valueString.length (), parsedLength);
227 if (!parsedLength) {
228 reportViewportWarning(document, UnrecognizedViewportArgumentValueError, valueString, keyString);
229 if (ok)
230 *ok = false;
231 return 0;
232 }
233 if (parsedLength < valueString.length())
234 reportViewportWarning(document, TruncatedViewportArgumentValueError, val ueString, keyString);
235 if (ok)
236 *ok = true;
237 return value;
238 }
239
240 static float findSizeValue(const String& keyString, const String& valueString, D ocument* document)
241 {
242 // 1) Non-negative number values are translated to px lengths.
243 // 2) Negative number values are translated to auto.
244 // 3) device-width and device-height are used as keywords.
245 // 4) Other keywords and unknown values translate to 0.0.
246
247 if (equalIgnoringCase(valueString, "device-width"))
248 return ViewportArguments::ValueDeviceWidth;
249 if (equalIgnoringCase(valueString, "device-height"))
250 return ViewportArguments::ValueDeviceHeight;
251
252 float value = numericPrefix(keyString, valueString, document);
253
254 if (value < 0)
255 return ViewportArguments::ValueAuto;
256
257 return value;
258 }
259
260 static float findScaleValue(const String& keyString, const String& valueString, Document* document)
261 {
262 // 1) Non-negative number values are translated to <number> values.
263 // 2) Negative number values are translated to auto.
264 // 3) yes is translated to 1.0.
265 // 4) device-width and device-height are translated to 10.0.
266 // 5) no and unknown values are translated to 0.0
267
268 if (equalIgnoringCase(valueString, "yes"))
269 return 1;
270 if (equalIgnoringCase(valueString, "no"))
271 return 0;
272 if (equalIgnoringCase(valueString, "device-width"))
273 return 10;
274 if (equalIgnoringCase(valueString, "device-height"))
275 return 10;
276
277 float value = numericPrefix(keyString, valueString, document);
278
279 if (value < 0)
280 return ViewportArguments::ValueAuto;
281
282 if (value > 10.0)
283 reportViewportWarning(document, MaximumScaleTooLargeError, String(), Str ing());
284
285 return value;
286 }
287
288 static float findUserScalableValue(const String& keyString, const String& valueS tring, Document* document)
289 {
290 // yes and no are used as keywords.
291 // Numbers >= 1, numbers <= -1, device-width and device-height are mapped to yes.
292 // Numbers in the range <-1, 1>, and unknown values, are mapped to no.
293
294 if (equalIgnoringCase(valueString, "yes"))
295 return 1;
296 if (equalIgnoringCase(valueString, "no"))
297 return 0;
298 if (equalIgnoringCase(valueString, "device-width"))
299 return 1;
300 if (equalIgnoringCase(valueString, "device-height"))
301 return 1;
302
303 float value = numericPrefix(keyString, valueString, document);
304
305 if (fabs(value) < 1)
306 return 0;
307
308 return 1;
309 }
310
311 static float findTargetDensityDPIValue(const String& keyString, const String& va lueString, Document* document)
312 {
313 if (equalIgnoringCase(valueString, "device-dpi"))
314 return ViewportArguments::ValueDeviceDPI;
315 if (equalIgnoringCase(valueString, "low-dpi"))
316 return ViewportArguments::ValueLowDPI;
317 if (equalIgnoringCase(valueString, "medium-dpi"))
318 return ViewportArguments::ValueMediumDPI;
319 if (equalIgnoringCase(valueString, "high-dpi"))
320 return ViewportArguments::ValueHighDPI;
321
322 bool ok;
323 float value = numericPrefix(keyString, valueString, document, &ok);
324 if (!ok || value < 70 || value > 400)
325 return ViewportArguments::ValueAuto;
326
327 return value;
328 }
329
330 void setViewportFeature(const String& keyString, const String& valueString, Docu ment* document, void* data)
331 {
332 ViewportArguments* arguments = static_cast<ViewportArguments*>(data);
333
334 if (keyString == "width")
335 arguments->width = findSizeValue(keyString, valueString, document);
336 else if (keyString == "height")
337 arguments->height = findSizeValue(keyString, valueString, document);
338 else if (keyString == "initial-scale")
339 arguments->zoom = findScaleValue(keyString, valueString, document);
340 else if (keyString == "minimum-scale")
341 arguments->minZoom = findScaleValue(keyString, valueString, document);
342 else if (keyString == "maximum-scale")
343 arguments->maxZoom = findScaleValue(keyString, valueString, document);
344 else if (keyString == "user-scalable")
345 arguments->userZoom = findUserScalableValue(keyString, valueString, docu ment);
346 else if (keyString == "target-densitydpi") {
347 arguments->deprecatedTargetDensityDPI = findTargetDensityDPIValue(keyStr ing, valueString, document);
348 reportViewportWarning(document, TargetDensityDpiUnsupported, String(), S tring());
349 } else
350 reportViewportWarning(document, UnrecognizedViewportArgumentKeyError, ke yString, String());
351 }
352
353 static const char* viewportErrorMessageTemplate(ViewportErrorCode errorCode)
354 {
355 static const char* const errors[] = {
356 "Viewport argument key \"%replacement1\" not recognized and ignored.",
357 "Viewport argument value \"%replacement1\" for key \"%replacement2\" is invalid, and has been ignored.",
358 "Viewport argument value \"%replacement1\" for key \"%replacement2\" was truncated to its numeric prefix.",
359 "Viewport maximum-scale cannot be larger than 10.0. The maximum-scale wi ll be set to 10.0.",
360 "Viewport target-densitydpi is not supported.",
361 };
362
363 return errors[errorCode];
364 }
365
366 static MessageLevel viewportErrorMessageLevel(ViewportErrorCode errorCode)
367 {
368 switch (errorCode) {
369 case TruncatedViewportArgumentValueError:
370 case TargetDensityDpiUnsupported:
371 return WarningMessageLevel;
372 case UnrecognizedViewportArgumentKeyError:
373 case UnrecognizedViewportArgumentValueError:
374 case MaximumScaleTooLargeError:
375 return ErrorMessageLevel;
376 }
377
378 ASSERT_NOT_REACHED();
379 return ErrorMessageLevel;
380 }
381
382 void reportViewportWarning(Document* document, ViewportErrorCode errorCode, cons t String& replacement1, const String& replacement2)
383 {
384 Frame* frame = document->frame();
385 if (!frame)
386 return;
387
388 String message = viewportErrorMessageTemplate(errorCode);
389 if (!replacement1.isNull())
390 message.replace("%replacement1", replacement1);
391 if (!replacement2.isNull())
392 message.replace("%replacement2", replacement2);
393
394 if ((errorCode == UnrecognizedViewportArgumentValueError || errorCode == Tru ncatedViewportArgumentValueError) && replacement1.find(';') != WTF::notFound)
395 message.append(" Note that ';' is not a separator in viewport values. Th e list should be comma-separated.");
396
397 // FIXME: This message should be moved off the console once a solution to ht tps://bugs.webkit.org/show_bug.cgi?id=103274 exists.
398 document->addConsoleMessage(RenderingMessageSource, viewportErrorMessageLeve l(errorCode), message);
399 }
400
401 } // namespace WebCore 140 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698