2 * CSS Media Query Evaluator
4 * Copyright (C) 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>.
5 * Copyright (C) 2013 Apple Inc. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "MediaQueryEvaluator.h"
32 #include "CSSAspectRatioValue.h"
33 #include "CSSPrimitiveValue.h"
34 #include "CSSToLengthConversionData.h"
35 #include "CSSValueKeywords.h"
36 #include "CSSValueList.h"
37 #include "FloatRect.h"
38 #include "FrameView.h"
40 #include "MainFrame.h"
41 #include "MediaFeatureNames.h"
42 #include "MediaList.h"
43 #include "MediaQuery.h"
44 #include "MediaQueryExp.h"
45 #include "NodeRenderStyle.h"
47 #include "PlatformScreen.h"
48 #include "RenderStyle.h"
49 #include "RenderView.h"
52 #include "StyleResolver.h"
53 #include <wtf/HashMap.h>
55 #if ENABLE(3D_TRANSFORMS)
56 #include "RenderLayerCompositor.h"
61 using namespace MediaFeatureNames;
63 enum MediaFeaturePrefix { MinPrefix, MaxPrefix, NoPrefix };
65 typedef bool (*EvalFunc)(CSSValue*, const CSSToLengthConversionData&, Frame*, MediaFeaturePrefix);
66 typedef HashMap<AtomicStringImpl*, EvalFunc> FunctionMap;
67 static FunctionMap* gFunctionMap;
70 * FIXME: following media features are not implemented: scan
72 * scan: The "scan" media feature describes the scanning process of
73 * tv output devices. It's unknown how to retrieve this information from
77 MediaQueryEvaluator::MediaQueryEvaluator(bool mediaFeatureResult)
78 : m_expResult(mediaFeatureResult)
82 MediaQueryEvaluator::MediaQueryEvaluator(const String& acceptedMediaType, bool mediaFeatureResult)
83 : m_mediaType(acceptedMediaType)
84 , m_expResult(mediaFeatureResult)
88 MediaQueryEvaluator::MediaQueryEvaluator(const String& acceptedMediaType, Frame* frame, const RenderStyle* style)
89 : m_mediaType(acceptedMediaType)
92 , m_expResult(false) // doesn't matter when we have m_frame and m_style
96 MediaQueryEvaluator::~MediaQueryEvaluator()
100 bool MediaQueryEvaluator::mediaTypeMatch(const String& mediaTypeToMatch) const
102 return mediaTypeToMatch.isEmpty()
103 || equalLettersIgnoringASCIICase(mediaTypeToMatch, "all")
104 || equalIgnoringASCIICase(mediaTypeToMatch, m_mediaType);
107 bool MediaQueryEvaluator::mediaTypeMatchSpecific(const char* mediaTypeToMatch) const
109 // Like mediaTypeMatch, but without the special cases for "" and "all".
110 ASSERT(mediaTypeToMatch);
111 ASSERT(mediaTypeToMatch[0] != '\0');
112 ASSERT(!equalLettersIgnoringASCIICase(StringView(mediaTypeToMatch), "all"));
113 return equalIgnoringASCIICase(m_mediaType, mediaTypeToMatch);
116 static bool applyRestrictor(MediaQuery::Restrictor r, bool value)
118 return r == MediaQuery::Not ? !value : value;
121 bool MediaQueryEvaluator::eval(const MediaQuerySet* querySet, StyleResolver* styleResolver) const
126 auto& queries = querySet->queryVector();
128 return true; // empty query list evaluates to true
130 // iterate over queries, stop if any of them eval to true (OR semantics)
132 for (size_t i = 0; i < queries.size() && !result; ++i) {
133 MediaQuery* query = queries[i].get();
135 if (query->ignored() || (!query->expressions().size() && query->mediaType().isEmpty()))
138 if (mediaTypeMatch(query->mediaType())) {
139 auto& expressions = query->expressions();
140 // iterate through expressions, stop if any of them eval to false
143 for (; j < expressions.size(); ++j) {
144 bool exprResult = eval(expressions.at(j).get());
145 if (styleResolver && expressions.at(j)->isViewportDependent())
146 styleResolver->addViewportDependentMediaQueryResult(expressions.at(j).get(), exprResult);
151 // assume true if we are at the end of the list,
152 // otherwise assume false
153 result = applyRestrictor(query->restrictor(), expressions.size() == j);
155 result = applyRestrictor(query->restrictor(), false);
161 bool MediaQueryEvaluator::evalCheckingViewportDependentResults(const MediaQuerySet* querySet, Vector<std::unique_ptr<MediaQueryResult>>& results)
166 auto& queries = querySet->queryVector();
171 for (size_t i = 0; i < queries.size() && !result; ++i) {
172 MediaQuery* query = queries[i].get();
174 if (query->ignored())
177 if (mediaTypeMatch(query->mediaType())) {
178 auto& expressions = query->expressions();
180 for (; j < expressions.size(); ++j) {
181 bool exprResult = eval(expressions.at(j).get());
182 if (expressions.at(j)->isViewportDependent())
183 results.append(std::make_unique<MediaQueryResult>(*expressions.at(j), exprResult));
187 result = applyRestrictor(query->restrictor(), expressions.size() == j);
189 result = applyRestrictor(query->restrictor(), false);
196 bool compareValue(T a, T b, MediaFeaturePrefix op)
209 static bool compareAspectRatioValue(CSSValue* value, int width, int height, MediaFeaturePrefix op)
211 if (is<CSSAspectRatioValue>(*value)) {
212 CSSAspectRatioValue& aspectRatio = downcast<CSSAspectRatioValue>(*value);
213 return compareValue(width * static_cast<int>(aspectRatio.denominatorValue()), height * static_cast<int>(aspectRatio.numeratorValue()), op);
219 static bool numberValue(CSSValue* value, float& result)
221 if (is<CSSPrimitiveValue>(*value) && downcast<CSSPrimitiveValue>(*value).isNumber()) {
222 result = downcast<CSSPrimitiveValue>(*value).getFloatValue(CSSPrimitiveValue::CSS_NUMBER);
228 static bool colorMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData&, Frame* frame, MediaFeaturePrefix op)
230 int bitsPerComponent = screenDepthPerComponent(frame->page()->mainFrame().view());
233 return numberValue(value, number) && compareValue(bitsPerComponent, static_cast<int>(number), op);
235 return bitsPerComponent != 0;
238 static bool color_indexMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData&, Frame*, MediaFeaturePrefix op)
240 // FIXME: It's unknown how to retrieve the information if the display mode is indexed
241 // Assume we don't support indexed display.
246 return numberValue(value, number) && compareValue(0, static_cast<int>(number), op);
249 static bool color_gamutMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData&, Frame* frame, MediaFeaturePrefix)
254 switch (downcast<CSSPrimitiveValue>(*value).getValueID()) {
258 // FIXME: For the moment we'll just assume an "extended
259 // color" display is at least as good as P3.
260 return screenSupportsExtendedColor(frame->page()->mainFrame().view());
261 case CSSValueRec2020:
262 // FIXME: At some point we should start detecting displays that
263 // support more colors.
266 ASSERT_NOT_REACHED();
271 static bool monochromeMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix op)
273 if (!screenIsMonochrome(frame->page()->mainFrame().view())) {
276 return numberValue(value, number) && compareValue(0, static_cast<int>(number), op);
281 return colorMediaFeatureEval(value, conversionData, frame, op);
284 static bool inverted_colorsMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData&, Frame*, MediaFeaturePrefix)
286 bool isInverted = screenHasInvertedColors();
291 const CSSValueID id = downcast<CSSPrimitiveValue>(*value).getValueID();
292 return (isInverted && id == CSSValueInverted) || (!isInverted && id == CSSValueNone);
295 static bool orientationMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData&, Frame* frame, MediaFeaturePrefix)
297 FrameView* view = frame->view();
301 int width = view->layoutWidth();
302 int height = view->layoutHeight();
303 if (is<CSSPrimitiveValue>(value)) {
304 const CSSValueID id = downcast<CSSPrimitiveValue>(*value).getValueID();
305 if (width > height) // Square viewport is portrait.
306 return CSSValueLandscape == id;
307 return CSSValuePortrait == id;
310 // Expression (orientation) evaluates to true if width and height >= 0.
311 return height >= 0 && width >= 0;
314 static bool aspect_ratioMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData&, Frame* frame, MediaFeaturePrefix op)
316 FrameView* view = frame->view();
321 return compareAspectRatioValue(value, view->layoutWidth(), view->layoutHeight(), op);
323 // ({,min-,max-}aspect-ratio)
324 // assume if we have a device, its aspect ratio is non-zero
328 static bool device_aspect_ratioMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData&, Frame* frame, MediaFeaturePrefix op)
331 FloatRect sg = screenRect(frame->page()->mainFrame().view());
332 return compareAspectRatioValue(value, static_cast<int>(sg.width()), static_cast<int>(sg.height()), op);
335 // ({,min-,max-}device-aspect-ratio)
336 // assume if we have a device, its aspect ratio is non-zero
340 static bool evalResolution(CSSValue* value, Frame* frame, MediaFeaturePrefix op)
342 // FIXME: Possible handle other media types than 'screen' and 'print'.
343 FrameView* view = frame->view();
347 float deviceScaleFactor = 0;
348 // This checks the actual media type applied to the document, and we know
349 // this method only got called if this media type matches the one defined
350 // in the query. Thus, if if the document's media type is "print", the
351 // media type of the query will either be "print" or "all".
352 String mediaType = view->mediaType();
353 if (equalLettersIgnoringASCIICase(mediaType, "screen"))
354 deviceScaleFactor = frame->page()->deviceScaleFactor();
355 else if (equalLettersIgnoringASCIICase(mediaType, "print")) {
356 // The resolution of images while printing should not depend on the dpi
357 // of the screen. Until we support proper ways of querying this info
358 // we use 300px which is considered minimum for current printers.
359 deviceScaleFactor = 3.125; // 300dpi / 96dpi;
363 return !!deviceScaleFactor;
365 if (!is<CSSPrimitiveValue>(*value))
368 CSSPrimitiveValue& resolution = downcast<CSSPrimitiveValue>(*value);
369 return compareValue(deviceScaleFactor, resolution.isNumber() ? resolution.getFloatValue() : resolution.getFloatValue(CSSPrimitiveValue::CSS_DPPX), op);
372 static bool device_pixel_ratioMediaFeatureEval(CSSValue *value, const CSSToLengthConversionData&, Frame* frame, MediaFeaturePrefix op)
374 return (!value || downcast<CSSPrimitiveValue>(*value).isNumber()) && evalResolution(value, frame, op);
377 static bool resolutionMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData&, Frame* frame, MediaFeaturePrefix op)
379 #if ENABLE(RESOLUTION_MEDIA_QUERY)
380 return (!value || downcast<CSSPrimitiveValue>(*value).isResolution()) && evalResolution(value, frame, op);
389 static bool gridMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData&, Frame*, MediaFeaturePrefix op)
391 // if output device is bitmap, grid: 0 == true
392 // assume we have bitmap device
394 if (value && numberValue(value, number))
395 return compareValue(static_cast<int>(number), 0, op);
399 static bool computeLength(CSSValue* value, bool strict, const CSSToLengthConversionData& conversionData, int& result)
401 if (!is<CSSPrimitiveValue>(*value))
404 CSSPrimitiveValue& primitiveValue = downcast<CSSPrimitiveValue>(*value);
406 if (primitiveValue.isNumber()) {
407 result = primitiveValue.getIntValue();
408 return !strict || !result;
411 if (primitiveValue.isLength()) {
412 result = primitiveValue.computeLength<int>(conversionData);
419 static bool device_heightMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix op)
422 FloatRect sg = screenRect(frame->page()->mainFrame().view());
424 long height = sg.height();
425 return computeLength(value, !frame->document()->inQuirksMode(), conversionData, length) && compareValue(static_cast<int>(height), length, op);
427 // ({,min-,max-}device-height)
428 // assume if we have a device, assume non-zero
432 static bool device_widthMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix op)
435 FloatRect sg = screenRect(frame->page()->mainFrame().view());
437 long width = sg.width();
438 return computeLength(value, !frame->document()->inQuirksMode(), conversionData, length) && compareValue(static_cast<int>(width), length, op);
440 // ({,min-,max-}device-width)
441 // assume if we have a device, assume non-zero
445 static bool heightMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix op)
447 FrameView* view = frame->view();
452 int height = view->layoutHeight();
453 if (RenderView* renderView = frame->document()->renderView())
454 height = adjustForAbsoluteZoom(height, *renderView);
456 return computeLength(value, !frame->document()->inQuirksMode(), conversionData, length) && compareValue(height, length, op);
459 return view->layoutHeight() != 0;
462 static bool widthMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix op)
464 FrameView* view = frame->view();
469 int width = view->layoutWidth();
470 if (RenderView* renderView = frame->document()->renderView())
471 width = adjustForAbsoluteZoom(width, *renderView);
473 return computeLength(value, !frame->document()->inQuirksMode(), conversionData, length) && compareValue(width, length, op);
476 return view->layoutWidth() != 0;
479 // rest of the functions are trampolines which set the prefix according to the media feature expression used
481 static bool min_colorMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
483 return colorMediaFeatureEval(value, conversionData, frame, MinPrefix);
486 static bool max_colorMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
488 return colorMediaFeatureEval(value, conversionData, frame, MaxPrefix);
491 static bool min_color_indexMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
493 return color_indexMediaFeatureEval(value, conversionData, frame, MinPrefix);
496 static bool max_color_indexMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
498 return color_indexMediaFeatureEval(value, conversionData, frame, MaxPrefix);
501 static bool min_monochromeMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
503 return monochromeMediaFeatureEval(value, conversionData, frame, MinPrefix);
506 static bool max_monochromeMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
508 return monochromeMediaFeatureEval(value, conversionData, frame, MaxPrefix);
511 static bool min_aspect_ratioMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
513 return aspect_ratioMediaFeatureEval(value, conversionData, frame, MinPrefix);
516 static bool max_aspect_ratioMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
518 return aspect_ratioMediaFeatureEval(value, conversionData, frame, MaxPrefix);
521 static bool min_device_aspect_ratioMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
523 return device_aspect_ratioMediaFeatureEval(value, conversionData, frame, MinPrefix);
526 static bool max_device_aspect_ratioMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
528 return device_aspect_ratioMediaFeatureEval(value, conversionData, frame, MaxPrefix);
531 static bool min_device_pixel_ratioMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
533 return device_pixel_ratioMediaFeatureEval(value, conversionData, frame, MinPrefix);
536 static bool max_device_pixel_ratioMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
538 return device_pixel_ratioMediaFeatureEval(value, conversionData, frame, MaxPrefix);
541 static bool min_heightMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
543 return heightMediaFeatureEval(value, conversionData, frame, MinPrefix);
546 static bool max_heightMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
548 return heightMediaFeatureEval(value, conversionData, frame, MaxPrefix);
551 static bool min_widthMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
553 return widthMediaFeatureEval(value, conversionData, frame, MinPrefix);
556 static bool max_widthMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
558 return widthMediaFeatureEval(value, conversionData, frame, MaxPrefix);
561 static bool min_device_heightMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
563 return device_heightMediaFeatureEval(value, conversionData, frame, MinPrefix);
566 static bool max_device_heightMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
568 return device_heightMediaFeatureEval(value, conversionData, frame, MaxPrefix);
571 static bool min_device_widthMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
573 return device_widthMediaFeatureEval(value, conversionData, frame, MinPrefix);
576 static bool max_device_widthMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
578 return device_widthMediaFeatureEval(value, conversionData, frame, MaxPrefix);
581 static bool min_resolutionMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
583 return resolutionMediaFeatureEval(value, conversionData, frame, MinPrefix);
586 static bool max_resolutionMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame* frame, MediaFeaturePrefix)
588 return resolutionMediaFeatureEval(value, conversionData, frame, MaxPrefix);
591 static bool animationMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData&, Frame*, MediaFeaturePrefix op)
595 return numberValue(value, number) && compareValue(1, static_cast<int>(number), op);
600 static bool transitionMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData&, Frame*, MediaFeaturePrefix op)
604 return numberValue(value, number) && compareValue(1, static_cast<int>(number), op);
609 static bool transform_2dMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData&, Frame*, MediaFeaturePrefix op)
613 return numberValue(value, number) && compareValue(1, static_cast<int>(number), op);
618 static bool transform_3dMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData&, Frame* frame, MediaFeaturePrefix op)
620 bool returnValueIfNoParameter;
623 #if ENABLE(3D_TRANSFORMS)
624 bool threeDEnabled = false;
625 if (RenderView* view = frame->contentRenderer())
626 threeDEnabled = view->compositor().canRender3DTransforms();
628 returnValueIfNoParameter = threeDEnabled;
629 have3dRendering = threeDEnabled ? 1 : 0;
632 returnValueIfNoParameter = false;
638 return numberValue(value, number) && compareValue(have3dRendering, static_cast<int>(number), op);
640 return returnValueIfNoParameter;
643 #if ENABLE(VIEW_MODE_CSS_MEDIA)
644 static bool view_modeMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData&, Frame* frame, MediaFeaturePrefix op)
650 const int viewModeCSSKeywordID = downcast<CSSPrimitiveValue>(*value).getValueID();
651 const Page::ViewMode viewMode = frame->page()->viewMode();
654 case Page::ViewModeWindowed:
655 result = viewModeCSSKeywordID == CSSValueWindowed;
657 case Page::ViewModeFloating:
658 result = viewModeCSSKeywordID == CSSValueFloating;
660 case Page::ViewModeFullscreen:
661 result = viewModeCSSKeywordID == CSSValueFullscreen;
663 case Page::ViewModeMaximized:
664 result = viewModeCSSKeywordID == CSSValueMaximized;
666 case Page::ViewModeMinimized:
667 result = viewModeCSSKeywordID == CSSValueMinimized;
676 #endif // ENABLE(VIEW_MODE_CSS_MEDIA)
678 static bool video_playable_inlineMediaFeatureEval(CSSValue*, const CSSToLengthConversionData&, Frame* frame, MediaFeaturePrefix)
680 return frame->settings().allowsInlineMediaPlayback();
683 static bool hoverMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData&, Frame*, MediaFeaturePrefix)
685 if (!is<CSSPrimitiveValue>(value)) {
686 #if ENABLE(TOUCH_EVENTS)
693 int hoverCSSKeywordID = downcast<CSSPrimitiveValue>(*value).getValueID();
694 #if ENABLE(TOUCH_EVENTS)
695 return hoverCSSKeywordID == CSSValueNone;
697 return hoverCSSKeywordID == CSSValueHover;
701 static bool any_hoverMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& cssToLengthConversionData, Frame* frame, MediaFeaturePrefix prefix)
703 return hoverMediaFeatureEval(value, cssToLengthConversionData, frame, prefix);
706 static bool pointerMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData&, Frame*, MediaFeaturePrefix)
708 if (!is<CSSPrimitiveValue>(value))
711 int pointerCSSKeywordID = downcast<CSSPrimitiveValue>(*value).getValueID();
712 #if ENABLE(TOUCH_EVENTS)
713 return pointerCSSKeywordID == CSSValueCoarse;
715 return pointerCSSKeywordID == CSSValueFine;
719 static bool any_pointerMediaFeatureEval(CSSValue* value, const CSSToLengthConversionData& cssToLengthConversionData, Frame* frame, MediaFeaturePrefix prefix)
721 return pointerMediaFeatureEval(value, cssToLengthConversionData, frame, prefix);
724 static void createFunctionMap()
727 gFunctionMap = new FunctionMap;
728 #define ADD_TO_FUNCTIONMAP(name, str) \
729 gFunctionMap->set(name##MediaFeature.impl(), name##MediaFeatureEval);
730 CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(ADD_TO_FUNCTIONMAP);
731 #undef ADD_TO_FUNCTIONMAP
734 bool MediaQueryEvaluator::eval(const MediaQueryExp* expr) const
736 if (!m_frame || !m_frame->view() || !m_style)
739 if (!expr->isValid())
745 // call the media feature evaluation function. Assume no prefix
746 // and let trampoline functions override the prefix if prefix is
748 EvalFunc func = gFunctionMap->get(expr->mediaFeature().impl());
750 CSSToLengthConversionData conversionData(m_style,
751 m_frame->document()->documentElement()->renderStyle(),
752 m_frame->document()->renderView(), 1, false);
753 return func(expr->value(), conversionData, m_frame, NoPrefix);