4 #include <harfbuzz-external.h>
5 #include <harfbuzz-impl.h>
6 #include <harfbuzz-shaper.h>
7 #include "harfbuzz-unicode.h"
9 #include "tables/grapheme-break-properties.h"
10 #include "tables/mirroring-properties.h"
11 #include "tables/script-properties.h"
14 utf16_to_code_point(const uint16_t *chars
, size_t len
, ssize_t
*iter
) {
15 const uint16_t v
= chars
[(*iter
)++];
16 if (HB_IsHighSurrogate(v
)) {
19 // the surrogate is incomplete.
20 return HB_InvalidCodePoint
;
22 const uint16_t v2
= chars
[(*iter
)++];
23 if (!HB_IsLowSurrogate(v2
)) {
24 // invalidate surrogate pair.
25 return HB_InvalidCodePoint
;
28 return HB_SurrogateToUcs4(v
, v2
);
31 if (HB_IsLowSurrogate(v
)) {
32 // this isn't a valid code point
33 return HB_InvalidCodePoint
;
40 utf16_to_code_point_prev(const uint16_t *chars
, size_t len
, ssize_t
*iter
) {
41 const uint16_t v
= chars
[(*iter
)--];
42 if (HB_IsLowSurrogate(v
)) {
45 // the surrogate is incomplete.
46 return HB_InvalidCodePoint
;
48 const uint16_t v2
= chars
[(*iter
)--];
49 if (!HB_IsHighSurrogate(v2
)) {
50 // invalidate surrogate pair.
51 return HB_InvalidCodePoint
;
54 return HB_SurrogateToUcs4(v2
, v
);
57 if (HB_IsHighSurrogate(v
)) {
58 // this isn't a valid code point
59 return HB_InvalidCodePoint
;
66 script_property_cmp(const void *vkey
, const void *vcandidate
) {
67 const uint32_t key
= (uint32_t) (intptr_t) vkey
;
68 const struct script_property
*candidate
= vcandidate
;
70 if (key
< candidate
->range_start
) {
72 } else if (key
> candidate
->range_end
) {
80 code_point_to_script(uint32_t cp
) {
81 const void *vprop
= bsearch((void *) (intptr_t) cp
, script_properties
,
82 script_properties_count
,
83 sizeof(struct script_property
),
86 return HB_Script_Common
;
88 return ((const struct script_property
*) vprop
)->script
;
92 hb_utf16_script_run_next(unsigned *num_code_points
, HB_ScriptItem
*output
,
93 const uint16_t *chars
, size_t len
, ssize_t
*iter
) {
98 const uint32_t init_cp
= utf16_to_code_point(chars
, len
, iter
);
100 if (init_cp
== HB_InvalidCodePoint
)
102 const HB_Script init_script
= code_point_to_script(init_cp
);
103 HB_Script current_script
= init_script
;
104 output
->script
= init_script
;
109 const ssize_t prev_iter
= *iter
;
110 const uint32_t cp
= utf16_to_code_point(chars
, len
, iter
);
111 if (cp
== HB_InvalidCodePoint
)
114 const HB_Script script
= code_point_to_script(cp
);
116 if (script
!= current_script
) {
117 if (current_script
== HB_Script_Inherited
&& init_script
== HB_Script_Inherited
) {
118 // If we started off as inherited, we take whatever we can find.
119 output
->script
= script
;
120 current_script
= script
;
122 } else if (script
== HB_Script_Inherited
) {
132 if (output
->script
== HB_Script_Inherited
)
133 output
->script
= HB_Script_Common
;
135 output
->length
= *iter
- output
->pos
;
137 *num_code_points
= cps
;
142 hb_utf16_script_run_prev(unsigned *num_code_points
, HB_ScriptItem
*output
,
143 const uint16_t *chars
, size_t len
, ssize_t
*iter
) {
144 if (*iter
== (size_t) -1)
147 const size_t ending_index
= *iter
;
148 const uint32_t init_cp
= utf16_to_code_point_prev(chars
, len
, iter
);
150 if (init_cp
== HB_InvalidCodePoint
)
152 const HB_Script init_script
= code_point_to_script(init_cp
);
153 HB_Script current_script
= init_script
;
154 output
->script
= init_script
;
159 const ssize_t prev_iter
= *iter
;
160 const uint32_t cp
= utf16_to_code_point_prev(chars
, len
, iter
);
161 if (cp
== HB_InvalidCodePoint
)
164 const HB_Script script
= code_point_to_script(cp
);
166 if (script
!= current_script
) {
167 if (current_script
== init_script
== HB_Script_Inherited
) {
168 // If we started off as inherited, we take whatever we can find.
169 output
->script
= script
;
170 current_script
= script
;
172 } else if (script
== HB_Script_Inherited
) {
173 // Just assume that whatever follows this combining character is within
174 // the same script. This is incorrect if you had language1 + combining
175 // char + language 2, but that is rare and this code is suspicious
186 if (output
->script
== HB_Script_Inherited
)
187 output
->script
= HB_Script_Common
;
189 output
->pos
= *iter
+ 1;
190 output
->length
= ending_index
- *iter
;
192 *num_code_points
= cps
;
197 grapheme_break_property_cmp(const void *vkey
, const void *vcandidate
) {
198 const uint32_t key
= (uint32_t) (intptr_t) vkey
;
199 const struct grapheme_break_property
*candidate
= vcandidate
;
201 if (key
< candidate
->range_start
) {
203 } else if (key
> candidate
->range_end
) {
211 HB_GetGraphemeClass(HB_UChar32 ch
) {
212 const void *vprop
= bsearch((void *) (intptr_t) ch
, grapheme_break_properties
,
213 grapheme_break_properties_count
,
214 sizeof(struct grapheme_break_property
),
215 grapheme_break_property_cmp
);
217 return HB_Grapheme_Other
;
219 return ((const struct grapheme_break_property
*) vprop
)->klass
;
223 HB_GetWordClass(HB_UChar32 ch
) {
229 HB_GetSentenceClass(HB_UChar32 ch
) {
235 HB_GetGraphemeAndLineBreakClass(HB_UChar32 ch
, HB_GraphemeClass
*gclass
, HB_LineBreakClass
*breakclass
) {
236 *gclass
= HB_GetGraphemeClass(ch
);
237 *breakclass
= HB_GetLineBreakClass(ch
);
241 mirroring_property_cmp(const void *vkey
, const void *vcandidate
) {
242 const uint32_t key
= (uint32_t) (intptr_t) vkey
;
243 const struct mirroring_property
*candidate
= vcandidate
;
245 if (key
< candidate
->a
) {
247 } else if (key
> candidate
->a
) {
255 HB_GetMirroredChar(HB_UChar16 ch
) {
256 const void *mprop
= bsearch((void *) (intptr_t) ch
, mirroring_properties
,
257 mirroring_properties_count
,
258 sizeof(struct mirroring_property
),
259 mirroring_property_cmp
);
263 return ((const struct mirroring_property
*) mprop
)->b
;
267 HB_Library_Resolve(const char *library
, int version
, const char *symbol
) {