1 |
|
|
/*************************************************************************** |
2 |
|
|
* Copyright (c) 2024 Microsoft Corporation |
3 |
|
|
* |
4 |
|
|
* This program and the accompanying materials are made available under the |
5 |
|
|
* terms of the MIT License which is available at |
6 |
|
|
* https://opensource.org/licenses/MIT. |
7 |
|
|
* |
8 |
|
|
* SPDX-License-Identifier: MIT |
9 |
|
|
**************************************************************************/ |
10 |
|
|
|
11 |
|
|
|
12 |
|
|
/**************************************************************************/ |
13 |
|
|
/**************************************************************************/ |
14 |
|
|
/** */ |
15 |
|
|
/** GUIX Component */ |
16 |
|
|
/** */ |
17 |
|
|
/** Utility (Utility) */ |
18 |
|
|
/** */ |
19 |
|
|
/**************************************************************************/ |
20 |
|
|
|
21 |
|
|
#define GX_SOURCE_CODE |
22 |
|
|
|
23 |
|
|
/* Include necessary system files. */ |
24 |
|
|
|
25 |
|
|
#include "gx_api.h" |
26 |
|
|
#include "gx_utility.h" |
27 |
|
|
|
28 |
|
|
|
29 |
|
|
/**************************************************************************/ |
30 |
|
|
/* */ |
31 |
|
|
/* FUNCTION RELEASE */ |
32 |
|
|
/* */ |
33 |
|
|
/* _gx_utility_utf8_string_character_get PORTABLE C */ |
34 |
|
|
/* 6.1 */ |
35 |
|
|
/* AUTHOR */ |
36 |
|
|
/* */ |
37 |
|
|
/* Kenneth Maxwell, Microsoft Corporation */ |
38 |
|
|
/* */ |
39 |
|
|
/* DESCRIPTION */ |
40 |
|
|
/* */ |
41 |
|
|
/* This function parses utf8 string to multibyte glyph. */ |
42 |
|
|
/* */ |
43 |
|
|
/* INPUT */ |
44 |
|
|
/* */ |
45 |
|
|
/* utf8_str UTF-8 string */ |
46 |
|
|
/* glyph_value Multibyte value of glyph */ |
47 |
|
|
/* byte_count Length of UTF-8 string in byte*/ |
48 |
|
|
/* glyph_len Length of glyph value in byte */ |
49 |
|
|
/* */ |
50 |
|
|
/* OUTPUT */ |
51 |
|
|
/* */ |
52 |
|
|
/* status Completion status */ |
53 |
|
|
/* */ |
54 |
|
|
/* CALLS */ |
55 |
|
|
/* */ |
56 |
|
|
/* */ |
57 |
|
|
/* CALLED BY */ |
58 |
|
|
/* */ |
59 |
|
|
/* _gx_system_string_width_get */ |
60 |
|
|
/* _gx_display_driver_indexed_color_text_draw */ |
61 |
|
|
/* */ |
62 |
|
|
/* RELEASE HISTORY */ |
63 |
|
|
/* */ |
64 |
|
|
/* DATE NAME DESCRIPTION */ |
65 |
|
|
/* */ |
66 |
|
|
/* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */ |
67 |
|
|
/* 09-30-2020 Kenneth Maxwell Modified comment(s), */ |
68 |
|
|
/* resulting in version 6.1 */ |
69 |
|
|
/* */ |
70 |
|
|
/**************************************************************************/ |
71 |
|
|
#ifdef GX_UTF8_SUPPORT |
72 |
|
32293962 |
UINT _gx_utility_utf8_string_character_get(GX_STRING *utf8_str, GX_CHAR_CODE *glyph_value, UINT *glyph_len) |
73 |
|
|
{ |
74 |
|
|
GX_CONST GX_CHAR *ch; |
75 |
|
|
UINT bytes; |
76 |
|
32293962 |
GX_CHAR_CODE value = 0; |
77 |
|
|
UINT len; |
78 |
|
|
UINT byte_count; |
79 |
|
|
|
80 |
|
32293962 |
ch = utf8_str -> gx_string_ptr; |
81 |
|
32293962 |
byte_count = utf8_str -> gx_string_length; |
82 |
|
|
|
83 |
|
|
/* BOM check. */ |
84 |
✓✓✓✓ ✓✓✓✓
|
32293962 |
if ((byte_count >= 3) && (*ch == (char)0xEF) && (*(ch + 1) == (char)0xBB) && (*(ch + 2) == (char)0xBF)) |
85 |
|
|
{ |
86 |
|
|
/* It is BOM. Skip it. */ |
87 |
|
1 |
ch += 3; |
88 |
|
1 |
byte_count -= 3; |
89 |
|
|
} |
90 |
|
|
|
91 |
✓✓ |
32293962 |
if (byte_count == 0) |
92 |
|
|
{ |
93 |
|
|
/* Zero length string. Return error. */ |
94 |
✓✓ |
7 |
if (glyph_value) |
95 |
|
|
{ |
96 |
|
1 |
*glyph_value = 0; |
97 |
|
|
} |
98 |
|
|
|
99 |
✓✓ |
7 |
if (glyph_len) |
100 |
|
|
{ |
101 |
|
6 |
*glyph_len = 0; |
102 |
|
|
} |
103 |
|
7 |
return GX_INVALID_VALUE; |
104 |
|
|
} |
105 |
|
|
|
106 |
|
|
/* Reset glyph length to 1. */ |
107 |
|
32293955 |
len = 1; |
108 |
|
|
|
109 |
|
|
/* Check the first byte */ |
110 |
✓✓ |
32293955 |
if ((*ch & 0x80) == 0) |
111 |
|
|
{ |
112 |
|
|
|
113 |
|
32113647 |
utf8_str -> gx_string_ptr = ch + 1; |
114 |
|
32113647 |
utf8_str -> gx_string_length -= 1; |
115 |
|
|
|
116 |
|
|
/* One byte glyph. */ |
117 |
✓✓ |
32113647 |
if (glyph_value) |
118 |
|
|
{ |
119 |
|
30737550 |
*glyph_value = (*ch & ~0x80) & 0xFF; |
120 |
|
|
} |
121 |
|
|
|
122 |
✓✓ |
32113647 |
if (glyph_len) |
123 |
|
|
{ |
124 |
|
1410684 |
*glyph_len = 1; |
125 |
|
|
} |
126 |
|
|
|
127 |
|
32113647 |
return GX_SUCCESS; |
128 |
|
|
} |
129 |
✓✓ |
180308 |
else if ((*ch & 0xE0) == 0xC0) |
130 |
|
|
{ |
131 |
|
|
|
132 |
|
|
/* Two bytes glyph. */ |
133 |
|
9099 |
bytes = 2; |
134 |
|
9099 |
value = (*ch & ~0xE0) & 0xFF; |
135 |
|
|
} |
136 |
✓✓ |
171209 |
else if ((*ch & 0xF0) == 0xE0) |
137 |
|
|
{ |
138 |
|
|
|
139 |
|
|
/* Three bytes glyph. */ |
140 |
|
171142 |
bytes = 3; |
141 |
|
171142 |
value = (*ch & ~0xF0) & 0xFF; |
142 |
|
|
} |
143 |
✓✓ |
67 |
else if ((*ch & 0xF8) == 0xF0) |
144 |
|
|
{ |
145 |
|
|
|
146 |
|
|
/* Four bytes glyph. */ |
147 |
|
1 |
bytes = 4; |
148 |
|
1 |
value = (*ch & ~0xF8) & 0xFF; |
149 |
|
|
} |
150 |
✓✓ |
66 |
else if ((*ch & 0xFC) == 0xF8) |
151 |
|
|
{ |
152 |
|
|
|
153 |
|
|
/* Five bytes glyph. */ |
154 |
|
1 |
bytes = 5; |
155 |
|
1 |
value = (*ch & ~0xFC) & 0xFF; |
156 |
|
|
} |
157 |
✓✓ |
65 |
else if ((*ch & 0xFE) == 0xFC) |
158 |
|
|
{ |
159 |
|
|
|
160 |
|
|
/* Six bytes glyph. */ |
161 |
|
4 |
bytes = 6; |
162 |
|
4 |
value = (*ch & ~0xFE) & 0xFF; |
163 |
|
|
} |
164 |
|
|
else |
165 |
|
|
{ |
166 |
|
|
/* Not a valid utf8 glyph. */ |
167 |
|
61 |
utf8_str -> gx_string_ptr = ch + 1; |
168 |
|
61 |
utf8_str -> gx_string_length -= 1; |
169 |
|
|
|
170 |
✓✓ |
61 |
if (glyph_value) |
171 |
|
|
{ |
172 |
|
55 |
*glyph_value = 0; |
173 |
|
|
} |
174 |
|
|
|
175 |
✓✓ |
61 |
if (glyph_len) |
176 |
|
|
{ |
177 |
|
6 |
*glyph_len = 1; |
178 |
|
|
} |
179 |
|
|
|
180 |
|
61 |
return GX_INVALID_VALUE; |
181 |
|
|
} |
182 |
|
|
|
183 |
✓✓ |
180247 |
if (byte_count < bytes) |
184 |
|
|
{ |
185 |
|
|
/* Not a valid utf8 glyph. */ |
186 |
✓✓ |
4 |
if (glyph_value) |
187 |
|
|
{ |
188 |
|
1 |
*glyph_value = 0; |
189 |
|
|
} |
190 |
|
|
|
191 |
✓✓ |
4 |
if (glyph_len) |
192 |
|
|
{ |
193 |
|
3 |
*glyph_len = bytes; |
194 |
|
|
} |
195 |
|
4 |
utf8_str -> gx_string_length -= bytes; |
196 |
|
|
|
197 |
|
4 |
return GX_INVALID_VALUE; |
198 |
|
|
} |
199 |
|
|
|
200 |
✓✓ |
531620 |
while (len < bytes) |
201 |
|
|
{ |
202 |
|
351383 |
ch++; |
203 |
|
351383 |
len++; |
204 |
|
|
|
205 |
✓✓ |
351383 |
if ((*ch & 0xC0) != 0x80) |
206 |
|
|
{ |
207 |
|
|
|
208 |
|
|
/* Not a valid utf8 glyph. */ |
209 |
✓✓ |
6 |
if (glyph_len) |
210 |
|
|
{ |
211 |
|
1 |
*glyph_len = len; |
212 |
|
|
} |
213 |
|
|
|
214 |
|
6 |
utf8_str -> gx_string_ptr = ch; |
215 |
|
6 |
utf8_str -> gx_string_length -= len; |
216 |
|
|
|
217 |
|
6 |
return GX_INVALID_VALUE; |
218 |
|
|
} |
219 |
|
|
|
220 |
|
351377 |
value = (GX_CHAR_CODE)(value << 6); |
221 |
|
351377 |
value = (GX_CHAR_CODE)(value + ((*ch & ~0xC0) & 0xFF)); |
222 |
|
|
} |
223 |
|
|
|
224 |
✓✓ |
180237 |
if (glyph_value) |
225 |
|
|
{ |
226 |
|
172699 |
*glyph_value = value; |
227 |
|
|
} |
228 |
|
|
|
229 |
✓✓ |
180237 |
if (glyph_len) |
230 |
|
|
{ |
231 |
|
7544 |
*glyph_len = len; |
232 |
|
|
} |
233 |
|
|
|
234 |
|
180237 |
utf8_str -> gx_string_ptr = ch + 1; |
235 |
|
180237 |
utf8_str -> gx_string_length -= len; |
236 |
|
|
|
237 |
|
180237 |
return GX_SUCCESS; |
238 |
|
|
} |
239 |
|
|
|
240 |
|
|
#endif /* GX_UTF8_SUPPORT */ |
241 |
|
|
|