| #ifndef _RIVE_SEMANTIC_STATE_HPP_ | |
| #define _RIVE_SEMANTIC_STATE_HPP_ | |
| #include "rive/generated/semantic/semantic_data_base.hpp" | |
| #include <cstdint> | |
| namespace rive | |
| { | |
| /// Bitmask constants for semantic state flags. | |
| /// These are stored in SemanticNode::stateFlags and transmitted in | |
| /// SemanticsDiffNode::stateFlags. The platform accessibility layer | |
| /// interprets them per-role. | |
| /// | |
| /// Bits 0-7 are trait-gated: they are only meaningful when the | |
| /// corresponding SemanticTrait is set on the node. | |
| /// Bits 8-13 are non-trait states (binary, role-implied). | |
| /// | |
| /// Values are pulled from SemanticDataBase's generated `*Bitmask` | |
| /// constants, which are derived from the authoritative JSON definitions. | |
| /// Editing the bit layout means editing dev/defs/semantic/semantic_data.json | |
| /// and regenerating — the enum values will track automatically. | |
| /// | |
| /// Check state is the exception: it is a two-bit *field* rather than a flag, | |
| /// because a checkbox is tri-state. It is not a member of this enum — read it | |
| /// with checkStateOf() and switch on SemanticCheckState. | |
| enum class SemanticState : uint32_t | |
| { | |
| None = 0, | |
| // Trait-gated states (only meaningful when trait is active) | |
| Expanded = SemanticDataBase::isExpandedBitmask, // requires Expandable | |
| Selected = SemanticDataBase::isSelectedBitmask, // requires Selectable | |
| // Checked is deliberately absent: it is a field, not a flag. See | |
| // SemanticCheckState / checkStateOf() below. | |
| Toggled = SemanticDataBase::isToggledBitmask, // requires Toggleable | |
| Required = SemanticDataBase::isRequiredBitmask, // requires Requirable | |
| Disabled = SemanticDataBase::isDisabledBitmask, // requires Enablable | |
| Focused = SemanticDataBase::isFocusedBitmask, // requires Focusable | |
| // Non-trait states (binary, always applicable or role-implied) | |
| Hidden = SemanticDataBase::isHiddenBitmask, | |
| LiveRegion = SemanticDataBase::isLiveRegionBitmask, | |
| ReadOnly = SemanticDataBase::isReadOnlyBitmask, | |
| Modal = SemanticDataBase::isModalBitmask, | |
| Obscured = SemanticDataBase::isObscuredBitmask, | |
| Multiline = SemanticDataBase::isMultilineBitmask, | |
| }; | |
| constexpr SemanticState operator|(SemanticState a, SemanticState b) | |
| { | |
| return static_cast<SemanticState>(static_cast<uint32_t>(a) | | |
| static_cast<uint32_t>(b)); | |
| } | |
| constexpr SemanticState operator&(SemanticState a, SemanticState b) | |
| { | |
| return static_cast<SemanticState>(static_cast<uint32_t>(a) & | |
| static_cast<uint32_t>(b)); | |
| } | |
| constexpr bool hasSemanticState(uint32_t flags, SemanticState flag) | |
| { | |
| return (flags & static_cast<uint32_t>(flag)) != 0; | |
| } | |
| /// The tri-state of a checkable node. Occupies two bits of stateFlags at | |
| /// SemanticDataBase::isCheckedBitOffset, so it is read as a value rather than | |
| /// tested as a flag. Only meaningful when the Checkable trait is set. | |
| enum class SemanticCheckState : uint8_t | |
| { | |
| Unchecked = 0, | |
| Checked = 1, | |
| Mixed = 2, | |
| }; | |
| /// Decodes the check field out of [flags]. The field is two bits so it can | |
| /// physically hold a fourth value; it has no meaning and is read as Mixed | |
| /// rather than falling through to an unnamed state. | |
| constexpr SemanticCheckState checkStateOf(uint32_t flags) | |
| { | |
| const uint32_t value = (flags & SemanticDataBase::isCheckedFieldMask) >> | |
| SemanticDataBase::isCheckedBitOffset; | |
| return value >= 2 ? SemanticCheckState::Mixed | |
| : static_cast<SemanticCheckState>(value); | |
| } | |
| } // namespace rive | |
| #endif |