|
Lines 35-64
a/Source/WebCore/style/ContainerQueryEvaluator.cpp_sec1
|
| 35 |
|
35 |
|
| 36 |
namespace WebCore::Style { |
36 |
namespace WebCore::Style { |
| 37 |
|
37 |
|
|
|
38 |
struct ContainerQueryEvaluator::EvaluationContext { |
| 39 |
RenderBox& renderer; |
| 40 |
CSSToLengthConversionData conversionData; |
| 41 |
}; |
| 42 |
|
| 38 |
ContainerQueryEvaluator::ContainerQueryEvaluator(const Vector<Ref<const Element>>& containers) |
43 |
ContainerQueryEvaluator::ContainerQueryEvaluator(const Vector<Ref<const Element>>& containers) |
| 39 |
: m_containers(containers) |
44 |
: m_containers(containers) |
| 40 |
{ |
45 |
{ |
| 41 |
} |
46 |
} |
| 42 |
|
47 |
|
| 43 |
static std::optional<LayoutUnit> computeSize(CSSValue* value, const CSSToLengthConversionData& conversionData) |
48 |
static std::optional<LayoutUnit> computeSize(const CSSPrimitiveValue& value, const CSSToLengthConversionData& conversionData) |
| 44 |
{ |
49 |
{ |
| 45 |
if (!is<CSSPrimitiveValue>(value)) |
50 |
if (value.isNumberOrInteger()) { |
| 46 |
return { }; |
51 |
if (value.doubleValue()) |
| 47 |
|
|
|
| 48 |
auto& primitiveValue = downcast<CSSPrimitiveValue>(*value); |
| 49 |
if (primitiveValue.isNumberOrInteger()) { |
| 50 |
if (primitiveValue.doubleValue()) |
| 51 |
return { }; |
52 |
return { }; |
| 52 |
return 0_lu; |
53 |
return 0_lu; |
| 53 |
} |
54 |
} |
| 54 |
|
55 |
|
| 55 |
if (!primitiveValue.isLength()) |
56 |
if (!value.isLength()) |
| 56 |
return { }; |
57 |
return { }; |
| 57 |
return primitiveValue.computeLength<LayoutUnit>(conversionData); |
58 |
return value.computeLength<LayoutUnit>(conversionData); |
| 58 |
} |
59 |
} |
| 59 |
|
60 |
|
| 60 |
enum class Comparator { Lesser, Greater, LesserOrEqual, GreaterOrEqual, Equal, True }; |
|
|
| 61 |
|
| 62 |
bool ContainerQueryEvaluator::evaluate(const FilteredContainerQuery& filteredContainerQuery) const |
61 |
bool ContainerQueryEvaluator::evaluate(const FilteredContainerQuery& filteredContainerQuery) const |
| 63 |
{ |
62 |
{ |
| 64 |
if (m_containers.isEmpty()) |
63 |
if (m_containers.isEmpty()) |
|
Lines 83-172
bool ContainerQueryEvaluator::evaluate(const FilteredContainerQuery& filteredCon
a/Source/WebCore/style/ContainerQueryEvaluator.cpp_sec2
|
| 83 |
return false; |
82 |
return false; |
| 84 |
|
83 |
|
| 85 |
auto& view = renderer->view(); |
84 |
auto& view = renderer->view(); |
| 86 |
CSSToLengthConversionData conversionData { &renderer->style(), &view.style(), nullptr, &view, 1 }; |
85 |
CSSToLengthConversionData { &renderer->style(), &view.style(), nullptr, &view, 1 }; |
| 87 |
|
86 |
|
| 88 |
auto evaluateSize = [&](const MediaQueryExpression& expression, Comparator comparator, auto&& sizeGetter) |
87 |
EvaluationContext evaluationContext { |
| 89 |
{ |
88 |
*renderer, |
|
|
89 |
CSSToLengthConversionData { &renderer->style(), &view.style(), nullptr, &view, 1 } |
| 90 |
}; |
| 91 |
|
| 92 |
return evaluateQuery(filteredContainerQuery.query, evaluationContext) == EvaluationResult::True; |
| 93 |
} |
| 94 |
|
| 95 |
auto ContainerQueryEvaluator::evaluateQuery(const CQ::ContainerQuery& containerQuery, const EvaluationContext& context) const -> EvaluationResult |
| 96 |
{ |
| 97 |
return WTF::switchOn(containerQuery, [&](const CQ::ContainerCondition& containerCondition) { |
| 98 |
return evaluateCondition(containerCondition, context); |
| 99 |
}, [&](const CQ::SizeQuery& sizeQuery) { |
| 100 |
return evaluateQuery(sizeQuery, context); |
| 101 |
}, [&](const CQ::UnknownQuery&) { |
| 102 |
return EvaluationResult::Unknown; |
| 103 |
}); |
| 104 |
} |
| 105 |
|
| 106 |
auto ContainerQueryEvaluator::evaluateQuery(const CQ::SizeQuery& sizeQuery, const EvaluationContext& context) const -> EvaluationResult |
| 107 |
{ |
| 108 |
return WTF::switchOn(sizeQuery, [&](const CQ::SizeCondition& sizeCondition) { |
| 109 |
return evaluateCondition(sizeCondition, context); |
| 110 |
}, [&](const CQ::SizeFeature& sizeFeature) { |
| 111 |
return evaluateSizeFeature(sizeFeature, context); |
| 112 |
}); |
| 113 |
} |
| 114 |
|
| 115 |
template<typename ConditionType> |
| 116 |
auto ContainerQueryEvaluator::evaluateCondition(const ConditionType& condition, const EvaluationContext& context) const -> EvaluationResult |
| 117 |
{ |
| 118 |
if (condition.queries.isEmpty()) |
| 119 |
return EvaluationResult::Unknown; |
| 120 |
|
| 121 |
switch (condition.logicalOperator) { |
| 122 |
case CQ::LogicalOperator::Not: { |
| 123 |
switch (evaluateQuery(condition.queries.first(), context)) { |
| 124 |
case EvaluationResult::True: |
| 125 |
return EvaluationResult::False; |
| 126 |
case EvaluationResult::False: |
| 127 |
return EvaluationResult::True; |
| 128 |
case EvaluationResult::Unknown: |
| 129 |
return EvaluationResult::Unknown; |
| 130 |
} |
| 131 |
} |
| 132 |
case CQ::LogicalOperator::And: { |
| 133 |
auto result = EvaluationResult::True; |
| 134 |
for (auto query : condition.queries) { |
| 135 |
auto queryResult = evaluateQuery(query, context); |
| 136 |
if (queryResult == EvaluationResult::False) |
| 137 |
return EvaluationResult::False; |
| 138 |
if (queryResult == EvaluationResult::Unknown) |
| 139 |
result = EvaluationResult::Unknown; |
| 140 |
} |
| 141 |
return result; |
| 142 |
} |
| 143 |
case CQ::LogicalOperator::Or: { |
| 144 |
auto result = EvaluationResult::False; |
| 145 |
for (auto query : condition.queries) { |
| 146 |
auto queryResult = evaluateQuery(query, context); |
| 147 |
if (queryResult == EvaluationResult::True) |
| 148 |
return EvaluationResult::True; |
| 149 |
if (queryResult == EvaluationResult::Unknown) |
| 150 |
result = EvaluationResult::Unknown; |
| 151 |
} |
| 152 |
return result; |
| 153 |
} |
| 154 |
} |
| 155 |
} |
| 156 |
|
| 157 |
auto ContainerQueryEvaluator::evaluateSizeFeature(const CQ::SizeFeature& sizeFeature, const EvaluationContext& context) const -> EvaluationResult |
| 158 |
{ |
| 159 |
auto evaluateSize = [&](LayoutUnit size) { |
| 90 |
std::optional<LayoutUnit> expressionSize; |
160 |
std::optional<LayoutUnit> expressionSize; |
| 91 |
|
161 |
|
| 92 |
if (comparator != Comparator::True) { |
162 |
if (sizeFeature.comparisonOperator != CQ::ComparisonOperator::True) { |
| 93 |
expressionSize = computeSize(expression.value(), conversionData); |
163 |
if (!sizeFeature.value) |
|
|
164 |
return false; |
| 165 |
expressionSize = computeSize(*sizeFeature.value, context.conversionData); |
| 94 |
if (!expressionSize) |
166 |
if (!expressionSize) |
| 95 |
return false; |
167 |
return false; |
| 96 |
} |
168 |
} |
| 97 |
|
169 |
|
| 98 |
auto size = sizeGetter(*renderer); |
170 |
switch (sizeFeature.comparisonOperator) { |
| 99 |
|
171 |
case CQ::ComparisonOperator::LessThan: |
| 100 |
switch (comparator) { |
|
|
| 101 |
case Comparator::Lesser: |
| 102 |
return size < *expressionSize; |
172 |
return size < *expressionSize; |
| 103 |
case Comparator::Greater: |
173 |
case CQ::ComparisonOperator::GreaterThan: |
| 104 |
return size > *expressionSize; |
174 |
return size > *expressionSize; |
| 105 |
case Comparator::LesserOrEqual: |
175 |
case CQ::ComparisonOperator::LessThanOrEqual: |
| 106 |
return size <= *expressionSize; |
176 |
return size <= *expressionSize; |
| 107 |
case Comparator::GreaterOrEqual: |
177 |
case CQ::ComparisonOperator::GreaterThanOrEqual: |
| 108 |
return size >= *expressionSize; |
178 |
return size >= *expressionSize; |
| 109 |
case Comparator::Equal: |
179 |
case CQ::ComparisonOperator::Equal: |
| 110 |
return size == *expressionSize; |
180 |
return size == *expressionSize; |
| 111 |
case Comparator::True: |
181 |
case CQ::ComparisonOperator::True: |
| 112 |
return !!size; |
182 |
return !!size; |
| 113 |
} |
183 |
} |
| 114 |
}; |
184 |
}; |
| 115 |
|
185 |
|
| 116 |
auto evaluateWidth = [&](const MediaQueryExpression& expression, Comparator comparator) |
186 |
// FIXME: Support all features. |
| 117 |
{ |
187 |
if (sizeFeature.name == MediaFeatureNames::width) |
| 118 |
return evaluateSize(expression, comparator, [&](const RenderBox& renderer) { |
188 |
return evaluateSize(context.renderer.width()) ? EvaluationResult::True : EvaluationResult::False; |
| 119 |
return renderer.width(); |
189 |
if (sizeFeature.name == MediaFeatureNames::height) |
| 120 |
}); |
190 |
return evaluateSize(context.renderer.height()) ? EvaluationResult::True : EvaluationResult::False; |
| 121 |
}; |
|
|
| 122 |
|
| 123 |
auto evaluateHeight = [&](const MediaQueryExpression& expression, Comparator comparator) |
| 124 |
{ |
| 125 |
return evaluateSize(expression, comparator, [&](const RenderBox& renderer) { |
| 126 |
return renderer.height(); |
| 127 |
}); |
| 128 |
}; |
| 129 |
|
| 130 |
bool result = false; |
| 131 |
|
| 132 |
// FIXME: This is very rudimentary. |
| 133 |
auto& queries = filteredContainerQuery.query->queryVector(); |
| 134 |
for (auto& query : queries) { |
| 135 |
for (auto& expression : query.expressions()) { |
| 136 |
if (expression.mediaFeature() == MediaFeatureNames::minWidth) { |
| 137 |
if (evaluateWidth(expression, Comparator::GreaterOrEqual)) |
| 138 |
result = true; |
| 139 |
continue; |
| 140 |
} |
| 141 |
if (expression.mediaFeature() == MediaFeatureNames::maxWidth) { |
| 142 |
if (evaluateWidth(expression, Comparator::LesserOrEqual)) |
| 143 |
result = true; |
| 144 |
continue; |
| 145 |
} |
| 146 |
if (expression.mediaFeature() == MediaFeatureNames::width) { |
| 147 |
if (evaluateWidth(expression, expression.value() ? Comparator::Equal : Comparator::True)) |
| 148 |
result = true; |
| 149 |
continue; |
| 150 |
} |
| 151 |
if (expression.mediaFeature() == MediaFeatureNames::minHeight) { |
| 152 |
if (evaluateHeight(expression, Comparator::GreaterOrEqual)) |
| 153 |
result = true; |
| 154 |
continue; |
| 155 |
} |
| 156 |
if (expression.mediaFeature() == MediaFeatureNames::maxHeight) { |
| 157 |
if (evaluateHeight(expression, Comparator::LesserOrEqual)) |
| 158 |
result = true; |
| 159 |
continue; |
| 160 |
} |
| 161 |
if (expression.mediaFeature() == MediaFeatureNames::height) { |
| 162 |
if (evaluateHeight(expression, expression.value() ? Comparator::Equal : Comparator::True)) |
| 163 |
result = true; |
| 164 |
continue; |
| 165 |
} |
| 166 |
} |
| 167 |
} |
| 168 |
|
191 |
|
| 169 |
return result; |
192 |
return EvaluationResult::Unknown; |
| 170 |
} |
193 |
} |
| 171 |
|
194 |
|
| 172 |
} |
195 |
} |