OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/editing/state_machines/ForwardGraphemeBoundaryStateMachine.h" | 5 #include "core/editing/state_machines/ForwardGraphemeBoundaryStateMachine.h" |
6 | 6 |
7 #include "core/editing/state_machines/StateMachineUtil.h" | 7 #include "core/editing/state_machines/StateMachineUtil.h" |
8 #include "core/editing/state_machines/TextSegmentationMachineState.h" | 8 #include "core/editing/state_machines/TextSegmentationMachineState.h" |
9 #include "platform/text/Character.h" | 9 #include "platform/text/Character.h" |
10 #include "wtf/text/Unicode.h" | 10 #include "wtf/text/Unicode.h" |
11 #include <ostream> // NOLINT | 11 #include <ostream> // NOLINT |
12 | 12 |
13 namespace blink { | 13 namespace blink { |
14 namespace { | 14 namespace { |
15 const UChar32 kInvalidCodePoint = WTF::Unicode::kMaxCodepoint + 1; | 15 const UChar32 kUnsetCodePoint = WTF::Unicode::kMaxCodepoint + 1; |
16 } // namespace | 16 } // namespace |
17 | 17 |
18 #define FOR_EACH_FORWARD_GRAPHEME_BOUNDARY_STATE(V) \ | 18 #define FOR_EACH_FORWARD_GRAPHEME_BOUNDARY_STATE(V) \ |
19 /* Counting preceding regional indicators. This is initial state. */ \ | 19 /* Counting preceding regional indicators. This is initial state. */ \ |
20 V(CountRIS) \ | 20 V(CountRIS) \ |
21 /* Waiting lead surrogate during counting regional indicators. */ \ | 21 /* Waiting lead surrogate during counting regional indicators. */ \ |
22 V(CountRISWaitLeadSurrogate) \ | 22 V(CountRISWaitLeadSurrogate) \ |
23 /* Waiting first following code unit. */ \ | 23 /* Waiting first following code unit. */ \ |
24 V(StartForward) \ | 24 V(StartForward) \ |
25 /* Waiting trail surrogate for the first following code point. */ \ | 25 /* Waiting trail surrogate for the first following code point. */ \ |
(...skipping 19 matching lines...) Expand all Loading... |
45 FOR_EACH_FORWARD_GRAPHEME_BOUNDARY_STATE(V) | 45 FOR_EACH_FORWARD_GRAPHEME_BOUNDARY_STATE(V) |
46 #undef V | 46 #undef V |
47 }; | 47 }; |
48 const auto& it = std::begin(texts) + static_cast<size_t>(state); | 48 const auto& it = std::begin(texts) + static_cast<size_t>(state); |
49 DCHECK_GE(it, std::begin(texts)) << "Unknown state value"; | 49 DCHECK_GE(it, std::begin(texts)) << "Unknown state value"; |
50 DCHECK_LT(it, std::end(texts)) << "Unknown state value"; | 50 DCHECK_LT(it, std::end(texts)) << "Unknown state value"; |
51 return os << *it; | 51 return os << *it; |
52 } | 52 } |
53 | 53 |
54 ForwardGraphemeBoundaryStateMachine::ForwardGraphemeBoundaryStateMachine() | 54 ForwardGraphemeBoundaryStateMachine::ForwardGraphemeBoundaryStateMachine() |
55 : m_prevCodePoint(kInvalidCodePoint), | 55 : m_prevCodePoint(kUnsetCodePoint), |
56 m_internalState(InternalState::CountRIS) {} | 56 m_internalState(InternalState::CountRIS) {} |
57 | 57 |
58 TextSegmentationMachineState | 58 TextSegmentationMachineState |
59 ForwardGraphemeBoundaryStateMachine::feedPrecedingCodeUnit(UChar codeUnit) { | 59 ForwardGraphemeBoundaryStateMachine::feedPrecedingCodeUnit(UChar codeUnit) { |
60 DCHECK_EQ(m_prevCodePoint, kInvalidCodePoint); | 60 DCHECK_EQ(m_prevCodePoint, kUnsetCodePoint); |
61 DCHECK_EQ(m_boundaryOffset, 0); | 61 DCHECK_EQ(m_boundaryOffset, 0); |
62 switch (m_internalState) { | 62 switch (m_internalState) { |
63 case InternalState::CountRIS: | 63 case InternalState::CountRIS: |
64 DCHECK_EQ(m_pendingCodeUnit, 0); | 64 DCHECK_EQ(m_pendingCodeUnit, 0); |
65 if (U16_IS_TRAIL(codeUnit)) { | 65 if (U16_IS_TRAIL(codeUnit)) { |
66 m_pendingCodeUnit = codeUnit; | 66 m_pendingCodeUnit = codeUnit; |
67 return moveToNextState(InternalState::CountRISWaitLeadSurrogate); | 67 return moveToNextState(InternalState::CountRISWaitLeadSurrogate); |
68 } | 68 } |
69 return moveToNextState(InternalState::StartForward); | 69 return moveToNextState(InternalState::StartForward); |
70 case InternalState::CountRISWaitLeadSurrogate: | 70 case InternalState::CountRISWaitLeadSurrogate: |
(...skipping 28 matching lines...) Expand all Loading... |
99 TextSegmentationMachineState | 99 TextSegmentationMachineState |
100 ForwardGraphemeBoundaryStateMachine::feedFollowingCodeUnit(UChar codeUnit) { | 100 ForwardGraphemeBoundaryStateMachine::feedFollowingCodeUnit(UChar codeUnit) { |
101 switch (m_internalState) { | 101 switch (m_internalState) { |
102 case InternalState::CountRIS: // Fallthrough | 102 case InternalState::CountRIS: // Fallthrough |
103 case InternalState::CountRISWaitLeadSurrogate: | 103 case InternalState::CountRISWaitLeadSurrogate: |
104 NOTREACHED() << "Do not call feedFollowingCodeUnit() until " | 104 NOTREACHED() << "Do not call feedFollowingCodeUnit() until " |
105 << TextSegmentationMachineState::NeedFollowingCodeUnit | 105 << TextSegmentationMachineState::NeedFollowingCodeUnit |
106 << " is returned. InternalState: " << m_internalState; | 106 << " is returned. InternalState: " << m_internalState; |
107 return finish(); | 107 return finish(); |
108 case InternalState::StartForward: | 108 case InternalState::StartForward: |
109 DCHECK_EQ(m_prevCodePoint, kInvalidCodePoint); | 109 DCHECK_EQ(m_prevCodePoint, kUnsetCodePoint); |
110 DCHECK_EQ(m_boundaryOffset, 0); | 110 DCHECK_EQ(m_boundaryOffset, 0); |
111 DCHECK_EQ(m_pendingCodeUnit, 0); | 111 DCHECK_EQ(m_pendingCodeUnit, 0); |
112 if (U16_IS_TRAIL(codeUnit)) { | 112 if (U16_IS_TRAIL(codeUnit)) { |
113 // Lonely trail surrogate. | 113 // Lonely trail surrogate. |
114 m_boundaryOffset = 1; | 114 m_boundaryOffset = 1; |
115 return finish(); | 115 return finish(); |
116 } | 116 } |
117 if (U16_IS_LEAD(codeUnit)) { | 117 if (U16_IS_LEAD(codeUnit)) { |
118 m_pendingCodeUnit = codeUnit; | 118 m_pendingCodeUnit = codeUnit; |
119 return moveToNextState(InternalState::StartForwardWaitTrailSurrgate); | 119 return moveToNextState(InternalState::StartForwardWaitTrailSurrgate); |
120 } | 120 } |
121 m_prevCodePoint = codeUnit; | 121 m_prevCodePoint = codeUnit; |
122 m_boundaryOffset = 1; | 122 m_boundaryOffset = 1; |
123 return moveToNextState(InternalState::Search); | 123 return moveToNextState(InternalState::Search); |
124 case InternalState::StartForwardWaitTrailSurrgate: | 124 case InternalState::StartForwardWaitTrailSurrgate: |
125 DCHECK_EQ(m_prevCodePoint, kInvalidCodePoint); | 125 DCHECK_EQ(m_prevCodePoint, kUnsetCodePoint); |
126 DCHECK_EQ(m_boundaryOffset, 0); | 126 DCHECK_EQ(m_boundaryOffset, 0); |
127 DCHECK_NE(m_pendingCodeUnit, 0); | 127 DCHECK_NE(m_pendingCodeUnit, 0); |
128 if (U16_IS_TRAIL(codeUnit)) { | 128 if (U16_IS_TRAIL(codeUnit)) { |
129 m_prevCodePoint = U16_GET_SUPPLEMENTARY(m_pendingCodeUnit, codeUnit); | 129 m_prevCodePoint = U16_GET_SUPPLEMENTARY(m_pendingCodeUnit, codeUnit); |
130 m_boundaryOffset = 2; | 130 m_boundaryOffset = 2; |
131 m_pendingCodeUnit = 0; | 131 m_pendingCodeUnit = 0; |
132 return moveToNextState(InternalState::Search); | 132 return moveToNextState(InternalState::Search); |
133 } | 133 } |
134 // Lonely lead surrogate. | 134 // Lonely lead surrogate. |
135 m_boundaryOffset = 1; | 135 m_boundaryOffset = 1; |
136 return finish(); | 136 return finish(); |
137 case InternalState::Search: | 137 case InternalState::Search: |
138 DCHECK_NE(m_prevCodePoint, kInvalidCodePoint); | 138 DCHECK_NE(m_prevCodePoint, kUnsetCodePoint); |
139 DCHECK_NE(m_boundaryOffset, 0); | 139 DCHECK_NE(m_boundaryOffset, 0); |
140 DCHECK_EQ(m_pendingCodeUnit, 0); | 140 DCHECK_EQ(m_pendingCodeUnit, 0); |
141 if (U16_IS_LEAD(codeUnit)) { | 141 if (U16_IS_LEAD(codeUnit)) { |
142 m_pendingCodeUnit = codeUnit; | 142 m_pendingCodeUnit = codeUnit; |
143 return moveToNextState(InternalState::SearchWaitTrailSurrogate); | 143 return moveToNextState(InternalState::SearchWaitTrailSurrogate); |
144 } | 144 } |
145 if (U16_IS_TRAIL(codeUnit)) | 145 if (U16_IS_TRAIL(codeUnit)) |
146 return finish(); // Lonely trail surrogate. | 146 return finish(); // Lonely trail surrogate. |
147 if (isGraphemeBreak(m_prevCodePoint, codeUnit)) | 147 if (isGraphemeBreak(m_prevCodePoint, codeUnit)) |
148 return finish(); | 148 return finish(); |
149 m_prevCodePoint = codeUnit; | 149 m_prevCodePoint = codeUnit; |
150 m_boundaryOffset += 1; | 150 m_boundaryOffset += 1; |
151 return staySameState(); | 151 return staySameState(); |
152 case InternalState::SearchWaitTrailSurrogate: | 152 case InternalState::SearchWaitTrailSurrogate: |
153 DCHECK_NE(m_prevCodePoint, kInvalidCodePoint); | 153 DCHECK_NE(m_prevCodePoint, kUnsetCodePoint); |
154 DCHECK_NE(m_boundaryOffset, 0); | 154 DCHECK_NE(m_boundaryOffset, 0); |
155 DCHECK_NE(m_pendingCodeUnit, 0); | 155 DCHECK_NE(m_pendingCodeUnit, 0); |
156 if (!U16_IS_TRAIL(codeUnit)) | 156 if (!U16_IS_TRAIL(codeUnit)) |
157 return finish(); // Lonely lead surrogate. | 157 return finish(); // Lonely lead surrogate. |
158 | 158 |
159 { | 159 { |
160 const UChar32 codePoint = | 160 const UChar32 codePoint = |
161 U16_GET_SUPPLEMENTARY(m_pendingCodeUnit, codeUnit); | 161 U16_GET_SUPPLEMENTARY(m_pendingCodeUnit, codeUnit); |
162 m_pendingCodeUnit = 0; | 162 m_pendingCodeUnit = 0; |
163 if (Character::isRegionalIndicator(m_prevCodePoint) && | 163 if (Character::isRegionalIndicator(m_prevCodePoint) && |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 if (m_internalState != InternalState::Finished) | 202 if (m_internalState != InternalState::Finished) |
203 finishWithEndOfText(); | 203 finishWithEndOfText(); |
204 DCHECK_GE(m_boundaryOffset, 0); | 204 DCHECK_GE(m_boundaryOffset, 0); |
205 return m_boundaryOffset; | 205 return m_boundaryOffset; |
206 } | 206 } |
207 | 207 |
208 void ForwardGraphemeBoundaryStateMachine::reset() { | 208 void ForwardGraphemeBoundaryStateMachine::reset() { |
209 m_pendingCodeUnit = 0; | 209 m_pendingCodeUnit = 0; |
210 m_boundaryOffset = 0; | 210 m_boundaryOffset = 0; |
211 m_precedingRISCount = 0; | 211 m_precedingRISCount = 0; |
212 m_prevCodePoint = kInvalidCodePoint; | 212 m_prevCodePoint = kUnsetCodePoint; |
213 m_internalState = InternalState::CountRIS; | 213 m_internalState = InternalState::CountRIS; |
214 } | 214 } |
215 | 215 |
216 TextSegmentationMachineState ForwardGraphemeBoundaryStateMachine::finish() { | 216 TextSegmentationMachineState ForwardGraphemeBoundaryStateMachine::finish() { |
217 DCHECK_NE(m_internalState, InternalState::Finished); | 217 DCHECK_NE(m_internalState, InternalState::Finished); |
218 m_internalState = InternalState::Finished; | 218 m_internalState = InternalState::Finished; |
219 return TextSegmentationMachineState::Finished; | 219 return TextSegmentationMachineState::Finished; |
220 } | 220 } |
221 | 221 |
222 TextSegmentationMachineState | 222 TextSegmentationMachineState |
(...skipping 25 matching lines...) Expand all Loading... |
248 return; | 248 return; |
249 case InternalState::Search: // Fallthrough | 249 case InternalState::Search: // Fallthrough |
250 case InternalState::SearchWaitTrailSurrogate: // Fallthrough | 250 case InternalState::SearchWaitTrailSurrogate: // Fallthrough |
251 return; | 251 return; |
252 case InternalState::Finished: // Fallthrough | 252 case InternalState::Finished: // Fallthrough |
253 NOTREACHED() << "Do not call finishWithEndOfText() once it finishes."; | 253 NOTREACHED() << "Do not call finishWithEndOfText() once it finishes."; |
254 } | 254 } |
255 NOTREACHED() << "Unhandled state: " << m_internalState; | 255 NOTREACHED() << "Unhandled state: " << m_internalState; |
256 } | 256 } |
257 } // namespace blink | 257 } // namespace blink |
OLD | NEW |