summaryrefslogtreecommitdiff
path: root/Source/WebCore/css/MediaQueryEvaluator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/css/MediaQueryEvaluator.cpp')
-rw-r--r--Source/WebCore/css/MediaQueryEvaluator.cpp735
1 files changed, 367 insertions, 368 deletions
diff --git a/Source/WebCore/css/MediaQueryEvaluator.cpp b/Source/WebCore/css/MediaQueryEvaluator.cpp
index 1d176edf1..f7027d28a 100644
--- a/Source/WebCore/css/MediaQueryEvaluator.cpp
+++ b/Source/WebCore/css/MediaQueryEvaluator.cpp
@@ -16,7 +16,7 @@
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -31,20 +31,16 @@
#include "CSSAspectRatioValue.h"
#include "CSSPrimitiveValue.h"
+#include "CSSToLengthConversionData.h"
#include "CSSValueKeywords.h"
#include "CSSValueList.h"
-#include "Chrome.h"
-#include "ChromeClient.h"
-#include "DOMWindow.h"
#include "FloatRect.h"
#include "FrameView.h"
-#include "InspectorInstrumentation.h"
#include "IntRect.h"
#include "MainFrame.h"
#include "MediaFeatureNames.h"
#include "MediaList.h"
#include "MediaQuery.h"
-#include "MediaQueryExp.h"
#include "NodeRenderStyle.h"
#include "Page.h"
#include "PlatformScreen.h"
@@ -53,66 +49,66 @@
#include "Screen.h"
#include "Settings.h"
#include "StyleResolver.h"
+#include "Theme.h"
#include <wtf/HashMap.h>
-#if ENABLE(3D_RENDERING) && USE(ACCELERATED_COMPOSITING)
+#if ENABLE(3D_TRANSFORMS)
#include "RenderLayerCompositor.h"
#endif
-#if PLATFORM(IOS)
-#include "WebCoreSystemInterface.h"
-#endif
-
namespace WebCore {
-using namespace MediaFeatureNames;
-
enum MediaFeaturePrefix { MinPrefix, MaxPrefix, NoPrefix };
-typedef bool (*EvalFunc)(CSSValue*, RenderStyle*, Frame*, MediaFeaturePrefix);
-typedef HashMap<AtomicStringImpl*, EvalFunc> FunctionMap;
-static FunctionMap* gFunctionMap;
+typedef bool (*MediaQueryFunction)(CSSValue*, const CSSToLengthConversionData&, Frame&, MediaFeaturePrefix);
+typedef HashMap<AtomicStringImpl*, MediaQueryFunction> MediaQueryFunctionMap;
-/*
- * FIXME: following media features are not implemented: scan
- *
- * scan: The "scan" media feature describes the scanning process of
- * tv output devices. It's unknown how to retrieve this information from
- * the platform
- */
+static bool isAccessibilitySettingsDependent(const AtomicString& mediaFeature)
+{
+ return mediaFeature == MediaFeatureNames::invertedColors
+ || mediaFeature == MediaFeatureNames::maxMonochrome
+ || mediaFeature == MediaFeatureNames::minMonochrome
+ || mediaFeature == MediaFeatureNames::monochrome
+ || mediaFeature == MediaFeatureNames::prefersReducedMotion;
+}
+
+static bool isViewportDependent(const AtomicString& mediaFeature)
+{
+ return mediaFeature == MediaFeatureNames::width
+ || mediaFeature == MediaFeatureNames::height
+ || mediaFeature == MediaFeatureNames::minWidth
+ || mediaFeature == MediaFeatureNames::minHeight
+ || mediaFeature == MediaFeatureNames::maxWidth
+ || mediaFeature == MediaFeatureNames::maxHeight
+ || mediaFeature == MediaFeatureNames::orientation
+ || mediaFeature == MediaFeatureNames::aspectRatio
+ || mediaFeature == MediaFeatureNames::minAspectRatio
+ || mediaFeature == MediaFeatureNames::maxAspectRatio;
+}
MediaQueryEvaluator::MediaQueryEvaluator(bool mediaFeatureResult)
- : m_frame(0)
- , m_style(0)
- , m_expResult(mediaFeatureResult)
+ : m_fallbackResult(mediaFeatureResult)
{
}
MediaQueryEvaluator::MediaQueryEvaluator(const String& acceptedMediaType, bool mediaFeatureResult)
: m_mediaType(acceptedMediaType)
- , m_frame(0)
- , m_style(0)
- , m_expResult(mediaFeatureResult)
+ , m_fallbackResult(mediaFeatureResult)
{
}
-MediaQueryEvaluator::MediaQueryEvaluator(const String& acceptedMediaType, Frame* frame, RenderStyle* style)
+MediaQueryEvaluator::MediaQueryEvaluator(const String& acceptedMediaType, const Document& document, const RenderStyle* style)
: m_mediaType(acceptedMediaType)
- , m_frame(frame)
+ , m_frame(document.frame())
, m_style(style)
- , m_expResult(false) // doesn't matter when we have m_frame and m_style
-{
-}
-
-MediaQueryEvaluator::~MediaQueryEvaluator()
{
}
bool MediaQueryEvaluator::mediaTypeMatch(const String& mediaTypeToMatch) const
{
return mediaTypeToMatch.isEmpty()
- || equalIgnoringCase(mediaTypeToMatch, "all")
- || equalIgnoringCase(mediaTypeToMatch, m_mediaType);
+ || equalLettersIgnoringASCIICase(mediaTypeToMatch, "all")
+ || equalIgnoringASCIICase(mediaTypeToMatch, m_mediaType);
}
bool MediaQueryEvaluator::mediaTypeMatchSpecific(const char* mediaTypeToMatch) const
@@ -120,8 +116,8 @@ bool MediaQueryEvaluator::mediaTypeMatchSpecific(const char* mediaTypeToMatch) c
// Like mediaTypeMatch, but without the special cases for "" and "all".
ASSERT(mediaTypeToMatch);
ASSERT(mediaTypeToMatch[0] != '\0');
- ASSERT(!equalIgnoringCase(mediaTypeToMatch, String("all")));
- return equalIgnoringCase(mediaTypeToMatch, m_mediaType);
+ ASSERT(!equalLettersIgnoringASCIICase(StringView(mediaTypeToMatch), "all"));
+ return equalIgnoringASCIICase(m_mediaType, mediaTypeToMatch);
}
static bool applyRestrictor(MediaQuery::Restrictor r, bool value)
@@ -129,48 +125,75 @@ static bool applyRestrictor(MediaQuery::Restrictor r, bool value)
return r == MediaQuery::Not ? !value : value;
}
-bool MediaQueryEvaluator::eval(const MediaQuerySet* querySet, StyleResolver* styleResolver) const
+bool MediaQueryEvaluator::evaluate(const MediaQuerySet& querySet, StyleResolver* styleResolver) const
{
- if (!querySet)
- return true;
-
- const Vector<OwnPtr<MediaQuery>>& queries = querySet->queryVector();
+ auto& queries = querySet.queryVector();
if (!queries.size())
- return true; // empty query list evaluates to true
+ return true; // Empty query list evaluates to true.
- // iterate over queries, stop if any of them eval to true (OR semantics)
+ // Iterate over queries, stop if any of them eval to true (OR semantics).
bool result = false;
for (size_t i = 0; i < queries.size() && !result; ++i) {
- MediaQuery* query = queries[i].get();
+ auto& query = queries[i];
- if (query->ignored())
+ if (query.ignored() || (!query.expressions().size() && query.mediaType().isEmpty()))
continue;
- if (mediaTypeMatch(query->mediaType())) {
- const Vector<OwnPtr<MediaQueryExp>>& expressions = query->expressions();
- // iterate through expressions, stop if any of them eval to false
- // (AND semantics)
+ if (mediaTypeMatch(query.mediaType())) {
+ auto& expressions = query.expressions();
+ // Iterate through expressions, stop if any of them eval to false (AND semantics).
size_t j = 0;
for (; j < expressions.size(); ++j) {
- bool exprResult = eval(expressions.at(j).get());
- if (styleResolver && expressions.at(j)->isViewportDependent())
- styleResolver->addViewportDependentMediaQueryResult(expressions.at(j).get(), exprResult);
- if (!exprResult)
+ bool expressionResult = evaluate(expressions[j]);
+ if (styleResolver && isViewportDependent(expressions[j].mediaFeature()))
+ styleResolver->addViewportDependentMediaQueryResult(expressions[j], expressionResult);
+ if (styleResolver && isAccessibilitySettingsDependent(expressions[j].mediaFeature()))
+ styleResolver->addAccessibilitySettingsDependentMediaQueryResult(expressions[j], expressionResult);
+ if (!expressionResult)
break;
}
- // assume true if we are at the end of the list,
- // otherwise assume false
- result = applyRestrictor(query->restrictor(), expressions.size() == j);
+ // Assume true if we are at the end of the list, otherwise assume false.
+ result = applyRestrictor(query.restrictor(), expressions.size() == j);
} else
- result = applyRestrictor(query->restrictor(), false);
+ result = applyRestrictor(query.restrictor(), false);
}
return result;
}
-template<typename T>
-bool compareValue(T a, T b, MediaFeaturePrefix op)
+bool MediaQueryEvaluator::evaluate(const MediaQuerySet& querySet, Vector<MediaQueryResult>& results) const
+{
+ auto& queries = querySet.queryVector();
+ if (!queries.size())
+ return true;
+
+ bool result = false;
+ for (size_t i = 0; i < queries.size() && !result; ++i) {
+ auto& query = queries[i];
+
+ if (query.ignored())
+ continue;
+
+ if (mediaTypeMatch(query.mediaType())) {
+ auto& expressions = query.expressions();
+ size_t j = 0;
+ for (; j < expressions.size(); ++j) {
+ bool expressionResult = evaluate(expressions[j]);
+ if (isViewportDependent(expressions[j].mediaFeature()))
+ results.append({ expressions[j], expressionResult });
+ if (!expressionResult)
+ break;
+ }
+ result = applyRestrictor(query.restrictor(), expressions.size() == j);
+ } else
+ result = applyRestrictor(query.restrictor(), false);
+ }
+
+ return result;
+}
+
+template<typename T, typename U> bool compareValue(T a, U b, MediaFeaturePrefix op)
{
switch (op) {
case MinPrefix:
@@ -185,119 +208,162 @@ bool compareValue(T a, T b, MediaFeaturePrefix op)
static bool compareAspectRatioValue(CSSValue* value, int width, int height, MediaFeaturePrefix op)
{
- if (value->isAspectRatioValue()) {
- CSSAspectRatioValue* aspectRatio = toCSSAspectRatioValue(value);
- return compareValue(width * static_cast<int>(aspectRatio->denominatorValue()), height * static_cast<int>(aspectRatio->numeratorValue()), op);
- }
+ if (!is<CSSAspectRatioValue>(value))
+ return false;
+ auto& aspectRatio = downcast<CSSAspectRatioValue>(*value);
+ return compareValue(width * aspectRatio.denominatorValue(), height * aspectRatio.numeratorValue(), op);
+}
- return false;
+static std::optional<double> doubleValue(CSSValue* value)
+{
+ if (!is<CSSPrimitiveValue>(value) || !downcast<CSSPrimitiveValue>(*value).isNumber())
+ return std::nullopt;
+ return downcast<CSSPrimitiveValue>(*value).doubleValue(CSSPrimitiveValue::CSS_NUMBER);
}
-static bool numberValue(CSSValue* value, float& result)
+static bool zeroEvaluate(CSSValue* value, MediaFeaturePrefix op)
{
- if (value->isPrimitiveValue()
- && toCSSPrimitiveValue(value)->isNumber()) {
- result = toCSSPrimitiveValue(value)->getFloatValue(CSSPrimitiveValue::CSS_NUMBER);
+ auto numericValue = doubleValue(value);
+ return numericValue && compareValue(0, numericValue.value(), op);
+}
+
+static bool oneEvaluate(CSSValue* value, MediaFeaturePrefix op)
+{
+ if (!value)
return true;
- }
- return false;
+ auto numericValue = doubleValue(value);
+ return numericValue && compareValue(1, numericValue.value(), op);
}
-static bool colorMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
+static bool colorEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame& frame, MediaFeaturePrefix op)
{
- int bitsPerComponent = screenDepthPerComponent(frame->page()->mainFrame().view());
- float number;
- if (value)
- return numberValue(value, number) && compareValue(bitsPerComponent, static_cast<int>(number), op);
+ int bitsPerComponent = screenDepthPerComponent(frame.mainFrame().view());
+ auto numericValue = doubleValue(value);
+ if (!numericValue)
+ return bitsPerComponent;
+ return compareValue(bitsPerComponent, numericValue.value(), op);
+}
- return bitsPerComponent != 0;
+static bool colorIndexEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame&, MediaFeaturePrefix op)
+{
+ // Always return false for indexed display.
+ return zeroEvaluate(value, op);
}
-static bool color_indexMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, MediaFeaturePrefix op)
+static bool colorGamutEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame& frame, MediaFeaturePrefix)
{
- // FIXME: It's unknown how to retrieve the information if the display mode is indexed
- // Assume we don't support indexed display.
if (!value)
+ return true;
+
+ switch (downcast<CSSPrimitiveValue>(*value).valueID()) {
+ case CSSValueSRGB:
+ return true;
+ case CSSValueP3:
+ // FIXME: For the moment we just assume any "extended color" display is at least as good as P3.
+ return screenSupportsExtendedColor(frame.mainFrame().view());
+ case CSSValueRec2020:
+ // FIXME: At some point we should start detecting displays that support more colors.
return false;
+ default:
+ return false; // Any unknown value should not be considered a match.
+ }
+}
+
+static bool monochromeEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix op)
+{
+ bool isMonochrome;
+
+ if (frame.settings().forcedDisplayIsMonochromeAccessibilityValue() == Settings::ForcedAccessibilityValue::On)
+ isMonochrome = true;
+ else if (frame.settings().forcedDisplayIsMonochromeAccessibilityValue() == Settings::ForcedAccessibilityValue::Off)
+ isMonochrome = false;
+ else
+ isMonochrome = screenIsMonochrome(frame.mainFrame().view());
- float number;
- return numberValue(value, number) && compareValue(0, static_cast<int>(number), op);
+ if (!isMonochrome)
+ return zeroEvaluate(value, op);
+ return colorEvaluate(value, conversionData, frame, op);
}
-static bool monochromeMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op)
+static bool invertedColorsEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame& frame, MediaFeaturePrefix)
{
- if (!screenIsMonochrome(frame->page()->mainFrame().view())) {
- if (value) {
- float number;
- return numberValue(value, number) && compareValue(0, static_cast<int>(number), op);
- }
- return false;
- }
+ bool isInverted;
+
+ if (frame.settings().forcedColorsAreInvertedAccessibilityValue() == Settings::ForcedAccessibilityValue::On)
+ isInverted = true;
+ else if (frame.settings().forcedColorsAreInvertedAccessibilityValue() == Settings::ForcedAccessibilityValue::Off)
+ isInverted = false;
+ else
+ isInverted = screenHasInvertedColors();
- return colorMediaFeatureEval(value, style, frame, op);
+ if (!value)
+ return isInverted;
+
+ return downcast<CSSPrimitiveValue>(*value).valueID() == (isInverted ? CSSValueInverted : CSSValueNone);
}
-static bool orientationMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix)
+static bool orientationEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame& frame, MediaFeaturePrefix)
{
- FrameView* view = frame->view();
+ FrameView* view = frame.view();
if (!view)
return false;
- int width = view->layoutWidth();
- int height = view->layoutHeight();
- if (value && value->isPrimitiveValue()) {
- const CSSValueID id = toCSSPrimitiveValue(value)->getValueID();
- if (width > height) // Square viewport is portrait.
- return CSSValueLandscape == id;
- return CSSValuePortrait == id;
+ auto width = view->layoutWidth();
+ auto height = view->layoutHeight();
+
+ if (!is<CSSPrimitiveValue>(value)) {
+ // Expression (orientation) evaluates to true if width and height >= 0.
+ return height >= 0 && width >= 0;
}
- // Expression (orientation) evaluates to true if width and height >= 0.
- return height >= 0 && width >= 0;
+ auto keyword = downcast<CSSPrimitiveValue>(*value).valueID();
+ if (width > height) // Square viewport is portrait.
+ return keyword == CSSValueLandscape;
+ return keyword == CSSValuePortrait;
}
-static bool aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
+static bool aspectRatioEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame& frame, MediaFeaturePrefix op)
{
- FrameView* view = frame->view();
- if (!view)
+ // ({,min-,max-}aspect-ratio)
+ // assume if we have a device, its aspect ratio is non-zero
+ if (!value)
return true;
- if (value)
- return compareAspectRatioValue(value, view->layoutWidth(), view->layoutHeight(), op);
+ FrameView* view = frame.view();
+ if (!view)
+ return true;
- // ({,min-,max-}aspect-ratio)
- // assume if we have a device, its aspect ratio is non-zero
- return true;
+ return compareAspectRatioValue(value, view->layoutWidth(), view->layoutHeight(), op);
}
-static bool device_aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
+static bool deviceAspectRatioEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame& frame, MediaFeaturePrefix op)
{
- if (value) {
- FloatRect sg = screenRect(frame->page()->mainFrame().view());
- return compareAspectRatioValue(value, static_cast<int>(sg.width()), static_cast<int>(sg.height()), op);
- }
-
// ({,min-,max-}device-aspect-ratio)
// assume if we have a device, its aspect ratio is non-zero
- return true;
+ if (!value)
+ return true;
+
+ auto size = screenRect(frame.mainFrame().view()).size();
+ return compareAspectRatioValue(value, size.width(), size.height(), op);
}
-static bool evalResolution(CSSValue* value, Frame* frame, MediaFeaturePrefix op)
+static bool evaluateResolution(CSSValue* value, Frame& frame, MediaFeaturePrefix op)
{
// FIXME: Possible handle other media types than 'screen' and 'print'.
- FrameView* view = frame->view();
+ FrameView* view = frame.view();
if (!view)
return false;
float deviceScaleFactor = 0;
+
// This checks the actual media type applied to the document, and we know
// this method only got called if this media type matches the one defined
// in the query. Thus, if if the document's media type is "print", the
// media type of the query will either be "print" or "all".
String mediaType = view->mediaType();
- if (equalIgnoringCase(mediaType, "screen"))
- deviceScaleFactor = frame->page()->deviceScaleFactor();
- else if (equalIgnoringCase(mediaType, "print")) {
+ if (equalLettersIgnoringASCIICase(mediaType, "screen"))
+ deviceScaleFactor = frame.page() ? frame.page()->deviceScaleFactor() : 1;
+ else if (equalLettersIgnoringASCIICase(mediaType, "print")) {
// The resolution of images while printing should not depend on the dpi
// of the screen. Until we support proper ways of querying this info
// we use 300px which is considered minimum for current printers.
@@ -307,22 +373,22 @@ static bool evalResolution(CSSValue* value, Frame* frame, MediaFeaturePrefix op)
if (!value)
return !!deviceScaleFactor;
- if (!value->isPrimitiveValue())
+ if (!is<CSSPrimitiveValue>(value))
return false;
- CSSPrimitiveValue* resolution = toCSSPrimitiveValue(value);
- return compareValue(deviceScaleFactor, resolution->isNumber() ? resolution->getFloatValue() : resolution->getFloatValue(CSSPrimitiveValue::CSS_DPPX), op);
+ auto& resolution = downcast<CSSPrimitiveValue>(*value);
+ return compareValue(deviceScaleFactor, resolution.isNumber() ? resolution.floatValue() : resolution.floatValue(CSSPrimitiveValue::CSS_DPPX), op);
}
-static bool device_pixel_ratioMediaFeatureEval(CSSValue *value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
+static bool devicePixelRatioEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame& frame, MediaFeaturePrefix op)
{
- return (!value || toCSSPrimitiveValue(value)->isNumber()) && evalResolution(value, frame, op);
+ return (!value || (is<CSSPrimitiveValue>(*value) && downcast<CSSPrimitiveValue>(*value).isNumber())) && evaluateResolution(value, frame, op);
}
-static bool resolutionMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
+static bool resolutionEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame& frame, MediaFeaturePrefix op)
{
#if ENABLE(RESOLUTION_MEDIA_QUERY)
- return (!value || toCSSPrimitiveValue(value)->isResolution()) && evalResolution(value, frame, op);
+ return (!value || (is<CSSPrimitiveValue>(*value) && downcast<CSSPrimitiveValue>(*value).isResolution())) && evaluateResolution(value, frame, op);
#else
UNUSED_PARAM(value);
UNUSED_PARAM(frame);
@@ -331,408 +397,341 @@ static bool resolutionMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* fra
#endif
}
-static bool gridMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, MediaFeaturePrefix op)
+static bool gridEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame&, MediaFeaturePrefix op)
{
- // if output device is bitmap, grid: 0 == true
- // assume we have bitmap device
- float number;
- if (value && numberValue(value, number))
- return compareValue(static_cast<int>(number), 0, op);
- return false;
+ return zeroEvaluate(value, op);
}
-static bool computeLength(CSSValue* value, bool strict, RenderStyle* style, RenderStyle* rootStyle, int& result)
+static bool computeLength(CSSValue* value, bool strict, const CSSToLengthConversionData& conversionData, int& result)
{
- if (!value->isPrimitiveValue())
+ if (!is<CSSPrimitiveValue>(value))
return false;
- CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
+ auto& primitiveValue = downcast<CSSPrimitiveValue>(*value);
- if (primitiveValue->isNumber()) {
- result = primitiveValue->getIntValue();
+ if (primitiveValue.isNumber()) {
+ result = primitiveValue.intValue();
return !strict || !result;
}
- if (primitiveValue->isLength()) {
- result = primitiveValue->computeLength<int>(style, rootStyle);
+ if (primitiveValue.isLength()) {
+ result = primitiveValue.computeLength<int>(conversionData);
return true;
}
return false;
}
-static bool device_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op)
+static bool deviceHeightEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix op)
{
- if (value) {
- FloatRect sg = screenRect(frame->page()->mainFrame().view());
- RenderStyle* rootStyle = frame->document()->documentElement()->renderStyle();
- int length;
- long height = sg.height();
- return computeLength(value, !frame->document()->inQuirksMode(), style, rootStyle, length) && compareValue(static_cast<int>(height), length, op);
- }
// ({,min-,max-}device-height)
// assume if we have a device, assume non-zero
- return true;
+ if (!value)
+ return true;
+ int length;
+ auto height = screenRect(frame.mainFrame().view()).height();
+ return computeLength(value, !frame.document()->inQuirksMode(), conversionData, length) && compareValue(height, length, op);
}
-static bool device_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op)
+static bool deviceWidthEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix op)
{
- if (value) {
- FloatRect sg = screenRect(frame->page()->mainFrame().view());
- RenderStyle* rootStyle = frame->document()->documentElement()->renderStyle();
- int length;
- long width = sg.width();
- return computeLength(value, !frame->document()->inQuirksMode(), style, rootStyle, length) && compareValue(static_cast<int>(width), length, op);
- }
// ({,min-,max-}device-width)
// assume if we have a device, assume non-zero
- return true;
+ if (!value)
+ return true;
+ int length;
+ auto width = screenRect(frame.mainFrame().view()).width();
+ return computeLength(value, !frame.document()->inQuirksMode(), conversionData, length) && compareValue(width, length, op);
}
-static bool heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op)
+static bool heightEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix op)
{
- FrameView* view = frame->view();
+ FrameView* view = frame.view();
if (!view)
return false;
-
- if (value) {
- int height = view->layoutHeight();
- if (RenderView* renderView = frame->document()->renderView())
- height = adjustForAbsoluteZoom(height, *renderView);
- RenderStyle* rootStyle = frame->document()->documentElement()->renderStyle();
- int length;
- return computeLength(value, !frame->document()->inQuirksMode(), style, rootStyle, length) && compareValue(height, length, op);
- }
-
- return view->layoutHeight() != 0;
+ int height = view->layoutHeight();
+ if (!value)
+ return height;
+ if (auto* renderView = frame.document()->renderView())
+ height = adjustForAbsoluteZoom(height, *renderView);
+ int length;
+ return computeLength(value, !frame.document()->inQuirksMode(), conversionData, length) && compareValue(height, length, op);
}
-static bool widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op)
+static bool widthEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix op)
{
- FrameView* view = frame->view();
+ FrameView* view = frame.view();
if (!view)
return false;
-
- if (value) {
- int width = view->layoutWidth();
- if (RenderView* renderView = frame->document()->renderView())
- width = adjustForAbsoluteZoom(width, *renderView);
- RenderStyle* rootStyle = frame->document()->documentElement()->renderStyle();
- int length;
- return computeLength(value, !frame->document()->inQuirksMode(), style, rootStyle, length) && compareValue(width, length, op);
- }
-
- return view->layoutWidth() != 0;
+ int width = view->layoutWidth();
+ if (!value)
+ return width;
+ if (auto* renderView = frame.document()->renderView())
+ width = adjustForAbsoluteZoom(width, *renderView);
+ int length;
+ return computeLength(value, !frame.document()->inQuirksMode(), conversionData, length) && compareValue(width, length, op);
}
-// rest of the functions are trampolines which set the prefix according to the media feature expression used
-
-static bool min_colorMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool minColorEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return colorMediaFeatureEval(value, style, frame, MinPrefix);
+ return colorEvaluate(value, conversionData, frame, MinPrefix);
}
-static bool max_colorMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool maxColorEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return colorMediaFeatureEval(value, style, frame, MaxPrefix);
+ return colorEvaluate(value, conversionData, frame, MaxPrefix);
}
-static bool min_color_indexMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool minColorIndexEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return color_indexMediaFeatureEval(value, style, frame, MinPrefix);
+ return colorIndexEvaluate(value, conversionData, frame, MinPrefix);
}
-static bool max_color_indexMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool maxColorIndexEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return color_indexMediaFeatureEval(value, style, frame, MaxPrefix);
+ return colorIndexEvaluate(value, conversionData, frame, MaxPrefix);
}
-static bool min_monochromeMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool minMonochromeEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return monochromeMediaFeatureEval(value, style, frame, MinPrefix);
+ return monochromeEvaluate(value, conversionData, frame, MinPrefix);
}
-static bool max_monochromeMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool maxMonochromeEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return monochromeMediaFeatureEval(value, style, frame, MaxPrefix);
+ return monochromeEvaluate(value, conversionData, frame, MaxPrefix);
}
-static bool min_aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool minAspectRatioEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return aspect_ratioMediaFeatureEval(value, style, frame, MinPrefix);
+ return aspectRatioEvaluate(value, conversionData, frame, MinPrefix);
}
-static bool max_aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool maxAspectRatioEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return aspect_ratioMediaFeatureEval(value, style, frame, MaxPrefix);
+ return aspectRatioEvaluate(value, conversionData, frame, MaxPrefix);
}
-static bool min_device_aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool minDeviceAspectRatioEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return device_aspect_ratioMediaFeatureEval(value, style, frame, MinPrefix);
+ return deviceAspectRatioEvaluate(value, conversionData, frame, MinPrefix);
}
-static bool max_device_aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool maxDeviceAspectRatioEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return device_aspect_ratioMediaFeatureEval(value, style, frame, MaxPrefix);
+ return deviceAspectRatioEvaluate(value, conversionData, frame, MaxPrefix);
}
-static bool min_device_pixel_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool minDevicePixelRatioEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return device_pixel_ratioMediaFeatureEval(value, style, frame, MinPrefix);
+ return devicePixelRatioEvaluate(value, conversionData, frame, MinPrefix);
}
-static bool max_device_pixel_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool maxDevicePixelRatioEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return device_pixel_ratioMediaFeatureEval(value, style, frame, MaxPrefix);
+ return devicePixelRatioEvaluate(value, conversionData, frame, MaxPrefix);
}
-static bool min_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool minHeightEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return heightMediaFeatureEval(value, style, frame, MinPrefix);
+ return heightEvaluate(value, conversionData, frame, MinPrefix);
}
-static bool max_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool maxHeightEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return heightMediaFeatureEval(value, style, frame, MaxPrefix);
+ return heightEvaluate(value, conversionData, frame, MaxPrefix);
}
-static bool min_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool minWidthEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return widthMediaFeatureEval(value, style, frame, MinPrefix);
+ return widthEvaluate(value, conversionData, frame, MinPrefix);
}
-static bool max_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool maxWidthEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return widthMediaFeatureEval(value, style, frame, MaxPrefix);
+ return widthEvaluate(value, conversionData, frame, MaxPrefix);
}
-static bool min_device_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool minDeviceHeightEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return device_heightMediaFeatureEval(value, style, frame, MinPrefix);
+ return deviceHeightEvaluate(value, conversionData, frame, MinPrefix);
}
-static bool max_device_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool maxDeviceHeightEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return device_heightMediaFeatureEval(value, style, frame, MaxPrefix);
+ return deviceHeightEvaluate(value, conversionData, frame, MaxPrefix);
}
-static bool min_device_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool minDeviceWidthEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return device_widthMediaFeatureEval(value, style, frame, MinPrefix);
+ return deviceWidthEvaluate(value, conversionData, frame, MinPrefix);
}
-static bool max_device_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool maxDeviceWidthEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return device_widthMediaFeatureEval(value, style, frame, MaxPrefix);
+ return deviceWidthEvaluate(value, conversionData, frame, MaxPrefix);
}
-static bool min_resolutionMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool minResolutionEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return resolutionMediaFeatureEval(value, style, frame, MinPrefix);
+ return resolutionEvaluate(value, conversionData, frame, MinPrefix);
}
-static bool max_resolutionMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+static bool maxResolutionEvaluate(CSSValue* value, const CSSToLengthConversionData& conversionData, Frame& frame, MediaFeaturePrefix)
{
- return resolutionMediaFeatureEval(value, style, frame, MaxPrefix);
+ return resolutionEvaluate(value, conversionData, frame, MaxPrefix);
}
-static bool animationMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, MediaFeaturePrefix op)
+static bool animationEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame&, MediaFeaturePrefix op)
{
- if (value) {
- float number;
- return numberValue(value, number) && compareValue(1, static_cast<int>(number), op);
- }
- return true;
+ return oneEvaluate(value, op);
}
-static bool transitionMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, MediaFeaturePrefix op)
+static bool transitionEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame&, MediaFeaturePrefix op)
{
- if (value) {
- float number;
- return numberValue(value, number) && compareValue(1, static_cast<int>(number), op);
- }
- return true;
+ return oneEvaluate(value, op);
}
-static bool transform_2dMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, MediaFeaturePrefix op)
+static bool transform2dEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame&, MediaFeaturePrefix op)
{
- if (value) {
- float number;
- return numberValue(value, number) && compareValue(1, static_cast<int>(number), op);
- }
- return true;
+ return oneEvaluate(value, op);
}
-static bool transform_3dMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
+static bool transform3dEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame& frame, MediaFeaturePrefix op)
{
- bool returnValueIfNoParameter;
- int have3dRendering;
-
-#if ENABLE(3D_RENDERING)
- bool threeDEnabled = false;
-#if USE(ACCELERATED_COMPOSITING)
- if (RenderView* view = frame->contentRenderer())
- threeDEnabled = view->compositor().canRender3DTransforms();
-#endif
-
- returnValueIfNoParameter = threeDEnabled;
- have3dRendering = threeDEnabled ? 1 : 0;
+#if ENABLE(3D_TRANSFORMS)
+ auto* view = frame.contentRenderer();
+ return view && view->compositor().canRender3DTransforms() ? oneEvaluate(value, op) : zeroEvaluate(value, op);
#else
UNUSED_PARAM(frame);
- returnValueIfNoParameter = false;
- have3dRendering = 0;
+ return zeroEvaluate(value, op);
#endif
-
- if (value) {
- float number;
- return numberValue(value, number) && compareValue(have3dRendering, static_cast<int>(number), op);
- }
- return returnValueIfNoParameter;
}
#if ENABLE(VIEW_MODE_CSS_MEDIA)
-static bool view_modeMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
+
+static bool viewModeEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame& frame, MediaFeaturePrefix)
{
- UNUSED_PARAM(op);
if (!value)
return true;
- const int viewModeCSSKeywordID = toCSSPrimitiveValue(value)->getValueID();
- const Page::ViewMode viewMode = frame->page()->viewMode();
- bool result = false;
- switch (viewMode) {
+ auto keyword = downcast<CSSPrimitiveValue>(*value).valueID();
+
+ switch (frame.page()->viewMode()) {
case Page::ViewModeWindowed:
- result = viewModeCSSKeywordID == CSSValueWindowed;
- break;
+ return keyword == CSSValueWindowed;
case Page::ViewModeFloating:
- result = viewModeCSSKeywordID == CSSValueFloating;
- break;
+ return keyword == CSSValueFloating;
case Page::ViewModeFullscreen:
- result = viewModeCSSKeywordID == CSSValueFullscreen;
- break;
+ return keyword == CSSValueFullscreen;
case Page::ViewModeMaximized:
- result = viewModeCSSKeywordID == CSSValueMaximized;
- break;
+ return keyword == CSSValueMaximized;
case Page::ViewModeMinimized:
- result = viewModeCSSKeywordID == CSSValueMinimized;
- break;
+ return keyword == CSSValueMinimized;
default:
- result = false;
break;
}
- return result;
+ return false;
}
+
#endif // ENABLE(VIEW_MODE_CSS_MEDIA)
-// FIXME: Find a better place for this function. Maybe ChromeClient?
-static inline bool isRunningOnIPhoneOrIPod()
+static bool videoPlayableInlineEvaluate(CSSValue*, const CSSToLengthConversionData&, Frame& frame, MediaFeaturePrefix)
+{
+ return frame.settings().allowsInlineMediaPlayback();
+}
+
+static bool hoverEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame&, MediaFeaturePrefix)
{
-#if PLATFORM(IOS)
- static wkDeviceClass deviceClass = iosDeviceClass();
- return deviceClass == wkDeviceClassiPhone || deviceClass == wkDeviceClassiPod;
+ if (!is<CSSPrimitiveValue>(value)) {
+#if ENABLE(TOUCH_EVENTS)
+ return false;
#else
- return false;
+ return true;
+#endif
+ }
+
+ auto keyword = downcast<CSSPrimitiveValue>(*value).valueID();
+#if ENABLE(TOUCH_EVENTS)
+ return keyword == CSSValueNone;
+#else
+ return keyword == CSSValueHover;
#endif
}
-static bool video_playable_inlineMediaFeatureEval(CSSValue*, RenderStyle*, Frame* frame, MediaFeaturePrefix)
+static bool anyHoverEvaluate(CSSValue* value, const CSSToLengthConversionData& cssToLengthConversionData, Frame& frame, MediaFeaturePrefix prefix)
{
- return !isRunningOnIPhoneOrIPod() || frame->settings().mediaPlaybackAllowsInline();
+ return hoverEvaluate(value, cssToLengthConversionData, frame, prefix);
}
-enum PointerDeviceType { TouchPointer, MousePointer, NoPointer, UnknownPointer };
-
-static PointerDeviceType leastCapablePrimaryPointerDeviceType(Frame* frame)
+static bool pointerEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame&, MediaFeaturePrefix)
{
- if (frame->settings().deviceSupportsTouch())
- return TouchPointer;
-
- // FIXME: We should also try to determine if we know we have a mouse.
- // When we do this, we'll also need to differentiate between known not to
- // have mouse or touch screen (NoPointer) and unknown (UnknownPointer).
- // We could also take into account other preferences like accessibility
- // settings to decide which of the available pointers should be considered
- // "primary".
+ if (!is<CSSPrimitiveValue>(value))
+ return true;
- return UnknownPointer;
+ auto keyword = downcast<CSSPrimitiveValue>(*value).valueID();
+#if ENABLE(TOUCH_EVENTS)
+ return keyword == CSSValueCoarse;
+#else
+ return keyword == CSSValueFine;
+#endif
}
-static bool hoverMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix)
+static bool anyPointerEvaluate(CSSValue* value, const CSSToLengthConversionData& cssToLengthConversionData, Frame& frame, MediaFeaturePrefix prefix)
{
- PointerDeviceType pointer = leastCapablePrimaryPointerDeviceType(frame);
-
- // If we're on a port that hasn't explicitly opted into providing pointer device information
- // (or otherwise can't be confident in the pointer hardware available), then behave exactly
- // as if this feature feature isn't supported.
- if (pointer == UnknownPointer)
- return false;
-
- float number = 1;
- if (value) {
- if (!numberValue(value, number))
- return false;
- }
-
- return (pointer == NoPointer && !number)
- || (pointer == TouchPointer && !number)
- || (pointer == MousePointer && number == 1);
+ return pointerEvaluate(value, cssToLengthConversionData, frame, prefix);
}
-static bool pointerMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix)
+static bool prefersReducedMotionEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame& frame, MediaFeaturePrefix)
{
- PointerDeviceType pointer = leastCapablePrimaryPointerDeviceType(frame);
+ bool userPrefersReducedMotion = false;
- // If we're on a port that hasn't explicitly opted into providing pointer device information
- // (or otherwise can't be confident in the pointer hardware available), then behave exactly
- // as if this feature feature isn't supported.
- if (pointer == UnknownPointer)
- return false;
+ if (frame.settings().forcedPrefersReducedMotionAccessibilityValue() == Settings::ForcedAccessibilityValue::On)
+ userPrefersReducedMotion = true;
+ else if (frame.settings().forcedPrefersReducedMotionAccessibilityValue() == Settings::ForcedAccessibilityValue::Off)
+ userPrefersReducedMotion = false;
+#if PLATFORM(IOS) || USE(NEW_THEME)
+ else
+ userPrefersReducedMotion = platformTheme()->userPrefersReducedMotion();
+#endif
if (!value)
- return pointer != NoPointer;
+ return userPrefersReducedMotion;
- if (!value->isPrimitiveValue())
- return false;
-
- const CSSValueID id = toCSSPrimitiveValue(value)->getValueID();
- return (pointer == NoPointer && id == CSSValueNone)
- || (pointer == TouchPointer && id == CSSValueCoarse)
- || (pointer == MousePointer && id == CSSValueFine);
+ return downcast<CSSPrimitiveValue>(*value).valueID() == (userPrefersReducedMotion ? CSSValueReduce : CSSValueNoPreference);
}
-// FIXME: Remove unnecessary '&' from the following 'ADD_TO_FUNCTIONMAP' definition
-// once we switch to a non-broken Visual Studio compiler. https://bugs.webkit.org/show_bug.cgi?id=121235
-static void createFunctionMap()
+// Use this function instead of calling add directly to avoid inlining.
+static void add(MediaQueryFunctionMap& map, AtomicStringImpl* key, MediaQueryFunction value)
{
- // Create the table.
- gFunctionMap = new FunctionMap;
-#define ADD_TO_FUNCTIONMAP(name, str) \
- gFunctionMap->set(name##MediaFeature.impl(), &name##MediaFeatureEval);
- CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(ADD_TO_FUNCTIONMAP);
-#undef ADD_TO_FUNCTIONMAP
+ map.add(key, value);
}
-bool MediaQueryEvaluator::eval(const MediaQueryExp* expr) const
+bool MediaQueryEvaluator::evaluate(const MediaQueryExpression& expression) const
{
if (!m_frame || !m_frame->view() || !m_style)
- return m_expResult;
+ return m_fallbackResult;
- if (!expr->isValid())
+ if (!expression.isValid())
return false;
- if (!gFunctionMap)
- createFunctionMap();
+ static NeverDestroyed<MediaQueryFunctionMap> map = [] {
+ MediaQueryFunctionMap map;
+#define ADD_TO_FUNCTIONMAP(name, str) add(map, MediaFeatureNames::name.impl(), name##Evaluate);
+ CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(ADD_TO_FUNCTIONMAP);
+#undef ADD_TO_FUNCTIONMAP
+ return map;
+ }();
- // call the media feature evaluation function. Assume no prefix
- // and let trampoline functions override the prefix if prefix is
- // used
- EvalFunc func = gFunctionMap->get(expr->mediaFeature().impl());
- if (func)
- return func(expr->value(), m_style.get(), m_frame, NoPrefix);
+ auto function = map.get().get(expression.mediaFeature().impl());
+ if (!function)
+ return false;
- return false;
+ Document& document = *m_frame->document();
+ if (!document.documentElement())
+ return false;
+ return function(expression.value(), { m_style, document.documentElement()->renderStyle(), document.renderView(), 1, false }, *m_frame, NoPrefix);
}
} // namespace