| /* |
| * Copyright (C) 2013 Google Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following disclaimer |
| * in the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of Google Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_TO_LENGTH_CONVERSION_DATA_H_ |
| #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_TO_LENGTH_CONVERSION_DATA_H_ |
| |
| #include <optional> |
| |
| #include "third_party/blink/renderer/core/core_export.h" |
| #include "third_party/blink/renderer/core/css/css_length_resolver.h" |
| #include "third_party/blink/renderer/core/css/css_primitive_value.h" |
| #include "third_party/blink/renderer/core/layout/geometry/axis.h" |
| #include "third_party/blink/renderer/core/style/computed_style.h" |
| #include "third_party/blink/renderer/platform/text/writing_mode.h" |
| #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" |
| #include "third_party/blink/renderer/platform/wtf/math_extras.h" |
| |
| namespace blink { |
| |
| class AnchorEvaluator; |
| class ComputedStyle; |
| class Element; |
| class Font; |
| class FontSizeStyle; |
| class LayoutView; |
| |
| class CORE_EXPORT CSSToLengthConversionData : public CSSLengthResolver { |
| STACK_ALLOCATED(); |
| |
| public: |
| class CORE_EXPORT FontSizes { |
| DISALLOW_NEW(); |
| |
| public: |
| FontSizes() = default; |
| FontSizes(float em, float rem, const Font* font, float font_zoom) |
| : em_(em), |
| rem_(rem), |
| font_(font), |
| root_font_(font), |
| font_zoom_(font_zoom), |
| root_font_zoom_(font_zoom) { |
| DCHECK(font_); |
| } |
| |
| FontSizes(float em, |
| float rem, |
| const Font* font, |
| const Font* root_font, |
| float font_zoom, |
| float root_font_zoom) |
| : em_(em), |
| rem_(rem), |
| font_(font), |
| root_font_(root_font), |
| font_zoom_(font_zoom), |
| root_font_zoom_(root_font_zoom) { |
| DCHECK(font_); |
| DCHECK(root_font_); |
| } |
| |
| FontSizes(const FontSizeStyle& style, const ComputedStyle* root_style) |
| : FontSizes(style.SpecifiedFontSize(), |
| root_style ? root_style->SpecifiedFontSize() |
| : style.SpecifiedFontSize(), |
| &style.GetFont(), |
| root_style ? &root_style->GetFont() : &style.GetFont(), |
| style.EffectiveZoom(), |
| root_style ? root_style->EffectiveZoom() |
| : style.EffectiveZoom()) {} |
| |
| float Em(float zoom) const { return em_ * zoom; } |
| float Rem(float zoom) const { return rem_ * zoom; } |
| float Ex(float zoom) const; |
| float Rex(float zoom) const; |
| float Ch(float zoom) const; |
| float Rch(float zoom) const; |
| float Ic(float zoom) const; |
| float Ric(float zoom) const; |
| float Cap(float zoom) const; |
| float Rcap(float zoom) const; |
| |
| private: |
| float em_ = 0; |
| float rem_ = 0; |
| const Font* font_ = nullptr; |
| const Font* root_font_ = nullptr; |
| // Font-metrics-based units (ex, ch, ic) are pre-zoomed by a factor of |
| // `font_zoom_`. |
| float font_zoom_ = 1; |
| float root_font_zoom_ = 1; |
| }; |
| |
| class CORE_EXPORT LineHeightSize { |
| DISALLOW_NEW(); |
| |
| public: |
| LineHeightSize() = default; |
| LineHeightSize(const Length& line_height, const Font* font, float font_zoom) |
| : line_height_(line_height), font_(font), font_zoom_(font_zoom) {} |
| LineHeightSize(const Length& line_height, |
| const Length& root_line_height, |
| const Font* font, |
| const Font* root_font, |
| float font_zoom, |
| float root_font_zoom) |
| : line_height_(line_height), |
| root_line_height_(root_line_height), |
| font_(font), |
| root_font_(root_font), |
| font_zoom_(font_zoom), |
| root_font_zoom_(root_font_zoom) {} |
| LineHeightSize(const FontSizeStyle& style, const ComputedStyle* root_style); |
| |
| float Lh(float zoom) const; |
| float Rlh(float zoom) const; |
| |
| private: |
| Length line_height_; |
| Length root_line_height_; |
| // Note that this Font may be different from the instance held |
| // by FontSizes (for the same CSSToLengthConversionData object). |
| const Font* font_ = nullptr; |
| const Font* root_font_ = nullptr; |
| // Like ex/ch/ic, lh is also based on font-metrics and is pre-zoomed by |
| // a factor of `font_zoom_`. |
| float font_zoom_ = 1; |
| float root_font_zoom_ = 1; |
| }; |
| |
| class CORE_EXPORT ViewportSize { |
| DISALLOW_NEW(); |
| |
| public: |
| ViewportSize() = default; |
| ViewportSize(double width, double height) |
| : large_width_(width), |
| large_height_(height), |
| small_width_(width), |
| small_height_(height), |
| dynamic_width_(width), |
| dynamic_height_(height) {} |
| |
| explicit ViewportSize(const LayoutView*); |
| bool operator==(const ViewportSize&) const = default; |
| |
| // v* |
| double Width() const { return LargeWidth(); } |
| double Height() const { return LargeHeight(); } |
| |
| // lv* |
| double LargeWidth() const { return large_width_; } |
| double LargeHeight() const { return large_height_; } |
| |
| // sv* |
| double SmallWidth() const { return small_width_; } |
| double SmallHeight() const { return small_height_; } |
| |
| // dv* |
| double DynamicWidth() const { return dynamic_width_; } |
| double DynamicHeight() const { return dynamic_height_; } |
| |
| private: |
| // v*, lv* |
| double large_width_ = 0; |
| double large_height_ = 0; |
| // sv* |
| double small_width_ = 0; |
| double small_height_ = 0; |
| // dv* |
| double dynamic_width_ = 0; |
| double dynamic_height_ = 0; |
| }; |
| |
| class CORE_EXPORT ContainerSizes { |
| DISALLOW_NEW(); |
| |
| public: |
| ContainerSizes() = default; |
| |
| // ContainerSizes will look for container-query containers in the inclusive |
| // ancestor chain of `context_element`. Optimally, the nearest container- |
| // query container is provided, although it's harmless to provide some |
| // descendant of that container (we'll just traverse a bit more). |
| explicit ContainerSizes(Element* context_element) |
| : context_element_(context_element) {} |
| |
| // ContainerSizes::Width/Height is normally computed lazily by looking |
| // the ancestor chain of `context_element_`. This function allows the |
| // sizes to be fetched eagerly instead. This is useful for situations where |
| // we don't have enough context to fetch the information lazily (e.g. |
| // generated images). |
| ContainerSizes PreCachedCopy() const; |
| |
| // Note that this will eagerly compute width/height for both `this` and |
| // the incoming object. |
| bool SizesEqual(const ContainerSizes&) const; |
| |
| void Trace(Visitor*) const; |
| |
| std::optional<double> Width() const; |
| std::optional<double> Height() const; |
| std::optional<double> Width(const ScopedCSSName&) const; |
| std::optional<double> Height(const ScopedCSSName&) const; |
| |
| private: |
| void CacheSizeIfNeeded(PhysicalAxes, std::optional<double>& cache) const; |
| std::optional<double> FindNamedSize(const ScopedCSSName&, |
| PhysicalAxes) const; |
| |
| Member<Element> context_element_; |
| mutable PhysicalAxes cached_physical_axes_{kPhysicalAxesNone}; |
| mutable std::optional<double> cached_width_; |
| mutable std::optional<double> cached_height_; |
| }; |
| |
| // Used to evaluate anchor() and anchor-size() functions. |
| // |
| // https://drafts.csswg.org/css-anchor-position-1/#anchor-pos |
| // https://drafts.csswg.org/css-anchor-position-1/#anchor-size-fn |
| class CORE_EXPORT AnchorData { |
| STACK_ALLOCATED(); |
| |
| public: |
| AnchorData() = default; |
| AnchorData(Element* anchored, AnchorEvaluator*); |
| AnchorEvaluator* GetEvaluator() const { return evaluator_; } |
| |
| private: |
| AnchorEvaluator* evaluator_ = nullptr; |
| }; |
| |
| using Flags = uint16_t; |
| |
| // Flags represent the units seen in a conversion. They are used for targeted |
| // invalidation, e.g. when root font-size changes, only elements dependent on |
| // rem units are recalculated. |
| enum class Flag : Flags { |
| // em |
| kEm = 1u << 0, |
| // rem |
| kRootFontRelative = 1u << 1, |
| // ex, ch, ic, lh, cap, rcap |
| kGlyphRelative = 1u << 2, |
| // rex, rch, ric have both kRootFontRelative and kGlyphRelative |
| // lh |
| kLineHeightRelative = 1u << 3, |
| // sv*, lv*, v* |
| kStaticViewport = 1u << 4, |
| // dv* |
| kDynamicViewport = 1u << 5, |
| // cq* |
| kContainerRelative = 1u << 6, |
| // https://drafts.csswg.org/css-scoping-1/#css-tree-scoped-reference |
| kTreeScopedReference = 1u << 7, |
| // vi, vb, cqi, cqb, etc |
| kLogicalDirectionRelative = 1u << 8, |
| // anchor(), anchor-size() |
| // https://drafts.csswg.org/css-anchor-position-1 |
| kAnchorRelative = 1u << 9, |
| // Adjust the Flags type above if adding more bits below. |
| }; |
| |
| CSSToLengthConversionData() : CSSLengthResolver(1 /* zoom */) {} |
| CSSToLengthConversionData(WritingMode, |
| const FontSizes&, |
| const LineHeightSize&, |
| const ViewportSize&, |
| const ContainerSizes&, |
| const AnchorData&, |
| float zoom, |
| Flags&); |
| template <typename ComputedStyleOrBuilder> |
| CSSToLengthConversionData(const ComputedStyleOrBuilder& element_style, |
| const ComputedStyle* parent_style, |
| const ComputedStyle* root_style, |
| const ViewportSize& viewport_size, |
| const ContainerSizes& container_sizes, |
| const AnchorData& anchor_data, |
| float zoom, |
| Flags& flags) |
| : CSSToLengthConversionData( |
| element_style.GetWritingMode(), |
| FontSizes(element_style.GetFontSizeStyle(), root_style), |
| LineHeightSize(parent_style ? parent_style->GetFontSizeStyle() |
| : element_style.GetFontSizeStyle(), |
| root_style), |
| viewport_size, |
| container_sizes, |
| anchor_data, |
| zoom, |
| flags) {} |
| |
| float EmFontSize(float zoom) const override; |
| float RemFontSize(float zoom) const override; |
| float ExFontSize(float zoom) const override; |
| float RexFontSize(float zoom) const override; |
| float ChFontSize(float zoom) const override; |
| float RchFontSize(float zoom) const override; |
| float IcFontSize(float zoom) const override; |
| float RicFontSize(float zoom) const override; |
| float LineHeight(float zoom) const override; |
| float RootLineHeight(float zoom) const override; |
| float CapFontSize(float zoom) const override; |
| float RcapFontSize(float zoom) const override; |
| double ViewportWidth() const override; |
| double ViewportHeight() const override; |
| double SmallViewportWidth() const override; |
| double SmallViewportHeight() const override; |
| double LargeViewportWidth() const override; |
| double LargeViewportHeight() const override; |
| double DynamicViewportWidth() const override; |
| double DynamicViewportHeight() const override; |
| double ContainerWidth() const override; |
| double ContainerHeight() const override; |
| double ContainerWidth(const ScopedCSSName&) const override; |
| double ContainerHeight(const ScopedCSSName&) const override; |
| WritingMode GetWritingMode() const override; |
| void ReferenceTreeScope() const override; |
| |
| void SetFontSizes(const FontSizes& font_sizes) { font_sizes_ = font_sizes; } |
| void SetLineHeightSize(const LineHeightSize& line_height_size) { |
| line_height_size_ = line_height_size; |
| } |
| |
| void ReferenceAnchor() const override; |
| |
| AnchorEvaluator* GetAnchorEvaluator() const override { |
| return anchor_data_.GetEvaluator(); |
| } |
| |
| // See ContainerSizes::PreCachedCopy. |
| // |
| // Calling this function will mark the associated ComputedStyle as |
| // dependent on container-relative units. |
| ContainerSizes PreCachedContainerSizesCopy() const; |
| |
| CSSToLengthConversionData CopyWithAdjustedZoom(float new_zoom) const { |
| DCHECK(flags_); |
| return CSSToLengthConversionData( |
| writing_mode_, font_sizes_, line_height_size_, viewport_size_, |
| container_sizes_, anchor_data_, new_zoom, *flags_); |
| } |
| CSSToLengthConversionData Unzoomed() const { |
| return CopyWithAdjustedZoom(1.0f); |
| } |
| |
| private: |
| void SetFlag(Flag flag) const { |
| if (flags_) { |
| *flags_ |= static_cast<Flags>(flag); |
| } |
| } |
| |
| WritingMode writing_mode_ = WritingMode::kHorizontalTb; |
| FontSizes font_sizes_; |
| LineHeightSize line_height_size_; |
| ViewportSize viewport_size_; |
| ContainerSizes container_sizes_; |
| AnchorData anchor_data_; |
| mutable Flags* flags_ = nullptr; |
| }; |
| |
| } // namespace blink |
| |
| #endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_TO_LENGTH_CONVERSION_DATA_H_ |