1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
|
/*
* Copyright (C) 2024 Apple Inc. All rights reserved.
* Copyright (C) 2024 Igalia S.L.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
*/
#pragma once
#include <WebCore/BoxSides.h>
#include <WebCore/StyleSelfAlignmentData.h>
#include <WebCore/WritingMode.h>
namespace WebCore {
// The axis that the span specifies.
// Represented as 3 bits: axis type, direction type, [Logical]BoxAxis value.
enum class PositionAreaAxis : uint8_t {
// Physical axes × Physical directions.
Horizontal = 0b000,
Vertical = 0b001,
// Physical axes × Logical directions.
X = 0b010,
Y = 0b011,
// Logical axes × Logical directions.
Inline = 0b110,
Block = 0b111,
};
WTF::TextStream& operator<<(WTF::TextStream&, PositionAreaAxis);
// Get the opposite axis of a given axis.
static inline PositionAreaAxis oppositePositionAreaAxis(PositionAreaAxis axis)
{
switch (axis) {
case PositionAreaAxis::Horizontal:
return PositionAreaAxis::Vertical;
case PositionAreaAxis::Vertical:
return PositionAreaAxis::Horizontal;
case PositionAreaAxis::X:
return PositionAreaAxis::Y;
case PositionAreaAxis::Y:
return PositionAreaAxis::X;
case PositionAreaAxis::Block:
return PositionAreaAxis::Inline;
case PositionAreaAxis::Inline:
return PositionAreaAxis::Block;
}
ASSERT_NOT_REACHED();
return PositionAreaAxis::Horizontal;
}
static inline bool isPositionAreaAxisLogical(const PositionAreaAxis positionAxis)
{
static const uint8_t axisBit = 0b100;
return static_cast<uint8_t>(positionAxis) & axisBit;
}
static inline bool isPositionAreaDirectionLogical(const PositionAreaAxis positionAxis)
{
static const uint8_t directionBit = 0b010;
return static_cast<uint8_t>(positionAxis) & directionBit;
}
static inline BoxAxis mapPositionAreaAxisToPhysicalAxis(const PositionAreaAxis positionAxis, const WritingMode writingMode)
{
static const uint8_t orientationBit = 0b001;
auto physicalAxis = static_cast<uint8_t>(positionAxis) & orientationBit;
if (isPositionAreaAxisLogical(positionAxis) && writingMode.isVertical())
physicalAxis = !physicalAxis;
return static_cast<BoxAxis>(physicalAxis);
}
static inline LogicalBoxAxis mapPositionAreaAxisToLogicalAxis(const PositionAreaAxis positionAxis, const WritingMode writingMode)
{
static const uint8_t orientationBit = 0b001;
auto logicalAxis = static_cast<uint8_t>(positionAxis) & orientationBit;
if (!isPositionAreaAxisLogical(positionAxis) && writingMode.isVertical())
logicalAxis = !logicalAxis;
return static_cast<LogicalBoxAxis>(logicalAxis);
}
// Specifies which tracks(s) on the axis that the position-area span occupies.
// Represented as 3 bits: start track, center track, end track.
enum class PositionAreaTrack : uint8_t {
Start = 0b001, // First track.
SpanStart = 0b011, // First and center tracks.
End = 0b100, // Last track.
SpanEnd = 0b110, // Center and last track.
Center = 0b010, // Center track.
SpanAll = 0b111, // All tracks along the axis.
};
WTF::TextStream& operator<<(WTF::TextStream&, PositionAreaTrack);
static inline PositionAreaTrack flipPositionAreaTrack(PositionAreaTrack track)
{
// We need to cast values out of the enum type restrictions in order to do math.
auto trackBits = static_cast<uint8_t>(track);
static constexpr uint8_t startBit = static_cast<uint8_t>(PositionAreaTrack::Start);
static constexpr uint8_t endBit = static_cast<uint8_t>(PositionAreaTrack::End);
static constexpr uint8_t sideBits = startBit | endBit;
bool isSymmetric = !(trackBits & startBit) == !(trackBits & endBit);
auto invertedValue = isSymmetric ? trackBits
// Flip side bits and merge with not-side bits.
: ((trackBits & sideBits) ^ sideBits) | (trackBits & ~sideBits);
return static_cast<PositionAreaTrack>(invertedValue);
}
// When the span refers to a logical axis that needs to be resolved to physical
// axis, this determines whether to use the writing mode of the element's
// containing block or the element itself.
enum class PositionAreaSelf : bool {
// Use the writing mode of the element's containing block.
No,
// Use the writing mode of the element itself.
Yes
};
WTF::TextStream& operator<<(WTF::TextStream&, PositionAreaSelf);
// A span in the position-area. position-area requires two spans of opposite
// axis to determine the containing block area.
//
// A span is uniquely determined by three properties:
// * the axis the span is on
// * which track(s) it occupies
// * "self" - whether to use the writing mode of the element itself or
// its containing block to resolve logical axes.
//
// How a CSS position-area keyword fits into this model:
// * Every keyword (except start, center, end, span-all) selects a physical
// or logical axis in PositionAreaAxis. For example, left/right/top/bottom
// select the physical Horizontal/Vertical axis, x-*/y-*/block-*/inline-*
// keywords select the logical X/Y/Block/Inline axis.
// * Every keyword also selects the "track", or the tiles on the axis it occupies,
// in PositionAxisTrack. For example:
// * left/top selects the Start track.
// * *-start/*-end keywords selects the Start/End track.
// * Span keywords select the SpanStart/SpanEnd track.
// * center/span-all select the Center/SpanAll track.
// * start, center, end, span-all are "axis ambiguous" - its axis depends on the
// axis of the other keyword in position-area. PositionAreaSpan does not support
// this; Style::BuilderConverter is responsible for resolving to a concrete axis
// before creating a PositionAreaSpan.
class PositionAreaSpan {
public:
PositionAreaSpan(PositionAreaAxis, PositionAreaTrack, PositionAreaSelf);
PositionAreaAxis axis() const { return static_cast<PositionAreaAxis>(m_axis); }
PositionAreaTrack track() const { return static_cast<PositionAreaTrack>(m_track); }
PositionAreaSelf self() const { return static_cast<PositionAreaSelf>(m_self); }
friend bool operator==(PositionAreaSpan, PositionAreaSpan) = default;
private:
uint8_t m_axis : 3;
uint8_t m_track : 3;
uint8_t m_self : 1;
};
WTF::TextStream& operator<<(WTF::TextStream&, PositionAreaSpan);
// A position-area is formed by two spans of opposite axes, that uniquely determine
// the area of the containing block.
class PositionArea {
public:
PositionArea(PositionAreaSpan blockOrXAxis, PositionAreaSpan inlineOrYAxis);
PositionAreaSpan blockOrXAxis() const { return m_blockOrXAxis; }
PositionAreaSpan inlineOrYAxis() const { return m_inlineOrYAxis; }
PositionAreaSpan spanForAxis(BoxAxis physicalAxis, WritingMode containerWritingMode, WritingMode selfWritingMode) const;
PositionAreaSpan spanForAxis(LogicalBoxAxis logicalAxis, WritingMode containerWritingMode, WritingMode selfWritingMode) const;
// Start/end based on container's coordinate-increasing direction (RenderBox coordinates)
PositionAreaTrack coordMatchedTrackForAxis(BoxAxis, WritingMode containerWritingMode, WritingMode selfWritingMode) const;
ItemPosition defaultAlignmentForAxis(BoxAxis, WritingMode containerWritingMode, WritingMode selfWritingMode) const;
bool operator==(const PositionArea&) const = default;
private:
PositionAreaSpan m_blockOrXAxis;
PositionAreaSpan m_inlineOrYAxis;
};
WTF::TextStream& operator<<(WTF::TextStream&, PositionArea);
} // namespace WebCore
|