Use a 1-byte enum class for TextDirection
[WebKit-https.git] / Source / WebCore / platform / text / WritingMode.h
1 /*
2  * Copyright (c) 2012, Google Inc. All rights reserved.
3  * Copyright (C) 2015, Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #pragma once
33
34 namespace WebCore {
35
36 enum class TextDirection : uint8_t { LTR, RTL };
37
38 inline bool isLeftToRightDirection(TextDirection direction)
39 {
40     return direction == TextDirection::LTR;
41 }
42
43 enum WritingMode {
44     TopToBottomWritingMode = 0, // horizontal-tb
45     BottomToTopWritingMode = 1, // horizontal-bt
46     LeftToRightWritingMode = 2, // vertical-lr
47     RightToLeftWritingMode = 3, // vertical-rl
48 };
49
50 #define MAKE_TEXT_FLOW(writingMode, direction)  ((writingMode) << 1 | static_cast<unsigned>(direction))
51
52 // Define the text flow in terms of the writing mode and the text direction. The first
53 // part is the line growing direction and the second part is the block growing direction.
54 enum TextFlow {
55     InlineEastBlockSouth = MAKE_TEXT_FLOW(TopToBottomWritingMode, TextDirection::LTR),
56     InlineWestBlockSouth = MAKE_TEXT_FLOW(TopToBottomWritingMode, TextDirection::RTL),
57     InlineEastBlockNorth = MAKE_TEXT_FLOW(BottomToTopWritingMode, TextDirection::LTR),
58     InlineWestBlockNorth = MAKE_TEXT_FLOW(BottomToTopWritingMode, TextDirection::RTL),
59     InlineSouthBlockEast = MAKE_TEXT_FLOW(LeftToRightWritingMode, TextDirection::LTR),
60     InlineSouthBlockWest = MAKE_TEXT_FLOW(LeftToRightWritingMode, TextDirection::RTL),
61     InlineNorthBlockEast = MAKE_TEXT_FLOW(RightToLeftWritingMode, TextDirection::LTR),
62     InlineNorthBlockWest = MAKE_TEXT_FLOW(RightToLeftWritingMode, TextDirection::RTL)
63 };
64
65 inline TextFlow makeTextFlow(WritingMode writingMode, TextDirection direction)
66 {
67     return static_cast<TextFlow>(MAKE_TEXT_FLOW(writingMode, direction));
68 }
69
70 #undef MAKE_TEXT_FLOW
71
72 const unsigned TextFlowReversedMask = 1;
73 const unsigned TextFlowFlippedMask = 2;
74 const unsigned TextFlowVerticalMask = 4;
75
76 inline bool isReversedTextFlow(TextFlow textflow)
77 {
78     return textflow & TextFlowReversedMask;
79 }
80
81 inline bool isFlippedTextFlow(TextFlow textflow)
82 {
83     return textflow & TextFlowFlippedMask;
84 }
85
86 inline bool isVerticalTextFlow(TextFlow textflow)
87 {
88     return textflow & TextFlowVerticalMask;
89 }
90
91 // Lines have vertical orientation; modes vertical-lr or vertical-rl.
92 inline bool isVerticalWritingMode(WritingMode writingMode)
93 {
94     return isVerticalTextFlow(makeTextFlow(writingMode, TextDirection::LTR));
95 }
96
97 // Block progression increases in the opposite direction to normal; modes vertical-rl or horizontal-bt.
98 inline bool isFlippedWritingMode(WritingMode writingMode)
99 {
100     return isFlippedTextFlow(makeTextFlow(writingMode, TextDirection::LTR));
101 }
102
103 // Lines have horizontal orientation; modes horizontal-tb or horizontal-bt.
104 inline bool isHorizontalWritingMode(WritingMode writingMode)
105 {
106     return !isVerticalWritingMode(writingMode);
107 }
108
109 // Bottom of the line occurs earlier in the block; modes vertical-lr or horizontal-bt.
110 inline bool isFlippedLinesWritingMode(WritingMode writingMode)
111 {
112     return isVerticalWritingMode(writingMode) != isFlippedWritingMode(writingMode);
113 }
114
115 enum class LogicalBoxSide : uint8_t {
116     Before,
117     End,
118     After,
119     Start
120 };
121
122 enum class PhysicalBoxSide : uint8_t {
123     Top,
124     Right,
125     Bottom,
126     Left
127 };
128
129 inline bool isHorizontalPhysicalSide(PhysicalBoxSide physicalSide)
130 {
131     return physicalSide == PhysicalBoxSide::Left || physicalSide == PhysicalBoxSide::Right;
132 }
133
134 inline PhysicalBoxSide mirrorPhysicalSide(PhysicalBoxSide physicalSide)
135 {
136     // top <-> bottom and left <-> right conversion
137     return static_cast<PhysicalBoxSide>((static_cast<int>(physicalSide) + 2) % 4);
138 }
139
140 inline PhysicalBoxSide rotatePhysicalSide(PhysicalBoxSide physicalSide)
141 {
142     // top <-> left and right <-> bottom conversion
143     bool horizontalSide = isHorizontalPhysicalSide(physicalSide);
144     return static_cast<PhysicalBoxSide>((static_cast<int>(physicalSide) + (horizontalSide ? 1 : 3)) % 4);
145 }
146
147 inline PhysicalBoxSide mapLogicalSideToPhysicalSide(TextFlow textflow, LogicalBoxSide logicalSide)
148 {
149     PhysicalBoxSide physicalSide = static_cast<PhysicalBoxSide>(logicalSide);
150     bool horizontalSide = isHorizontalPhysicalSide(physicalSide);
151
152     if (isVerticalTextFlow(textflow))
153         physicalSide = rotatePhysicalSide(physicalSide);
154
155     if ((horizontalSide && isReversedTextFlow(textflow)) || (!horizontalSide && isFlippedTextFlow(textflow)))
156         physicalSide = mirrorPhysicalSide(physicalSide);
157
158     return physicalSide;
159 }
160
161 inline PhysicalBoxSide mapLogicalSideToPhysicalSide(WritingMode writingMode, LogicalBoxSide logicalSide)
162 {
163     // Set the direction such that side is mirrored if isFlippedWritingMode() is true
164     TextDirection direction = isFlippedWritingMode(writingMode) ? TextDirection::RTL : TextDirection::LTR;
165     return mapLogicalSideToPhysicalSide(makeTextFlow(writingMode, direction), logicalSide);
166 }
167
168 } // namespace WebCore