blob: ca4d280ec5ac4c40a4d56244db2e14e86b85040a [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_WHITE_SPACE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_WHITE_SPACE_H_
#include <cstdint>
namespace blink {
//
// This file contains definitions of the `white-space` shorthand property and
// its longhands.
// https://w3c.github.io/csswg-drafts/css-text-4/#propdef-white-space
//
//
// The `white-space-collapse` property.
// https://w3c.github.io/csswg-drafts/css-text-4/#white-space-collapsing
//
enum class WhiteSpaceCollapse : uint8_t {
kCollapse = 0,
kPreserve = 1,
// `KPreserve` is a bit-flag, but bit 2 is shared by two different behaviors
// below to save memory. Use functions below instead of direct comparisons.
kPreserveBreaks = 2,
kBreakSpaces = kPreserve | 2,
// Ensure `kWhiteSpaceCollapseBits` can hold all values.
};
// Ensure this is in sync with `css_properties.json5`.
static constexpr int kWhiteSpaceCollapseBits = 2;
static constexpr uint8_t kWhiteSpaceCollapseMask =
(1 << kWhiteSpaceCollapseBits) - 1;
inline bool IsWhiteSpaceCollapseAny(WhiteSpaceCollapse value,
WhiteSpaceCollapse flags) {
return static_cast<uint8_t>(value) & static_cast<uint8_t>(flags);
}
// Whether to collapse or preserve all whitespaces: spaces (U+0020), tabs
// (U+0009), and segment breaks.
// https://w3c.github.io/csswg-drafts/css-text-4/#white-space
inline bool ShouldPreserveWhiteSpaces(WhiteSpaceCollapse collapse) {
return IsWhiteSpaceCollapseAny(collapse, WhiteSpaceCollapse::kPreserve);
}
inline bool ShouldCollapseWhiteSpaces(WhiteSpaceCollapse collapse) {
return !ShouldPreserveWhiteSpaces(collapse);
}
// Whether to collapse or preserve segment breaks.
// https://w3c.github.io/csswg-drafts/css-text-4/#segment-break
inline bool ShouldPreserveBreaks(WhiteSpaceCollapse collapse) {
return collapse != WhiteSpaceCollapse::kCollapse;
}
inline bool ShouldCollapseBreaks(WhiteSpaceCollapse collapse) {
return !ShouldPreserveBreaks(collapse);
}
inline bool ShouldBreakSpaces(WhiteSpaceCollapse collapse) {
return collapse == WhiteSpaceCollapse::kBreakSpaces;
}
//
// The `text-wrap` property.
// https://w3c.github.io/csswg-drafts/css-text-4/#propdef-text-wrap
//
enum class TextWrap : uint8_t {
kWrap = 0,
kNoWrap = 1,
kBalance = 2,
kPretty = 3,
// Ensure `kTextWrapBits` can hold all values.
};
// Ensure this is in sync with `css_properties.json5`.
static constexpr int kTextWrapBits = 2;
inline bool ShouldWrapLine(TextWrap wrap) {
return wrap != TextWrap::kNoWrap;
}
//
// The `white-space` property.
// https://w3c.github.io/csswg-drafts/css-text-4/#propdef-white-space
//
// `EWhiteSpace` is represented by bit-flags of combinations of all possible
// longhand values. Thus `ToWhiteSpace()` may return values that are not defined
// as the `EWhiteSpace` value. `IsValidWhiteSpace()` can check if a value is one
// of pre-defined keywords.
//
constexpr uint8_t ToWhiteSpaceValue(WhiteSpaceCollapse collapse,
TextWrap wrap) {
return static_cast<uint8_t>(collapse) |
(static_cast<uint8_t>(wrap) << kWhiteSpaceCollapseBits);
}
enum class EWhiteSpace : uint8_t {
kNormal = ToWhiteSpaceValue(WhiteSpaceCollapse::kCollapse, TextWrap::kWrap),
kNowrap = ToWhiteSpaceValue(WhiteSpaceCollapse::kCollapse, TextWrap::kNoWrap),
kPre = ToWhiteSpaceValue(WhiteSpaceCollapse::kPreserve, TextWrap::kNoWrap),
kPreLine =
ToWhiteSpaceValue(WhiteSpaceCollapse::kPreserveBreaks, TextWrap::kWrap),
kPreWrap = ToWhiteSpaceValue(WhiteSpaceCollapse::kPreserve, TextWrap::kWrap),
kBreakSpaces =
ToWhiteSpaceValue(WhiteSpaceCollapse::kBreakSpaces, TextWrap::kWrap),
};
static_assert(kWhiteSpaceCollapseBits + kTextWrapBits <=
sizeof(EWhiteSpace) * 8);
// Convert longhands of `white-space` to `EWhiteSpace`. The return value may not
// be one of the defined enum values. Please see the comment above.
inline EWhiteSpace ToWhiteSpace(WhiteSpaceCollapse collapse, TextWrap wrap) {
return static_cast<EWhiteSpace>(ToWhiteSpaceValue(collapse, wrap));
}
inline bool IsValidWhiteSpace(EWhiteSpace whitespace) {
return whitespace == EWhiteSpace::kNormal ||
whitespace == EWhiteSpace::kNowrap ||
whitespace == EWhiteSpace::kPre ||
whitespace == EWhiteSpace::kPreLine ||
whitespace == EWhiteSpace::kPreWrap ||
whitespace == EWhiteSpace::kBreakSpaces;
}
// Convert `EWhiteSpace` to longhands.
inline WhiteSpaceCollapse ToWhiteSpaceCollapse(EWhiteSpace whitespace) {
return static_cast<WhiteSpaceCollapse>(static_cast<uint8_t>(whitespace) &
kWhiteSpaceCollapseMask);
}
inline TextWrap ToTextWrap(EWhiteSpace whitespace) {
return static_cast<TextWrap>(static_cast<uint8_t>(whitespace) >>
kWhiteSpaceCollapseBits);
}
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_WHITE_SPACE_H_