SizesAttributeParser.cpp [plain text]
#include "config.h"
#include "SizesAttributeParser.h"
#include "CSSPrimitiveValue.h"
#include "CSSToLengthConversionData.h"
#include "CSSTokenizer.h"
#include "FontCascade.h"
#include "MediaList.h"
#include "MediaQueryEvaluator.h"
#include "MediaQueryParser.h"
#include "MediaQueryParserContext.h"
#include "RenderView.h"
#include "SizesCalcParser.h"
#include "StyleScope.h"
namespace WebCore {
float SizesAttributeParser::computeLength(double value, CSSUnitType type, const Document& document)
{
auto* renderer = document.renderView();
if (!renderer)
return 0;
auto& style = renderer->style();
CSSToLengthConversionData conversionData(&style, &style, renderer->parentStyle(), renderer);
if (type == CSSUnitType::CSS_EXS || type == CSSUnitType::CSS_CHS) {
RefPtr<FontSelector> fontSelector = style.fontCascade().fontSelector();
style.fontCascade().update(nullptr);
float result = CSSPrimitiveValue::computeNonCalcLengthDouble(conversionData, type, value);
style.fontCascade().update(fontSelector.get());
return result;
}
return clampTo<float>(CSSPrimitiveValue::computeNonCalcLengthDouble(conversionData, type, value));
}
SizesAttributeParser::SizesAttributeParser(const String& attribute, const Document& document, MediaQueryDynamicResults* mediaQueryDynamicResults)
: m_document(document)
, m_mediaQueryDynamicResults(mediaQueryDynamicResults)
{
m_isValid = parse(CSSTokenizer(attribute).tokenRange());
}
float SizesAttributeParser::length()
{
if (m_isValid)
return effectiveSize();
return effectiveSizeDefaultValue();
}
bool SizesAttributeParser::calculateLengthInPixels(CSSParserTokenRange range, float& result)
{
const CSSParserToken& startToken = range.peek();
CSSParserTokenType type = startToken.type();
if (type == DimensionToken) {
if (!CSSPrimitiveValue::isLength(startToken.unitType()))
return false;
result = computeLength(startToken.numericValue(), startToken.unitType(), m_document);
if (result >= 0)
return true;
} else if (type == FunctionToken) {
SizesCalcParser calcParser(range, m_document);
if (!calcParser.isValid())
return false;
result = calcParser.result();
return true;
} else if (type == NumberToken && !startToken.numericValue()) {
result = 0;
return true;
}
return false;
}
bool SizesAttributeParser::mediaConditionMatches(const MediaQuerySet& mediaCondition)
{
auto* renderer = m_document.renderView();
if (!renderer)
return false;
auto& style = renderer->style();
return MediaQueryEvaluator { "screen", m_document, &style }.evaluate(mediaCondition, m_mediaQueryDynamicResults);
}
bool SizesAttributeParser::parse(CSSParserTokenRange range)
{
while (!range.atEnd()) {
const CSSParserToken* mediaConditionStart = &range.peek();
const CSSParserToken* lengthTokenStart = &range.peek();
const CSSParserToken* lengthTokenEnd = &range.peek();
while (!range.atEnd() && range.peek().type() != CommaToken) {
lengthTokenStart = &range.peek();
range.consumeComponentValue();
lengthTokenEnd = &range.peek();
range.consumeWhitespace();
}
range.consume();
float length;
if (!calculateLengthInPixels(range.makeSubRange(lengthTokenStart, lengthTokenEnd), length))
continue;
RefPtr<MediaQuerySet> mediaCondition = MediaQueryParser::parseMediaCondition(range.makeSubRange(mediaConditionStart, lengthTokenStart), MediaQueryParserContext(m_document));
if (!mediaCondition || !mediaConditionMatches(*mediaCondition))
continue;
m_length = length;
m_lengthWasSet = true;
return true;
}
return false;
}
float SizesAttributeParser::effectiveSize()
{
if (m_lengthWasSet)
return m_length;
return effectiveSizeDefaultValue();
}
unsigned SizesAttributeParser::effectiveSizeDefaultValue()
{
auto* renderer = m_document.renderView();
if (!renderer)
return 0;
auto& style = renderer->style();
return clampTo<float>(CSSPrimitiveValue::computeNonCalcLengthDouble({ &style, &style, renderer->parentStyle(), renderer }, CSSUnitType::CSS_VW, 100.0));
}
}