| // Copyright 2024 The Dawn & Tint Authors |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are met: |
| // |
| // 1. Redistributions of source code must retain the above copyright notice, |
| // this |
| // list of conditions and the following disclaimer. |
| // |
| // 2. 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. |
| // |
| // 3. Neither the name of the copyright holder 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 HOLDER 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 SRC_TINT_UTILS_TEXT_TEXT_STYLE_H_ |
| #define SRC_TINT_UTILS_TEXT_TEXT_STYLE_H_ |
| |
| #include <cstdint> |
| #include <tuple> |
| #include <type_traits> |
| |
| // Forward declarations |
| namespace tint { |
| template <typename... VALUES> |
| struct ScopedTextStyle; |
| } |
| |
| namespace tint { |
| |
| /// TextStyle is a styling that can be applied to span of a StyledText. |
| class TextStyle { |
| public: |
| /// Bits is the integer type used to store the text style. |
| using Bits = uint16_t; |
| |
| /// Bit patterns |
| |
| static constexpr Bits kStyleMask /* */ = 0b00'00000'0000'00'111; |
| static constexpr Bits kStyleUnderlined /* */ = 0b00'00000'0000'00'001; |
| static constexpr Bits kStyleBold /* */ = 0b00'00000'0000'00'010; |
| static constexpr Bits kStyleNoQuote /* */ = 0b00'00000'0000'00'100; |
| |
| static constexpr Bits kCompareMask /* */ = 0b00'00000'0000'11'000; |
| static constexpr Bits kCompareMatch /* */ = 0b00'00000'0000'01'000; |
| static constexpr Bits kCompareMismatch /* */ = 0b00'00000'0000'10'000; |
| |
| static constexpr Bits kSeverityMask /* */ = 0b00'00000'1111'00'000; |
| static constexpr Bits kSeverityDefault /* */ = 0b00'00000'0000'00'000; |
| static constexpr Bits kSeveritySuccess /* */ = 0b00'00000'0001'00'000; |
| static constexpr Bits kSeverityWarning /* */ = 0b00'00000'0010'00'000; |
| static constexpr Bits kSeverityError /* */ = 0b00'00000'0011'00'000; |
| static constexpr Bits kSeverityFatal /* */ = 0b00'00000'0100'00'000; |
| |
| static constexpr Bits kKindMask /* */ = 0b00'11111'0000'00'000; |
| static constexpr Bits kKindCode /* */ = 0b00'00001'0000'00'000; |
| static constexpr Bits kKindKeyword /* */ = 0b00'00011'0000'00'000; // includes kKindCode |
| static constexpr Bits kKindVariable /* */ = 0b00'00101'0000'00'000; // includes kKindCode |
| static constexpr Bits kKindType /* */ = 0b00'00111'0000'00'000; // includes kKindCode |
| static constexpr Bits kKindFunction /* */ = 0b00'01001'0000'00'000; // includes kKindCode |
| static constexpr Bits kKindEnum /* */ = 0b00'01011'0000'00'000; // includes kKindCode |
| static constexpr Bits kKindLiteral /* */ = 0b00'01101'0000'00'000; // includes kKindCode |
| static constexpr Bits kKindAttribute /* */ = 0b00'01111'0000'00'000; // includes kKindCode |
| static constexpr Bits kKindComment /* */ = 0b00'10001'0000'00'000; // includes kKindCode |
| static constexpr Bits kKindLabel /* */ = 0b00'10011'0000'00'000; // includes kKindCode |
| static constexpr Bits kKindInstruction /* */ = 0b00'10101'0000'00'000; // includes kKindCode |
| static constexpr Bits kKindSquiggle /* */ = 0b00'00010'0000'00'000; |
| |
| /// Getters |
| |
| constexpr bool IsBold() const { return (bits & kStyleBold) != 0; } |
| constexpr bool IsUnderlined() const { return (bits & kStyleUnderlined) == kStyleUnderlined; } |
| constexpr bool IsNoQuote() const { return (bits & kStyleNoQuote) == kStyleNoQuote; } |
| |
| constexpr bool HasCompare() const { return (bits & kCompareMask) != 0; } |
| constexpr bool IsMatch() const { return (bits & kCompareMask) == kCompareMatch; } |
| constexpr bool IsMismatch() const { return (bits & kCompareMask) == kCompareMismatch; } |
| |
| constexpr bool HasSeverity() const { return (bits & kSeverityMask) != 0; } |
| constexpr bool IsSuccess() const { return (bits & kSeverityMask) == kSeveritySuccess; } |
| constexpr bool IsWarning() const { return (bits & kSeverityMask) == kSeverityWarning; } |
| constexpr bool IsError() const { return (bits & kSeverityMask) == kSeverityError; } |
| constexpr bool IsFatal() const { return (bits & kSeverityMask) == kSeverityFatal; } |
| |
| constexpr bool HasKind() const { return (bits & kKindMask) != 0; } |
| constexpr bool IsCode() const { return (bits & kKindCode) == kKindCode; } |
| constexpr bool IsKeyword() const { return (bits & kKindMask) == kKindKeyword; } |
| constexpr bool IsVariable() const { return (bits & kKindMask) == kKindVariable; } |
| constexpr bool IsType() const { return (bits & kKindMask) == kKindType; } |
| constexpr bool IsFunction() const { return (bits & kKindMask) == kKindFunction; } |
| constexpr bool IsEnum() const { return (bits & kKindMask) == kKindEnum; } |
| constexpr bool IsLiteral() const { return (bits & kKindMask) == kKindLiteral; } |
| constexpr bool IsAttribute() const { return (bits & kKindMask) == kKindAttribute; } |
| constexpr bool IsComment() const { return (bits & kKindMask) == kKindComment; } |
| constexpr bool IsLabel() const { return (bits & kKindMask) == kKindLabel; } |
| constexpr bool IsInstruction() const { return (bits & kKindMask) == kKindInstruction; } |
| constexpr bool IsSquiggle() const { return (bits & kKindMask) == kKindSquiggle; } |
| |
| /// Equality operator |
| constexpr bool operator==(TextStyle other) const { return bits == other.bits; } |
| |
| /// Inequality operator |
| constexpr bool operator!=(TextStyle other) const { return bits != other.bits; } |
| |
| /// @returns the combination of this TextStyle and @p other. |
| /// If both this TextStyle and @p other have a compare style, severity style or kind style, then |
| /// the style collision will resolve by using the style of @p other. |
| constexpr TextStyle operator+(TextStyle other) const { |
| Bits out = other.bits; |
| out |= bits & kStyleMask; |
| if (HasCompare() && !other.HasCompare()) { |
| out |= bits & kCompareMask; |
| } |
| if (HasSeverity() && !other.HasSeverity()) { |
| out |= bits & kSeverityMask; |
| } |
| if (HasKind() && !other.HasKind()) { |
| out |= bits & kKindMask; |
| } |
| return TextStyle{out}; |
| } |
| |
| /// @returns a new ScopedTextStyle of @p values using with this TextStyle |
| template <typename... VALUES> |
| inline ScopedTextStyle<VALUES...> operator()(VALUES&&... values) const; |
| |
| /// The style bit pattern |
| Bits bits = 0; |
| }; |
| |
| /// ScopedTextStyle is a span of text, styled with a TextStyle |
| template <typename... VALUES> |
| struct ScopedTextStyle { |
| std::tuple<VALUES...> values; |
| TextStyle style; |
| }; |
| |
| template <typename... VALUES> |
| ScopedTextStyle<VALUES...> TextStyle::operator()(VALUES&&... values) const { |
| return ScopedTextStyle<VALUES...>{std::forward_as_tuple(values...), *this}; |
| } |
| |
| namespace detail { |
| template <typename T> |
| struct IsScopedTextStyle : std::false_type {}; |
| template <typename... VALUES> |
| struct IsScopedTextStyle<ScopedTextStyle<VALUES...> > : std::true_type {}; |
| } // namespace detail |
| |
| /// Resolves to true iff T is a ScopedTextStyle. |
| template <typename T> |
| static constexpr bool IsScopedTextStyle = detail::IsScopedTextStyle<T>::value; |
| |
| } // namespace tint |
| |
| namespace tint::style { |
| |
| /// Plain renders text without any styling |
| static constexpr TextStyle Plain = TextStyle{}; |
| /// Bold renders text with a heavy weight |
| static constexpr TextStyle Bold = TextStyle{TextStyle::kStyleBold}; |
| /// Underlined renders text with an underline |
| static constexpr TextStyle Underlined = TextStyle{TextStyle::kStyleUnderlined}; |
| /// Code renders without a single quote when printed as plain text. |
| static constexpr TextStyle NoQuote = TextStyle{TextStyle::kStyleNoQuote}; |
| /// Match renders text with the compare-match style |
| static constexpr TextStyle Match = TextStyle{TextStyle::kCompareMatch}; |
| /// Mismatch renders text with the compare-mismatch style |
| static constexpr TextStyle Mismatch = TextStyle{TextStyle::kCompareMismatch}; |
| /// Success renders text with the styling for a successful status |
| static constexpr TextStyle Success = TextStyle{TextStyle::kSeveritySuccess}; |
| /// Warning renders text with the styling for a warning status |
| static constexpr TextStyle Warning = TextStyle{TextStyle::kSeverityWarning}; |
| /// Error renders text with the styling for a error status |
| static constexpr TextStyle Error = TextStyle{TextStyle::kSeverityError}; |
| /// Fatal renders text with the styling for a fatal status |
| static constexpr TextStyle Fatal = TextStyle{TextStyle::kSeverityFatal}; |
| /// Code renders text with a 'code' style |
| static constexpr TextStyle Code = TextStyle{TextStyle::kKindCode}; |
| /// Keyword renders text with a 'code' style that represents a 'keyword' token |
| static constexpr TextStyle Keyword = TextStyle{TextStyle::kKindKeyword}; |
| /// Variable renders text with a 'code' style that represents a 'variable' token |
| static constexpr TextStyle Variable = TextStyle{TextStyle::kKindVariable}; |
| /// Type renders text with a 'code' style that represents a 'type' token |
| static constexpr TextStyle Type = TextStyle{TextStyle::kKindType}; |
| /// Function renders text with a 'code' style that represents a 'function' token |
| static constexpr TextStyle Function = TextStyle{TextStyle::kKindFunction}; |
| /// Enum renders text with a 'code' style that represents a 'enum' token |
| static constexpr TextStyle Enum = TextStyle{TextStyle::kKindEnum}; |
| /// Literal renders text with a 'code' style that represents a 'literal' token |
| static constexpr TextStyle Literal = TextStyle{TextStyle::kKindLiteral}; |
| /// Attribute renders text with a 'code' style that represents an 'attribute' token |
| static constexpr TextStyle Attribute = TextStyle{TextStyle::kKindAttribute}; |
| /// Comment renders text with a 'code' style that represents an 'comment' token |
| static constexpr TextStyle Comment = TextStyle{TextStyle::kKindComment}; |
| /// Label renders text with a 'code' style that represents an 'label' token |
| static constexpr TextStyle Label = TextStyle{TextStyle::kKindLabel}; |
| /// Instruction renders text with a 'code' style that represents an 'instruction' token |
| static constexpr TextStyle Instruction = TextStyle{TextStyle::kKindInstruction}; |
| /// Squiggle renders text with a squiggle-highlight style (`^^^^^`) |
| static constexpr TextStyle Squiggle = TextStyle{TextStyle::kKindSquiggle}; |
| |
| } // namespace tint::style |
| |
| #endif // SRC_TINT_UTILS_TEXT_TEXT_STYLE_H_ |