1 /*
2 * CSS Media Query Evaluator
3 *
4 * Copyright (C) 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include "config.h"
29 #include "MediaQueryEvaluator.h"
30
31 #include "Chrome.h"
32 #include "CSSPrimitiveValue.h"
33 #include "CSSStyleSelector.h"
34 #include "CSSValueList.h"
35 #include "FloatRect.h"
36 #include "Frame.h"
37 #include "FrameView.h"
38 #include "IntRect.h"
39 #include "MediaFeatureNames.h"
40 #include "MediaList.h"
41 #include "MediaQuery.h"
42 #include "MediaQueryExp.h"
43 #include "NodeRenderStyle.h"
44 #include "Page.h"
45 #include "RenderView.h"
46 #include "RenderStyle.h"
47 #include "PlatformScreen.h"
48 #include <wtf/HashMap.h>
49
50 #if ENABLE(3D_RENDERING)
51 #include "RenderLayerCompositor.h"
52 #endif
53
54 namespace WebCore {
55
56 using namespace MediaFeatureNames;
57
58 enum MediaFeaturePrefix { MinPrefix, MaxPrefix, NoPrefix };
59
60 typedef bool (*EvalFunc)(CSSValue*, RenderStyle*, Frame*, MediaFeaturePrefix);
61 typedef HashMap<AtomicStringImpl*, EvalFunc> FunctionMap;
62 static FunctionMap* gFunctionMap;
63
64 /*
65 * FIXME: following media features are not implemented: color_index, scan, resolution
66 *
67 * color_index, min-color-index, max_color_index: It's unknown how to retrieve
68 * the information if the display mode is indexed
69 * scan: The "scan" media feature describes the scanning process of
70 * tv output devices. It's unknown how to retrieve this information from
71 * the platform
72 * resolution, min-resolution, max-resolution: css parser doesn't seem to
73 * support CSS_DIMENSION
74 */
75
MediaQueryEvaluator(bool mediaFeatureResult)76 MediaQueryEvaluator::MediaQueryEvaluator(bool mediaFeatureResult)
77 : m_frame(0)
78 , m_style(0)
79 , m_expResult(mediaFeatureResult)
80 {
81 }
82
MediaQueryEvaluator(const String & acceptedMediaType,bool mediaFeatureResult)83 MediaQueryEvaluator:: MediaQueryEvaluator(const String& acceptedMediaType, bool mediaFeatureResult)
84 : m_mediaType(acceptedMediaType)
85 , m_frame(0)
86 , m_style(0)
87 , m_expResult(mediaFeatureResult)
88 {
89 }
90
MediaQueryEvaluator(const char * acceptedMediaType,bool mediaFeatureResult)91 MediaQueryEvaluator:: MediaQueryEvaluator(const char* acceptedMediaType, bool mediaFeatureResult)
92 : m_mediaType(acceptedMediaType)
93 , m_frame(0)
94 , m_style(0)
95 , m_expResult(mediaFeatureResult)
96 {
97 }
98
MediaQueryEvaluator(const String & acceptedMediaType,Frame * frame,RenderStyle * style)99 MediaQueryEvaluator:: MediaQueryEvaluator(const String& acceptedMediaType, Frame* frame, RenderStyle* style)
100 : m_mediaType(acceptedMediaType)
101 , m_frame(frame)
102 , m_style(style)
103 , m_expResult(false) // doesn't matter when we have m_frame and m_style
104 {
105 }
106
~MediaQueryEvaluator()107 MediaQueryEvaluator::~MediaQueryEvaluator()
108 {
109 }
110
mediaTypeMatch(const String & mediaTypeToMatch) const111 bool MediaQueryEvaluator::mediaTypeMatch(const String& mediaTypeToMatch) const
112 {
113 return mediaTypeToMatch.isEmpty()
114 || equalIgnoringCase(mediaTypeToMatch, "all")
115 || equalIgnoringCase(mediaTypeToMatch, m_mediaType);
116 }
117
mediaTypeMatchSpecific(const char * mediaTypeToMatch) const118 bool MediaQueryEvaluator::mediaTypeMatchSpecific(const char* mediaTypeToMatch) const
119 {
120 // Like mediaTypeMatch, but without the special cases for "" and "all".
121 ASSERT(mediaTypeToMatch);
122 ASSERT(mediaTypeToMatch[0] != '\0');
123 ASSERT(!equalIgnoringCase(mediaTypeToMatch, String("all")));
124 return equalIgnoringCase(mediaTypeToMatch, m_mediaType);
125 }
126
applyRestrictor(MediaQuery::Restrictor r,bool value)127 static bool applyRestrictor(MediaQuery::Restrictor r, bool value)
128 {
129 return r == MediaQuery::Not ? !value : value;
130 }
131
eval(const MediaList * mediaList,CSSStyleSelector * styleSelector) const132 bool MediaQueryEvaluator::eval(const MediaList* mediaList, CSSStyleSelector* styleSelector) const
133 {
134 if (!mediaList)
135 return true;
136
137 const Vector<MediaQuery*>& queries = mediaList->mediaQueries();
138 if (!queries.size())
139 return true; // empty query list evaluates to true
140
141 // iterate over queries, stop if any of them eval to true (OR semantics)
142 bool result = false;
143 for (size_t i = 0; i < queries.size() && !result; ++i) {
144 MediaQuery* query = queries.at(i);
145
146 if (mediaTypeMatch(query->mediaType())) {
147 const Vector<MediaQueryExp*>* exps = query->expressions();
148 // iterate through expressions, stop if any of them eval to false
149 // (AND semantics)
150 size_t j = 0;
151 for (; j < exps->size(); ++j) {
152 bool exprResult = eval(exps->at(j));
153 if (styleSelector && exps->at(j)->isViewportDependent())
154 styleSelector->addViewportDependentMediaQueryResult(exps->at(j), exprResult);
155 if (!exprResult)
156 break;
157 }
158
159 // assume true if we are at the end of the list,
160 // otherwise assume false
161 result = applyRestrictor(query->restrictor(), exps->size() == j);
162 } else
163 result = applyRestrictor(query->restrictor(), false);
164 }
165
166 return result;
167 }
168
parseAspectRatio(CSSValue * value,int & h,int & v)169 static bool parseAspectRatio(CSSValue* value, int& h, int& v)
170 {
171 if (value->isValueList()) {
172 CSSValueList* valueList = static_cast<CSSValueList*>(value);
173 if (valueList->length() == 3) {
174 CSSValue* i0 = valueList->itemWithoutBoundsCheck(0);
175 CSSValue* i1 = valueList->itemWithoutBoundsCheck(1);
176 CSSValue* i2 = valueList->itemWithoutBoundsCheck(2);
177 if (i0->isPrimitiveValue() && static_cast<CSSPrimitiveValue*>(i0)->primitiveType() == CSSPrimitiveValue::CSS_NUMBER
178 && i1->isPrimitiveValue() && static_cast<CSSPrimitiveValue*>(i1)->primitiveType() == CSSPrimitiveValue::CSS_STRING
179 && i2->isPrimitiveValue() && static_cast<CSSPrimitiveValue*>(i2)->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) {
180 String str = static_cast<CSSPrimitiveValue*>(i1)->getStringValue();
181 if (!str.isNull() && str.length() == 1 && str[0] == '/') {
182 h = static_cast<CSSPrimitiveValue*>(i0)->getIntValue(CSSPrimitiveValue::CSS_NUMBER);
183 v = static_cast<CSSPrimitiveValue*>(i2)->getIntValue(CSSPrimitiveValue::CSS_NUMBER);
184 return true;
185 }
186 }
187 }
188 }
189 return false;
190 }
191
192 template<typename T>
compareValue(T a,T b,MediaFeaturePrefix op)193 bool compareValue(T a, T b, MediaFeaturePrefix op)
194 {
195 switch (op) {
196 case MinPrefix:
197 return a >= b;
198 case MaxPrefix:
199 return a <= b;
200 case NoPrefix:
201 return a == b;
202 }
203 return false;
204 }
205
numberValue(CSSValue * value,float & result)206 static bool numberValue(CSSValue* value, float& result)
207 {
208 if (value->isPrimitiveValue()
209 && static_cast<CSSPrimitiveValue*>(value)->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) {
210 result = static_cast<CSSPrimitiveValue*>(value)->getFloatValue(CSSPrimitiveValue::CSS_NUMBER);
211 return true;
212 }
213 return false;
214 }
215
colorMediaFeatureEval(CSSValue * value,RenderStyle *,Frame * frame,MediaFeaturePrefix op)216 static bool colorMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
217 {
218 int bitsPerComponent = screenDepthPerComponent(frame->page()->mainFrame()->view());
219 float number;
220 if (value)
221 return numberValue(value, number) && compareValue(bitsPerComponent, static_cast<int>(number), op);
222
223 return bitsPerComponent != 0;
224 }
225
monochromeMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix op)226 static bool monochromeMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op)
227 {
228 if (!screenIsMonochrome(frame->page()->mainFrame()->view())) {
229 if (value) {
230 float number;
231 return numberValue(value, number) && compareValue(0, static_cast<int>(number), op);
232 }
233 return false;
234 }
235
236 return colorMediaFeatureEval(value, style, frame, op);
237 }
238
orientationMediaFeatureEval(CSSValue * value,RenderStyle *,Frame * frame,MediaFeaturePrefix)239 static bool orientationMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix)
240 {
241 // A missing parameter should fail
242 if (!value)
243 return false;
244
245 FrameView* view = frame->view();
246 int width = view->layoutWidth();
247 int height = view->layoutHeight();
248 if (width > height) // Square viewport is portrait
249 return "landscape" == static_cast<CSSPrimitiveValue*>(value)->getStringValue();
250 return "portrait" == static_cast<CSSPrimitiveValue*>(value)->getStringValue();
251 }
252
aspect_ratioMediaFeatureEval(CSSValue * value,RenderStyle *,Frame * frame,MediaFeaturePrefix op)253 static bool aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
254 {
255 if (value) {
256 FrameView* view = frame->view();
257 int width = view->layoutWidth();
258 int height = view->layoutHeight();
259 int h = 0;
260 int v = 0;
261 if (parseAspectRatio(value, h, v))
262 return v != 0 && compareValue(width * v, height * h, op);
263 return false;
264 }
265
266 // ({,min-,max-}aspect-ratio)
267 // assume if we have a device, its aspect ratio is non-zero
268 return true;
269 }
270
device_aspect_ratioMediaFeatureEval(CSSValue * value,RenderStyle *,Frame * frame,MediaFeaturePrefix op)271 static bool device_aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
272 {
273 if (value) {
274 FloatRect sg = screenRect(frame->page()->mainFrame()->view());
275 int h = 0;
276 int v = 0;
277 if (parseAspectRatio(value, h, v))
278 return v != 0 && compareValue(static_cast<int>(sg.width()) * v, static_cast<int>(sg.height()) * h, op);
279 return false;
280 }
281
282 // ({,min-,max-}device-aspect-ratio)
283 // assume if we have a device, its aspect ratio is non-zero
284 return true;
285 }
286
device_pixel_ratioMediaFeatureEval(CSSValue * value,RenderStyle *,Frame * frame,MediaFeaturePrefix op)287 static bool device_pixel_ratioMediaFeatureEval(CSSValue *value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
288 {
289 if (value)
290 return value->isPrimitiveValue() && compareValue(frame->page()->chrome()->scaleFactor(), static_cast<CSSPrimitiveValue*>(value)->getFloatValue(), op);
291
292 return frame->page()->chrome()->scaleFactor() != 0;
293 }
294
gridMediaFeatureEval(CSSValue * value,RenderStyle *,Frame *,MediaFeaturePrefix op)295 static bool gridMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, MediaFeaturePrefix op)
296 {
297 // if output device is bitmap, grid: 0 == true
298 // assume we have bitmap device
299 float number;
300 if (value && numberValue(value, number))
301 return compareValue(static_cast<int>(number), 0, op);
302 return false;
303 }
304
device_heightMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix op)305 static bool device_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op)
306 {
307 if (value) {
308 FloatRect sg = screenRect(frame->page()->mainFrame()->view());
309 RenderStyle* rootStyle = frame->document()->documentElement()->renderStyle();
310 return value->isPrimitiveValue() && compareValue(static_cast<int>(sg.height()), static_cast<CSSPrimitiveValue*>(value)->computeLengthInt(style, rootStyle), op);
311 }
312 // ({,min-,max-}device-height)
313 // assume if we have a device, assume non-zero
314 return true;
315 }
316
device_widthMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix op)317 static bool device_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op)
318 {
319 if (value) {
320 FloatRect sg = screenRect(frame->page()->mainFrame()->view());
321 RenderStyle* rootStyle = frame->document()->documentElement()->renderStyle();
322 return value->isPrimitiveValue() && compareValue(static_cast<int>(sg.width()), static_cast<CSSPrimitiveValue*>(value)->computeLengthInt(style, rootStyle), op);
323 }
324 // ({,min-,max-}device-width)
325 // assume if we have a device, assume non-zero
326 return true;
327 }
328
heightMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix op)329 static bool heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op)
330 {
331 FrameView* view = frame->view();
332 RenderStyle* rootStyle = frame->document()->documentElement()->renderStyle();
333
334 if (value)
335 return value->isPrimitiveValue() && compareValue(view->layoutHeight(), static_cast<CSSPrimitiveValue*>(value)->computeLengthInt(style, rootStyle), op);
336
337 return view->layoutHeight() != 0;
338 }
339
widthMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix op)340 static bool widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op)
341 {
342 FrameView* view = frame->view();
343 RenderStyle* rootStyle = frame->document()->documentElement()->renderStyle();
344
345 if (value)
346 return value->isPrimitiveValue() && compareValue(view->layoutWidth(), static_cast<CSSPrimitiveValue*>(value)->computeLengthInt(style, rootStyle), op);
347
348 return view->layoutWidth() != 0;
349 }
350
351 // rest of the functions are trampolines which set the prefix according to the media feature expression used
352
min_colorMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix)353 static bool min_colorMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
354 {
355 return colorMediaFeatureEval(value, style, frame, MinPrefix);
356 }
357
max_colorMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix)358 static bool max_colorMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
359 {
360 return colorMediaFeatureEval(value, style, frame, MaxPrefix);
361 }
362
min_monochromeMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix)363 static bool min_monochromeMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
364 {
365 return monochromeMediaFeatureEval(value, style, frame, MinPrefix);
366 }
367
max_monochromeMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix)368 static bool max_monochromeMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
369 {
370 return monochromeMediaFeatureEval(value, style, frame, MaxPrefix);
371 }
372
min_aspect_ratioMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix)373 static bool min_aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
374 {
375 return aspect_ratioMediaFeatureEval(value, style, frame, MinPrefix);
376 }
377
max_aspect_ratioMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix)378 static bool max_aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
379 {
380 return aspect_ratioMediaFeatureEval(value, style, frame, MaxPrefix);
381 }
382
min_device_aspect_ratioMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix)383 static bool min_device_aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
384 {
385 return device_aspect_ratioMediaFeatureEval(value, style, frame, MinPrefix);
386 }
387
max_device_aspect_ratioMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix)388 static bool max_device_aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
389 {
390 return device_aspect_ratioMediaFeatureEval(value, style, frame, MaxPrefix);
391 }
392
min_device_pixel_ratioMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix)393 static bool min_device_pixel_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
394 {
395 return device_pixel_ratioMediaFeatureEval(value, style, frame, MinPrefix);
396 }
397
max_device_pixel_ratioMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix)398 static bool max_device_pixel_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
399 {
400 return device_pixel_ratioMediaFeatureEval(value, style, frame, MaxPrefix);
401 }
402
min_heightMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix)403 static bool min_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
404 {
405 return heightMediaFeatureEval(value, style, frame, MinPrefix);
406 }
407
max_heightMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix)408 static bool max_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
409 {
410 return heightMediaFeatureEval(value, style, frame, MaxPrefix);
411 }
412
min_widthMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix)413 static bool min_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
414 {
415 return widthMediaFeatureEval(value, style, frame, MinPrefix);
416 }
417
max_widthMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix)418 static bool max_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
419 {
420 return widthMediaFeatureEval(value, style, frame, MaxPrefix);
421 }
422
min_device_heightMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix)423 static bool min_device_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
424 {
425 return device_heightMediaFeatureEval(value, style, frame, MinPrefix);
426 }
427
max_device_heightMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix)428 static bool max_device_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
429 {
430 return device_heightMediaFeatureEval(value, style, frame, MaxPrefix);
431 }
432
min_device_widthMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix)433 static bool min_device_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
434 {
435 return device_widthMediaFeatureEval(value, style, frame, MinPrefix);
436 }
437
max_device_widthMediaFeatureEval(CSSValue * value,RenderStyle * style,Frame * frame,MediaFeaturePrefix)438 static bool max_device_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
439 {
440 return device_widthMediaFeatureEval(value, style, frame, MaxPrefix);
441 }
442
animationMediaFeatureEval(CSSValue * value,RenderStyle *,Frame *,MediaFeaturePrefix op)443 static bool animationMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, MediaFeaturePrefix op)
444 {
445 if (value) {
446 float number;
447 return numberValue(value, number) && compareValue(1, static_cast<int>(number), op);
448 }
449 return true;
450 }
451
transitionMediaFeatureEval(CSSValue * value,RenderStyle *,Frame *,MediaFeaturePrefix op)452 static bool transitionMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, MediaFeaturePrefix op)
453 {
454 if (value) {
455 float number;
456 return numberValue(value, number) && compareValue(1, static_cast<int>(number), op);
457 }
458 return true;
459 }
460
transform_2dMediaFeatureEval(CSSValue * value,RenderStyle *,Frame *,MediaFeaturePrefix op)461 static bool transform_2dMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, MediaFeaturePrefix op)
462 {
463 if (value) {
464 float number;
465 return numberValue(value, number) && compareValue(1, static_cast<int>(number), op);
466 }
467 return true;
468 }
469
transform_3dMediaFeatureEval(CSSValue * value,RenderStyle *,Frame * frame,MediaFeaturePrefix op)470 static bool transform_3dMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
471 {
472 bool returnValueIfNoParameter;
473 int have3dRendering;
474
475 #if ENABLE(3D_RENDERING)
476 bool threeDEnabled = false;
477 if (RenderView* view = frame->contentRenderer())
478 threeDEnabled = view->compositor()->hasAcceleratedCompositing();
479
480 returnValueIfNoParameter = threeDEnabled;
481 have3dRendering = threeDEnabled ? 1 : 0;
482 #else
483 UNUSED_PARAM(frame);
484 returnValueIfNoParameter = false;
485 have3dRendering = 0;
486 #endif
487
488 if (value) {
489 float number;
490 return numberValue(value, number) && compareValue(have3dRendering, static_cast<int>(number), op);
491 }
492 return returnValueIfNoParameter;
493 }
494
createFunctionMap()495 static void createFunctionMap()
496 {
497 // Create the table.
498 gFunctionMap = new FunctionMap;
499 #define ADD_TO_FUNCTIONMAP(name, str) \
500 gFunctionMap->set(name##MediaFeature.impl(), name##MediaFeatureEval);
501 CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(ADD_TO_FUNCTIONMAP);
502 #undef ADD_TO_FUNCTIONMAP
503 }
504
eval(const MediaQueryExp * expr) const505 bool MediaQueryEvaluator::eval(const MediaQueryExp* expr) const
506 {
507 if (!m_frame || !m_style)
508 return m_expResult;
509
510 if (!gFunctionMap)
511 createFunctionMap();
512
513 // call the media feature evaluation function. Assume no prefix
514 // and let trampoline functions override the prefix if prefix is
515 // used
516 EvalFunc func = gFunctionMap->get(expr->mediaFeature().impl());
517 if (func)
518 return func(expr->value(), m_style, m_frame, NoPrefix);
519
520 return false;
521 }
522
523 } // namespace
524