• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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