Commit 62c3e4da authored by Oriol Brufau's avatar Oriol Brufau Committed by Chromium LUCI CQ

[css-logical] Implement logical property groups

In order to have proper CSSOM support for logical properties, we will
need to determine whether two properties belong to the same logical
property group but with a different mapping logic.

Before this patch, we only knew the physical properties belonging to the
same logical property group as a given logical property. But given a
physical property, we didn't know if there were logical properties that
could map to it.

Therefore this patch adds:
 - CSSProperty::IsInLogicalPropertyGroup, which returns true for logical
   properties and for their corresponding physical ones.
 - CSSProperty::IsInSameLogicalPropertyGroupWithDifferentMappingLogic
   which checks what the name says, given a CSSPropertyID.
 - CSSDirectionAwareResolver::LogicalMapping and PhysicalMapping,
   representing the properties of a logical property group with a flow-
   relative or a physical mapping logic, respectively.

In css_properties.json5, the terminology becomes closer to the spec:
 - direction_aware_options becomes logical_property_group, and physical
   properties have it too.
 - direction_aware_options.physical_group becomes
   logical_property_group.name
 - direction_aware_options.resolver accepts physical axis and box sides
   (horizontal, vertical, top, right, bottom, left).

This patch should have no effect in practice.

Bug: 1155858

Change-Id: I1a01e80a2405315d9caaf057e6bfd465f3615cce
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2574940
Commit-Queue: Oriol Brufau <obrufau@igalia.com>
Reviewed-by: default avatarAnders Hartvoll Ruud <andruud@chromium.org>
Cr-Commit-Position: refs/heads/master@{#834200}
parent 46a1d77a
......@@ -320,15 +320,27 @@ class CSSProperties(object):
set_if_none(property_, 'custom_compare', False)
set_if_none(property_, 'mutable', False)
if property_['direction_aware_options']:
if not property_['style_builder_template']:
if property_['logical_property_group']:
group = property_['logical_property_group']
assert 'name' in group, 'name option is required'
assert 'resolver' in group, 'resolver option is required'
logicals = {
'block', 'inline', 'block-start', 'block-end', 'inline-start',
'inline-end'
}
physicals = {
'vertical', 'horizontal', 'top', 'bottom', 'left', 'right'
}
if group['resolver'] in logicals:
group['is_logical'] = True
elif group['resolver'] in physicals:
group['is_logical'] = False
else:
assert 0, 'invalid resolver option'
group['name'] = NameStyleConverter(group['name'])
group['resolver_name'] = NameStyleConverter(group['resolver'])
if not property_['style_builder_template'] and group['is_logical']:
property_['style_builder_template'] = 'direction_aware'
options = property_['direction_aware_options']
assert 'resolver' in options, 'resolver option is required'
assert 'physical_group' in options, 'physical_group option is required'
options['resolver_name'] = NameStyleConverter(options['resolver'])
options['physical_group_name'] = NameStyleConverter(
options['physical_group'])
@property
def default_parameters(self):
......
......@@ -101,10 +101,11 @@ bool {{class_name}}::ComputedValuesEqual(const ComputedStyle& a, const ComputedS
{% endif %}
}
{% endif %}
{% if property.direction_aware_options %}
{% set options = property.direction_aware_options %}
{% set resolver_name = options.resolver_name.to_upper_camel_case() %}
{% set physical_group_name = options.physical_group_name.to_upper_camel_case() %}
{% if property.logical_property_group %}
{% set group = property.logical_property_group %}
{% set group_name = group.name.to_upper_camel_case() %}
{% set resolver_name = group.resolver_name.to_upper_camel_case() %}
{% if group.is_logical %}
const CSSProperty* {{class_name}}::SurrogateFor(TextDirection direction,
blink::WritingMode writing_mode) const {
return &ResolveDirectionAwareProperty(direction, writing_mode);
......@@ -114,8 +115,19 @@ const CSSProperty& {{class_name}}::ResolveDirectionAwareProperty(
TextDirection direction,
blink::WritingMode writing_mode) const {
return CSSDirectionAwareResolver::Resolve{{resolver_name}}(direction, writing_mode,
CSSDirectionAwareResolver::{{physical_group_name}}Group());
CSSDirectionAwareResolver::Physical{{group_name}}Mapping());
}
bool {{class_name}}::IsInSameLogicalPropertyGroupWithDifferentMappingLogic(
CSSPropertyID id) const {
return CSSDirectionAwareResolver::Physical{{group_name}}Mapping().Contains(id);
}
{% else %}
bool {{class_name}}::IsInSameLogicalPropertyGroupWithDifferentMappingLogic(
CSSPropertyID id) const {
return CSSDirectionAwareResolver::Logical{{group_name}}Mapping().Contains(id);
}
{% endif %}
{% endif %}
{{style_builder_functions(property)}}
......
......@@ -29,7 +29,8 @@ namespace {{namespace}} {
{% for property in properties %}
{% set class_name = property.name.to_upper_camel_case() %}
{% set is_alias = property.alias_for %}
{% set is_surrogate = property.surrogate_for or property.direction_aware_options %}
{% set is_surrogate = property.surrogate_for or
(property.logical_property_group and property.logical_property_group.is_logical) %}
{% set property_id = 'CSSPropertyID::' + property.enum_key %}
{% set separator = '\'' + (property.separator or '\\0') + '\'' %}
{% set flags = [
......@@ -51,6 +52,7 @@ namespace {{namespace}} {
(property.computed_value_comparable and 'kComputedValueComparable' or ''),
(property.tree_scoped_value and 'kTreeScopedValue' or ''),
(property.valid_for_highlight and 'kValidForHighlight' or ''),
(property.logical_property_group and 'kInLogicalPropertyGroup' or ''),
] | reject('==', '') | join(' | ') %}
{% set ctor_args = (not is_alias and [property_id, flags, separator] or []) %}
// {{property.name}}
......@@ -80,7 +82,7 @@ class {{class_name}} final : public {{property.superclass}} {
{% if property.unvisited_property %}
const CSSProperty* GetUnvisitedProperty() const override;
{% endif %}
{% if property.surrogate_for or property.direction_aware_options %}
{% if is_surrogate %}
const CSSProperty* SurrogateFor(TextDirection, blink::WritingMode) const override;
{% endif %}
{% for property_method in property.property_methods %}
......@@ -89,7 +91,9 @@ class {{class_name}} final : public {{property.superclass}} {
{% if property.computed_value_comparable %}
bool ComputedValuesEqual(const ComputedStyle& a, const ComputedStyle& b) const override;
{% endif %}
{% if property.direction_aware_options %}
{% if property.logical_property_group %}
bool IsInSameLogicalPropertyGroupWithDifferentMappingLogic(CSSPropertyID) const override;
{% if property.logical_property_group.is_logical %}
const CSSProperty& ResolveDirectionAwareProperty(TextDirection, blink::WritingMode) const override;
const CSSValue* CSSValueFromComputedStyleInternal(
const ComputedStyle&,
......@@ -101,6 +105,7 @@ class {{class_name}} final : public {{property.superclass}} {
NOTREACHED();
return nullptr;
}
{% endif %}
{% endif %}
{% if property.style_builder_declare %}
void ApplyInitial(StyleResolverState&) const override;
......
......@@ -11,65 +11,130 @@
namespace blink {
enum class CSSPropertyID;
class CSSProperty;
class StylePropertyShorthand;
class CSSDirectionAwareResolver {
STATIC_ONLY(CSSDirectionAwareResolver);
public:
// A group of physical properties that's used by the 'Resolve*' functions
// to convert a direction-aware property into a physical property.
private:
template <size_t size>
class PhysicalGroup {
class Group {
public:
PhysicalGroup(const StylePropertyShorthand&);
PhysicalGroup(const CSSProperty* (&properties)[size]);
explicit Group(const StylePropertyShorthand&);
explicit Group(const CSSProperty* (&properties)[size]);
const CSSProperty& GetProperty(size_t index) const;
bool Contains(CSSPropertyID) const;
private:
const CSSProperty** properties_;
};
static PhysicalGroup<4> BorderGroup();
static PhysicalGroup<4> BorderColorGroup();
static PhysicalGroup<4> BorderStyleGroup();
static PhysicalGroup<4> BorderWidthGroup();
static PhysicalGroup<4> InsetGroup();
static PhysicalGroup<4> MarginGroup();
static PhysicalGroup<2> MaxSizeGroup();
static PhysicalGroup<2> MinSizeGroup();
static PhysicalGroup<2> OverflowGroup();
static PhysicalGroup<2> OverscrollBehaviorGroup();
static PhysicalGroup<4> PaddingGroup();
static PhysicalGroup<4> ScrollMarginGroup();
static PhysicalGroup<4> ScrollPaddingGroup();
static PhysicalGroup<2> SizeGroup();
static PhysicalGroup<4> VisitedBorderColorGroup();
// These resolvers expect a PhysicalGroup with box sides, in the following
public:
// A group of logical properties that's used by the 'Resolve*' functions
// to convert a physical property into a direction-aware property.
// It represents the properties in a logical property group [1] with
// a flow-relative mapping logic [2].
// [1]: https://drafts.csswg.org/css-logical/#logical-property-group
// [2]: https://drafts.csswg.org/css-logical/#mapping-logic
template <size_t size>
class LogicalMapping : public Group<size> {
using Group<size>::Group;
};
// A group of physical properties that's used by the 'Resolve*' functions
// to convert a direction-aware property into a physical property.
// It represents the properties in a logical property group [1] with
// a physical mapping logic [2].
// [1]: https://drafts.csswg.org/css-logical/#logical-property-group
// [2]: https://drafts.csswg.org/css-logical/#mapping-logic
template <size_t size>
class PhysicalMapping : public Group<size> {
using Group<size>::Group;
};
static LogicalMapping<4> LogicalBorderMapping();
static LogicalMapping<4> LogicalBorderColorMapping();
static LogicalMapping<4> LogicalBorderStyleMapping();
static LogicalMapping<4> LogicalBorderWidthMapping();
static LogicalMapping<4> LogicalInsetMapping();
static LogicalMapping<4> LogicalMarginMapping();
static LogicalMapping<2> LogicalMaxSizeMapping();
static LogicalMapping<2> LogicalMinSizeMapping();
static LogicalMapping<2> LogicalOverflowMapping();
static LogicalMapping<2> LogicalOverscrollBehaviorMapping();
static LogicalMapping<4> LogicalPaddingMapping();
static LogicalMapping<4> LogicalScrollMarginMapping();
static LogicalMapping<4> LogicalScrollPaddingMapping();
static LogicalMapping<2> LogicalSizeMapping();
static LogicalMapping<4> LogicalVisitedBorderColorMapping();
static PhysicalMapping<4> PhysicalBorderMapping();
static PhysicalMapping<4> PhysicalBorderColorMapping();
static PhysicalMapping<4> PhysicalBorderStyleMapping();
static PhysicalMapping<4> PhysicalBorderWidthMapping();
static PhysicalMapping<4> PhysicalInsetMapping();
static PhysicalMapping<4> PhysicalMarginMapping();
static PhysicalMapping<2> PhysicalMaxSizeMapping();
static PhysicalMapping<2> PhysicalMinSizeMapping();
static PhysicalMapping<2> PhysicalOverflowMapping();
static PhysicalMapping<2> PhysicalOverscrollBehaviorMapping();
static PhysicalMapping<4> PhysicalPaddingMapping();
static PhysicalMapping<4> PhysicalScrollMarginMapping();
static PhysicalMapping<4> PhysicalScrollPaddingMapping();
static PhysicalMapping<2> PhysicalSizeMapping();
static PhysicalMapping<4> PhysicalVisitedBorderColorMapping();
// These resolvers expect a PhysicalMapping with box sides, in the following
// order: top, right, bottom, left.
static const CSSProperty& ResolveInlineStart(TextDirection,
WritingMode,
const PhysicalGroup<4>&);
const PhysicalMapping<4>&);
static const CSSProperty& ResolveInlineEnd(TextDirection,
WritingMode,
const PhysicalGroup<4>&);
const PhysicalMapping<4>&);
static const CSSProperty& ResolveBlockStart(TextDirection,
WritingMode,
const PhysicalGroup<4>&);
const PhysicalMapping<4>&);
static const CSSProperty& ResolveBlockEnd(TextDirection,
WritingMode,
const PhysicalGroup<4>&);
const PhysicalMapping<4>&);
// These resolvers expect a LogicalMapping with box sides, in the following
// order: block-start, block-end, inline-start, inline-end.
// TODO(layout-dev): Implement them, if needed.
static const CSSProperty& ResolveTop(TextDirection,
WritingMode,
const LogicalMapping<4>&);
static const CSSProperty& ResolveBottom(TextDirection,
WritingMode,
const LogicalMapping<4>&);
static const CSSProperty& ResolveLeft(TextDirection,
WritingMode,
const LogicalMapping<4>&);
static const CSSProperty& ResolveRight(TextDirection,
WritingMode,
const LogicalMapping<4>&);
// These resolvers expect a PhysicalGroup with dimensions, in the following
// These resolvers expect a PhysicalMapping with dimensions, in the following
// order: horizontal, vertical.
static const CSSProperty& ResolveInline(TextDirection,
WritingMode,
const PhysicalGroup<2>&);
const PhysicalMapping<2>&);
static const CSSProperty& ResolveBlock(TextDirection,
WritingMode,
const PhysicalGroup<2>&);
const PhysicalMapping<2>&);
// These resolvers expect a LogicalMapping with dimensions, in the following
// order: block, inline.
// TODO(layout-dev): Implement them, if needed.
static const CSSProperty& ResolveHorizontal(TextDirection,
WritingMode,
const LogicalMapping<2>&);
static const CSSProperty& ResolveVertical(TextDirection,
WritingMode,
const LogicalMapping<2>&);
};
} // namespace blink
......
......@@ -8,6 +8,7 @@
#include <memory>
#include "third_party/blink/renderer/core/css/css_property_name.h"
#include "third_party/blink/renderer/core/css/css_value.h"
#include "third_party/blink/renderer/core/css/properties/css_direction_aware_resolver.h"
#include "third_party/blink/renderer/core/css/properties/css_unresolved_property.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
#include "third_party/blink/renderer/platform/text/text_direction.h"
......@@ -62,6 +63,9 @@ class CORE_EXPORT CSSProperty : public CSSUnresolvedProperty {
return flags_ & kComputedValueComparable;
}
bool TakesTreeScopedValue() const { return flags_ & kTreeScopedValue; }
bool IsInLogicalPropertyGroup() const {
return flags_ & kInLogicalPropertyGroup;
}
bool IsRepeated() const { return repetition_separator_ != '\0'; }
char RepetitionSeparator() const { return repetition_separator_; }
......@@ -100,6 +104,10 @@ class CORE_EXPORT CSSProperty : public CSSUnresolvedProperty {
WritingMode) const {
return *this;
}
virtual bool IsInSameLogicalPropertyGroupWithDifferentMappingLogic(
CSSPropertyID) const {
return false;
}
virtual const CSSProperty* GetVisitedProperty() const { return nullptr; }
virtual const CSSProperty* GetUnvisitedProperty() const { return nullptr; }
......@@ -151,6 +159,8 @@ class CORE_EXPORT CSSProperty : public CSSUnresolvedProperty {
kTreeScopedValue = 1 << 18,
// https://drafts.csswg.org/css-pseudo-4/#highlight-styling
kValidForHighlight = 1 << 19,
// https://drafts.csswg.org/css-logical/#logical-property-group
kInLogicalPropertyGroup = 1 << 20,
};
constexpr CSSProperty(CSSPropertyID property_id,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment