1 /* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */
2
3 #include "ui_draw_str.h"
4
5 #include <pobl/bl_mem.h> /* alloca */
6 #include <vt_drcs.h>
7
8 #ifndef NO_IMAGE
9 #include "ui_picture.h"
10
11 #define INLINEPIC_ID(glyph) (((glyph) >> PICTURE_POS_BITS) & (MAX_INLINE_PICTURES - 1))
12 #define INLINEPIC_POS(glyph) ((glyph) & ((1 << PICTURE_POS_BITS) - 1))
13 #endif
14
15 #if 0
16 #define PERF_DEBUG
17 #endif
18
19 #if 0
20 #define CLIP_LINE
21 #endif
22
23 /* --- static functions --- */
24
calculate_char_width(ui_font_t * font,u_int code,ef_charset_t cs,int is_awidth,vt_char_t * comb,u_int comb_size,int * draw_alone)25 static u_int calculate_char_width(ui_font_t *font, u_int code, ef_charset_t cs, int is_awidth,
26 vt_char_t *comb, u_int comb_size, int *draw_alone) {
27 u_int width;
28
29 width = ui_calculate_char_width(font, code, cs, is_awidth, draw_alone);
30
31 if (cs == ISO10646_UCS4_1_V) {
32 u_int w;
33
34 for (; comb_size > 0; comb_size--, comb++) {
35 #ifdef DEBUG
36 if (vt_char_cs(comb) != ISO10646_UCS4_1_V) {
37 bl_debug_printf(BL_DEBUG_TAG
38 " %x cs is unexpectedly"
39 " combined to ISO10646_UCS4_1_V.\n");
40
41 continue;
42 }
43 #endif
44
45 if ((w = vt_char_get_advance(comb)) > width) {
46 width = w;
47 }
48 }
49 }
50
51 return width;
52 }
53
54 #ifndef USE_CONSOLE
draw_line(ui_window_t * window,ui_color_t * color,int is_vertical,int line_style,int x,int y,u_int width,u_int height,u_int ascent,int top_margin)55 static void draw_line(ui_window_t *window, ui_color_t *color, int is_vertical, int line_style,
56 int x, int y, u_int width, u_int height, u_int ascent, int top_margin) {
57 u_int w;
58 u_int h;
59 int x2;
60 int y2;
61
62 if (is_vertical) {
63 w = 1;
64 h = height;
65
66 if (line_style == LS_UNDERLINE_DOUBLE) {
67 x2 = x + 2;
68 y2 = y;
69 } else {
70 w += ((ascent - top_margin) / 16);
71
72 if (line_style == LS_CROSSED_OUT) {
73 x += ((width - 1) / 2);
74 } else if (line_style == LS_OVERLINE) {
75 x += (width - (width >= 2 ? 2 : 1));
76 }
77 }
78 } else {
79 w = width;
80 h = 1;
81
82 if (line_style == LS_UNDERLINE_DOUBLE) {
83 x2 = x;
84
85 if (ascent + 2 >= height) {
86 y2 = y + height - 1;
87 y = y2 - 2;
88 } else {
89 y += ascent;
90 y2 = y + 2;
91 }
92 } else {
93 h += ((ascent - top_margin) / 16);
94
95 if (line_style == LS_CROSSED_OUT) {
96 y += ((height + 1) / 2);
97 } else if (line_style == LS_OVERLINE) {
98 /* do nothing */
99 } else {
100 y += ascent;
101 }
102 }
103 }
104
105 ui_window_fill_with(window, color, x, y, w, h);
106
107 if (line_style == LS_UNDERLINE_DOUBLE) {
108 ui_window_fill_with(window, color, x2, y2, w, h);
109 }
110 }
111 #endif
112
113 #ifndef NO_IMAGE
draw_picture(ui_window_t * window,u_int32_t * glyphs,u_int num_glyphs,int dst_x,int dst_y,u_int ch_width,u_int line_height,ui_color_t * bg_xcolor)114 static int draw_picture(ui_window_t *window, u_int32_t *glyphs, u_int num_glyphs, int dst_x,
115 int dst_y, u_int ch_width, u_int line_height, ui_color_t *bg_xcolor) {
116 u_int count;
117 ui_inline_picture_t *cur_pic;
118 u_int num_rows;
119 int src_x;
120 int src_y;
121 u_int src_width;
122 u_int src_height;
123 u_int dst_width;
124 int need_clear;
125 int is_end;
126
127 cur_pic = NULL;
128 is_end = 0;
129
130 for (count = 0; count < num_glyphs; count++) {
131 ui_inline_picture_t *pic;
132 int pos;
133 int x;
134 u_int w;
135
136 if (!(pic = ui_get_inline_picture(INLINEPIC_ID(glyphs[count])))) {
137 dst_x += ch_width;
138
139 continue;
140 }
141
142 /*
143 * XXX
144 * pic->col_width isn't used in this function, so it can be
145 * removed in the future.
146 */
147
148 if (pic != cur_pic) {
149 num_rows = (pic->height + pic->line_height - 1) / pic->line_height;
150 }
151
152 pos = INLINEPIC_POS(glyphs[count]);
153 x = (pos / num_rows) * ch_width;
154
155 if (x + ch_width > pic->width) {
156 w = pic->width > x ? pic->width - x : 0;
157 } else {
158 w = ch_width;
159 }
160
161 if (count == 0) {
162 goto new_picture;
163 } else if (w > 0 && pic == cur_pic && src_x + src_width == x) {
164 if (!need_clear && w < ch_width) {
165 if (!bg_xcolor) {
166 ui_window_clear(window, dst_x + dst_width, dst_y, ch_width, line_height);
167 } else {
168 ui_window_fill_with(window, bg_xcolor, dst_x + dst_width, dst_y, ch_width, line_height);
169 }
170 }
171
172 src_width += w;
173 dst_width += ch_width;
174
175 if (count + 1 < num_glyphs) {
176 continue;
177 }
178
179 is_end = 1;
180 }
181
182 if (need_clear > 0) {
183 if (!bg_xcolor) {
184 ui_window_clear(window, dst_x, dst_y, dst_width, line_height);
185 } else {
186 ui_window_fill_with(window, bg_xcolor, dst_x, dst_y, dst_width, line_height);
187 }
188 }
189
190 if (src_width > 0 && src_height > 0
191 #ifndef INLINE_PICTURE_MOVABLE_BETWEEN_DISPLAYS
192 && cur_pic->disp == window->disp
193 #endif
194 ) {
195 #ifdef __DEBUG
196 bl_debug_printf("Drawing picture at %d %d (pix %p mask %p x %d y %d w %d h %d)\n", dst_x,
197 dst_y, cur_pic->pixmap, cur_pic->mask, src_x, src_y, src_width, src_height);
198 #endif
199
200 ui_window_copy_area(window, cur_pic->pixmap, cur_pic->mask, src_x, src_y, src_width,
201 src_height, dst_x, dst_y);
202 }
203
204 if (is_end) {
205 return 1;
206 }
207
208 dst_x += dst_width;
209
210 new_picture:
211 src_y = (pos % num_rows) * line_height;
212 src_x = x;
213 dst_width = ch_width;
214 cur_pic = pic;
215 need_clear = 0;
216
217 if (cur_pic->mask) {
218 need_clear = 1;
219 }
220
221 if (src_y + line_height > pic->height) {
222 need_clear = 1;
223 src_height = pic->height > src_y ? pic->height - src_y : 0;
224 } else {
225 src_height = line_height;
226 }
227
228 if (strstr(cur_pic->file_path, "mlterm/animx") && cur_pic->next_frame >= 0) {
229 /* Don't clear if cur_pic is 2nd or later GIF Animation frame. */
230 need_clear = -1;
231 }
232
233 if ((src_width = w) < ch_width && !need_clear) {
234 if (!bg_xcolor) {
235 ui_window_clear(window, dst_x, dst_y, ch_width, line_height);
236 } else {
237 ui_window_fill_with(window, bg_xcolor, dst_x, dst_y, ch_width, line_height);
238 }
239 }
240 }
241
242 if (need_clear > 0) {
243 if (!bg_xcolor) {
244 ui_window_clear(window, dst_x, dst_y, dst_width, line_height);
245 } else {
246 ui_window_fill_with(window, bg_xcolor, dst_x, dst_y, dst_width, line_height);
247 }
248 }
249
250 #ifdef __DEBUG
251 bl_debug_printf("Drawing picture at %d %d (pix %p mask %p x %d y %d w %d h %d)\n", dst_x, dst_y,
252 cur_pic->pixmap, cur_pic->mask, src_x, src_y, src_width, src_height);
253 #endif
254
255 if (src_width > 0 && src_height > 0
256 #ifndef INLINE_PICTURE_MOVABLE_BETWEEN_DISPLAYS
257 && cur_pic->disp == window->disp
258 #endif
259 ) {
260 ui_window_copy_area(window, cur_pic->pixmap, cur_pic->mask, src_x, src_y, src_width, src_height,
261 dst_x, dst_y);
262 }
263
264 return 1;
265 }
266 #endif
267
268 #ifndef USE_CONSOLE
get_drcs_bitmap(char * glyph,u_int width,int x,int y)269 static int get_drcs_bitmap(char *glyph, u_int width, int x, int y) {
270 return (glyph[(y / 6) * (width + 1) + x] - '?') & (1 << (y % 6));
271 }
272
draw_drcs(ui_window_t * window,char ** glyphs,u_int num_glyphs,int x,int y,u_int ch_width,u_int line_height,ui_color_t * fg_xcolor,int size_attr)273 static int draw_drcs(ui_window_t *window, char **glyphs, u_int num_glyphs, int x, int y,
274 u_int ch_width, u_int line_height, ui_color_t *fg_xcolor, int size_attr) {
275 int y_off = 0;
276
277 if (size_attr >= DOUBLE_HEIGHT_TOP) {
278 if (size_attr == DOUBLE_HEIGHT_BOTTOM) {
279 y_off = line_height;
280 }
281
282 line_height *= 2;
283 }
284
285 for (; y_off < line_height; y_off++) {
286 u_int w;
287 int x_off_sum; /* x_off for all glyphs */
288 int x_off; /* x_off for each glyph */
289 char *glyph;
290 u_int glyph_width;
291 u_int glyph_height;
292 u_int smpl_width;
293 u_int smpl_height;
294
295 w = 0;
296
297 for (x_off_sum = 0; x_off_sum < ch_width * num_glyphs; x_off_sum++) {
298 int left_x;
299 int top_y;
300 int hit;
301 int n_smpl;
302 int smpl_x;
303 int smpl_y;
304
305 if ((x_off = x_off_sum % ch_width) == 0) {
306 glyph = glyphs[x_off_sum / ch_width];
307
308 glyph_width = glyph[0];
309 glyph_height = glyph[1];
310 glyph += 2;
311
312 if ((smpl_width = glyph_width / ch_width + 1) >= 3) {
313 smpl_width = 2;
314 }
315
316 if ((smpl_height = glyph_height / line_height + 1) >= 3) {
317 smpl_height = 2;
318 }
319 }
320
321 left_x = (x_off * glyph_width * 10 / ch_width + 5) / 10 - smpl_width / 2;
322 top_y = (y_off * glyph_height * 10 / line_height + 5) / 10 - smpl_height / 2;
323 /*
324 * If top_y < 0 or top_y >= glyph_height, w is always 0
325 * regardless of content of glyph.
326 */
327 if (top_y < 0) {
328 top_y = 0;
329 } else if (top_y >= glyph_height) {
330 top_y = glyph_height - 1;
331 }
332
333 #if 0
334 bl_debug_printf(BL_DEBUG_TAG "x_off %d: center x %f -> %d\n", x_off,
335 (double)(x_off * glyph_width) / (double)ch_width, left_x + smpl_width / 2);
336 bl_debug_printf(BL_DEBUG_TAG "y_off %d: center y %f -> %d\n", y_off,
337 (double)(y_off * glyph_height) / (double)line_height,
338 top_y + smpl_height / 2);
339 #endif
340
341 hit = n_smpl = 0;
342
343 for (smpl_y = 0; smpl_y < smpl_height; smpl_y++) {
344 for (smpl_x = 0; smpl_x < smpl_width; smpl_x++) {
345 if (0 <= left_x + smpl_x && left_x + smpl_x < glyph_width && 0 <= top_y + smpl_y &&
346 top_y + smpl_y < glyph_height) {
347 if (get_drcs_bitmap(glyph, glyph_width, left_x + smpl_x, top_y + smpl_y)) {
348 hit++;
349 }
350 n_smpl++;
351 }
352 }
353 }
354
355 if (n_smpl <= hit * 2) {
356 w++;
357
358 if (x_off_sum + 1 == ch_width * num_glyphs) {
359 /* for x_off - w */
360 x_off_sum++;
361 } else {
362 continue;
363 }
364 } else if (w == 0) {
365 continue;
366 }
367
368 if (size_attr >= DOUBLE_HEIGHT_TOP) {
369 int exp_y;
370
371 if (size_attr == DOUBLE_HEIGHT_TOP) {
372 if (y_off >= line_height / 2) {
373 return 1;
374 }
375
376 exp_y = y + y_off;
377 } else {
378 exp_y = y + y_off - line_height / 2;
379 }
380
381 ui_window_fill_with(window, fg_xcolor, x + x_off_sum - w, exp_y, w, 1);
382 } else {
383 ui_window_fill_with(window, fg_xcolor, x + x_off_sum - w, y + y_off, w, 1);
384 }
385
386 w = 0;
387 }
388 }
389
390 return 1;
391 }
392 #endif
393
get_state(ef_charset_t ch_cs,u_int32_t ch_code,vt_char_t * comb_chars,u_int32_t * pic_glyph,char ** drcs_glyph,int * draw_alone)394 static int get_state(ef_charset_t ch_cs, u_int32_t ch_code, vt_char_t *comb_chars,
395 u_int32_t *pic_glyph, char **drcs_glyph, int *draw_alone) {
396 #ifndef NO_IMAGE
397 if (comb_chars && vt_char_cs(comb_chars) == PICTURE_CHARSET) {
398 *draw_alone = 0; /* forcibly set 0 regardless of uifont. */
399 *pic_glyph = vt_char_code(comb_chars) | (vt_char_picture_id(comb_chars) << PICTURE_POS_BITS);
400 *drcs_glyph = NULL;
401
402 return 4;
403 } else
404 #endif
405 {
406 *pic_glyph = 0;
407
408 if ((*drcs_glyph = vt_drcs_get_glyph(ch_cs, ch_code))) {
409 *draw_alone = 0; /* forcibly set 0 regardless of uifont. */
410
411 return 3;
412 } else {
413 if (comb_chars) {
414 *draw_alone = 1;
415 }
416
417 if (ch_cs == DEC_SPECIAL) {
418 return 1;
419 } else {
420 return 0;
421 }
422 }
423 }
424 }
425
426 #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) || defined(USE_TYPE_CAIRO)
427
fc_draw_combining_chars(ui_window_t * window,ui_font_manager_t * font_man,ui_color_t * xcolor,vt_char_t * chars,u_int size,int x,int y)428 static void fc_draw_combining_chars(ui_window_t *window, ui_font_manager_t *font_man,
429 ui_color_t *xcolor, /* fg color */
430 vt_char_t *chars, u_int size, int x, int y) {
431 u_int count;
432 u_int32_t ch_code;
433 ef_charset_t ch_cs;
434 ui_font_t *uifont;
435
436 for (count = 0; count < size; count++) {
437 if (vt_char_is_zerowidth(&chars[count])) {
438 continue;
439 }
440
441 ch_code = vt_char_code(&chars[count]);
442 ch_cs = vt_char_cs(&chars[count]);
443 uifont = ui_get_font(font_man, vt_char_font(&chars[count]));
444
445 if (ch_cs == DEC_SPECIAL) {
446 u_char c;
447
448 c = ch_code;
449 ui_window_draw_decsp_string(window, uifont, xcolor, x, y, &c, 1);
450 }
451 /* ISCII characters never have combined ones. */
452 else if (ch_cs == US_ASCII || ch_cs == ISO8859_1_R /* || IS_ISCII(ch_cs) */) {
453 u_char c;
454
455 c = ch_code;
456 ui_window_ft_draw_string8(window, uifont, xcolor, x, y, &c, 1);
457 } else {
458 /* FcChar32 */ u_int32_t ucs4;
459
460 if (ch_cs == ISO10646_UCS4_1_V) {
461 ui_window_ft_draw_string32(window, uifont, xcolor, x + vt_char_get_xoffset(&chars[count]),
462 y - vt_char_get_yoffset(&chars[count]), &ch_code, 1);
463 } else if ((ucs4 = ui_convert_to_xft_ucs4(ch_code, ch_cs))) {
464 ui_window_ft_draw_string32(window, uifont, xcolor, x, y, &ucs4, 1);
465 }
466 }
467 }
468 }
469
fc_draw_str(ui_window_t * window,ui_font_manager_t * font_man,ui_color_manager_t * color_man,u_int * updated_width,vt_char_t * chars,u_int num_chars,int x,int y,u_int height,u_int ascent,int top_margin,int hide_underline,int underline_offset)470 static int fc_draw_str(ui_window_t *window, ui_font_manager_t *font_man,
471 ui_color_manager_t *color_man, u_int *updated_width, vt_char_t *chars,
472 u_int num_chars, int x, int y, u_int height, u_int ascent,
473 int top_margin, int hide_underline, int underline_offset) {
474 int count;
475 int start_draw;
476 int end_of_str;
477 u_int current_width;
478 /* FcChar8 */ u_int8_t *str8;
479 /* FcChar32 */ u_int32_t *str32;
480 u_int str_len;
481
482 u_int32_t ch_code;
483 u_int ch_width;
484 ef_charset_t ch_cs;
485
486 int state;
487 ui_font_t *uifont;
488 vt_font_t font;
489 vt_color_t fg_color;
490 vt_color_t bg_color;
491 int line_style;
492 vt_char_t *comb_chars;
493 u_int comb_size;
494 int draw_alone;
495 u_int32_t pic_glyph;
496 u_int32_t *pic_glyphs;
497 char *drcs_glyph;
498 char **drcs_glyphs;
499
500 int next_state;
501 ui_font_t *next_uifont;
502 vt_font_t next_font;
503 vt_color_t next_fg_color;
504 vt_color_t next_bg_color;
505 int next_line_style;
506 vt_char_t *next_comb_chars;
507 u_int next_comb_size;
508 u_int next_ch_width;
509 int next_draw_alone;
510
511 #ifdef PERF_DEBUG
512 int draw_count = 0;
513 #endif
514
515 if (num_chars == 0) {
516 #ifdef __DEBUG
517 bl_debug_printf(BL_DEBUG_TAG " input chars length is 0(ui_window_draw_str).\n");
518 #endif
519
520 return 1;
521 }
522
523 start_draw = 0;
524 end_of_str = 0;
525
526 count = 0;
527 while (vt_char_is_zerowidth(&chars[count])) {
528 if (++count >= num_chars) {
529 return 1;
530 }
531 }
532
533 ch_code = vt_char_code(&chars[count]);
534 uifont = ui_get_font(font_man, (font = vt_char_font(&chars[count])));
535 ch_cs = FONT_CS(font);
536 comb_chars = vt_get_combining_chars(&chars[count], &comb_size);
537
538 ch_width = calculate_char_width(uifont, ch_code, ch_cs, vt_char_is_awidth(&chars[count]),
539 comb_chars, comb_size, &draw_alone);
540
541 if ((current_width = x + ch_width) > window->width || y + height > window->height) {
542 #ifdef DEBUG
543 bl_warn_printf(BL_DEBUG_TAG " draw string outside screen. (x %d w %d y %d h %d)\n", x, ch_width,
544 y, height);
545 #endif
546
547 return 0;
548 }
549
550 if ((state = get_state(ch_cs, ch_code, comb_chars, &pic_glyph, &drcs_glyph, &draw_alone)) == 0 &&
551 ch_cs != US_ASCII && ch_cs != ISO8859_1_R && !IS_ISCII(ch_cs)) {
552 state = 2;
553 }
554
555 fg_color = vt_char_fg_color(&chars[count]);
556 bg_color = vt_char_bg_color(&chars[count]);
557
558 line_style = vt_char_line_style(&chars[count]);
559
560 if (!(str8 = str32 = pic_glyphs = drcs_glyphs =
561 alloca(BL_MAX(sizeof(*str8),
562 BL_MAX(sizeof(*str32),
563 BL_MAX(sizeof(*pic_glyphs), sizeof(*drcs_glyphs)))) *
564 num_chars))) {
565 return 0;
566 }
567
568 str_len = 0;
569
570 while (1) {
571 if (state <= 1) {
572 str8[str_len++] = ch_code;
573 } else if (state >= 3) {
574 if (drcs_glyph) {
575 drcs_glyphs[str_len++] = drcs_glyph;
576 } else /* if(pic_glyph) */ {
577 pic_glyphs[str_len++] = pic_glyph;
578 }
579 } else /* if(state == 2) */ {
580 u_int32_t ucs4;
581
582 /* state == 2 means that ch_cs is not US_ASCII, ISO8859_1_R and IS_ISCII */
583 if (!(ucs4 = ui_convert_to_xft_ucs4(ch_code, ch_cs))) {
584 #ifdef DEBUG
585 bl_warn_printf(BL_DEBUG_TAG " strange character 0x%x, ignored.\n", ch_code);
586 #endif
587 } else {
588 str32[str_len++] = ucs4;
589 }
590 }
591
592 /*
593 * next character.
594 */
595
596 do {
597 if (++count >= num_chars) {
598 start_draw = 1;
599 end_of_str = 1;
600
601 break;
602 }
603 } while (vt_char_is_zerowidth(&chars[count]));
604
605 if (!end_of_str) {
606 ch_code = vt_char_code(&chars[count]);
607 next_uifont = ui_get_font(font_man, (next_font = vt_char_font(&chars[count])));
608 ch_cs = FONT_CS(next_font);
609 next_fg_color = vt_char_fg_color(&chars[count]);
610 next_bg_color = vt_char_bg_color(&chars[count]);
611 next_line_style = vt_char_line_style(&chars[count]);
612 next_comb_chars = vt_get_combining_chars(&chars[count], &next_comb_size);
613 next_ch_width = calculate_char_width(next_uifont, ch_code, ch_cs,
614 vt_char_is_awidth(&chars[count]), next_comb_chars,
615 next_comb_size, &next_draw_alone);
616
617 if ((next_state = get_state(ch_cs, ch_code, next_comb_chars, &pic_glyph, &drcs_glyph,
618 &next_draw_alone)) == 0 &&
619 ch_cs != US_ASCII && ch_cs != ISO8859_1_R && !IS_ISCII(ch_cs)) {
620 next_state = 2;
621 }
622
623 if (current_width + next_ch_width > window->width) {
624 start_draw = 1;
625 end_of_str = 1;
626 }
627 /*
628 * !! Notice !!
629 * next_uifont != uifont doesn't necessarily detect change of 'state'
630 * (for example, same Unicode font is used for both US_ASCII and
631 * other half-width unicode characters) and 'bold'(ui_get_font()
632 * might substitute normal fonts for bold ones), 'next_state' and
633 * 'font & FONT_BOLD' is necessary.
634 */
635 else if (next_uifont != uifont || next_fg_color != fg_color || next_bg_color != bg_color ||
636 next_line_style != line_style ||
637 /* If line_style > 0, line is drawn one by one in vertical mode. */
638 (line_style && uifont->is_vertical) || state != next_state ||
639 draw_alone || next_draw_alone ||
640 /* FONT_BOLD flag is not the same. */
641 ((font ^ next_font) & FONT_BOLD)) {
642 start_draw = 1;
643 } else {
644 start_draw = 0;
645 }
646 }
647
648 if (start_draw) {
649 /*
650 * status is changed.
651 */
652
653 ui_color_t *fg_xcolor;
654 ui_color_t *bg_xcolor;
655
656 #ifdef PERF_DEBUG
657 draw_count++;
658 #endif
659
660 bg_xcolor = ui_get_xcolor(color_man, bg_color);
661
662 #ifndef NO_IMAGE
663 if (state == 4) {
664 draw_picture(window, pic_glyphs, str_len, x, y, ch_width, height,
665 bg_color == VT_BG_COLOR ? NULL : bg_xcolor);
666
667 goto end_draw;
668 }
669 #endif
670
671 fg_xcolor = ui_get_xcolor(color_man, fg_color);
672
673 /*
674 * clearing background
675 */
676 if (bg_color == VT_BG_COLOR) {
677 if (updated_width) {
678 ui_window_clear(window, x, y, current_width - x, height);
679 }
680 } else {
681 ui_window_fill_with(window, bg_xcolor, x, y, current_width - x, height);
682 }
683
684 /*
685 * drawing string
686 */
687 if (fg_color == bg_color) {
688 /* don't draw it */
689 } else if (state == 0) {
690 ui_window_ft_draw_string8(window, uifont, fg_xcolor, x, y + ascent, str8, str_len);
691 } else if (state == 1) {
692 ui_window_draw_decsp_string(window, uifont, fg_xcolor, x, y + ascent, str8, str_len);
693 } else if (state == 2) {
694 ui_window_ft_draw_string32(window, uifont, fg_xcolor, x, y + ascent, str32, str_len);
695 } else /* if (state == 3) */ {
696 draw_drcs(window, drcs_glyphs, str_len, x, y, ch_width, height, fg_xcolor,
697 font_man->size_attr);
698 }
699
700 if (comb_chars) {
701 /*
702 * 'current_width' is for some thai fonts which
703 * automatically draw combining chars.
704 * e.g.)
705 * -thai-fixed-medium-r-normal--14-100-100-100-m-70-tis620.2529-1
706 * (distributed by ZzzThai
707 * http://zzzthai.fedu.uec.ac.jp/ZzzThai/)
708 * win32 unicode font.
709 */
710 #if 0
711 fc_draw_combining_chars(window, font_man, fg_xcolor, comb_chars, comb_size,
712 current_width, y + ascent);
713 #else
714 fc_draw_combining_chars(window, font_man, fg_xcolor, comb_chars, comb_size,
715 current_width - ch_width, y + ascent);
716 #endif
717 }
718
719 if (line_style) {
720 if ((line_style & LS_UNDERLINE) && !hide_underline) {
721 draw_line(window, fg_xcolor, uifont->is_vertical,
722 line_style & LS_UNDERLINE,
723 x, y, current_width - x, height, ascent + underline_offset, top_margin);
724 }
725
726 if (line_style & LS_CROSSED_OUT) {
727 draw_line(window, fg_xcolor, uifont->is_vertical,
728 LS_CROSSED_OUT, x, y, current_width - x, height, ascent, top_margin);
729 }
730
731 if (line_style & LS_OVERLINE) {
732 draw_line(window, fg_xcolor, uifont->is_vertical,
733 LS_OVERLINE, x, y, current_width - x, height, ascent, top_margin);
734 }
735 }
736
737 end_draw:
738 start_draw = 0;
739
740 x = current_width;
741 str_len = 0;
742 }
743
744 if (end_of_str) {
745 break;
746 }
747
748 line_style = next_line_style;
749 uifont = next_uifont;
750 font = next_font;
751 fg_color = next_fg_color;
752 bg_color = next_bg_color;
753 state = next_state;
754 draw_alone = next_draw_alone;
755 comb_chars = next_comb_chars;
756 comb_size = next_comb_size;
757 current_width += (ch_width = next_ch_width);
758 }
759
760 if (updated_width != NULL) {
761 *updated_width = current_width;
762 }
763
764 #ifdef PERF_DEBUG
765 bl_debug_printf(" drawing %d times in a line.\n", draw_count);
766 #endif
767
768 return 1;
769 }
770
771 #endif
772
773 #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE)
774
775 #ifndef USE_CONSOLE
xcore_draw_combining_chars(ui_window_t * window,ui_font_manager_t * font_man,ui_color_t * xcolor,vt_char_t * chars,u_int size,int x,int y)776 static int xcore_draw_combining_chars(ui_window_t *window, ui_font_manager_t *font_man,
777 ui_color_t *xcolor, /* fg color */
778 vt_char_t *chars, u_int size, int x, int y) {
779 u_int count;
780 u_int32_t ch_code;
781 ef_charset_t ch_cs;
782 ui_font_t *uifont;
783 int x_off;
784 int y_off;
785
786 for (count = 0; count < size; count++) {
787 if (vt_char_is_zerowidth(&chars[count])) {
788 continue;
789 }
790
791 ch_code = vt_char_code(&chars[count]);
792 ch_cs = vt_char_cs(&chars[count]);
793 uifont = ui_get_font(font_man, vt_char_font(&chars[count]));
794
795 if (ch_cs == DEC_SPECIAL) {
796 u_char c;
797
798 c = ch_code;
799 ui_window_draw_decsp_string(window, uifont, xcolor, x, y, &c, 1);
800 } else {
801 if (ch_cs == ISO10646_UCS4_1_V) {
802 x_off = vt_char_get_xoffset(&chars[count]);
803 y_off = vt_char_get_yoffset(&chars[count]);
804 } else {
805 x_off = y_off = 0;
806 }
807
808 if (ch_code < 0x100) {
809 u_char c;
810
811 c = ch_code;
812 ui_window_draw_string(window, uifont, xcolor, x + x_off, y - y_off, &c, 1);
813 } else {
814 /* UCS4 */
815
816 /* [2] is for surroage pair. */
817 XChar2b xch[2];
818 u_int len;
819
820 if (IS_ISO10646_UCS4(ch_cs)) {
821 if ((len = ui_convert_ucs4_to_utf16(xch, ch_code) / 2) == 0) {
822 continue;
823 }
824 } else {
825 xch[0].byte1 = (ch_code >> 8) & 0xff;
826 xch[0].byte2 = ch_code & 0xff;
827 len = 1;
828 }
829
830 ui_window_draw_string16(window, uifont, xcolor, x + x_off, y - y_off, xch, len);
831 }
832 }
833 }
834
835 return 1;
836 }
837 #endif
838
xcore_draw_str(ui_window_t * window,ui_font_manager_t * font_man,ui_color_manager_t * color_man,u_int * updated_width,vt_char_t * chars,u_int num_chars,int x,int y,u_int height,u_int ascent,int top_margin,int hide_underline,int underline_offset)839 static int xcore_draw_str(ui_window_t *window, ui_font_manager_t *font_man,
840 ui_color_manager_t *color_man, u_int *updated_width, vt_char_t *chars,
841 u_int num_chars, int x, int y, u_int height, u_int ascent,
842 int top_margin, int hide_underline, int underline_offset) {
843 int count;
844 int start_draw;
845 int end_of_str;
846 u_int current_width;
847 u_char *str;
848 XChar2b *str2b;
849 u_int str_len;
850 u_int32_t ch_code;
851 ef_charset_t ch_cs;
852
853 int state; /* 0(8bit),1(decsp),2(16bit) */
854 vt_char_t *comb_chars;
855 u_int comb_size;
856 u_int ch_width;
857 ui_font_t *uifont;
858 vt_font_t font;
859 vt_color_t fg_color;
860 vt_color_t bg_color;
861 int line_style;
862 int draw_alone;
863 u_int32_t pic_glyph;
864 u_int32_t *pic_glyphs;
865 char *drcs_glyph;
866 char **drcs_glyphs;
867
868 int next_state;
869 vt_char_t *next_comb_chars;
870 u_int next_comb_size;
871 u_int next_ch_width;
872 ui_font_t *next_uifont;
873 vt_font_t next_font;
874 vt_color_t next_fg_color;
875 vt_color_t next_bg_color;
876 int next_line_style;
877 int next_draw_alone;
878 #ifdef PERF_DEBUG
879 int draw_count = 0;
880 #endif
881
882 if (num_chars == 0) {
883 #ifdef DEBUG
884 bl_debug_printf(BL_DEBUG_TAG " input chars length is 0(ui_window_draw_str).\n");
885 #endif
886
887 return 1;
888 }
889
890 count = 0;
891 while (vt_char_is_zerowidth(&chars[count])) {
892 if (++count >= num_chars) {
893 return 1;
894 }
895 }
896
897 start_draw = 0;
898 end_of_str = 0;
899
900 ch_code = vt_char_code(&chars[count]);
901 uifont = ui_get_font(font_man, (font = vt_char_font(&chars[count])));
902 ch_cs = FONT_CS(font);
903 comb_chars = vt_get_combining_chars(&chars[count], &comb_size);
904
905 ch_width = calculate_char_width(uifont, ch_code, ch_cs, vt_char_is_awidth(&chars[count]),
906 comb_chars, comb_size, &draw_alone);
907
908 if ((current_width = x + ch_width) > window->width || y + height > window->height) {
909 #ifdef DEBUG
910 bl_warn_printf(BL_DEBUG_TAG " draw string outside screen. (x %d w %d y %d h %d)\n", x, ch_width,
911 y, height);
912 #endif
913
914 return 0;
915 }
916
917 if ((state = get_state(ch_cs, ch_code, comb_chars, &pic_glyph, &drcs_glyph, &draw_alone)) == 0 &&
918 ch_code >= 0x100) {
919 state = 2;
920 }
921
922 fg_color = vt_char_fg_color(&chars[count]);
923 bg_color = vt_char_bg_color(&chars[count]);
924 line_style = vt_char_line_style(&chars[count]);
925
926 if (!(str2b = str = pic_glyphs = drcs_glyphs =
927 /* '* 2' is for UTF16 surrogate pair. */
928 alloca(BL_MAX(sizeof(*str2b) * 2,
929 BL_MAX(sizeof(*str), BL_MAX(sizeof(*pic_glyphs), sizeof(*drcs_glyphs)))) *
930 num_chars))) {
931 return 0;
932 }
933
934 str_len = 0;
935
936 while (1) {
937 if (state <= 1) {
938 str[str_len++] = ch_code;
939 } else if (state >= 3) {
940 if (pic_glyph) {
941 pic_glyphs[str_len++] = pic_glyph;
942 } else /* if (drcs_glyph) */ {
943 drcs_glyphs[str_len++] = drcs_glyph;
944 }
945 } else if (!IS_ISO10646_UCS4(ch_cs)) {
946 str2b[str_len].byte1 = (ch_code >> 8) & 0xff;
947 str2b[str_len].byte2 = ch_code & 0xff;
948 str_len++;
949 } else {
950 /* UCS4 */
951
952 str_len += (ui_convert_ucs4_to_utf16(str2b + str_len, ch_code) / 2);
953 }
954
955 /*
956 * next character.
957 */
958
959 do {
960 if (++count >= num_chars) {
961 start_draw = 1;
962 end_of_str = 1;
963
964 break;
965 }
966 } while (vt_char_is_zerowidth(&chars[count]));
967
968 if (!end_of_str) {
969 ch_code = vt_char_code(&chars[count]);
970 next_uifont = ui_get_font(font_man, (next_font = vt_char_font(&chars[count])));
971 ch_cs = FONT_CS(next_font);
972 next_fg_color = vt_char_fg_color(&chars[count]);
973 next_bg_color = vt_char_bg_color(&chars[count]);
974 next_line_style = vt_char_line_style(&chars[count]);
975 next_comb_chars = vt_get_combining_chars(&chars[count], &next_comb_size);
976 next_ch_width = calculate_char_width(next_uifont, ch_code, ch_cs,
977 vt_char_is_awidth(&chars[count]), next_comb_chars,
978 next_comb_size, &next_draw_alone);
979
980 if ((next_state = get_state(ch_cs, ch_code, next_comb_chars, &pic_glyph, &drcs_glyph,
981 &next_draw_alone)) == 0 &&
982 ch_code >= 0x100) {
983 next_state = 2;
984 }
985
986 if (current_width + next_ch_width > window->width) {
987 start_draw = 1;
988 end_of_str = 1;
989 }
990 /*
991 * !! Notice !!
992 * next_uifont != uifont doesn't necessarily detect change of 'state'
993 * (for example, same Unicode font is used for both US_ASCII and
994 * other half-width unicode characters) and 'bold'(ui_get_font()
995 * might substitute normal fonts for bold ones), 'next_state' and
996 * 'font & FONT_BOLD' is necessary.
997 */
998 else if (next_uifont != uifont || next_fg_color != fg_color || next_bg_color != bg_color ||
999 next_line_style != line_style ||
1000 /* If line_style > 0, line is drawn one by one in vertical mode. */
1001 (line_style && uifont->is_vertical) || next_state != state ||
1002 draw_alone || next_draw_alone ||
1003 /* FONT_BOLD flag is not the same */
1004 ((font ^ next_font) & FONT_BOLD)) {
1005 start_draw = 1;
1006 } else {
1007 start_draw = 0;
1008 }
1009 }
1010
1011 if (start_draw) {
1012 /*
1013 * status is changed.
1014 */
1015
1016 ui_color_t *fg_xcolor;
1017 ui_color_t *bg_xcolor;
1018
1019 #ifdef PERF_DEBUG
1020 draw_count++;
1021 #endif
1022
1023 #ifdef DRAW_SCREEN_IN_PIXELS
1024 if (ui_window_has_wall_picture(window) && bg_color == VT_BG_COLOR) {
1025 bg_xcolor = NULL;
1026 } else
1027 #endif
1028 {
1029 bg_xcolor = ui_get_xcolor(color_man, bg_color);
1030 }
1031
1032 #ifndef NO_IMAGE
1033 if (state == 4) {
1034 draw_picture(window, pic_glyphs, str_len, x, y, ch_width, height,
1035 bg_color == VT_BG_COLOR ? NULL : bg_xcolor);
1036
1037 goto end_draw;
1038 }
1039 #endif
1040
1041 fg_xcolor = ui_get_xcolor(color_man, fg_color);
1042
1043 #ifdef USE_CONSOLE
1044 /* XXX DRCS (state == 3) is ignored */
1045 if (state < 3) {
1046 u_int comb_count;
1047
1048 for (comb_count = 0; comb_count < comb_size; comb_count++) {
1049 u_int comb_code;
1050
1051 comb_code = vt_char_code(&comb_chars[comb_count]);
1052
1053 if (state <= 1) {
1054 str[str_len++] = comb_code;
1055 } else if (!IS_ISO10646_UCS4(ch_cs)) {
1056 str2b[str_len].byte1 = (comb_code >> 8) & 0xff;
1057 str2b[str_len].byte2 = comb_code & 0xff;
1058 str_len++;
1059 } else {
1060 /* UCS4 */
1061 str_len += (ui_convert_ucs4_to_utf16(str2b + str_len, comb_code) / 2);
1062 }
1063 }
1064
1065 /* XXX Wall picture is overwritten by bg_xcolor. */
1066
1067 if (state == 2) {
1068 ui_window_console_draw_string16(window, uifont, fg_xcolor, bg_xcolor, x, y + ascent, str2b,
1069 str_len, line_style);
1070 } else if (state == 1) {
1071 ui_window_console_draw_decsp_string(window, uifont, fg_xcolor, bg_xcolor, x, y + ascent,
1072 str, str_len, line_style);
1073 } else /* if (state == 0) */ {
1074 ui_window_console_draw_string(window, uifont, fg_xcolor, bg_xcolor, x, y + ascent, str,
1075 str_len, line_style);
1076 }
1077 }
1078 #else /* !USE_CONSOLE */
1079 #ifdef USE_SDL2
1080 if (uifont->height != height || state == 3 ||
1081 (uifont->is_proportional && ui_window_has_wall_picture(window))) {
1082 if (bg_color == VT_BG_COLOR) {
1083 if (updated_width) {
1084 ui_window_clear(window, x, y, current_width - x, height);
1085 }
1086 } else {
1087 ui_window_fill_with(window, bg_xcolor, x, y, current_width - x, height);
1088 }
1089 }
1090
1091 if (state == 2) {
1092 ui_window_draw_image_string16(window, uifont, fg_xcolor, bg_xcolor, x, y + ascent, str2b,
1093 str_len);
1094 } else if (state == 1) {
1095 ui_window_draw_decsp_image_string(window, uifont, fg_xcolor, bg_xcolor, x, y + ascent, str,
1096 str_len);
1097 } else if(state == 0) {
1098 ui_window_draw_image_string(window, uifont, fg_xcolor, bg_xcolor, x, y + ascent, str,
1099 str_len);
1100 } else /* if (state == 3) */ {
1101 draw_drcs(window, drcs_glyphs, str_len, x, y, ch_width, height, fg_xcolor,
1102 font_man->size_attr);
1103 }
1104 #else /* !USE_SDL2 */
1105 #ifndef NO_DRAW_IMAGE_STRING
1106 if (uifont->height != height || state == 3
1107 #ifdef DRAW_SCREEN_IN_PIXELS
1108 #ifdef USE_FREETYPE
1109 /*
1110 * ISCII or ISO10646_UCS4_1_V
1111 * (see #ifdef USE_FREETYPE #endif in draw_string() in ui_window.c)
1112 */
1113 || (uifont->is_proportional && ui_window_has_wall_picture(window))
1114 #endif
1115 /* || draw_alone */ /* draw_alone is always false on framebuffer. */
1116 #else /* DRAW_SCREEN_IN_PIXELS */
1117 || (ui_window_has_wall_picture(window) && bg_color == VT_BG_COLOR) || draw_alone
1118 #endif /* DRAW_SCREEN_IN_PIXELS */
1119 )
1120 #endif /* NO_DRAW_IMAGE_STRING */
1121 {
1122 if (bg_color == VT_BG_COLOR) {
1123 if (updated_width) {
1124 ui_window_clear(window, x, y, current_width - x, height);
1125 }
1126 } else {
1127 ui_window_fill_with(window, bg_xcolor, x, y, current_width - x, height);
1128 }
1129
1130 if (fg_color == bg_color) {
1131 /* don't draw it */
1132 } else if (state == 2) {
1133 ui_window_draw_string16(window, uifont, fg_xcolor, x, y + ascent, str2b, str_len);
1134 } else if (state == 1) {
1135 ui_window_draw_decsp_string(window, uifont, fg_xcolor, x, y + ascent, str, str_len);
1136 } else if (state == 0) {
1137 ui_window_draw_string(window, uifont, fg_xcolor, x, y + ascent, str, str_len);
1138 } else /* if (state == 3) */ {
1139 draw_drcs(window, drcs_glyphs, str_len, x, y, ch_width, height, fg_xcolor,
1140 font_man->size_attr);
1141 }
1142 }
1143 #ifndef NO_DRAW_IMAGE_STRING
1144 else {
1145 if (state == 2) {
1146 ui_window_draw_image_string16(window, uifont, fg_xcolor, bg_xcolor, x, y + ascent, str2b,
1147 str_len);
1148 } else if (state == 1) {
1149 ui_window_draw_decsp_image_string(window, uifont, fg_xcolor, bg_xcolor, x, y + ascent, str,
1150 str_len);
1151 } else /* if (state == 0) */ {
1152 ui_window_draw_image_string(window, uifont, fg_xcolor, bg_xcolor, x, y + ascent, str,
1153 str_len);
1154 }
1155 }
1156 #endif
1157 #endif /* USE_SDL2 */
1158
1159 if (comb_chars) {
1160 xcore_draw_combining_chars(window, font_man, fg_xcolor, comb_chars, comb_size,
1161 /*
1162 * 'current_width' is for some thai fonts which automatically
1163 * draw combining chars.
1164 * e.g.)
1165 * -thai-fixed-medium-r-normal--14-100-100-100-m-70-tis620.2529-1
1166 * (distributed by ZzzThai http://zzzthai.fedu.uec.ac.jp/ZzzThai/)
1167 * win32 unicode font.
1168 */
1169 #if 0
1170 current_width
1171 #else
1172 current_width - ch_width
1173 #endif
1174 ,
1175 y + ascent);
1176 }
1177
1178 if (line_style) {
1179 if ((line_style & LS_UNDERLINE) && !hide_underline) {
1180 draw_line(window, fg_xcolor, uifont->is_vertical,
1181 line_style & LS_UNDERLINE,
1182 x, y, current_width - x, height, ascent + underline_offset, top_margin);
1183 }
1184
1185 if (line_style & LS_CROSSED_OUT) {
1186 draw_line(window, fg_xcolor, uifont->is_vertical,
1187 LS_CROSSED_OUT, x, y, current_width - x, height, ascent, top_margin);
1188 }
1189
1190 if (line_style & LS_OVERLINE) {
1191 draw_line(window, fg_xcolor, uifont->is_vertical,
1192 LS_OVERLINE, x, y, current_width - x, height, ascent, top_margin);
1193 }
1194 }
1195 #endif /* USE_CONSOLE */
1196
1197 end_draw:
1198 start_draw = 0;
1199
1200 x = current_width;
1201 str_len = 0;
1202 }
1203
1204 if (end_of_str) {
1205 break;
1206 }
1207
1208 uifont = next_uifont;
1209 font = next_font;
1210 fg_color = next_fg_color;
1211 bg_color = next_bg_color;
1212 line_style = next_line_style;
1213 state = next_state;
1214 draw_alone = next_draw_alone;
1215 comb_chars = next_comb_chars;
1216 comb_size = next_comb_size;
1217 current_width += (ch_width = next_ch_width);
1218 }
1219
1220 if (updated_width != NULL) {
1221 *updated_width = current_width;
1222 }
1223
1224 #ifdef PERF_DEBUG
1225 bl_debug_printf(" drawing %d times in a line.\n", draw_count);
1226 #endif
1227
1228 return 1;
1229 }
1230
1231 #endif
1232
1233 /* --- global functions --- */
1234
ui_draw_str(ui_window_t * window,ui_font_manager_t * font_man,ui_color_manager_t * color_man,vt_char_t * chars,u_int num_chars,int x,int y,u_int height,u_int ascent,int top_margin,int hide_underline,int underline_offset)1235 int ui_draw_str(ui_window_t *window, ui_font_manager_t *font_man, ui_color_manager_t *color_man,
1236 vt_char_t *chars, u_int num_chars, int x, int y, u_int height, u_int ascent,
1237 int top_margin, int hide_underline, int underline_offset) {
1238 u_int updated_width;
1239 int ret;
1240 int clip;
1241
1242 #ifdef __DEBUG
1243 bl_debug_printf("Draw %d characters.\n", num_chars);
1244 #endif
1245
1246 if (font_man->size_attr >= DOUBLE_HEIGHT_TOP) {
1247 ui_window_set_clip(window, x, y, window->width - x, height);
1248 clip = 1;
1249
1250 ascent = height - (height - ascent) * 2;
1251 if (font_man->size_attr == DOUBLE_HEIGHT_TOP) {
1252 ascent += height;
1253 }
1254 }
1255 #ifdef CLIP_LINE
1256 else if (top_margin < 0) { /* XXX line_space = -1 -> top_margin == 0 */
1257 ui_window_set_clip(window, x, y, window->width - x, height);
1258 clip = 1;
1259 }
1260 #endif
1261 else {
1262 clip = 0;
1263 }
1264
1265 switch (ui_get_type_engine(font_man)) {
1266 default:
1267 ret = 0;
1268 break;
1269
1270 #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) || defined(USE_TYPE_CAIRO)
1271 case TYPE_XFT:
1272 case TYPE_CAIRO:
1273 ret = fc_draw_str(window, font_man, color_man, &updated_width, chars, num_chars, x, y,
1274 height, ascent, top_margin, hide_underline, underline_offset);
1275
1276 break;
1277 #endif
1278
1279 #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE)
1280 case TYPE_XCORE:
1281 ret = xcore_draw_str(window, font_man, color_man, &updated_width, chars, num_chars, x, y,
1282 height, ascent, top_margin, hide_underline, underline_offset);
1283
1284 break;
1285 #endif
1286 }
1287
1288 if (clip) {
1289 ui_window_unset_clip(window);
1290 }
1291
1292 return ret;
1293 }
1294
ui_draw_str_to_eol(ui_window_t * window,ui_font_manager_t * font_man,ui_color_manager_t * color_man,vt_char_t * chars,u_int num_chars,int x,int y,u_int height,u_int ascent,int top_margin,int hide_underline,int underline_offset)1295 int ui_draw_str_to_eol(ui_window_t *window, ui_font_manager_t *font_man,
1296 ui_color_manager_t *color_man, vt_char_t *chars, u_int num_chars, int x,
1297 int y, u_int height, u_int ascent, int top_margin,
1298 int hide_underline, int underline_offset) {
1299 u_int updated_width;
1300 int ret;
1301 int clip;
1302
1303 #ifdef __DEBUG
1304 bl_debug_printf("Draw %d characters to eol.\n", num_chars);
1305 #endif
1306
1307 if (font_man->size_attr >= DOUBLE_HEIGHT_TOP) {
1308 ui_window_set_clip(window, x, y, window->width - x, height);
1309 clip = 1;
1310
1311 ascent = height - (height - ascent) * 2;
1312 if (font_man->size_attr == DOUBLE_HEIGHT_TOP) {
1313 ascent += height;
1314 }
1315 }
1316 #ifdef CLIP_LINE
1317 else if (top_margin < 0) { /* XXX line_space = -1 -> top_margin == 0 */
1318 ui_window_set_clip(window, x, y, window->width - x, height);
1319 clip = 1;
1320 }
1321 #endif
1322 else {
1323 clip = 0;
1324 }
1325
1326 switch (ui_get_type_engine(font_man)) {
1327 default:
1328 ret = 0;
1329 break;
1330
1331 #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) || defined(USE_TYPE_CAIRO)
1332 case TYPE_XFT:
1333 case TYPE_CAIRO:
1334 ui_window_clear(window, x, y, window->width - x, height);
1335
1336 ret = fc_draw_str(window, font_man, color_man,
1337 NULL /* NULL disables ui_window_clear() in fc_draw_str() */,
1338 chars, num_chars, x, y, height, ascent, top_margin, hide_underline,
1339 underline_offset);
1340
1341 break;
1342 #endif
1343
1344 #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE)
1345 case TYPE_XCORE:
1346 #ifndef USE_XLIB
1347 /* This shows indic scripts correctly. */
1348
1349 ui_window_clear(window, x, y, window->width - x, height);
1350
1351 ret = xcore_draw_str(window, font_man, color_man,
1352 NULL /* NULL disables ui_window_clear() in fc_draw_str() */,
1353 chars, num_chars, x, y, height, ascent, top_margin, hide_underline,
1354 underline_offset);
1355 #else
1356 ret = xcore_draw_str(window, font_man, color_man, &updated_width,
1357 chars, num_chars, x, y, height, ascent, top_margin, hide_underline,
1358 underline_offset);
1359 if (updated_width < window->width) {
1360 ui_window_clear(window, updated_width, y, window->width - updated_width, height);
1361 }
1362 #endif
1363
1364 break;
1365 #endif
1366 }
1367
1368 if (clip) {
1369 ui_window_unset_clip(window);
1370 }
1371
1372 return ret;
1373 }
1374
ui_calculate_vtchar_width(ui_font_t * font,vt_char_t * ch,int * draw_alone)1375 u_int ui_calculate_vtchar_width(ui_font_t *font, vt_char_t *ch, int *draw_alone) {
1376 ef_charset_t cs;
1377 vt_char_t *comb;
1378 u_int comb_size;
1379
1380 if ((cs = FONT_CS(font->id)) == ISO10646_UCS4_1_V) {
1381 comb = vt_get_combining_chars(ch, &comb_size);
1382 } else {
1383 comb = NULL;
1384 comb_size = 0;
1385 }
1386
1387 return calculate_char_width(font, vt_char_code(ch), cs, vt_char_is_awidth(ch),
1388 comb, comb_size, draw_alone);
1389 }
1390