#include "config.h"
#include "MediaQueryExp.h"
#include "CSSAspectRatioValue.h"
#include "CSSParser.h"
#include "CSSPrimitiveValue.h"
#include "CSSValueList.h"
#include <wtf/text/StringBuilder.h>
namespace WebCore {
static inline bool featureWithCSSValueID(const AtomicString& mediaFeature, const CSSParserValue* value)
{
if (!value->id)
return false;
return mediaFeature == MediaFeatureNames::orientationMediaFeature
#if ENABLE(VIEW_MODE_CSS_MEDIA)
|| mediaFeature == MediaFeatureNames::view_modeMediaFeature
#endif // ENABLE(VIEW_MODE_CSS_MEDIA)
|| mediaFeature == MediaFeatureNames::any_hoverMediaFeature
|| mediaFeature == MediaFeatureNames::any_pointerMediaFeature
|| mediaFeature == MediaFeatureNames::hoverMediaFeature
|| mediaFeature == MediaFeatureNames::inverted_colorsMediaFeature
|| mediaFeature == MediaFeatureNames::pointerMediaFeature;
}
static inline bool featureWithValidPositiveLenghtOrNumber(const AtomicString& mediaFeature, const CSSParserValue* value)
{
if (!(CSSPrimitiveValue::isLength(value->unit) || value->unit == CSSPrimitiveValue::CSS_NUMBER) || value->fValue < 0)
return false;
return mediaFeature == MediaFeatureNames::heightMediaFeature
|| mediaFeature == MediaFeatureNames::max_heightMediaFeature
|| mediaFeature == MediaFeatureNames::min_heightMediaFeature
|| mediaFeature == MediaFeatureNames::widthMediaFeature
|| mediaFeature == MediaFeatureNames::max_widthMediaFeature
|| mediaFeature == MediaFeatureNames::min_widthMediaFeature
|| mediaFeature == MediaFeatureNames::device_heightMediaFeature
|| mediaFeature == MediaFeatureNames::max_device_heightMediaFeature
|| mediaFeature == MediaFeatureNames::min_device_heightMediaFeature
|| mediaFeature == MediaFeatureNames::device_widthMediaFeature
|| mediaFeature == MediaFeatureNames::max_device_widthMediaFeature
|| mediaFeature == MediaFeatureNames::min_device_widthMediaFeature;
}
static inline bool featureWithValidDensity(const AtomicString& mediaFeature, const CSSParserValue* value)
{
if (!CSSPrimitiveValue::isResolution(value->unit) || value->fValue <= 0)
return false;
return mediaFeature == MediaFeatureNames::resolutionMediaFeature
|| mediaFeature == MediaFeatureNames::max_resolutionMediaFeature
|| mediaFeature == MediaFeatureNames::min_resolutionMediaFeature;
}
static inline bool featureWithPositiveInteger(const AtomicString& mediaFeature, const CSSParserValue* value)
{
if (!value->isInt || value->fValue < 0)
return false;
return mediaFeature == MediaFeatureNames::colorMediaFeature
|| mediaFeature == MediaFeatureNames::max_colorMediaFeature
|| mediaFeature == MediaFeatureNames::min_colorMediaFeature
|| mediaFeature == MediaFeatureNames::color_indexMediaFeature
|| mediaFeature == MediaFeatureNames::max_color_indexMediaFeature
|| mediaFeature == MediaFeatureNames::min_color_indexMediaFeature
|| mediaFeature == MediaFeatureNames::min_monochromeMediaFeature
|| mediaFeature == MediaFeatureNames::max_monochromeMediaFeature;
}
static inline bool featureWithPositiveNumber(const AtomicString& mediaFeature, const CSSParserValue* value)
{
if (value->unit != CSSPrimitiveValue::CSS_NUMBER || value->fValue < 0)
return false;
return mediaFeature == MediaFeatureNames::transform_2dMediaFeature
|| mediaFeature == MediaFeatureNames::transform_3dMediaFeature
|| mediaFeature == MediaFeatureNames::transitionMediaFeature
|| mediaFeature == MediaFeatureNames::animationMediaFeature
|| mediaFeature == MediaFeatureNames::device_pixel_ratioMediaFeature
|| mediaFeature == MediaFeatureNames::max_device_pixel_ratioMediaFeature
|| mediaFeature == MediaFeatureNames::min_device_pixel_ratioMediaFeature;
}
static inline bool featureWithZeroOrOne(const AtomicString& mediaFeature, const CSSParserValue* value)
{
if (!value->isInt || !(value->fValue == 1 || !value->fValue))
return false;
return mediaFeature == MediaFeatureNames::gridMediaFeature;
}
static inline bool featureWithAspectRatio(const AtomicString& mediaFeature)
{
return mediaFeature == MediaFeatureNames::aspect_ratioMediaFeature
|| mediaFeature == MediaFeatureNames::device_aspect_ratioMediaFeature
|| mediaFeature == MediaFeatureNames::min_aspect_ratioMediaFeature
|| mediaFeature == MediaFeatureNames::max_aspect_ratioMediaFeature
|| mediaFeature == MediaFeatureNames::min_device_aspect_ratioMediaFeature
|| mediaFeature == MediaFeatureNames::max_device_aspect_ratioMediaFeature;
}
static inline bool featureWithoutValue(const AtomicString& mediaFeature)
{
return mediaFeature == MediaFeatureNames::any_hoverMediaFeature
|| mediaFeature == MediaFeatureNames::any_pointerMediaFeature
|| mediaFeature == MediaFeatureNames::monochromeMediaFeature
|| mediaFeature == MediaFeatureNames::colorMediaFeature
|| mediaFeature == MediaFeatureNames::color_indexMediaFeature
|| mediaFeature == MediaFeatureNames::gridMediaFeature
|| mediaFeature == MediaFeatureNames::heightMediaFeature
|| mediaFeature == MediaFeatureNames::widthMediaFeature
|| mediaFeature == MediaFeatureNames::device_heightMediaFeature
|| mediaFeature == MediaFeatureNames::device_widthMediaFeature
|| mediaFeature == MediaFeatureNames::orientationMediaFeature
|| mediaFeature == MediaFeatureNames::aspect_ratioMediaFeature
|| mediaFeature == MediaFeatureNames::device_aspect_ratioMediaFeature
|| mediaFeature == MediaFeatureNames::hoverMediaFeature
|| mediaFeature == MediaFeatureNames::transform_2dMediaFeature
|| mediaFeature == MediaFeatureNames::transform_3dMediaFeature
|| mediaFeature == MediaFeatureNames::transitionMediaFeature
|| mediaFeature == MediaFeatureNames::animationMediaFeature
|| mediaFeature == MediaFeatureNames::inverted_colorsMediaFeature
#if ENABLE(VIEW_MODE_CSS_MEDIA)
|| mediaFeature == MediaFeatureNames::view_modeMediaFeature
#endif // ENABLE(VIEW_MODE_CSS_MEDIA)
|| mediaFeature == MediaFeatureNames::pointerMediaFeature
|| mediaFeature == MediaFeatureNames::device_pixel_ratioMediaFeature
|| mediaFeature == MediaFeatureNames::resolutionMediaFeature;
}
MediaQueryExp::MediaQueryExp(const AtomicString& mediaFeature, CSSParserValueList* valueList)
: m_mediaFeature(mediaFeature)
{
if (valueList) {
if (valueList->size() == 1) {
CSSParserValue* value = valueList->current();
if (featureWithCSSValueID(mediaFeature, value))
m_value = CSSPrimitiveValue::createIdentifier(value->id);
else if (featureWithValidDensity(mediaFeature, value))
m_value = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
else if (featureWithValidPositiveLenghtOrNumber(mediaFeature, value))
m_value = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
else if (featureWithPositiveInteger(mediaFeature, value))
m_value = CSSPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_NUMBER);
else if (featureWithPositiveNumber(mediaFeature, value))
m_value = CSSPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_NUMBER);
else if (featureWithZeroOrOne(mediaFeature, value))
m_value = CSSPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_NUMBER);
m_isValid = m_value;
} else if (valueList->size() == 3 && featureWithAspectRatio(mediaFeature)) {
bool isValid = true;
float numeratorValue = 0;
float denominatorValue = 0;
for (unsigned i = 0; i < 3; ++i, valueList->next()) {
const CSSParserValue* value = valueList->current();
if (i != 1 && value->unit == CSSPrimitiveValue::CSS_NUMBER && value->fValue > 0 && value->isInt) {
if (!i)
numeratorValue = value->fValue;
else
denominatorValue = value->fValue;
} else if (i == 1 && value->unit == CSSParserValue::Operator && value->iValue == '/')
continue;
else {
isValid = false;
break;
}
}
if (isValid)
m_value = CSSAspectRatioValue::create(numeratorValue, denominatorValue);
m_isValid = m_value;
}
} else if (featureWithoutValue(mediaFeature))
m_isValid = true;
}
String MediaQueryExp::serialize() const
{
if (!m_serializationCache.isNull())
return m_serializationCache;
StringBuilder result;
result.append('(');
result.append(m_mediaFeature.lower());
if (m_value) {
result.appendLiteral(": ");
result.append(m_value->cssText());
}
result.append(')');
m_serializationCache = result.toString();
return m_serializationCache;
}
}