comparison src/redisplay-x.c @ 4881:a4322ac49e37

break out common separate-into-runs routines into redisplay-xlike-inc.c -------------------- ChangeLog entries follow: -------------------- src/ChangeLog addition: 2010-01-18 Ben Wing <ben@xemacs.org> * redisplay-xlike-inc.c: * redisplay-xlike-inc.c (separate_textual_runs_nomule): * redisplay-xlike-inc.c (separate_textual_runs_xft_nomule): * redisplay-xlike-inc.c (separate_textual_runs_xft_mule): * redisplay-xlike-inc.c (separate_textual_runs_mule): Break separate_textual_runs_* functions from redisplay-x.c. (Code in redisplay-gtk.c should have been identical but was bit-rotted.) * redisplay-gtk.c: * redisplay-x.c: Delete code, replace with include statement. * depend: Regenerate.
author Ben Wing <ben@xemacs.org>
date Mon, 18 Jan 2010 06:21:05 -0600
parents 11daf37dae4d
children eab9498ecc0e
comparison
equal deleted inserted replaced
4880:ae81a2c00f4f 4881:a4322ac49e37
75 #ifdef USE_XFT 75 #ifdef USE_XFT
76 #define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \ 76 #define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \
77 ? ((unsigned long) (x)) : ((unsigned long) (y))) 77 ? ((unsigned long) (x)) : ((unsigned long) (y)))
78 #endif /* USE_XFT */ 78 #endif /* USE_XFT */
79 79
80 80 #include "redisplay-xlike-inc.c"
81 /* Note: We do not use the Xmb*() functions and XFontSets, nor the
82 Motif XFontLists and CompoundStrings.
83 Those functions are generally losing for a number of reasons.
84 Most important, they only support one locale (e.g. you could
85 display Japanese and ASCII text, but not mixed Japanese/Chinese
86 text). You could maybe call setlocale() frequently to try to deal
87 with this, but that would generally fail because an XFontSet is
88 tied to one locale and won't have the other character sets in it.
89
90 fontconfig (the font database for Xft) has some specifier-like
91 properties, but it's not sufficient (witness the existence of
92 Pango). Pango might do the trick, but it's not a cross-platform
93 solution; it would need significant advantages to be worth the
94 effort.
95 */
96
97 /* #### Break me out into a separate header */
98 struct textual_run
99 {
100 Lisp_Object charset;
101 unsigned char *ptr;
102 int len;
103 int dimension;
104 };
105
106 /* Separate out the text in DYN into a series of textual runs of a
107 particular charset. Also convert the characters as necessary into
108 the format needed by XDrawImageString(), XDrawImageString16(), et
109 al. This means converting to one or two byte format, possibly
110 tweaking the high bits, and possibly running a CCL program. You
111 must pre-allocate the space used and pass it in. (This is done so
112 you can ALLOCA () the space.) (sizeof(bufchar) * len) bytes must be
113 allocated for TEXT_STORAGE and (len * sizeof (struct textual_run))
114 bytes of RUN_STORAGE, where LEN is the length of the dynarr.
115
116 bufchar might not be fixed width (in the case of UTF-8).
117
118 Returns the number of runs actually used. */
119
120 /* Notes on Xft implementation
121
122 - With Unicode, we're no longer going to have repertoires reified as
123 charsets. (Not that we ever really did, what with corporate variants,
124 and so on.) So we really should be querying the face for the desired
125 font, rather than the character for the charset, and that's what would
126 determine the separation into runs.
127 - The widechar versions of fontconfig (and therefore Xft) functions
128 seem to be just bigendian Unicode. So there's actually no need to use
129 the 8-bit versions in computing runs and runes, it would seem.
130 */
131
132 #if !defined(USE_XFT) && !defined(MULE)
133 static int
134 separate_textual_runs_nomule (unsigned char *text_storage,
135 struct textual_run *run_storage,
136 const Ichar *str, Charcount len,
137 struct face_cachel *UNUSED(cachel))
138 {
139 if (!len)
140 return 0;
141
142 run_storage[0].ptr = text_storage;
143 run_storage[0].len = len;
144 run_storage[0].dimension = 1;
145 run_storage[0].charset = Qnil;
146
147 while (len--)
148 *text_storage++ = *str++;
149 return 1;
150 }
151 #endif
152
153 #if defined(USE_XFT) && !defined(MULE)
154 /*
155 Note that in this configuration the "Croatian hack" of using an 8-bit,
156 non-Latin-1 font to get localized display without Mule simply isn't
157 available. That's by design -- Unicode does not aid or abet that kind
158 of punning.
159 This means that the cast to XftChar16 gives the correct "conversion" to
160 UCS-2.
161 #### Is there an alignment issue with text_storage?
162 */
163 static int
164 separate_textual_runs_xft_nomule (unsigned char *text_storage,
165 struct textual_run *run_storage,
166 const Ichar *str, Charcount len,
167 struct face_cachel *UNUSED(cachel))
168 {
169 int i;
170 if (!len)
171 return 0;
172
173 run_storage[0].ptr = text_storage;
174 run_storage[0].len = len;
175 run_storage[0].dimension = 2;
176 run_storage[0].charset = Qnil;
177
178 for (i = 0; i < len; i++)
179 {
180 *(XftChar16 *)text_storage = str[i];
181 text_storage += sizeof(XftChar16);
182 }
183 return 1;
184 }
185 #endif
186
187 #if defined(USE_XFT) && defined(MULE)
188 static int
189 separate_textual_runs_xft_mule (unsigned char *text_storage,
190 struct textual_run *run_storage,
191 const Ichar *str, Charcount len,
192 struct face_cachel *UNUSED(cachel))
193 {
194 Lisp_Object prev_charset = Qunbound;
195 int runs_so_far = 0, i;
196
197 run_storage[0].ptr = text_storage;
198 run_storage[0].len = len;
199 run_storage[0].dimension = 2;
200 run_storage[0].charset = Qnil;
201
202 for (i = 0; i < len; i++)
203 {
204 Ichar ch = str[i];
205 Lisp_Object charset = ichar_charset(ch);
206 int ucs = ichar_to_unicode(ch);
207
208 /* If UCS is less than zero or greater than 0xFFFF, set ucs2 to
209 REPLACMENT CHARACTER. */
210 /* That means we can't handle characters outside of the BMP for now */
211 ucs = (ucs & ~0xFFFF) ? 0xFFFD : ucs;
212
213 if (!EQ (charset, prev_charset))
214 {
215 if (runs_so_far)
216 run_storage[runs_so_far-1].len = (text_storage - run_storage[runs_so_far-1].ptr) >> 1;
217 run_storage[runs_so_far].ptr = text_storage;
218 run_storage[runs_so_far].dimension = 2;
219 run_storage[runs_so_far].charset = charset;
220 prev_charset = charset;
221 runs_so_far++;
222 }
223
224 *(XftChar16 *)text_storage = ucs;
225 text_storage += sizeof(XftChar16);
226 }
227
228 if (runs_so_far)
229 run_storage[runs_so_far-1].len = (text_storage - run_storage[runs_so_far-1].ptr) >> 1;
230 return runs_so_far;
231 }
232 #endif
233
234 #if !defined(USE_XFT) && defined(MULE)
235 /*
236 This is the most complex function of this group, due to the various
237 indexing schemes used by different fonts. For our purposes, they
238 fall into three classes. Some fonts are indexed compatibly with ISO
239 2022; those fonts just use the Mule internal representation directly
240 (typically the high bit must be reset; this is determined by the `graphic'
241 flag). Some fonts are indexed by Unicode, specifically by UCS-2. These
242 are all translated using `ichar_to_unicode'. Finally some fonts have
243 irregular indexes, and must be translated ad hoc. In XEmacs ad hoc
244 translations are accomplished with CCL programs. */
245 static int
246 separate_textual_runs_mule (unsigned char *text_storage,
247 struct textual_run *run_storage,
248 const Ichar *str, Charcount len,
249 struct face_cachel *cachel)
250 {
251 Lisp_Object prev_charset = Qunbound;
252 int runs_so_far = 0, i;
253 Ibyte charset_leading_byte = LEADING_BYTE_ASCII;
254 int dimension = 1, graphic = 0, need_ccl_conversion = 0;
255 Lisp_Object ccl_prog;
256 struct ccl_program char_converter;
257
258 int translate_to_ucs_2 = 0;
259
260 for (i = 0; i < len; i++)
261 {
262 Ichar ch = str[i];
263 Lisp_Object charset;
264 int byte1, byte2; /* BREAKUP_ICHAR dereferences the addresses
265 of its arguments as pointer to int. */
266 BREAKUP_ICHAR (ch, charset, byte1, byte2);
267
268 if (!EQ (charset, prev_charset))
269 {
270 /* At this point, dimension' and `prev_charset' refer to just-
271 completed run. `runs_so_far' and `text_storage' refer to the
272 run about to start. */
273 if (runs_so_far)
274 {
275 /* Update metadata for previous run. */
276 run_storage[runs_so_far - 1].len =
277 text_storage - run_storage[runs_so_far - 1].ptr;
278 if (2 == dimension) run_storage[runs_so_far - 1].len >>= 1;
279 }
280
281 /* Compute metadata for current run.
282 First, classify font.
283 If the font is indexed by UCS-2, set `translate_to_ucs_2'.
284 Else if the charset has a CCL program, set `need_ccl_conversion'.
285 Else if the font is indexed by an ISO 2022 "graphic register",
286 set `graphic'.
287 These flags are almost mutually exclusive, but we're sloppy
288 about resetting "shadowed" flags. So the flags must be checked
289 in the proper order in computing byte1 and byte2, below. */
290 charset_leading_byte = XCHARSET_LEADING_BYTE(charset);
291 translate_to_ucs_2 =
292 bit_vector_bit (FACE_CACHEL_FONT_FINAL_STAGE (cachel),
293 charset_leading_byte - MIN_LEADING_BYTE);
294 if (translate_to_ucs_2)
295 {
296 dimension = 2;
297 }
298 else
299 {
300 dimension = XCHARSET_DIMENSION (charset);
301
302 /* Check for CCL charset.
303 If setup_ccl_program fails, we'll get a garbaged display.
304 This should never happen, and even if it does, it should
305 be harmless (unless the X server has buggy handling of
306 characters undefined in the font). It may be marginally
307 more useful to users and debuggers than substituting a
308 fixed replacement character. */
309 ccl_prog = XCHARSET_CCL_PROGRAM (charset);
310 if ((!NILP (ccl_prog))
311 && (setup_ccl_program (&char_converter, ccl_prog) >= 0))
312 {
313 need_ccl_conversion = 1;
314 }
315 else
316 {
317 /* The charset must have an ISO 2022-compatible font index.
318 There are 2 "registers" (what such fonts use as index).
319 GL (graphic == 0) has the high bit of each octet reset,
320 GR (graphic == 1) has it set. */
321 graphic = XCHARSET_GRAPHIC (charset);
322 need_ccl_conversion = 0;
323 }
324 }
325
326 /* Initialize metadata for current run. */
327 run_storage[runs_so_far].ptr = text_storage;
328 run_storage[runs_so_far].charset = charset;
329 run_storage[runs_so_far].dimension = dimension;
330
331 /* Update loop variables. */
332 prev_charset = charset;
333 runs_so_far++;
334 }
335
336 /* Must check flags in this order. See comment above. */
337 if (translate_to_ucs_2)
338 {
339 int ucs = ichar_to_unicode(ch);
340 /* If UCS is less than zero or greater than 0xFFFF, set ucs2 to
341 REPLACMENT CHARACTER. */
342 ucs = (ucs & ~0xFFFF) ? 0xFFFD : ucs;
343
344 byte1 = ucs >> 8;
345 byte2 = ucs;
346 }
347 else if (need_ccl_conversion)
348 {
349 char_converter.reg[0] = charset_leading_byte;
350 char_converter.reg[1] = byte1;
351 char_converter.reg[2] = byte2;
352 ccl_driver (&char_converter, 0, 0, 0, 0, CCL_MODE_ENCODING);
353 byte1 = char_converter.reg[1];
354 byte2 = char_converter.reg[2];
355 }
356 else if (graphic == 0)
357 {
358 byte1 &= 0x7F;
359 byte2 &= 0x7F;
360 }
361 else
362 {
363 byte1 |= 0x80;
364 byte2 |= 0x80;
365 }
366
367 *text_storage++ = (unsigned char)byte1;
368
369 if (2 == dimension) *text_storage++ = (unsigned char)byte2;
370 }
371
372 if (runs_so_far)
373 {
374 run_storage[runs_so_far - 1].len =
375 text_storage - run_storage[runs_so_far - 1].ptr;
376 /* Dimension retains the relevant value for the run before it. */
377 if (2 == dimension)
378 run_storage[runs_so_far - 1].len >>= 1;
379 }
380
381 return runs_so_far;
382 }
383 #endif
384
385 static int
386 separate_textual_runs (unsigned char *text_storage,
387 struct textual_run *run_storage,
388 const Ichar *str, Charcount len,
389 struct face_cachel *cachel)
390 {
391 #if defined(USE_XFT) && defined(MULE)
392 return separate_textual_runs_xft_mule(text_storage, run_storage, str, len, cachel);
393 #endif
394 #if defined(USE_XFT) && !defined(MULE)
395 return separate_textual_runs_xft_nomule(text_storage, run_storage, str, len, cachel);
396 #endif
397 #if !defined(USE_XFT) && defined(MULE)
398 return separate_textual_runs_mule(text_storage, run_storage, str, len, cachel);
399 #endif
400 #if !defined(USE_XFT) && !defined(MULE)
401 return separate_textual_runs_nomule(text_storage, run_storage, str, len, cachel);
402 #endif
403 }
404 81
405 /****************************************************************************/ 82 /****************************************************************************/
406 /* */ 83 /* */
407 /* X output routines */ 84 /* X output routines */
408 /* */ 85 /* */