Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(340)

Side by Side Diff: views/ime/character_composer.cc

Issue 7264015: CL for readability review (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Style fixes Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « views/ime/character_composer.h ('k') | views/ime/character_composer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "character_composer.h" 5 #include "character_composer.h"
6 6
7 #include <cstdlib> 7 #include <algorithm>
8 #include <iterator>
8 9
9 #include "third_party/gtk+/gdk/gdkkeysyms.h" 10 #include "third_party/gtk+/gdk/gdkkeysyms.h"
11 #include "ui/base/gtk/gtk_integers.h"
10 12
11 namespace { 13 namespace {
12 14
13 inline int CompareSequenceValue(unsigned int key, uint16 value) { 15 typedef std::vector<unsigned int> ComposeBufferType;
14 return (key > value) ? 1 : ((key < value) ? -1 : 0); 16
17 // An iterator class to apply std::lower_bound for composition table.
18 class SequenceIterator
19 : public std::iterator<std::random_access_iterator_tag, const uint16*> {
20 public:
21 SequenceIterator() : ptr_(NULL), stride_(0) {}
22 SequenceIterator(const uint16* ptr, int stride)
23 : ptr_(ptr), stride_(stride) {}
24
25 const uint16* ptr() const {return ptr_;}
26 int stride() const {return stride_;}
27
28 SequenceIterator& operator++() {
29 ptr_ += stride_;
30 return *this;
31 }
32 SequenceIterator& operator+=(int n) {
33 ptr_ += stride_*n;
34 return *this;
35 }
36
37 const uint16* operator*() const {return ptr_;}
38
39 private:
40 const uint16* ptr_;
41 int stride_;
42 };
43
44 inline SequenceIterator operator+(const SequenceIterator& l, int r) {
45 return SequenceIterator(l) += r;
15 } 46 }
16 47
48 inline int operator-(const SequenceIterator& l, const SequenceIterator& r) {
49 const int d = l.ptr() - r.ptr();
50 DCHECK(l.stride() == r.stride() && l.stride() > 0 && d%l.stride() == 0);
51 return d/l.stride();
52 }
53
54 inline bool operator==(const SequenceIterator& l, const SequenceIterator& r) {
55 DCHECK(l.stride() == r.stride());
56 return l.ptr() == r.ptr();
57 }
58
59 inline bool operator!=(const SequenceIterator& l, const SequenceIterator& r) {
60 return !(l == r);
61 }
62
63 // A function to compare keycode value.
64 inline int CompareSequenceValue(unsigned int l, unsigned int r) {
65 return (l > r) ? 1 : ((l < r) ? -1 : 0);
66 }
67
68 // A template to make |CompareFunc| work like operator<.
69 // |CompareFunc| is required to implement a member function,
70 // int operator()(const ComposeBufferType& l, const uint16* r) const.
71 template<typename CompareFunc>
72 struct ComparatorAdoptor {
73 bool operator()(const ComposeBufferType& l, const uint16* r) const {
74 return CompareFunc()(l, r) == -1;
75 }
76 bool operator()(const uint16* l, const ComposeBufferType& r) const {
77 return CompareFunc()(r, l) == 1;
78 }
79 };
80
17 class ComposeChecker { 81 class ComposeChecker {
18 public: 82 public:
83 // This class does not take the ownership of |data|, |data| should be alive
84 // for the lifetime of the object.
85 // |data| is a pointer to the head of an array of
86 // length (|max_sequence_length| + 2)*|n_sequences|.
87 // Every (|max_sequence_length| + 2) elements of |data| represent an entry.
88 // First |max_sequence_length| elements of an entry is the sequecne which
89 // composes the character represented by the last two elements of the entry.
19 ComposeChecker(const uint16* data, int max_sequence_length, int n_sequences); 90 ComposeChecker(const uint16* data, int max_sequence_length, int n_sequences);
20 bool CheckSequence(const std::vector<unsigned int>& sequence, 91 bool CheckSequence(const ComposeBufferType& sequence,
21 uint32* composed_character) const; 92 uint32* composed_character) const;
22 93
23 private: 94 private:
24 static int CompareSequence(const void* key_void, const void* value_void); 95 struct CompareSequence {
96 int operator()(const ComposeBufferType& l, const uint16* r) const;
97 };
25 98
99 // This class does not take the ownership of |data_|,
100 // the dtor does not delete |data_|.
26 const uint16* data_; 101 const uint16* data_;
27 int max_sequence_length_; 102 int max_sequence_length_;
28 int n_sequences_; 103 int n_sequences_;
29 int row_stride_; 104 int row_stride_;
30 105
31 DISALLOW_COPY_AND_ASSIGN(ComposeChecker); 106 DISALLOW_COPY_AND_ASSIGN(ComposeChecker);
32 }; 107 };
33 108
34 ComposeChecker::ComposeChecker(const uint16* data, 109 ComposeChecker::ComposeChecker(const uint16* data,
35 int max_sequence_length, 110 int max_sequence_length,
36 int n_sequences) 111 int n_sequences)
37 : data_(data), 112 : data_(data),
38 max_sequence_length_(max_sequence_length), 113 max_sequence_length_(max_sequence_length),
39 n_sequences_(n_sequences), 114 n_sequences_(n_sequences),
40 row_stride_(max_sequence_length + 2) { 115 row_stride_(max_sequence_length + 2) {
41 } 116 }
42 117
43 bool ComposeChecker::CheckSequence( 118 bool ComposeChecker::CheckSequence(const ComposeBufferType& sequence,
44 const std::vector<unsigned int>& sequence, 119 uint32* composed_character) const {
45 uint32* composed_character) const {
46 const int sequence_length = sequence.size(); 120 const int sequence_length = sequence.size();
47 if (sequence_length > max_sequence_length_) 121 if (sequence_length > max_sequence_length_)
48 return false; 122 return false;
49 // Find sequence in the table 123 // Find sequence in the table.
50 const uint16* found = static_cast<const uint16*>( 124 const SequenceIterator begin(data_, row_stride_);
51 bsearch(&sequence, data_, n_sequences_, 125 const SequenceIterator end = begin + n_sequences_;
52 sizeof(uint16)*row_stride_, CompareSequence)); 126 const SequenceIterator found = std::lower_bound(
53 if (!found) 127 begin, end, sequence, ComparatorAdoptor<CompareSequence>());
128 if (found == end || CompareSequence()(sequence, *found) != 0)
54 return false; 129 return false;
55 // Ensure |found| is pointing the first matching element
56 while (found > data_ &&
57 CompareSequence(&sequence, found - row_stride_) == 0)
58 found -= row_stride_;
59 130
60 if (sequence_length == max_sequence_length_ || found[sequence_length] == 0) { 131 if (sequence_length == max_sequence_length_ ||
61 // |found| is not partially matching. It's fully matching 132 (*found)[sequence_length] == 0) {
62 const uint16* data_end = data_ + row_stride_*n_sequences_; 133 // |found| is not partially matching. It's fully matching.
63 if (found + row_stride_ >= data_end || 134 if (found + 1 == end ||
64 CompareSequence(&sequence, found + row_stride_) != 0) { 135 CompareSequence()(sequence, *(found + 1)) != 0) {
65 // There is no composition longer than |found| which matches to |sequence| 136 // There is no composition longer than |found| which matches to
66 const uint32 value = (found[max_sequence_length_] << 16) | 137 // |sequence|.
67 found[max_sequence_length_ + 1]; 138 const uint32 value = ((*found)[max_sequence_length_] << 16) |
139 (*found)[max_sequence_length_ + 1];
68 *composed_character = value; 140 *composed_character = value;
69 } 141 }
70 } 142 }
71 return true; 143 return true;
72 } 144 }
73 145
74 // static 146 int ComposeChecker::CompareSequence::operator()(const ComposeBufferType& l,
75 int ComposeChecker::CompareSequence(const void* key_void, 147 const uint16* r) const {
76 const void* value_void) { 148 for(size_t i = 0; i < l.size(); ++i) {
77 typedef std::vector<unsigned int> KeyType; 149 const int compare_result = CompareSequenceValue(l[i], r[i]);
78 const KeyType& key = *static_cast<const KeyType*>(key_void);
79 const uint16* value = static_cast<const uint16*>(value_void);
80
81 for(size_t i = 0; i < key.size(); ++i) {
82 const int compare_result = CompareSequenceValue(key[i], value[i]);
83 if(compare_result) 150 if(compare_result)
84 return compare_result; 151 return compare_result;
85 } 152 }
86 return 0; 153 return 0;
87 } 154 }
88 155
89 156
90 class ComposeCheckerWithCompactTable { 157 class ComposeCheckerWithCompactTable {
91 public: 158 public:
159 // This class does not take the ownership of |data|, |data| should be alive
160 // for the lifetime of the object.
161 // First |index_size|*|index_stride| elements of |data| are an index table.
162 // Every |index_stride| elements of an index table are an index entry.
163 // If you are checking with a sequence of length N beginning with character C,
164 // you have to find an index entry whose first element is C, then get the N-th
165 // element of the index entry as the index.
166 // The index is pointing the element of |data| where the composition table for
167 // sequences of length N beginning with C is placed.
168
92 ComposeCheckerWithCompactTable(const uint16* data, 169 ComposeCheckerWithCompactTable(const uint16* data,
93 int max_sequence_length, 170 int max_sequence_length,
94 int index_size, 171 int index_size,
95 int index_stride); 172 int index_stride);
96 bool CheckSequence(const std::vector<unsigned int>& sequence, 173 bool CheckSequence(const ComposeBufferType& sequence,
97 uint32* composed_character) const; 174 uint32* composed_character) const;
98 175
99 private: 176 private:
100 static int CompareSequenceFront(const void* key_void, const void* value_void); 177 struct CompareSequenceFront {
101 static int CompareSequenceSkipFront(const void* key_void, 178 int operator()(const ComposeBufferType& l, const uint16* r) const;
102 const void* value_void); 179 };
180 struct CompareSequenceSkipFront {
181 int operator()(const ComposeBufferType& l, const uint16* r) const;
182 };
103 183
184 // This class does not take the ownership of |data_|,
185 // the dtor does not delete |data_|.
104 const uint16* data_; 186 const uint16* data_;
105 int max_sequence_length_; 187 int max_sequence_length_;
106 int index_size_; 188 int index_size_;
107 int index_stride_; 189 int index_stride_;
108 }; 190 };
109 191
110 ComposeCheckerWithCompactTable::ComposeCheckerWithCompactTable( 192 ComposeCheckerWithCompactTable::ComposeCheckerWithCompactTable(
111 const uint16* data, 193 const uint16* data,
112 int max_sequence_length, 194 int max_sequence_length,
113 int index_size, 195 int index_size,
114 int index_stride) 196 int index_stride)
115 : data_(data), 197 : data_(data),
116 max_sequence_length_(max_sequence_length), 198 max_sequence_length_(max_sequence_length),
117 index_size_(index_size), 199 index_size_(index_size),
118 index_stride_(index_stride) { 200 index_stride_(index_stride) {
119 } 201 }
120 202
121 bool ComposeCheckerWithCompactTable::CheckSequence( 203 bool ComposeCheckerWithCompactTable::CheckSequence(
122 const std::vector<unsigned int>& sequence, 204 const ComposeBufferType& sequence,
123 uint32* composed_character) const { 205 uint32* composed_character) const {
124 const int compose_length = sequence.size(); 206 const int compose_length = sequence.size();
125 if (compose_length > max_sequence_length_) 207 if (compose_length > max_sequence_length_)
126 return false; 208 return false;
127 // Find corresponding index for the first keypress 209 // Find corresponding index for the first keypress.
128 const uint16* index = static_cast<const uint16*>( 210 const SequenceIterator index_begin(data_, index_stride_);
129 bsearch(&sequence, data_, index_size_, 211 const SequenceIterator index_end = index_begin + index_size_;
130 sizeof(uint16)*index_stride_, CompareSequenceFront)); 212 const SequenceIterator index =
131 if (!index) 213 std::lower_bound(index_begin, index_end, sequence,
214 ComparatorAdoptor<CompareSequenceFront>());
215 if (index == index_end || CompareSequenceFront()(sequence, *index) != 0)
132 return false; 216 return false;
133 if (compose_length == 1) 217 if (compose_length == 1)
134 return true; 218 return true;
135 // Check for composition sequences 219 // Check for composition sequences.
136 for (int length = compose_length - 1; length < max_sequence_length_; 220 for (int length = compose_length - 1; length < max_sequence_length_;
137 ++length) { 221 ++length) {
138 const uint16* table = data_ + index[length]; 222 const uint16* table = data_ + (*index)[length];
139 const uint16* table_next = data_ + index[length + 1]; 223 const uint16* table_next = data_ + (*index)[length + 1];
140 if (table_next > table) { 224 if (table_next > table) {
141 // There are composition sequences for this |length| 225 // There are composition sequences for this |length|.
142 const int row_stride = length + 1; 226 const int row_stride = length + 1;
143 const int n_sequences = (table_next - table)/row_stride; 227 const int n_sequences = (table_next - table)/row_stride;
144 const uint16* seq = static_cast<const uint16*>( 228 const SequenceIterator table_begin(table, row_stride);
145 bsearch(&sequence, table, n_sequences, 229 const SequenceIterator table_end = table_begin + n_sequences;
146 sizeof(uint16)*row_stride, CompareSequenceSkipFront)); 230 const SequenceIterator found =
147 if (seq) { 231 std::lower_bound(table_begin, table_end, sequence,
148 if (length == compose_length - 1) // exact match 232 ComparatorAdoptor<CompareSequenceSkipFront>());
149 *composed_character = seq[length]; 233 if (found != table_end &&
234 CompareSequenceSkipFront()(sequence, *found) == 0) {
235 if (length == compose_length - 1) // Exact match.
236 *composed_character = (*found)[length];
150 return true; 237 return true;
151 } 238 }
152 } 239 }
153 } 240 }
154 return false; 241 return false;
155 } 242 }
156 243
157 // static 244 int ComposeCheckerWithCompactTable::CompareSequenceFront::operator()(
158 int ComposeCheckerWithCompactTable::CompareSequenceFront( 245 const ComposeBufferType& l, const uint16* r) const {
159 const void* key_void, 246 return CompareSequenceValue(l[0], r[0]);
160 const void* value_void) {
161 typedef std::vector<unsigned int> KeyType;
162 const KeyType& key = *static_cast<const KeyType*>(key_void);
163 const uint16* value = static_cast<const uint16*>(value_void);
164
165 return CompareSequenceValue(key[0], value[0]);
166 } 247 }
167 248
168 // static 249 int ComposeCheckerWithCompactTable::CompareSequenceSkipFront::operator()(
169 int ComposeCheckerWithCompactTable::CompareSequenceSkipFront( 250 const ComposeBufferType& l, const uint16* r) const {
170 const void* key_void, 251 for(size_t i = 1; i < l.size(); ++i) {
171 const void* value_void) { 252 const int compare_result = CompareSequenceValue(l[i], r[i - 1]);
172 typedef std::vector<unsigned int> KeyType;
173 const KeyType& key = *static_cast<const KeyType*>(key_void);
174 const uint16* value = static_cast<const uint16*>(value_void);
175
176 for(size_t i = 1; i < key.size(); ++i) {
177 const int compare_result = CompareSequenceValue(key[i], value[i - 1]);
178 if(compare_result) 253 if(compare_result)
179 return compare_result; 254 return compare_result;
180 } 255 }
181 return 0; 256 return 0;
182 } 257 }
183 258
184 // Main table 259
185 typedef uint16 guint16; 260 // Main table.
261
262 // This file is included here intentionally, instead of the top of the file,
263 // because including this file outside the anonymous namespace will define a
264 // global constant and contaminate the global namespace.
186 #include "third_party/gtk+/gtk/gtkimcontextsimpleseqs.h" 265 #include "third_party/gtk+/gtk/gtkimcontextsimpleseqs.h"
187 266
188 // Additional table 267
268 // Additional table.
189 269
190 // The difference between this and the default input method is the handling 270 // The difference between this and the default input method is the handling
191 // of C+acute - this method produces C WITH CEDILLA rather than C WITH ACUTE. 271 // of C+acute - this method produces C WITH CEDILLA rather than C WITH ACUTE.
192 // For languages that use CCedilla and not acute, this is the preferred mapping, 272 // For languages that use CCedilla and not acute, this is the preferred mapping,
193 // and is particularly important for pt_BR, where the us-intl keyboard is 273 // and is particularly important for pt_BR, where the us-intl keyboard is
194 // used extensively. 274 // used extensively.
195 275
196 const uint16 cedilla_compose_seqs[] = { 276 const uint16 cedilla_compose_seqs[] = {
197 // LATIN_CAPITAL_LETTER_C_WITH_CEDILLA 277 // LATIN_CAPITAL_LETTER_C_WITH_CEDILLA
198 GDK_KEY_dead_acute, GDK_KEY_C, 0, 0, 0, 0x00C7, 278 GDK_KEY_dead_acute, GDK_KEY_C, 0, 0, 0, 0x00C7,
(...skipping 26 matching lines...) Expand all
225 case GDK_KEY_Hyper_L: 305 case GDK_KEY_Hyper_L:
226 case GDK_KEY_Hyper_R: 306 case GDK_KEY_Hyper_R:
227 case GDK_KEY_Mode_switch: 307 case GDK_KEY_Mode_switch:
228 case GDK_KEY_ISO_Level3_Shift: 308 case GDK_KEY_ISO_Level3_Shift:
229 return true; 309 return true;
230 default: 310 default:
231 return false; 311 return false;
232 } 312 }
233 } 313 }
234 314
235 bool CheckCharacterComposeTable(const std::vector<unsigned int>& sequence, 315 bool CheckCharacterComposeTable(const ComposeBufferType& sequence,
236 uint32* composed_character) { 316 uint32* composed_character) {
237 // Check cedilla compose table 317 // Check cedilla compose table.
238 const ComposeChecker kCedillaComposeChecker( 318 const ComposeChecker kCedillaComposeChecker(
239 cedilla_compose_seqs, 4, arraysize(cedilla_compose_seqs)/(4 + 2)); 319 cedilla_compose_seqs, 4, arraysize(cedilla_compose_seqs)/(4 + 2));
240 if (kCedillaComposeChecker.CheckSequence(sequence, composed_character)) 320 if (kCedillaComposeChecker.CheckSequence(sequence, composed_character))
241 return true; 321 return true;
242 322
243 // Check main compose table 323 // Check main compose table.
244 const ComposeCheckerWithCompactTable kMainComposeChecker( 324 const ComposeCheckerWithCompactTable kMainComposeChecker(
245 gtk_compose_seqs_compact, 5, 24, 6); 325 gtk_compose_seqs_compact, 5, 24, 6);
246 if (kMainComposeChecker.CheckSequence(sequence, composed_character)) 326 if (kMainComposeChecker.CheckSequence(sequence, composed_character))
247 return true; 327 return true;
248 328
249 return false; 329 return false;
250 } 330 }
251 331
252 } // anonymous namespace 332 } // namespace
253 333
254 namespace views { 334 namespace views {
255 335
256 CharacterComposer::CharacterComposer() {} 336 CharacterComposer::CharacterComposer() {}
257 337
258 CharacterComposer::~CharacterComposer() {} 338 CharacterComposer::~CharacterComposer() {}
259 339
260 void CharacterComposer::Reset() { 340 void CharacterComposer::Reset() {
261 compose_buffer_.clear(); 341 compose_buffer_.clear();
262 composed_character_.clear(); 342 composed_character_.clear();
263 } 343 }
264 344
265 bool CharacterComposer::FilterKeyPress(unsigned int keycode) { 345 bool CharacterComposer::FilterKeyPress(unsigned int keycode) {
266 if(KeypressShouldBeIgnored(keycode)) 346 if(KeypressShouldBeIgnored(keycode))
267 return false; 347 return false;
268 348
269 compose_buffer_.push_back(keycode); 349 compose_buffer_.push_back(keycode);
270 350
271 // Check compose table 351 // Check compose table.
272 composed_character_.clear(); 352 composed_character_.clear();
273 uint32 composed_character_utf32 = 0; 353 uint32 composed_character_utf32 = 0;
274 if (CheckCharacterComposeTable(compose_buffer_, &composed_character_utf32)) { 354 if (CheckCharacterComposeTable(compose_buffer_, &composed_character_utf32)) {
275 // Key press is recognized as a part of composition 355 // Key press is recognized as a part of composition.
276 if (composed_character_utf32 !=0) { 356 if (composed_character_utf32 !=0) {
277 // We get a composed character 357 // We get a composed character.
278 compose_buffer_.clear(); 358 compose_buffer_.clear();
279 // We assume that composed character is in BMP 359 // We assume that composed character is in BMP.
280 if (composed_character_utf32 <= 0xffff) 360 if (composed_character_utf32 <= 0xffff)
281 composed_character_ += static_cast<char16>(composed_character_utf32); 361 composed_character_ += static_cast<char16>(composed_character_utf32);
282 } 362 }
283 return true; 363 return true;
284 } 364 }
285 // Key press is not a part of composition 365 // Key press is not a part of composition.
286 compose_buffer_.pop_back(); // remove the keypress added this time 366 compose_buffer_.pop_back(); // Remove the keypress added this time.
287 if (!compose_buffer_.empty()) { 367 if (!compose_buffer_.empty()) {
288 compose_buffer_.clear(); 368 compose_buffer_.clear();
289 return true; 369 return true;
290 } 370 }
291 return false; 371 return false;
292 } 372 }
293 373
294 } // namespace views 374 } // namespace views
OLDNEW
« no previous file with comments | « views/ime/character_composer.h ('k') | views/ime/character_composer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698