Line data Source code
1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* vim:set ts=4 sw=4 sts=4 et cindent: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef NS_UNICODEPROPERTIES_H
8 : #define NS_UNICODEPROPERTIES_H
9 :
10 : #include "nsBidiUtils.h"
11 : #include "nsUGenCategory.h"
12 : #include "nsUnicodeScriptCodes.h"
13 : #include "harfbuzz/hb.h"
14 :
15 : #if ENABLE_INTL_API
16 : #include "unicode/uchar.h"
17 : #include "unicode/uscript.h"
18 : #endif
19 :
20 : const nsCharProps2& GetCharProps2(uint32_t aCh);
21 :
22 : namespace mozilla {
23 :
24 : namespace unicode {
25 :
26 : extern const nsUGenCategory sDetailedToGeneralCategory[];
27 :
28 : /* This MUST match the values assigned by genUnicodePropertyData.pl! */
29 : enum VerticalOrientation {
30 : VERTICAL_ORIENTATION_U = 0,
31 : VERTICAL_ORIENTATION_R = 1,
32 : VERTICAL_ORIENTATION_Tu = 2,
33 : VERTICAL_ORIENTATION_Tr = 3
34 : };
35 :
36 : /* This MUST match the values assigned by genUnicodePropertyData.pl! */
37 : enum PairedBracketType {
38 : PAIRED_BRACKET_TYPE_NONE = 0,
39 : PAIRED_BRACKET_TYPE_OPEN = 1,
40 : PAIRED_BRACKET_TYPE_CLOSE = 2
41 : };
42 :
43 : /* Flags for Unicode security IdentifierType.txt attributes. Only a subset
44 : of these are currently checked by Gecko, so we only define flags for the
45 : ones we need. */
46 : enum IdentifierType {
47 : IDTYPE_RESTRICTED = 0,
48 : IDTYPE_ALLOWED = 1,
49 : };
50 :
51 : #if ENABLE_INTL_API // ICU is available, so simply forward to its API
52 :
53 : extern const hb_unicode_general_category_t sICUtoHBcategory[];
54 :
55 : inline uint32_t
56 0 : GetMirroredChar(uint32_t aCh)
57 : {
58 0 : return u_charMirror(aCh);
59 : }
60 :
61 : inline bool
62 0 : HasMirroredChar(uint32_t aCh)
63 : {
64 0 : return u_isMirrored(aCh);
65 : }
66 :
67 : inline uint8_t
68 0 : GetCombiningClass(uint32_t aCh)
69 : {
70 0 : return u_getCombiningClass(aCh);
71 : }
72 :
73 : inline uint8_t
74 1158 : GetGeneralCategory(uint32_t aCh)
75 : {
76 1158 : return sICUtoHBcategory[u_charType(aCh)];
77 : }
78 :
79 : inline nsCharType
80 1 : GetBidiCat(uint32_t aCh)
81 : {
82 1 : return nsCharType(u_charDirection(aCh));
83 : }
84 :
85 : inline int8_t
86 0 : GetNumericValue(uint32_t aCh)
87 : {
88 : UNumericType type =
89 0 : UNumericType(u_getIntPropertyValue(aCh, UCHAR_NUMERIC_TYPE));
90 0 : return type == U_NT_DECIMAL || type == U_NT_DIGIT
91 0 : ? int8_t(u_getNumericValue(aCh)) : -1;
92 : }
93 :
94 : inline uint8_t
95 0 : GetLineBreakClass(uint32_t aCh)
96 : {
97 0 : return u_getIntPropertyValue(aCh, UCHAR_LINE_BREAK);
98 : }
99 :
100 : inline Script
101 658 : GetScriptCode(uint32_t aCh)
102 : {
103 658 : UErrorCode err = U_ZERO_ERROR;
104 658 : return Script(uscript_getScript(aCh, &err));
105 : }
106 :
107 : inline bool
108 0 : HasScript(uint32_t aCh, Script aScript)
109 : {
110 0 : return uscript_hasScript(aCh, UScriptCode(aScript));
111 : }
112 :
113 : inline uint32_t
114 379 : GetScriptTagForCode(Script aScriptCode)
115 : {
116 379 : const char* tag = uscript_getShortName(UScriptCode(aScriptCode));
117 379 : return HB_TAG(tag[0], tag[1], tag[2], tag[3]);
118 : }
119 :
120 : inline PairedBracketType
121 : GetPairedBracketType(uint32_t aCh)
122 : {
123 : return PairedBracketType
124 : (u_getIntPropertyValue(aCh, UCHAR_BIDI_PAIRED_BRACKET_TYPE));
125 : }
126 :
127 : inline uint32_t
128 : GetPairedBracket(uint32_t aCh)
129 : {
130 : return u_getBidiPairedBracket(aCh);
131 : }
132 :
133 : inline uint32_t
134 0 : GetUppercase(uint32_t aCh)
135 : {
136 0 : return u_toupper(aCh);
137 : }
138 :
139 : inline uint32_t
140 0 : GetLowercase(uint32_t aCh)
141 : {
142 0 : return u_tolower(aCh);
143 : }
144 :
145 : inline uint32_t
146 0 : GetTitlecaseForLower(uint32_t aCh) // maps LC to titlecase, UC unchanged
147 : {
148 0 : return u_isULowercase(aCh) ? u_totitle(aCh) : aCh;
149 : }
150 :
151 : inline uint32_t
152 : GetTitlecaseForAll(uint32_t aCh) // maps both UC and LC to titlecase
153 : {
154 : return u_totitle(aCh);
155 : }
156 :
157 : inline bool
158 0 : IsEastAsianWidthFWH(uint32_t aCh)
159 : {
160 0 : switch (u_getIntPropertyValue(aCh, UCHAR_EAST_ASIAN_WIDTH)) {
161 : case U_EA_FULLWIDTH:
162 : case U_EA_WIDE:
163 : case U_EA_HALFWIDTH:
164 0 : return true;
165 : case U_EA_AMBIGUOUS:
166 : case U_EA_NARROW:
167 : case U_EA_NEUTRAL:
168 0 : return false;
169 : }
170 0 : return false;
171 : }
172 :
173 : inline bool
174 265 : IsDefaultIgnorable(uint32_t aCh)
175 : {
176 265 : return u_hasBinaryProperty(aCh, UCHAR_DEFAULT_IGNORABLE_CODE_POINT);
177 : }
178 :
179 : #else // not ENABLE_INTL_API
180 :
181 : // Return whether the char has a mirrored-pair counterpart.
182 : uint32_t GetMirroredChar(uint32_t aCh);
183 :
184 : bool HasMirroredChar(uint32_t aChr);
185 :
186 : uint8_t GetCombiningClass(uint32_t aCh);
187 :
188 : // returns the detailed General Category in terms of HB_UNICODE_* values
189 : uint8_t GetGeneralCategory(uint32_t aCh);
190 :
191 : nsCharType GetBidiCat(uint32_t aCh);
192 :
193 : uint8_t GetLineBreakClass(uint32_t aCh);
194 :
195 : Script GetScriptCode(uint32_t aCh);
196 :
197 : // We don't support ScriptExtensions.txt data when building without ICU.
198 : // The most important cases will still be handled in gfxScriptItemizer
199 : // by checking IsClusterExtender to avoid breaking script runs within
200 : // a cluster.
201 : inline bool
202 : HasScript(uint32_t aCh, Script aScript)
203 : {
204 : return false;
205 : }
206 :
207 : uint32_t GetScriptTagForCode(Script aScriptCode);
208 :
209 : PairedBracketType GetPairedBracketType(uint32_t aCh);
210 : uint32_t GetPairedBracket(uint32_t aCh);
211 :
212 : /**
213 : * Return the numeric value of the character. The value returned is the value
214 : * of the Numeric_Value in field 7 of the UCD, or -1 if field 7 is empty.
215 : * To restrict to decimal digits, the caller should also check whether
216 : * GetGeneralCategory returns HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER
217 : */
218 : int8_t GetNumericValue(uint32_t aCh);
219 :
220 : uint32_t GetUppercase(uint32_t aCh);
221 : uint32_t GetLowercase(uint32_t aCh);
222 : uint32_t GetTitlecaseForLower(uint32_t aCh); // maps LC to titlecase, UC unchanged
223 : uint32_t GetTitlecaseForAll(uint32_t aCh); // maps both UC and LC to titlecase
224 :
225 : // Return whether the char has EastAsianWidth class F or W or H.
226 : bool IsEastAsianWidthFWH(uint32_t aCh);
227 :
228 : // Return whether the char is default-ignorable.
229 : inline bool IsDefaultIgnorable(uint32_t aCh)
230 : {
231 : return GetCharProps2(aCh).mDefaultIgnorable;
232 : }
233 :
234 : #endif // !ENABLE_INTL_API
235 :
236 : // returns the simplified Gen Category as defined in nsUGenCategory
237 111 : inline nsUGenCategory GetGenCategory(uint32_t aCh) {
238 111 : return sDetailedToGeneralCategory[GetGeneralCategory(aCh)];
239 : }
240 :
241 0 : inline VerticalOrientation GetVerticalOrientation(uint32_t aCh) {
242 0 : return VerticalOrientation(GetCharProps2(aCh).mVertOrient);
243 : }
244 :
245 0 : inline IdentifierType GetIdentifierType(uint32_t aCh) {
246 0 : return IdentifierType(GetCharProps2(aCh).mIdType);
247 : }
248 :
249 : uint32_t GetFullWidth(uint32_t aCh);
250 : // This is the reverse function of GetFullWidth which guarantees that
251 : // for every codepoint c, GetFullWidthInverse(GetFullWidth(c)) == c.
252 : // Note that, this function does not guarantee to convert all wide
253 : // form characters to their possible narrow form.
254 : uint32_t GetFullWidthInverse(uint32_t aCh);
255 :
256 : bool IsClusterExtender(uint32_t aCh, uint8_t aCategory);
257 :
258 727 : inline bool IsClusterExtender(uint32_t aCh) {
259 727 : return IsClusterExtender(aCh, GetGeneralCategory(aCh));
260 : }
261 :
262 : // A simple iterator for a string of char16_t codepoints that advances
263 : // by Unicode grapheme clusters
264 : class ClusterIterator
265 : {
266 : public:
267 2 : ClusterIterator(const char16_t* aText, uint32_t aLength)
268 4 : : mPos(aText), mLimit(aText + aLength)
269 : #ifdef DEBUG
270 4 : , mText(aText)
271 : #endif
272 2 : { }
273 :
274 22 : operator const char16_t* () const {
275 22 : return mPos;
276 : }
277 :
278 24 : bool AtEnd() const {
279 24 : return mPos >= mLimit;
280 : }
281 :
282 : void Next();
283 :
284 : private:
285 : const char16_t* mPos;
286 : const char16_t* mLimit;
287 : #ifdef DEBUG
288 : const char16_t* mText;
289 : #endif
290 : };
291 :
292 : // Count the number of grapheme clusters in the given string
293 : uint32_t CountGraphemeClusters(const char16_t* aText, uint32_t aLength);
294 :
295 : // A simple reverse iterator for a string of char16_t codepoints that
296 : // advances by Unicode grapheme clusters
297 : class ClusterReverseIterator
298 : {
299 : public:
300 0 : ClusterReverseIterator(const char16_t* aText, uint32_t aLength)
301 0 : : mPos(aText + aLength), mLimit(aText)
302 0 : { }
303 :
304 0 : operator const char16_t* () const {
305 0 : return mPos;
306 : }
307 :
308 0 : bool AtEnd() const {
309 0 : return mPos <= mLimit;
310 : }
311 :
312 : void Next();
313 :
314 : private:
315 : const char16_t* mPos;
316 : const char16_t* mLimit;
317 : };
318 :
319 : } // end namespace unicode
320 :
321 : } // end namespace mozilla
322 :
323 : #endif /* NS_UNICODEPROPERTIES_H */
|