Skip to content

Commit

Permalink
feat: add container query parser and container selector.
Browse files Browse the repository at this point in the history
  • Loading branch information
andycall committed Oct 10, 2024
1 parent 6873d89 commit f189c4a
Show file tree
Hide file tree
Showing 6 changed files with 558 additions and 0 deletions.
35 changes: 35 additions & 0 deletions bridge/core/css/container_query.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "container_query.h"
#include "core/css/css_markup.h"

namespace webf {

ContainerQuery::ContainerQuery(ContainerSelector selector,
std::shared_ptr<const MediaQueryExpNode> query)
: selector_(std::move(selector)), query_(query) {}

ContainerQuery::ContainerQuery(const ContainerQuery& other)
: selector_(other.selector_), query_(other.query_) {}

std::string ContainerQuery::ToString() const {
StringBuilder result;
std::string name = selector_.Name();
if (!name.empty()) {
SerializeIdentifier(name, result);
result.Append(' ');
}
result.Append(query_->Serialize());
return result.ReleaseString();
}

std::shared_ptr<ContainerQuery> ContainerQuery::CopyWithParent(
std::shared_ptr<const ContainerQuery> parent) const {
auto copy = std::make_shared<ContainerQuery>(*this);
copy->parent_ = std::move(parent);
return copy;
}

}
39 changes: 39 additions & 0 deletions bridge/core/css/container_query.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef WEBF_CORE_CSS_CONTAINER_QUERY_H_
#define WEBF_CORE_CSS_CONTAINER_QUERY_H_

#include "core/css/container_selector.h"

namespace webf {

class ContainerQuery final {
public:
ContainerQuery(ContainerSelector, std::shared_ptr<const MediaQueryExpNode> query);
ContainerQuery(const ContainerQuery&);

const ContainerSelector& Selector() const { return selector_; }
const ContainerQuery* Parent() const { return parent_.get(); }

std::shared_ptr<ContainerQuery> CopyWithParent(std::shared_ptr<const ContainerQuery>) const;

std::string ToString() const;

private:
friend class ContainerQueryTest;
friend class ContainerQueryEvaluator;
friend class CSSContainerRule;
friend class StyleRuleContainer;

const MediaQueryExpNode& Query() const { return *query_; }

ContainerSelector selector_;
std::shared_ptr<const MediaQueryExpNode> query_;
std::shared_ptr<const ContainerQuery> parent_;
};

}

#endif // WEBF_CORE_CSS_CONTAINER_QUERY_H_
73 changes: 73 additions & 0 deletions bridge/core/css/container_selector.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "container_selector.h"
#include "core/base/hash/hash.h"
#include "core/style/computed_style_constants.h"
#include "core/platform/hash_functions.h"

namespace webf {

ContainerSelector::ContainerSelector(const std::string& name,
const MediaQueryExpNode& query)
: name_(std::move(name)) {
MediaQueryExpNode::FeatureFlags feature_flags = query.CollectFeatureFlags();

if (feature_flags & MediaQueryExpNode::kFeatureInlineSize) {
logical_axes_ |= kLogicalAxesInline;
}
if (feature_flags & MediaQueryExpNode::kFeatureBlockSize) {
logical_axes_ |= kLogicalAxesBlock;
}
if (feature_flags & MediaQueryExpNode::kFeatureWidth) {
physical_axes_ |= kPhysicalAxesHorizontal;
}
if (feature_flags & MediaQueryExpNode::kFeatureHeight) {
physical_axes_ |= kPhysicalAxesVertical;
}
if (feature_flags & MediaQueryExpNode::kFeatureStyle) {
has_style_query_ = true;
}
if (feature_flags & MediaQueryExpNode::kFeatureSticky) {
has_sticky_query_ = true;
}
if (feature_flags & MediaQueryExpNode::kFeatureSnap) {
has_snap_query_ = true;
}
if (feature_flags & MediaQueryExpNode::kFeatureUnknown) {
has_unknown_feature_ = true;
}
}

unsigned ContainerSelector::GetHash() const {
unsigned hash = !name_.empty() ? SuperFastHash(name_.c_str(), name_.size()) : 0;
AddIntToHash(hash, physical_axes_.value());
AddIntToHash(hash, logical_axes_.value());
AddIntToHash(hash, has_style_query_);
AddIntToHash(hash, has_sticky_query_);
return hash;
}

unsigned ContainerSelector::Type(WritingMode writing_mode) const {
unsigned type = kContainerTypeNormal;

LogicalAxes axes =
logical_axes_ | ToLogicalAxes(physical_axes_, writing_mode);

if ((axes & kLogicalAxesInline).value()) {
type |= kContainerTypeInlineSize;
}
if ((axes & kLogicalAxesBlock).value()) {
type |= kContainerTypeBlockSize;
}
if (has_sticky_query_ || has_snap_query_) {
type |= kContainerTypeScrollState;
}
return type;
}

void ScopedContainerSelector::Trace(GCVisitor* visitor) const {
}

}
105 changes: 105 additions & 0 deletions bridge/core/css/container_selector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef WEBF_CORE_CSS_CONTAINER_SELECTOR_H_
#define WEBF_CORE_CSS_CONTAINER_SELECTOR_H_

#include "core/layout/geometry/axis.h"
#include "core/css/media_query_exp.h"
#include "core/base/hash/hash.h"
#include "core/platform/hash_functions.h"

namespace webf {

class Element;

// Not to be confused with regular selectors. This refers to container
// selection by e.g. a given name, or by implicit container selection
// according to the queried features.
//
// https://drafts.csswg.org/css-contain-3/#container-rule
class ContainerSelector {
public:
ContainerSelector() = default;
explicit ContainerSelector(PhysicalAxes physical_axes)
: physical_axes_(physical_axes) {}
ContainerSelector(const std::string& name,
PhysicalAxes physical_axes,
LogicalAxes logical_axes)
: name_(std::move(name)),
physical_axes_(physical_axes),
logical_axes_(logical_axes) {}
ContainerSelector(const std::string& name, const MediaQueryExpNode&);

bool operator==(const ContainerSelector& o) const {
return (name_ == o.name_) && (physical_axes_ == o.physical_axes_) &&
(logical_axes_ == o.logical_axes_) &&
(has_style_query_ == o.has_style_query_) &&
(has_sticky_query_ == o.has_sticky_query_) &&
(has_snap_query_ == o.has_snap_query_);
}
bool operator!=(const ContainerSelector& o) const { return !(*this == o); }

unsigned GetHash() const;

const std::string& Name() const { return name_; }

// Given the specified writing mode, return the EContainerTypes required
// for this selector to match.
unsigned Type(WritingMode) const;

bool SelectsSizeContainers() const {
return physical_axes_ != kPhysicalAxesNone ||
logical_axes_ != kLogicalAxesNone;
}

bool SelectsStyleContainers() const { return has_style_query_; }
bool SelectsStickyContainers() const { return has_sticky_query_; }
bool SelectsSnapContainers() const { return has_snap_query_; }
bool SelectsStateContainers() const {
return SelectsStickyContainers() || SelectsSnapContainers();
}
bool HasUnknownFeature() const { return has_unknown_feature_; }

PhysicalAxes GetPhysicalAxes() const { return physical_axes_; }
LogicalAxes GetLogicalAxes() const { return logical_axes_; }

private:
std::string name_;
PhysicalAxes physical_axes_{kPhysicalAxesNone};
LogicalAxes logical_axes_{kLogicalAxesNone};
bool has_style_query_{false};
bool has_sticky_query_{false};
bool has_snap_query_{false};
bool has_unknown_feature_{false};
};


class ScopedContainerSelector {
public:
ScopedContainerSelector(ContainerSelector selector,
const TreeScope* tree_scope)
: selector_(selector), tree_scope_(tree_scope) {}

unsigned GetHash() const {
unsigned hash = selector_.GetHash();
AddIntToHash(hash, reinterpret_cast<uint64_t>(tree_scope_));
return hash;
}

bool operator==(const ScopedContainerSelector& other) const {
return selector_ == other.selector_ && tree_scope_ == other.tree_scope_;
}

void Trace(GCVisitor* visitor) const;

private:
ContainerSelector selector_;
const TreeScope* tree_scope_;
};


}

#endif // WEBF_CORE_CSS_CONTAINER_SELECTOR_H_
Loading

0 comments on commit f189c4a

Please sign in to comment.