OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights | 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights |
5 * reserved. | 5 * reserved. |
6 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) | 6 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) |
7 * Copyright (C) 2010 Daniel Bates (dbates@intudata.com) | 7 * Copyright (C) 2010 Daniel Bates (dbates@intudata.com) |
8 * | 8 * |
9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
(...skipping 21 matching lines...) Expand all Loading... |
32 namespace blink { | 32 namespace blink { |
33 | 33 |
34 namespace ListMarkerText { | 34 namespace ListMarkerText { |
35 | 35 |
36 enum SequenceType { NumericSequence, AlphabeticSequence }; | 36 enum SequenceType { NumericSequence, AlphabeticSequence }; |
37 | 37 |
38 static String toRoman(int number, bool upper) { | 38 static String toRoman(int number, bool upper) { |
39 // FIXME: CSS3 describes how to make this work for much larger numbers, | 39 // FIXME: CSS3 describes how to make this work for much larger numbers, |
40 // using overbars and special characters. It also specifies the characters | 40 // using overbars and special characters. It also specifies the characters |
41 // in the range U+2160 to U+217F instead of standard ASCII ones. | 41 // in the range U+2160 to U+217F instead of standard ASCII ones. |
42 ASSERT(number >= 1 && number <= 3999); | 42 DCHECK_GE(number, 1); |
| 43 DCHECK_LE(number, 3999); |
43 | 44 |
44 // Big enough to store largest roman number less than 3999 which | 45 // Big enough to store largest roman number less than 3999 which |
45 // is 3888 (MMMDCCCLXXXVIII) | 46 // is 3888 (MMMDCCCLXXXVIII) |
46 const int lettersSize = 15; | 47 const int lettersSize = 15; |
47 LChar letters[lettersSize]; | 48 LChar letters[lettersSize]; |
48 | 49 |
49 int length = 0; | 50 int length = 0; |
50 const LChar ldigits[] = {'i', 'v', 'x', 'l', 'c', 'd', 'm'}; | 51 const LChar ldigits[] = {'i', 'v', 'x', 'l', 'c', 'd', 'm'}; |
51 const LChar udigits[] = {'I', 'V', 'X', 'L', 'C', 'D', 'M'}; | 52 const LChar udigits[] = {'I', 'V', 'X', 'L', 'C', 'D', 'M'}; |
52 const LChar* digits = upper ? udigits : ldigits; | 53 const LChar* digits = upper ? udigits : ldigits; |
53 int d = 0; | 54 int d = 0; |
54 do { | 55 do { |
55 int num = number % 10; | 56 int num = number % 10; |
56 if (num % 5 < 4) | 57 if (num % 5 < 4) |
57 for (int i = num % 5; i > 0; i--) | 58 for (int i = num % 5; i > 0; i--) |
58 letters[lettersSize - ++length] = digits[d]; | 59 letters[lettersSize - ++length] = digits[d]; |
59 if (num >= 4 && num <= 8) | 60 if (num >= 4 && num <= 8) |
60 letters[lettersSize - ++length] = digits[d + 1]; | 61 letters[lettersSize - ++length] = digits[d + 1]; |
61 if (num == 9) | 62 if (num == 9) |
62 letters[lettersSize - ++length] = digits[d + 2]; | 63 letters[lettersSize - ++length] = digits[d + 2]; |
63 if (num % 5 == 4) | 64 if (num % 5 == 4) |
64 letters[lettersSize - ++length] = digits[d]; | 65 letters[lettersSize - ++length] = digits[d]; |
65 number /= 10; | 66 number /= 10; |
66 d += 2; | 67 d += 2; |
67 } while (number); | 68 } while (number); |
68 | 69 |
69 ASSERT(length <= lettersSize); | 70 DCHECK_LE(length, lettersSize); |
70 return String(&letters[lettersSize - length], length); | 71 return String(&letters[lettersSize - length], length); |
71 } | 72 } |
72 | 73 |
73 // The typedef is needed because taking sizeof(number) in the const expression | 74 // The typedef is needed because taking sizeof(number) in the const expression |
74 // below doesn't work with some compilers. This is likely the case because of | 75 // below doesn't work with some compilers. This is likely the case because of |
75 // the template. | 76 // the template. |
76 typedef int numberType; | 77 typedef int numberType; |
77 | 78 |
78 template <typename CharacterType> | 79 template <typename CharacterType> |
79 static inline String toAlphabeticOrNumeric(numberType number, | 80 static inline String toAlphabeticOrNumeric(numberType number, |
80 const CharacterType* sequence, | 81 const CharacterType* sequence, |
81 unsigned sequenceSize, | 82 unsigned sequenceSize, |
82 SequenceType type) { | 83 SequenceType type) { |
83 ASSERT(sequenceSize >= 2); | 84 DCHECK_GE(sequenceSize, 2u); |
84 | 85 |
85 // Binary is the worst case; requires one character per bit plus a minus sign. | 86 // Binary is the worst case; requires one character per bit plus a minus sign. |
86 const int lettersSize = sizeof(numberType) * 8 + 1; | 87 const int lettersSize = sizeof(numberType) * 8 + 1; |
87 | 88 |
88 CharacterType letters[lettersSize]; | 89 CharacterType letters[lettersSize]; |
89 | 90 |
90 bool isNegativeNumber = false; | 91 bool isNegativeNumber = false; |
91 unsigned numberShadow = number; | 92 unsigned numberShadow = number; |
92 if (type == AlphabeticSequence) { | 93 if (type == AlphabeticSequence) { |
93 ASSERT(number > 0); | 94 DCHECK_GT(number, 0); |
94 --numberShadow; | 95 --numberShadow; |
95 } else if (number < 0) { | 96 } else if (number < 0) { |
96 numberShadow = -number; | 97 numberShadow = -number; |
97 isNegativeNumber = true; | 98 isNegativeNumber = true; |
98 } | 99 } |
99 letters[lettersSize - 1] = sequence[numberShadow % sequenceSize]; | 100 letters[lettersSize - 1] = sequence[numberShadow % sequenceSize]; |
100 int length = 1; | 101 int length = 1; |
101 | 102 |
102 if (type == AlphabeticSequence) { | 103 if (type == AlphabeticSequence) { |
103 while ((numberShadow /= sequenceSize) > 0) { | 104 while ((numberShadow /= sequenceSize) > 0) { |
104 --numberShadow; | 105 --numberShadow; |
105 letters[lettersSize - ++length] = sequence[numberShadow % sequenceSize]; | 106 letters[lettersSize - ++length] = sequence[numberShadow % sequenceSize]; |
106 } | 107 } |
107 } else { | 108 } else { |
108 while ((numberShadow /= sequenceSize) > 0) | 109 while ((numberShadow /= sequenceSize) > 0) |
109 letters[lettersSize - ++length] = sequence[numberShadow % sequenceSize]; | 110 letters[lettersSize - ++length] = sequence[numberShadow % sequenceSize]; |
110 } | 111 } |
111 if (isNegativeNumber) | 112 if (isNegativeNumber) |
112 letters[lettersSize - ++length] = hyphenMinusCharacter; | 113 letters[lettersSize - ++length] = hyphenMinusCharacter; |
113 | 114 |
114 ASSERT(length <= lettersSize); | 115 DCHECK_LE(length, lettersSize); |
115 return String(&letters[lettersSize - length], length); | 116 return String(&letters[lettersSize - length], length); |
116 } | 117 } |
117 | 118 |
118 template <typename CharacterType> | 119 template <typename CharacterType> |
119 static String toSymbolic(int number, | 120 static String toSymbolic(int number, |
120 const CharacterType* symbols, | 121 const CharacterType* symbols, |
121 unsigned symbolsSize) { | 122 unsigned symbolsSize) { |
122 ASSERT(number > 0); | 123 DCHECK_GT(number, 0); |
123 ASSERT(symbolsSize >= 1); | 124 DCHECK_GE(symbolsSize, 1u); |
124 unsigned numberShadow = number; | 125 unsigned numberShadow = number; |
125 --numberShadow; | 126 --numberShadow; |
126 | 127 |
127 // The asterisks list-style-type is the worst case; we show |numberShadow| | 128 // The asterisks list-style-type is the worst case; we show |numberShadow| |
128 // asterisks. | 129 // asterisks. |
129 StringBuilder letters; | 130 StringBuilder letters; |
130 letters.append(symbols[numberShadow % symbolsSize]); | 131 letters.append(symbols[numberShadow % symbolsSize]); |
131 unsigned numSymbols = numberShadow / symbolsSize; | 132 unsigned numSymbols = numberShadow / symbolsSize; |
132 while (numSymbols--) | 133 while (numSymbols--) |
133 letters.append(symbols[numberShadow % symbolsSize]); | 134 letters.append(symbols[numberShadow % symbolsSize]); |
(...skipping 30 matching lines...) Expand all Loading... |
164 template <typename CharacterType, size_t size> | 165 template <typename CharacterType, size_t size> |
165 static inline String toSymbolic(int number, | 166 static inline String toSymbolic(int number, |
166 const CharacterType (&alphabet)[size]) { | 167 const CharacterType (&alphabet)[size]) { |
167 return toSymbolic(number, alphabet, size); | 168 return toSymbolic(number, alphabet, size); |
168 } | 169 } |
169 | 170 |
170 static void toHebrewUnder1000(int number, Vector<UChar>& letters) { | 171 static void toHebrewUnder1000(int number, Vector<UChar>& letters) { |
171 // FIXME: CSS3 mentions various refinements not implemented here. | 172 // FIXME: CSS3 mentions various refinements not implemented here. |
172 // FIXME: Should take a look at Mozilla's HebrewToText function (in | 173 // FIXME: Should take a look at Mozilla's HebrewToText function (in |
173 // nsBulletFrame). | 174 // nsBulletFrame). |
174 ASSERT(number >= 0 && number < 1000); | 175 DCHECK_GE(number, 0); |
| 176 DCHECK_LT(number, 1000); |
175 int fourHundreds = number / 400; | 177 int fourHundreds = number / 400; |
176 for (int i = 0; i < fourHundreds; i++) | 178 for (int i = 0; i < fourHundreds; i++) |
177 letters.push_front(1511 + 3); | 179 letters.push_front(1511 + 3); |
178 number %= 400; | 180 number %= 400; |
179 if (number / 100) | 181 if (number / 100) |
180 letters.push_front(1511 + (number / 100) - 1); | 182 letters.push_front(1511 + (number / 100) - 1); |
181 number %= 100; | 183 number %= 100; |
182 if (number == 15 || number == 16) { | 184 if (number == 15 || number == 16) { |
183 letters.push_front(1487 + 9); | 185 letters.push_front(1487 + 9); |
184 letters.push_front(1487 + number - 9); | 186 letters.push_front(1487 + number - 9); |
185 } else { | 187 } else { |
186 if (int tens = number / 10) { | 188 if (int tens = number / 10) { |
187 static const UChar hebrewTens[9] = {1497, 1499, 1500, 1502, 1504, | 189 static const UChar hebrewTens[9] = {1497, 1499, 1500, 1502, 1504, |
188 1505, 1506, 1508, 1510}; | 190 1505, 1506, 1508, 1510}; |
189 letters.push_front(hebrewTens[tens - 1]); | 191 letters.push_front(hebrewTens[tens - 1]); |
190 } | 192 } |
191 if (int ones = number % 10) | 193 if (int ones = number % 10) |
192 letters.push_front(1487 + ones); | 194 letters.push_front(1487 + ones); |
193 } | 195 } |
194 } | 196 } |
195 | 197 |
196 static String toHebrew(int number) { | 198 static String toHebrew(int number) { |
197 // FIXME: CSS3 mentions ways to make this work for much larger numbers. | 199 // FIXME: CSS3 mentions ways to make this work for much larger numbers. |
198 ASSERT(number >= 0 && number <= 999999); | 200 DCHECK_GE(number, 0); |
| 201 DCHECK_LE(number, 999999); |
199 | 202 |
200 if (number == 0) { | 203 if (number == 0) { |
201 static const UChar hebrewZero[3] = {0x05E1, 0x05E4, 0x05D0}; | 204 static const UChar hebrewZero[3] = {0x05E1, 0x05E4, 0x05D0}; |
202 return String(hebrewZero, 3); | 205 return String(hebrewZero, 3); |
203 } | 206 } |
204 | 207 |
205 Vector<UChar> letters; | 208 Vector<UChar> letters; |
206 if (number > 999) { | 209 if (number > 999) { |
207 toHebrewUnder1000(number / 1000, letters); | 210 toHebrewUnder1000(number / 1000, letters); |
208 letters.push_front('\''); | 211 letters.push_front('\''); |
209 number = number % 1000; | 212 number = number % 1000; |
210 } | 213 } |
211 toHebrewUnder1000(number, letters); | 214 toHebrewUnder1000(number, letters); |
212 return String(letters); | 215 return String(letters); |
213 } | 216 } |
214 | 217 |
215 static int toArmenianUnder10000(int number, | 218 static int toArmenianUnder10000(int number, |
216 bool upper, | 219 bool upper, |
217 bool addCircumflex, | 220 bool addCircumflex, |
218 UChar letters[9]) { | 221 UChar letters[9]) { |
219 ASSERT(number >= 0 && number < 10000); | 222 DCHECK_GE(number, 0); |
| 223 DCHECK_LT(number, 10000); |
220 int length = 0; | 224 int length = 0; |
221 | 225 |
222 int lowerOffset = upper ? 0 : 0x0030; | 226 int lowerOffset = upper ? 0 : 0x0030; |
223 | 227 |
224 if (int thousands = number / 1000) { | 228 if (int thousands = number / 1000) { |
225 if (thousands == 7) { | 229 if (thousands == 7) { |
226 letters[length++] = 0x0552 + lowerOffset; | 230 letters[length++] = 0x0552 + lowerOffset; |
227 if (addCircumflex) | 231 if (addCircumflex) |
228 letters[length++] = 0x0302; | 232 letters[length++] = 0x0302; |
229 } else { | 233 } else { |
(...skipping 18 matching lines...) Expand all Loading... |
248 if (int ones = number % 10) { | 252 if (int ones = number % 10) { |
249 letters[length++] = (0x531 - 1 + lowerOffset) + ones; | 253 letters[length++] = (0x531 - 1 + lowerOffset) + ones; |
250 if (addCircumflex) | 254 if (addCircumflex) |
251 letters[length++] = 0x0302; | 255 letters[length++] = 0x0302; |
252 } | 256 } |
253 | 257 |
254 return length; | 258 return length; |
255 } | 259 } |
256 | 260 |
257 static String toArmenian(int number, bool upper) { | 261 static String toArmenian(int number, bool upper) { |
258 ASSERT(number >= 1 && number <= 99999999); | 262 DCHECK_GE(number, 1); |
| 263 DCHECK_LE(number, 99999999); |
259 | 264 |
260 const int lettersSize = 18; // twice what toArmenianUnder10000 needs | 265 const int lettersSize = 18; // twice what toArmenianUnder10000 needs |
261 UChar letters[lettersSize]; | 266 UChar letters[lettersSize]; |
262 | 267 |
263 int length = toArmenianUnder10000(number / 10000, upper, true, letters); | 268 int length = toArmenianUnder10000(number / 10000, upper, true, letters); |
264 length += | 269 length += |
265 toArmenianUnder10000(number % 10000, upper, false, letters + length); | 270 toArmenianUnder10000(number % 10000, upper, false, letters + length); |
266 | 271 |
267 ASSERT(length <= lettersSize); | 272 DCHECK_LE(length, lettersSize); |
268 return String(letters, length); | 273 return String(letters, length); |
269 } | 274 } |
270 | 275 |
271 static String toGeorgian(int number) { | 276 static String toGeorgian(int number) { |
272 ASSERT(number >= 1 && number <= 19999); | 277 DCHECK_GE(number, 1); |
| 278 DCHECK_LE(number, 19999); |
273 | 279 |
274 const int lettersSize = 5; | 280 const int lettersSize = 5; |
275 UChar letters[lettersSize]; | 281 UChar letters[lettersSize]; |
276 | 282 |
277 int length = 0; | 283 int length = 0; |
278 | 284 |
279 if (number > 9999) | 285 if (number > 9999) |
280 letters[length++] = 0x10F5; | 286 letters[length++] = 0x10F5; |
281 | 287 |
282 if (int thousands = (number / 1000) % 10) { | 288 if (int thousands = (number / 1000) % 10) { |
(...skipping 13 matching lines...) Expand all Loading... |
296 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10F2, 0x10DD, 0x10DE, 0x10DF}; | 302 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10F2, 0x10DD, 0x10DE, 0x10DF}; |
297 letters[length++] = georgianTens[tens - 1]; | 303 letters[length++] = georgianTens[tens - 1]; |
298 } | 304 } |
299 | 305 |
300 if (int ones = number % 10) { | 306 if (int ones = number % 10) { |
301 static const UChar georgianOnes[9] = { | 307 static const UChar georgianOnes[9] = { |
302 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10F1, 0x10D7}; | 308 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10F1, 0x10D7}; |
303 letters[length++] = georgianOnes[ones - 1]; | 309 letters[length++] = georgianOnes[ones - 1]; |
304 } | 310 } |
305 | 311 |
306 ASSERT(length <= lettersSize); | 312 DCHECK_LE(length, lettersSize); |
307 return String(letters, length); | 313 return String(letters, length); |
308 } | 314 } |
309 | 315 |
310 enum CJKLang { Chinese = 1, Korean, Japanese }; | 316 enum CJKLang { Chinese = 1, Korean, Japanese }; |
311 | 317 |
312 enum CJKStyle { Formal, Informal }; | 318 enum CJKStyle { Formal, Informal }; |
313 | 319 |
314 // The table uses the order from the CSS3 specification: | 320 // The table uses the order from the CSS3 specification: |
315 // first 3 group markers, then 3 digit markers, then ten digits, then negative | 321 // first 3 group markers, then 3 digit markers, then ten digits, then negative |
316 // symbols. | 322 // symbols. |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 | 416 |
411 if (trailingZero && i > 0) { | 417 if (trailingZero && i > 0) { |
412 group[6] = group[7]; | 418 group[6] = group[7]; |
413 group[7] = group[8]; | 419 group[7] = group[8]; |
414 group[8] = Digit0; | 420 group[8] = Digit0; |
415 } | 421 } |
416 | 422 |
417 // Remove the tens digit, but leave the marker, for any group that has | 423 // Remove the tens digit, but leave the marker, for any group that has |
418 // a value of less than 20. | 424 // a value of less than 20. |
419 if (table[Lang] == Chinese && cjkStyle == Informal && groupValue < 20) { | 425 if (table[Lang] == Chinese && cjkStyle == Informal && groupValue < 20) { |
420 ASSERT(group[4] == NoChar || group[4] == Digit0 || group[4] == Digit1); | 426 DCHECK(group[4] == NoChar || group[4] == Digit0 || group[4] == Digit1); |
421 group[4] = NoChar; | 427 group[4] = NoChar; |
422 } | 428 } |
423 | 429 |
424 if (number == 0) | 430 if (number == 0) |
425 break; | 431 break; |
426 } | 432 } |
427 | 433 |
428 // Convert into characters, omitting consecutive runs of Digit0 and | 434 // Convert into characters, omitting consecutive runs of Digit0 and |
429 // any trailing Digit0. | 435 // any trailing Digit0. |
430 int length = 0; | 436 int length = 0; |
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
934 return toHebrew(count); | 940 return toHebrew(count); |
935 } | 941 } |
936 | 942 |
937 NOTREACHED(); | 943 NOTREACHED(); |
938 return ""; | 944 return ""; |
939 } | 945 } |
940 | 946 |
941 } // namespace ListMarkerText | 947 } // namespace ListMarkerText |
942 | 948 |
943 } // namespace blink | 949 } // namespace blink |
OLD | NEW |