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