diff --git a/ChangeLog b/ChangeLog index f8b13a797..199196980 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2024-02-03 Araki Ken + + * ui_draw_str.c: draw_picture() doesn't clear the background + if ui_inline_picture_t::transparent is 1. + + * ui_virtual_kbd.c, ui_sb_view.h, pixmap_engine.c: Fix with the modification + of ui_imagelib_load_file(). + + * vt_parser.[ch], ui_screen.c, ui_screen_manager.c, vterm.c: + Add 'transparent' to vt_xterm_event_listener_t::get_picture_data(). + + * ui_picture.[ch]: Add 'transparent' to ui_inline_picture_t. + + * ui_imagelib.h, */ui_imagelib.c: Add 'transparent' to arguments of + ui_imagelib_load_file(). + + * c_sixel.c: load_sixel_from_{data|file}() check whether P2 is 1 or not + and return it by 'transparent' argument. + 2024-01-08 Araki Ken * README, man/mlterm.1, README.ja: Updated. diff --git a/common/c_imagelib.c b/common/c_imagelib.c index 54895fd3a..28ca6c456 100644 --- a/common/c_imagelib.c +++ b/common/c_imagelib.c @@ -152,7 +152,7 @@ static GdkPixbuf *gdk_pixbuf_new_from_sixel(const char *path) { u_int width; u_int height; - if (!(pixels = load_sixel_from_file(path, &width, &height))) { + if (!(pixels = load_sixel_from_file(path, &width, &height, NULL))) { return NULL; } diff --git a/common/c_sixel.c b/common/c_sixel.c index a29171c75..da3608b26 100644 --- a/common/c_sixel.c +++ b/common/c_sixel.c @@ -292,7 +292,8 @@ static void correct_height(pixel_t *pixels, int width, int *height /* multiple o * the actual image size is less than it. * It is the caller that should shrink (realloc) it. */ -static u_char *load_sixel_from_data(const char *file_data, u_int *width_ret, u_int *height_ret) { +static u_char *load_sixel_from_data(const char *file_data, u_int *width_ret, u_int *height_ret, + int *transparent) { const char *p = file_data; u_char *pixels; int params[6]; @@ -375,6 +376,11 @@ static u_char *load_sixel_from_data(const char *file_data, u_int *width_ret, u_i } #endif + /* Place here this in case 'goto end' or 'goto body'. */ + if (transparent) { + *transparent = 0; /* can be changed in processing P2. */ + } + restart: while (1) { if (*p == '\0') { @@ -465,25 +471,34 @@ static u_char *load_sixel_from_data(const char *file_data, u_int *width_ret, u_i switch (*p) { case 'q': goto body; + #ifdef SIXEL_ORMODE case '5': ormode = 1; break; #endif -#if 0 - case '0': - case '2': - ... + + case '1': + if (transparent) { + *transparent = 1; + } break; - default: -#else case '\0': -#endif #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Illegal format.\n."); #endif goto end; + +#if 0 + case '0': + case '2': +#endif + default: +#ifdef DEBUG + bl_debug_printf(BL_DEBUG_TAG " Illegal format.\n."); +#endif + break; } if (p[1] == ';') { @@ -956,12 +971,13 @@ static u_char *load_sixel_from_data(const char *file_data, u_int *width_ret, u_i #if !defined(SIXEL_1BPP) && !defined(SIXEL_SHAREPALETTE) -static u_char *load_sixel_from_file(const char *path, u_int *width_ret, u_int *height_ret) { +static u_char *load_sixel_from_file(const char *path, u_int *width_ret, u_int *height_ret, + int *transparent) { char *file_data; u_char *pixels; if ((file_data = read_sixel_file(path))) { - pixels = load_sixel_from_data(file_data, width_ret, height_ret); + pixels = load_sixel_from_data(file_data, width_ret, height_ret, transparent); free(file_data); return pixels; diff --git a/contrib/scrollbar/pixmap_engine/pixmap_engine.c b/contrib/scrollbar/pixmap_engine/pixmap_engine.c index 6d6b93388..8f4cda133 100644 --- a/contrib/scrollbar/pixmap_engine/pixmap_engine.c +++ b/contrib/scrollbar/pixmap_engine/pixmap_engine.c @@ -143,7 +143,7 @@ static void load_image(ui_display_t *disp, ui_sb_view_conf_t *conf, const char * path = malloc(sizeof(char) * (len + 1)); sprintf(path, "%s/%s.png", conf->dir, file); - if (!(*conf->load_image)(disp, path, NULL, pixmap, mask, width, height, 0)) { + if (!(*conf->load_image)(disp, path, 0, NULL, pixmap, mask, width, height, NULL)) { #ifdef __DEBUG printf("ui_imagelib_load_file() failed\n"); ; diff --git a/drcssixel/DRCS-SIXEL-v2 b/drcssixel/DRCS-SIXEL-v2 index 176ecd65d..2ce4a9933 100644 --- a/drcssixel/DRCS-SIXEL-v2 +++ b/drcssixel/DRCS-SIXEL-v2 @@ -19,6 +19,9 @@ from the top-left corner cell. which consists of 96 characters is next to 0x7f of 0x7e set which consists of 94 characters. +(*3) P2=1 (Pixel positions specified as 0 remain at their current color) is + not supported for now. + [Appendix] o The number of columns and rows of sixel graphic image are calculated diff --git a/libvterm/vterm.c b/libvterm/vterm.c index 62ccf010c..ee32d100c 100644 --- a/libvterm/vterm.c +++ b/libvterm/vterm.c @@ -239,7 +239,8 @@ static vt_char_t *xterm_get_picture_data(void *p, char *file_path, int *num_rows, /* If *num_rows > 0, ignored. */ int *num_cols_small /* set only if drcs_sixel is 1. */, int *num_rows_small /* set only if drcs_sixel is 1. */, - u_int32_t **sixel_palette, int drcs_sixel) { + u_int32_t **sixel_palette, int *transparent, + int keep_aspect, int drcs_sixel) { static int old_drcs_sixel = -1; VTerm *vterm = p; u_int width; @@ -293,6 +294,10 @@ static vt_char_t *xterm_get_picture_data(void *p, char *file_path, } } + if (transparent) { + *transparent = 0; + } + if (sscanf(data_p, "\"%d;%d;%d;%d", &x, &y, &width, &height) != 4 || width == 0 || height == 0) { struct stat st; @@ -308,7 +313,7 @@ static vt_char_t *xterm_get_picture_data(void *p, char *file_path, len += fread(all_data + len, 1, st.st_size - len, fp); all_data[len] = '\0'; - if (!(picture = load_sixel_from_data_1bpp(all_data, &width, &height))) { + if (!(picture = load_sixel_from_data_1bpp(all_data, &width, &height, transparent))) { free(all_data); goto error_closing_fp; diff --git a/uitoolkit/beos/ui_imagelib.c b/uitoolkit/beos/ui_imagelib.c index 4a4ad12b2..056db9601 100644 --- a/uitoolkit/beos/ui_imagelib.c +++ b/uitoolkit/beos/ui_imagelib.c @@ -132,15 +132,15 @@ static int check_has_alpha(u_char *image, u_int width, u_int height) { } static int load_file(char *path, /* must be UTF-8 */ - u_int *width, u_int *height, ui_picture_modifier_t *pic_mod, Pixmap *pixmap, - PixmapMask *mask) { + u_int *width, u_int *height, ui_picture_modifier_t *pic_mod, + Pixmap *pixmap, PixmapMask *mask, int *transparent) { char *suffix; u_char *image; suffix = path + strlen(path) - 4; #ifdef BUILTIN_SIXEL if (strcasecmp(suffix, ".six") == 0 && *width == 0 && *height == 0 && - (image = load_sixel_from_file(path, width, height))) { + (image = load_sixel_from_file(path, width, height, transparent))) { adjust_pixmap(image, *width, *height, pic_mod); *pixmap = beos_create_image(image, (*width) * (*height) * 4, *width, *height); } else @@ -163,19 +163,48 @@ static int load_file(char *path, /* must be UTF-8 */ return 0; } + if (transparent) { + *transparent = 0; + } + if (!ui_picture_modifier_is_normal(pic_mod)) { Pixmap new_pixmap; + u_char *image2; image = beos_get_bits(*pixmap); - adjust_pixmap2(image, *width, *height, pic_mod); - new_pixmap = beos_create_image(image, (*width) * (*height) * 4, *width, *height); - beos_destroy_image(*pixmap); - *pixmap = new_pixmap; + if ((image2 = malloc((*width) * (*height) * 4))) { + image = memcpy(image2, image, (*width) * (*height) * 4); + beos_destroy_image(*pixmap); + adjust_pixmap2(image, *width, *height, pic_mod); + new_pixmap = beos_create_image(image, (*width) * (*height) * 4, *width, *height); + free(image); + *pixmap = new_pixmap; + } } } - if (mask) { - *mask = None; + if (transparent && *transparent) { + dummy_mask: + if (mask) { + /* dummy (If cur_pic->mask is non-zero, need_clear = 1 in draw_picture() in ui_draw_str.c) */ + *mask = 1; + } + } else { + int x, y; + u_int32_t *p = (u_int32_t*)image; + + for (y = 0; y < *height; y++) { + for (x = 0; x < *width; x++) { + if ((((*p) >> 24) & 0xff) <= 0x7f) { /* alpha */ + goto dummy_mask; + } + p ++; + } + } + + if (mask) { + *mask = None; + } } return 1; @@ -193,7 +222,7 @@ Pixmap ui_imagelib_load_file_for_background(ui_window_t *win, char *path, u_int width = 0; u_int height = 0; - if (!load_file(path, &width, &height, pic_mod, &pixmap, NULL)) { + if (!load_file(path, &width, &height, pic_mod, &pixmap, NULL, NULL)) { return None; } @@ -210,8 +239,9 @@ Pixmap ui_imagelib_get_transparent_background(ui_window_t *win, ui_picture_modif return None; } -int ui_imagelib_load_file(ui_display_t *disp, char *path, u_int32_t **cardinal, Pixmap *pixmap, - PixmapMask *mask, u_int *width, u_int *height, int keep_aspect) { +int ui_imagelib_load_file(ui_display_t *disp, char *path, int keep_aspect, u_int32_t **cardinal, + Pixmap *pixmap, PixmapMask *mask, u_int *width, u_int *height, + int *transparent) { u_int pix_width = 0; u_int pix_height = 0; @@ -219,7 +249,7 @@ int ui_imagelib_load_file(ui_display_t *disp, char *path, u_int32_t **cardinal, return 0; } - if (!load_file(path, &pix_width, &pix_height, NULL, pixmap, mask)) { + if (!load_file(path, &pix_width, &pix_height, NULL, pixmap, mask, transparent)) { return 0; } diff --git a/uitoolkit/console/ui_imagelib.c b/uitoolkit/console/ui_imagelib.c index 0923d77af..0d15f7050 100644 --- a/uitoolkit/console/ui_imagelib.c +++ b/uitoolkit/console/ui_imagelib.c @@ -253,7 +253,7 @@ static int resize_sixel(Pixmap pixmap, u_int width, u_int height, u_int bytes_pe static int load_file(Display *display, char *path, u_int width, u_int height, int keep_aspect, ui_picture_modifier_t *pic_mod, u_int depth, Pixmap *pixmap, - PixmapMask *mask) { + PixmapMask *mask, int *transparent) { pid_t pid; int fds[2]; ssize_t size; @@ -270,7 +270,8 @@ static int load_file(Display *display, char *path, u_int width, u_int height, in width == 0 && height == 0 && #endif (*pixmap = calloc(1, sizeof(**pixmap)))) { - if (((*pixmap)->image = load_sixel_from_file(path, &(*pixmap)->width, &(*pixmap)->height)) && + if (((*pixmap)->image = load_sixel_from_file(path, &(*pixmap)->width, &(*pixmap)->height, + NULL)) && /* resize_sixel() frees pixmap->image in failure. */ resize_sixel(*pixmap, width, height, 4)) { goto loaded; @@ -280,6 +281,10 @@ static int load_file(Display *display, char *path, u_int width, u_int height, in } #endif + if (transparent) { + *transparent = 0; + } + #ifdef __ANDROID__ if (!(*pixmap = calloc(1, sizeof(**pixmap)))) { return 0; @@ -415,7 +420,7 @@ Pixmap ui_imagelib_load_file_for_background(ui_window_t *win, char *path, Pixmap pixmap; if (!load_file(win->disp->display, path, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win), 0, pic_mod, - win->disp->depth, &pixmap, NULL)) { + win->disp->depth, &pixmap, NULL, NULL)) { pixmap = None; } @@ -428,14 +433,15 @@ Pixmap ui_imagelib_get_transparent_background(ui_window_t *win, ui_picture_modif return None; } -int ui_imagelib_load_file(ui_display_t *disp, char *path, u_int32_t **cardinal, Pixmap *pixmap, - PixmapMask *mask, u_int *width, u_int *height, int keep_aspect) { +int ui_imagelib_load_file(ui_display_t *disp, char *path, int keep_aspect, u_int32_t **cardinal, + Pixmap *pixmap, PixmapMask *mask, u_int *width, u_int *height, + int *transparent) { if (cardinal) { return 0; } if (!load_file(disp->display, path, *width, *height, keep_aspect, NULL, - disp->depth, pixmap, mask)) { + disp->depth, pixmap, mask, transparent)) { return 0; } diff --git a/uitoolkit/fb/ui_imagelib.c b/uitoolkit/fb/ui_imagelib.c index 8fd5cf432..c2485d166 100644 --- a/uitoolkit/fb/ui_imagelib.c +++ b/uitoolkit/fb/ui_imagelib.c @@ -294,7 +294,8 @@ static int resize_sixel(Pixmap pixmap, u_int width, u_int height, u_int bytes_pe /* depth should be checked by the caller. */ static int load_sixel_with_mask_from_data_1bpp(char *file_data, u_int width, u_int height, - Pixmap *pixmap, PixmapMask *mask) { + Pixmap *pixmap, PixmapMask *mask, + int *transparent) { int x; int y; u_char *src; @@ -307,7 +308,7 @@ static int load_sixel_with_mask_from_data_1bpp(char *file_data, u_int width, u_i } if (!((*pixmap)->image = - load_sixel_from_data_1bpp(file_data, &(*pixmap)->width, &(*pixmap)->height)) || + load_sixel_from_data_1bpp(file_data, &(*pixmap)->width, &(*pixmap)->height, transparent)) || /* resize_sixel() frees pixmap->image in failure. */ !resize_sixel(*pixmap, width, height, 1)) { free(*pixmap); @@ -662,7 +663,7 @@ static int exec_mlimgloader(char *path, u_int width, u_int height, int keep_aspe static int load_file(Display *display, char *path, u_int width, u_int height, int keep_aspect, ui_picture_modifier_t *pic_mod, u_int depth, Pixmap *pixmap, - PixmapMask *mask) { + PixmapMask *mask, int *transparent) { if (!path || !*path) { return 0; } @@ -679,7 +680,8 @@ static int load_file(Display *display, char *path, u_int width, u_int height, in #if (defined(__NetBSD__) || defined(__OpenBSD__)) && !defined(USE_GRF) if (depth == 1) { /* pic_mod is ignored. */ - if (load_sixel_with_mask_from_data_1bpp(file_data, width, height, pixmap, mask)) { + if (load_sixel_with_mask_from_data_1bpp(file_data, width, height, pixmap, mask, + transparent)) { free(file_data); return 1; } @@ -703,7 +705,8 @@ static int load_file(Display *display, char *path, u_int width, u_int height, in if (depth <= 8) { if (ui_picture_modifier_is_normal(pic_mod) /* see modify_pixmap() */) { if (((*pixmap)->image = load_sixel_from_data_sharepalette(file_data, &(*pixmap)->width, - &(*pixmap)->height)) && + &(*pixmap)->height, + transparent)) && resize_sixel(*pixmap, width, height, BPP_PSEUDO)) { if (mask) { *mask = NULL; @@ -727,7 +730,7 @@ static int load_file(Display *display, char *path, u_int width, u_int height, in #endif if (((*pixmap)->image = load_sixel_from_data(file_data, &(*pixmap)->width, - &(*pixmap)->height)) && + &(*pixmap)->height, transparent)) && /* resize_sixel() frees pixmap->image in failure. */ resize_sixel(*pixmap, width, height, 4)) { #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE @@ -748,6 +751,10 @@ static int load_file(Display *display, char *path, u_int width, u_int height, in } #endif /* BUILTIN_SIXEL */ + if (transparent) { + *transparent = 0; + } + if (!exec_mlimgloader(path, width, height, keep_aspect, pixmap)) { return 0; } @@ -810,7 +817,7 @@ Pixmap ui_imagelib_load_file_for_background(ui_window_t *win, char *path, #endif if (!load_file(win->disp->display, path, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win), 0, pic_mod, - win->disp->depth, &pixmap, NULL)) { + win->disp->depth, &pixmap, NULL, NULL)) { pixmap = None; } @@ -827,14 +834,15 @@ Pixmap ui_imagelib_get_transparent_background(ui_window_t *win, ui_picture_modif return None; } -int ui_imagelib_load_file(ui_display_t *disp, char *path, u_int32_t **cardinal, Pixmap *pixmap, - PixmapMask *mask, u_int *width, u_int *height, int keep_aspect) { +int ui_imagelib_load_file(ui_display_t *disp, char *path, int keep_aspect, u_int32_t **cardinal, + Pixmap *pixmap, PixmapMask *mask, u_int *width, u_int *height, + int *transparent) { if (cardinal) { return 0; } if (!load_file(disp->display, path, *width, *height, keep_aspect, NULL, disp->depth, - pixmap, mask)) { + pixmap, mask, transparent)) { return 0; } diff --git a/uitoolkit/fb/ui_virtual_kbd.c b/uitoolkit/fb/ui_virtual_kbd.c index 5a8e8330a..34cf9116d 100644 --- a/uitoolkit/fb/ui_virtual_kbd.c +++ b/uitoolkit/fb/ui_virtual_kbd.c @@ -240,8 +240,8 @@ static int start_virtual_kbd(ui_display_t *disp) { } else { width = 0; height = 0; - if (!ui_imagelib_load_file(disp, KBD_DIR "/pressed_kbd.six", NULL, &pressed_pixmap, NULL, - &width, &height, 0)) { + if (!ui_imagelib_load_file(disp, KBD_DIR "/pressed_kbd.six", 0, NULL, &pressed_pixmap, NULL, + &width, &height, NULL)) { /* * Note that pressed_pixmap can be non-NULL even if * ui_imagelib_load_file() fails. @@ -253,8 +253,8 @@ static int start_virtual_kbd(ui_display_t *disp) { width = 0; height = 0; - if (!ui_imagelib_load_file(disp, KBD_DIR "/kbd.six", NULL, &normal_pixmap, NULL, &width, - &height, 0)) { + if (!ui_imagelib_load_file(disp, KBD_DIR "/kbd.six", 0, NULL, &normal_pixmap, NULL, + &width, &height, NULL)) { /* * Note that normal_pixmap can be non-NULL even if * ui_imagelib_load_file() fails. diff --git a/uitoolkit/quartz/ui_imagelib.c b/uitoolkit/quartz/ui_imagelib.c index 0dc3be535..c65295cac 100644 --- a/uitoolkit/quartz/ui_imagelib.c +++ b/uitoolkit/quartz/ui_imagelib.c @@ -138,8 +138,8 @@ static int check_has_alpha(u_char *image, u_int width, u_int height) { } static int load_file(char *path, /* must be UTF-8 */ - u_int *width, u_int *height, ui_picture_modifier_t *pic_mod, Pixmap *pixmap, - PixmapMask *mask) { + u_int *width, u_int *height, ui_picture_modifier_t *pic_mod, + Pixmap *pixmap, PixmapMask *mask, int *transparent) { char *suffix; u_char *image; CGImageAlphaInfo info; @@ -147,7 +147,7 @@ static int load_file(char *path, /* must be UTF-8 */ suffix = path + strlen(path) - 4; #ifdef BUILTIN_SIXEL if (strcasecmp(suffix, ".six") == 0 && *width == 0 && *height == 0 && - (image = load_sixel_from_file(path, width, height))) { + (image = load_sixel_from_file(path, width, height, transparent))) { adjust_pixmap(image, *width, *height, pic_mod); info = check_has_alpha(image, *width, *height) ? kCGImageAlphaPremultipliedLast @@ -179,6 +179,10 @@ static int load_file(char *path, /* must be UTF-8 */ return 0; } + if (transparent) { + *transparent = 0; + } + info = CGImageGetAlphaInfo(*pixmap); if (!ui_picture_modifier_is_normal(pic_mod)) { @@ -206,7 +210,8 @@ static int load_file(char *path, /* must be UTF-8 */ if (info == kCGImageAlphaPremultipliedLast || info == kCGImageAlphaPremultipliedFirst || info == kCGImageAlphaLast || info == kCGImageAlphaFirst) { - *mask = 1L; /* dummy */ + /* dummy (If cur_pic->mask is non-zero, need_clear = 1 in draw_picture() in ui_draw_str.c) */ + *mask = 1L; } return 1; @@ -237,7 +242,7 @@ Pixmap ui_imagelib_load_file_for_background(ui_window_t *win, char *path, u_int width = 0; u_int height = 0; - if (!load_file(path, &width, &height, pic_mod, &pixmap, NULL)) { + if (!load_file(path, &width, &height, pic_mod, &pixmap, NULL, NULL)) { return None; } @@ -254,8 +259,9 @@ Pixmap ui_imagelib_get_transparent_background(ui_window_t *win, ui_picture_modif return None; } -int ui_imagelib_load_file(ui_display_t *disp, char *path, u_int32_t **cardinal, Pixmap *pixmap, - PixmapMask *mask, u_int *width, u_int *height, int keep_aspect) { +int ui_imagelib_load_file(ui_display_t *disp, char *path, int keep_aspect, u_int32_t **cardinal, + Pixmap *pixmap, PixmapMask *mask, u_int *width, u_int *height, + int *transparent) { u_int pix_width = 0; u_int pix_height = 0; @@ -263,7 +269,7 @@ int ui_imagelib_load_file(ui_display_t *disp, char *path, u_int32_t **cardinal, return 0; } - if (!load_file(path, &pix_width, &pix_height, NULL, pixmap, mask)) { + if (!load_file(path, &pix_width, &pix_height, NULL, pixmap, mask, transparent)) { return 0; } diff --git a/uitoolkit/ui_draw_str.c b/uitoolkit/ui_draw_str.c index 87c8b510b..cf177a788 100644 --- a/uitoolkit/ui_draw_str.c +++ b/uitoolkit/ui_draw_str.c @@ -111,6 +111,14 @@ static void draw_line(ui_window_t *window, ui_color_t *color, int is_vertical, i #endif #ifndef NO_IMAGE +void draw_background(ui_window_t *win, ui_color_t *color, int x, int y, u_int width, u_int height) { + if (!color) { + ui_window_clear(win, x, y, width, height); + } else { + ui_window_fill_with(win, color, x, y, width, height); + } +} + static int 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) { u_int count; @@ -161,12 +169,8 @@ static int draw_picture(ui_window_t *window, u_int32_t *glyphs, u_int num_glyphs if (count == 0) { goto new_picture; } else if (w > 0 && pic == cur_pic && src_x + src_width == x) { - if (!need_clear && w < ch_width) { - if (!bg_xcolor) { - ui_window_clear(window, dst_x + dst_width, dst_y, ch_width, line_height); - } else { - ui_window_fill_with(window, bg_xcolor, dst_x + dst_width, dst_y, ch_width, line_height); - } + if (!cur_pic->transparent && !need_clear && w < ch_width) { + draw_background(window, bg_xcolor, dst_x + dst_width, dst_y, ch_width, line_height); } src_width += w; @@ -180,11 +184,8 @@ static int draw_picture(ui_window_t *window, u_int32_t *glyphs, u_int num_glyphs } if (need_clear > 0) { - if (!bg_xcolor) { - ui_window_clear(window, dst_x, dst_y, dst_width, line_height); - } else { - ui_window_fill_with(window, bg_xcolor, dst_x, dst_y, dst_width, line_height); - } + /* cur_pic->transparent is always false. */ + draw_background(window, bg_xcolor, dst_x, dst_y, dst_width, line_height); } if (src_width > 0 && src_height > 0 @@ -214,10 +215,6 @@ static int draw_picture(ui_window_t *window, u_int32_t *glyphs, u_int num_glyphs cur_pic = pic; need_clear = 0; - if (cur_pic->mask) { - need_clear = 1; - } - if (src_y + line_height > pic->height) { need_clear = 1; src_height = pic->height > src_y ? pic->height - src_y : 0; @@ -225,38 +222,41 @@ static int draw_picture(ui_window_t *window, u_int32_t *glyphs, u_int num_glyphs src_height = line_height; } - if (strstr(cur_pic->file_path, "mlterm/animx") && cur_pic->next_frame >= 0) { - /* Don't clear if cur_pic is 2nd or later GIF Animation frame. */ - need_clear = -1; - } + src_width = w; - if ((src_width = w) < ch_width && !need_clear) { - if (!bg_xcolor) { - ui_window_clear(window, dst_x, dst_y, ch_width, line_height); - } else { - ui_window_fill_with(window, bg_xcolor, dst_x, dst_y, ch_width, line_height); + if (!cur_pic->transparent) { + if (cur_pic->mask) { + need_clear = 1; } - } - } - if (need_clear > 0) { - if (!bg_xcolor) { - ui_window_clear(window, dst_x, dst_y, dst_width, line_height); + if (strstr(cur_pic->file_path, "mlterm/animx") && cur_pic->next_frame >= 0) { + /* Don't clear if cur_pic is 2nd or later GIF Animation frame. */ + need_clear = -1; + } + + if (src_width < ch_width && !need_clear) { + draw_background(window, bg_xcolor, dst_x, dst_y, ch_width, line_height); + } } else { - ui_window_fill_with(window, bg_xcolor, dst_x, dst_y, dst_width, line_height); + need_clear = 0; } } -#ifdef __DEBUG - 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, - cur_pic->pixmap, cur_pic->mask, src_x, src_y, src_width, src_height); -#endif + if (need_clear > 0) { + /* cur_pic->transparent is always false. */ + draw_background(window, bg_xcolor, dst_x, dst_y, dst_width, line_height); + } if (src_width > 0 && src_height > 0 #ifndef INLINE_PICTURE_MOVABLE_BETWEEN_DISPLAYS && cur_pic->disp == window->disp #endif ) { +#ifdef __DEBUG + 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, cur_pic->pixmap, cur_pic->mask, src_x, src_y, src_width, src_height); +#endif + ui_window_copy_area(window, cur_pic->pixmap, cur_pic->mask, src_x, src_y, src_width, src_height, dst_x, dst_y); } @@ -657,17 +657,16 @@ static int fc_draw_str(ui_window_t *window, ui_font_manager_t *font_man, draw_count++; #endif - bg_xcolor = ui_get_xcolor(color_man, bg_color); - #ifndef NO_IMAGE if (state == 4) { draw_picture(window, pic_glyphs, str_len, x, y, ch_width, height, - bg_color == VT_BG_COLOR ? NULL : bg_xcolor); + bg_color == VT_BG_COLOR ? NULL : ui_get_xcolor(color_man, bg_color)); goto end_draw; } #endif + bg_xcolor = ui_get_xcolor(color_man, bg_color); fg_xcolor = ui_get_xcolor(color_man, fg_color); /* @@ -1020,6 +1019,15 @@ static int xcore_draw_str(ui_window_t *window, ui_font_manager_t *font_man, draw_count++; #endif +#ifndef NO_IMAGE + if (state == 4) { + draw_picture(window, pic_glyphs, str_len, x, y, ch_width, height, + bg_color == VT_BG_COLOR ? NULL : ui_get_xcolor(color_man, bg_color)); + + goto end_draw; + } +#endif + #ifdef DRAW_SCREEN_IN_PIXELS if (ui_window_has_wall_picture(window) && bg_color == VT_BG_COLOR) { bg_xcolor = NULL; @@ -1029,15 +1037,6 @@ static int xcore_draw_str(ui_window_t *window, ui_font_manager_t *font_man, bg_xcolor = ui_get_xcolor(color_man, bg_color); } -#ifndef NO_IMAGE - if (state == 4) { - draw_picture(window, pic_glyphs, str_len, x, y, ch_width, height, - bg_color == VT_BG_COLOR ? NULL : bg_xcolor); - - goto end_draw; - } -#endif - fg_xcolor = ui_get_xcolor(color_man, fg_color); #ifdef USE_CONSOLE diff --git a/uitoolkit/ui_imagelib.h b/uitoolkit/ui_imagelib.h index 636f9b29b..830b0fe51 100644 --- a/uitoolkit/ui_imagelib.h +++ b/uitoolkit/ui_imagelib.h @@ -17,8 +17,9 @@ Pixmap ui_imagelib_load_file_for_background(ui_window_t *win, char *path, Pixmap ui_imagelib_get_transparent_background(ui_window_t *win, ui_picture_modifier_t *pic_mod); -int ui_imagelib_load_file(ui_display_t *disp, char *path, u_int32_t **cardinal, Pixmap *pixmap, - PixmapMask *mask, u_int *width, u_int *height, int keep_aspect); +int ui_imagelib_load_file(ui_display_t *disp, char *path, int keep_aspect, + u_int32_t **cardinal, Pixmap *pixmap, PixmapMask *mask, + u_int *width, u_int *height, int *transparent); void ui_destroy_image(Display *display, Pixmap pixmap); diff --git a/uitoolkit/ui_picture.c b/uitoolkit/ui_picture.c index 956eb8697..640ad39af 100644 --- a/uitoolkit/ui_picture.c +++ b/uitoolkit/ui_picture.c @@ -189,8 +189,8 @@ static ui_icon_picture_t *create_icon_picture(ui_display_t *disp, } if ((pic->file_path = strdup(file_path)) == NULL || - !ui_imagelib_load_file(disp, file_path, &(pic->cardinal), &(pic->pixmap), &(pic->mask), - &icon_size, &icon_size, 0)) { + !ui_imagelib_load_file(disp, file_path, 0, &(pic->cardinal), &(pic->pixmap), &(pic->mask), + &icon_size, &icon_size, NULL)) { free(pic->file_path); free(pic); @@ -536,13 +536,15 @@ static int load_file(void *p) { PixmapMask mask; u_int width; u_int height; + int transparent; idx = ((inline_pic_args_t*)p)->idx; width = inline_pics[idx].width; height = inline_pics[idx].height; - if (ui_imagelib_load_file(inline_pics[idx].disp, inline_pics[idx].file_path, NULL, &pixmap, &mask, - &width, &height, ((inline_pic_args_t*)p)->keep_aspect)) { + if (ui_imagelib_load_file(inline_pics[idx].disp, inline_pics[idx].file_path, + ((inline_pic_args_t*)p)->keep_aspect, NULL, + &pixmap, &mask, &width, &height, &transparent)) { if (strstr(inline_pics[idx].file_path, "mlterm/anim")) { /* GIF Animation frame */ unlink(inline_pics[idx].file_path); @@ -553,11 +555,12 @@ static int load_file(void *p) { inline_pics[idx].width = width; inline_pics[idx].height = height; inline_pics[idx].pixmap = pixmap; + inline_pics[idx].transparent = transparent; #ifdef DEBUG - bl_debug_printf(BL_DEBUG_TAG " new inline picture (%s %d %d %d %p %p) is created.\n", - inline_pics[idx].file_path, idx, width, height, inline_pics[idx].pixmap, - inline_pics[idx].mask); + bl_debug_printf(BL_DEBUG_TAG " new inline picture (%s %d %d %d %d %p %p) is created.\n", + inline_pics[idx].file_path, idx, width, height, transparent, + pixmap, mask); #endif return 1; @@ -1173,7 +1176,7 @@ int ui_load_tmp_picture(ui_display_t *disp, char *file_path, Pixmap *pixmap, Pix u_int *width, u_int *height) { *width = *height = 0; - if (ui_imagelib_load_file(disp, file_path, NULL, pixmap, mask, width, height, 0)) { + if (ui_imagelib_load_file(disp, file_path, 0, NULL, pixmap, mask, width, height, NULL)) { return 1; } else { return 0; diff --git a/uitoolkit/ui_picture.h b/uitoolkit/ui_picture.h index dcb6012eb..1dcb32e5c 100644 --- a/uitoolkit/ui_picture.h +++ b/uitoolkit/ui_picture.h @@ -56,8 +56,8 @@ typedef struct ui_inline_picture { vt_term_t *term; u_int8_t col_width; u_int8_t line_height; - int16_t next_frame; + int8_t transparent; } ui_inline_picture_t; diff --git a/uitoolkit/ui_sb_view.h b/uitoolkit/ui_sb_view.h index d11398674..54c3ec143 100644 --- a/uitoolkit/ui_sb_view.h +++ b/uitoolkit/ui_sb_view.h @@ -74,9 +74,9 @@ typedef struct ui_sb_view_conf { unsigned int rc_num; unsigned int use_count; - int (*load_image)(__ui_display_ptr_t disp, char *path, + int (*load_image)(__ui_display_ptr_t disp, char *path, int keep_aspect, /* u_int32_t */ unsigned int **cardinal, Pixmap *pixmap, PixmapMask *mask, - unsigned int *width, unsigned int *height, int); + unsigned int *width, unsigned int *height, int *transparent); } ui_sb_view_conf_t; diff --git a/uitoolkit/ui_screen.c b/uitoolkit/ui_screen.c index 4fb60c839..e2b828c56 100644 --- a/uitoolkit/ui_screen.c +++ b/uitoolkit/ui_screen.c @@ -6258,8 +6258,9 @@ static vt_char_t *xterm_get_picture_data(void *p, char *file_path, int *num_cols int *num_rows /* can be 0 */, int *num_cols_small /* set only if drcs_sixel is 1. */, int *num_rows_small /* set only if drcs_sixel is 1. */, - u_int32_t **sixel_palette, int keep_aspect, - int drcs_sixel) { + u_int32_t **sixel_palette, + int *transparent /* can be NULL */, + int keep_aspect, int drcs_sixel) { ui_screen_t *screen; u_int width; u_int height; @@ -6282,8 +6283,8 @@ static vt_char_t *xterm_get_picture_data(void *p, char *file_path, int *num_cols *sixel_palette = ui_set_custom_sixel_palette(*sixel_palette); } - if ((idx = ui_load_inline_picture(screen->window.disp, file_path, &width, &height, col_width, - line_height, keep_aspect, screen->term)) != -1) { + if ((idx = ui_load_inline_picture(screen->window.disp, file_path, &width, &height, + col_width, line_height, keep_aspect, screen->term)) != -1) { vt_char_t *buf; u_int cols_padding[2]; u_int rows_padding[2]; @@ -6375,6 +6376,10 @@ static vt_char_t *xterm_get_picture_data(void *p, char *file_path, int *num_cols *num_cols += (cols_padding[0] + cols_padding[1]); *num_rows += (rows_padding[0] + rows_padding[1]); + if (transparent) { + *transparent = ui_get_inline_picture(idx)->transparent; + } + return buf; } } @@ -6459,8 +6464,8 @@ static void xterm_add_frame_to_animation(void *p, char *file_path, int *num_cols width = (*num_cols) *(col_width = ui_col_width(screen)); height = (*num_rows) *(line_height = ui_line_height(screen)); - if ((idx = ui_load_inline_picture(screen->window.disp, file_path, &width, &height, col_width, - line_height, 0, screen->term)) != -1 && + if ((idx = ui_load_inline_picture(screen->window.disp, file_path, &width, &height, + col_width, line_height, 0, screen->term)) != -1 && screen->prev_inline_pic != idx) { ui_add_frame_to_animation(screen->prev_inline_pic, idx); screen->prev_inline_pic = idx; diff --git a/uitoolkit/ui_screen_manager.c b/uitoolkit/ui_screen_manager.c index 0b2cfd55b..0cc639491 100644 --- a/uitoolkit/ui_screen_manager.c +++ b/uitoolkit/ui_screen_manager.c @@ -421,7 +421,8 @@ static vt_char_t *get_picture_data(void *p, char *file_path, int *num_cols /* ca int *num_rows /* can be 0 */, int *num_cols_small /* set only if drcs_sixel is 1. */, int *num_rows_small /* set only if drcs_sixel is 1. */, - u_int32_t **sixel_palette, int keep_aspect, int drcs_sixel) { + u_int32_t **sixel_palette, int *transparent, + int keep_aspect, int drcs_sixel) { vt_char_t *data; if (num_screens > 0) { @@ -432,7 +433,8 @@ static vt_char_t *get_picture_data(void *p, char *file_path, int *num_cols /* ca data = (*screens[0]->xterm_listener.get_picture_data)(screens[0]->xterm_listener.self, file_path, num_cols, num_rows, num_cols_small, num_rows_small, - sixel_palette, 0, drcs_sixel); + sixel_palette, transparent, + 0, drcs_sixel); screens[0]->term = orig_term; } else { data = NULL; diff --git a/uitoolkit/win32/ui_imagelib.c b/uitoolkit/win32/ui_imagelib.c index 98bbd1775..1054741b4 100644 --- a/uitoolkit/win32/ui_imagelib.c +++ b/uitoolkit/win32/ui_imagelib.c @@ -83,9 +83,9 @@ static void adjust_pixmap(u_char *image, u_int width, u_int height, } } -static int load_file(char *path, /* must be UTF-8 */ - u_int *width, u_int *height, int keep_aspect, ui_picture_modifier_t *pic_mod, - HBITMAP *hbmp, HBITMAP *hbmp_mask) { +static int load_file(char *path /* must be UTF-8 */, int keep_aspect, + u_int *width, u_int *height, ui_picture_modifier_t *pic_mod, + HBITMAP *hbmp, HBITMAP *hbmp_mask, int *transparent) { char *suffix; char *cmd_line; WCHAR *w_cmd_line; @@ -107,11 +107,15 @@ static int load_file(char *path, /* must be UTF-8 */ if (strcasecmp(suffix, ".six") == 0 && *width == 0 && *height == 0 && /* XXX fopen() in load_sixel_from_file() on win32api doesn't support UTF-8. */ - (image = (u_int32_t *)load_sixel_from_file(path, width, height))) { + (image = (u_int32_t *)load_sixel_from_file(path, width, height, transparent))) { goto loaded; } #endif + if (transparent) { + *transparent = 0; + } + if (strcasecmp(suffix, ".rgs") == 0) { convert_regis_to_bmp(path); } @@ -312,7 +316,7 @@ Pixmap ui_imagelib_load_file_for_background(ui_window_t *win, char *path, HDC hmdc; width = height = 0; - if (!load_file(path, &width, &height, 0, pic_mod, &hbmp, NULL)) { + if (!load_file(path, 0, &width, &height, pic_mod, &hbmp, NULL, NULL)) { BITMAP bmp; #if defined(__CYGWIN__) || defined(__MSYS__) /* MAX_PATH which is 260 (3+255+1+1) is defined in win32 alone. */ @@ -359,8 +363,9 @@ Pixmap ui_imagelib_get_transparent_background(ui_window_t *win, ui_picture_modif return None; } -int ui_imagelib_load_file(ui_display_t *disp, char *path, u_int32_t **cardinal, Pixmap *pixmap, - PixmapMask *mask, u_int *width, u_int *height, int keep_aspect) { +int ui_imagelib_load_file(ui_display_t *disp, char *path, int keep_aspect, u_int32_t **cardinal, + Pixmap *pixmap, PixmapMask *mask, u_int *width, u_int *height, + int *transparent) { HBITMAP hbmp; HDC hdc; HDC hmdc; @@ -369,7 +374,7 @@ int ui_imagelib_load_file(ui_display_t *disp, char *path, u_int32_t **cardinal, return 0; } - if (!load_file(path, width, height, keep_aspect, NULL, &hbmp, mask)) { + if (!load_file(path, keep_aspect, width, height, NULL, &hbmp, mask, transparent)) { BITMAP bmp; #if defined(__CYGWIN__) || defined(__MSYS__) /* MAX_PATH which is 260 (3+255+1+1) is defined in win32 alone. */ diff --git a/uitoolkit/xlib/ui_imagelib.c b/uitoolkit/xlib/ui_imagelib.c index 5c08248e3..d17d62c3e 100644 --- a/uitoolkit/xlib/ui_imagelib.c +++ b/uitoolkit/xlib/ui_imagelib.c @@ -415,8 +415,8 @@ static void update_diff_table_last(char *diff_next, int x, static int load_sixel(ui_display_t *disp, char *path, Pixmap *pixmap, Pixmap *mask, /* Can be NULL */ u_int *width, /* Can be NULL */ - u_int *height /* Can be NULL */ - ) { + u_int *height, /* Can be NULL */ + int *transparent /* Can be NULL */) { XImage *image; u_int32_t *data; u_int32_t *in; @@ -428,7 +428,7 @@ static int load_sixel(ui_display_t *disp, char *path, Pixmap *pixmap, GC mask_gc; int num_cells; - if (disp->depth < 8 || !(data = in = load_sixel_from_file(path, &w, &h))) { + if (disp->depth < 8 || !(data = in = load_sixel_from_file(path, &w, &h, transparent))) { return 0; } @@ -1711,8 +1711,9 @@ Pixmap ui_imagelib_get_transparent_background(ui_window_t *win, ui_picture_modif * *\return Success => 1, Failure => 0 */ -int ui_imagelib_load_file(ui_display_t *disp, char *path, u_int32_t **cardinal, Pixmap *pixmap, - PixmapMask *mask, u_int *width, u_int *height, int keep_aspect) { +int ui_imagelib_load_file(ui_display_t *disp, char *path, int keep_aspect, u_int32_t **cardinal, + Pixmap *pixmap, PixmapMask *mask, u_int *width, u_int *height, + int *transparent) { u_int dst_height, dst_width; #ifdef BUILTIN_IMAGELIB GdkPixbuf *pixbuf; @@ -1723,11 +1724,15 @@ int ui_imagelib_load_file(ui_display_t *disp, char *path, u_int32_t **cardinal, #if defined(BUILTIN_IMAGELIB) || defined(BUILTIN_SIXEL) if (!cardinal && strcasecmp(path + strlen(path) - 4, ".six") == 0 && dst_width == 0 && - dst_height == 0 && load_sixel(disp, path, pixmap, mask, width, height)) { + dst_height == 0 && load_sixel(disp, path, pixmap, mask, width, height, transparent)) { return 1; } #endif + if (transparent) { + *transparent = 0; + } + #ifdef BUILTIN_IMAGELIB if (path) { diff --git a/vtemu/vt_char.h b/vtemu/vt_char.h index b1893f563..05091a2ef 100644 --- a/vtemu/vt_char.h +++ b/vtemu/vt_char.h @@ -93,9 +93,13 @@ typedef struct vt_char { u_int bg_color2 : 16; #endif u_int code : 21; + /* + * also used for transparent flag of PICTURE_CHARSET + * (see vt_char_{get|set}_picture_transparent_flag() + */ u_int attr2 : 2; - u_int fg_color : 9; - u_int bg_color : 9; + u_int fg_color : 9; /* also used for PICTURE_CHARSET (see vt_char_combine_picture()) */ + u_int bg_color : 9; /* also used for PICTURE_CHARSET (see vt_char_combine_picture()) */ u_int attr : 23; #else u_int attr : 23; diff --git a/vtemu/vt_parser.c b/vtemu/vt_parser.c index 7ede199a2..aeb8c20c7 100644 --- a/vtemu/vt_parser.c +++ b/vtemu/vt_parser.c @@ -1948,6 +1948,7 @@ static void show_picture(vt_parser_t *vt_parser, char *file_path, int clip_beg_c if (HAS_XTERM_LISTENER(vt_parser, get_picture_data)) { vt_char_t *data; + int transparent; #ifdef __DEBUG struct timeval tv1, tv2; @@ -1956,7 +1957,7 @@ static void show_picture(vt_parser_t *vt_parser, char *file_path, int clip_beg_c if ((data = (*vt_parser->xterm_listener->get_picture_data)( vt_parser->xterm_listener->self, file_path, &img_cols, &img_rows, NULL, NULL, - is_sixel ? &vt_parser->sixel_palette : NULL, keep_aspect, 0)) && + is_sixel ? &vt_parser->sixel_palette : NULL, &transparent, keep_aspect, 0)) && clip_beg_row < img_rows && clip_beg_col < img_cols) { vt_char_t *p; int row; @@ -1967,6 +1968,14 @@ static void show_picture(vt_parser_t *vt_parser, char *file_path, int clip_beg_c /* Flush buffer before vt_screen_overwrite_chars(picture data). */ flush_buffer(vt_parser); + if (transparent) { + /* + * Clear the cursor not to show it in the background of the transparent + * (sixel P2=1) image. + */ + interrupt_vt100_cmd(vt_parser); + } + #ifdef __DEBUG gettimeofday(&tv2, NULL); bl_debug_printf("Processing sixel time (msec) %lu - %lu = %lu\n", @@ -2096,9 +2105,13 @@ static void define_drcs_picture(vt_parser_t *vt_parser, char *path, ef_charset_t } if (idx <= 0x5f && + /* + * DRCS Sixel doesn't support P2=1 (transparent) for now. + * (RLogin 2.28.9 also doesn't support it) + */ (data = (*vt_parser->xterm_listener->get_picture_data)(vt_parser->xterm_listener->self, path, &cols, &rows, &cols_small, - &rows_small, NULL, 0, 1))) { + &rows_small, NULL, NULL, 0, 1))) { u_int pages; u_int offset = 0; vt_drcs_font_t *font; diff --git a/vtemu/vt_parser.h b/vtemu/vt_parser.h index 38d6f58fc..90cbd6a4a 100644 --- a/vtemu/vt_parser.h +++ b/vtemu/vt_parser.h @@ -128,8 +128,8 @@ typedef struct vt_xterm_event_listener { void (*get_window_size)(void *, u_int *, u_int *); /* called in logical context. */ int (*get_rgb)(void *, u_int8_t *, u_int8_t *, u_int8_t *, vt_color_t); /* called in logical context. */ - vt_char_t *(*get_picture_data)(void *, char *, int *, int *, int *, int *, - u_int32_t **, int, int); /* called in logical context. */ + vt_char_t *(*get_picture_data)(void *, char *, int *, int *, int *, int *, u_int32_t **, + int *, int, int); /* called in logical context. */ int (*get_emoji_data)(void *, vt_char_t *, vt_char_t *); /* called in logical context. */ void (*show_tmp_picture)(void *, char *); /* called in logical context. */ #ifdef ENABLE_OSC5379PICTURE