1 /* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */
2
3 #ifndef NO_IMAGE
4
5 #include "../ui_imagelib.h"
6
7 #include <stdio.h> /* sprintf */
8 #include <unistd.h> /* write , STDIN_FILENO */
9 #if !defined(USE_WIN32API) && !defined(__ANDROID__)
10 #include <sys/wait.h> /* waitpid */
11 #endif
12 #ifdef DLOPEN_LIBM
13 #include <pobl/bl_dlfcn.h> /* dynamically loading pow */
14 #else
15 #include <math.h> /* pow */
16 #endif
17 #include <pobl/bl_debug.h>
18 #include <pobl/bl_mem.h>
19 #include <pobl/bl_path.h> /* BL_LIBEXECDIR */
20
21 #include "ui_display.h" /* ui_cmap_get_closest_color */
22
23 /* Trailing "/" is appended in value_table_refresh(). */
24 #ifndef LIBMDIR
25 #define LIBMDIR "/lib"
26 #endif
27
28 #if 1
29 #define BUILTIN_SIXEL
30 #endif
31
32 #ifdef USE_GRF
33 #define BPP_PSEUDO 2
34 #else
35 #define BPP_PSEUDO 1
36 #endif
37
38 /* --- static functions --- */
39
value_table_refresh(u_char * value_table,ui_picture_modifier_t * mod)40 static void value_table_refresh(u_char *value_table, /* 256 bytes */
41 ui_picture_modifier_t *mod) {
42 int i, tmp;
43 double real_gamma, real_brightness, real_contrast;
44 static double (*pow_func)(double, double);
45
46 real_gamma = (double)(mod->gamma) / 100;
47 real_contrast = (double)(mod->contrast) / 100;
48 real_brightness = (double)(mod->brightness) / 100;
49
50 if (!pow_func) {
51 #ifdef DLOPEN_LIBM
52 bl_dl_handle_t handle;
53
54 if ((!(handle = bl_dl_open(LIBMDIR "/", "m")) && !(handle = bl_dl_open("", "m"))) ||
55 !(pow_func = bl_dl_func_symbol(handle, "pow"))) {
56 #ifdef DEBUG
57 bl_debug_printf(BL_DEBUG_TAG " Failed to load pow in libm.so\n");
58 #endif
59
60 if (handle) {
61 bl_dl_close(handle);
62 }
63
64 /*
65 * gamma, contrast and brightness options are ignored.
66 * (alpha option still survives.)
67 */
68 for (i = 0; i < 256; i++) {
69 value_table[i] = i;
70 }
71
72 return;
73 }
74
75 bl_dl_close_at_exit(handle);
76 #else /* DLOPEN_LIBM */
77 pow_func = pow;
78 #endif /* DLOPEN_LIBM */
79 }
80
81 for (i = 0; i < 256; i++) {
82 tmp = real_contrast * (255 * (*pow_func)(((double)i + 0.5) / 255, real_gamma) - 128) +
83 128 * real_brightness;
84 if (tmp >= 255) {
85 break;
86 } else if (tmp < 0) {
87 value_table[i] = 0;
88 } else {
89 value_table[i] = tmp;
90 }
91 }
92
93 for (; i < 256; i++) {
94 value_table[i] = 255;
95 }
96 }
97
modify_pixmap(Display * display,Pixmap pixmap,ui_picture_modifier_t * pic_mod,u_int depth)98 static void modify_pixmap(Display *display, Pixmap pixmap, ui_picture_modifier_t *pic_mod,
99 u_int depth) {
100 u_char *value_table;
101 u_int32_t *src;
102 u_char *dst;
103 u_int num_pixels;
104 u_int count;
105 u_char r, g, b;
106 u_long pixel;
107
108 if (!ui_picture_modifier_is_normal(pic_mod) && (value_table = alloca(256))) {
109 value_table_refresh(value_table, pic_mod);
110 } else if (display->bytes_per_pixel == 4 &&
111 /* RRGGBB */
112 display->rgbinfo.r_offset == 16 && display->rgbinfo.g_offset == 8 &&
113 display->rgbinfo.b_offset == 0) {
114 return;
115 } else {
116 value_table = NULL;
117 }
118
119 src = dst = pixmap->image;
120 num_pixels = pixmap->width * pixmap->height;
121
122 for (count = 0; count < num_pixels; count++) {
123 pixel = *(src++);
124
125 r = (pixel >> 16) & 0xff;
126 g = (pixel >> 8) & 0xff;
127 b = pixel & 0xff;
128
129 if (value_table) {
130 r = (value_table[r] * (255 - pic_mod->alpha) + pic_mod->blend_red * pic_mod->alpha) / 255;
131 g = (value_table[g] * (255 - pic_mod->alpha) + pic_mod->blend_green * pic_mod->alpha) / 255;
132 b = (value_table[b] * (255 - pic_mod->alpha) + pic_mod->blend_blue * pic_mod->alpha) / 255;
133 }
134
135 if (ui_cmap_get_closest_color(&pixel, r, g, b)) {
136 #ifdef USE_GRF
137 *((u_int16_t *)dst) = pixel;
138 dst += 2;
139 #else
140 *(dst++) = pixel;
141 #endif
142 } else {
143 pixel = RGB_TO_PIXEL(r, g, b, display->rgbinfo) | (depth == 32 ? (pixel & 0xff000000) : 0);
144
145 if (display->bytes_per_pixel == 2) {
146 *((u_int16_t *)dst) = pixel;
147 dst += 2;
148 } else /* if( display->bytes_per_pixel == 4) */
149 {
150 *((u_int32_t *)dst) = pixel;
151 dst += 4;
152 }
153 }
154 }
155
156 if (display->bytes_per_pixel < 4) {
157 void *p;
158
159 if ((p = realloc(pixmap->image, pixmap->width * pixmap->height * display->bytes_per_pixel))) {
160 pixmap->image = p;
161 }
162 }
163 }
164
165 #ifdef BUILTIN_SIXEL
166
167 #include <string.h>
168 #include <pobl/bl_util.h>
169 #include <pobl/bl_def.h> /* SSIZE_MAX */
170
171 /*
172 * This function resizes the sixel image to the specified size and shrink
173 * pixmap->image.
174 * It frees pixmap->image in failure.
175 * Call resize_sixel() after load_sixel_from_file() because it returns at least
176 * 1024*1024 pixels memory even if the actual image size is less than 1024*1024.
177 */
resize_sixel(Pixmap pixmap,u_int width,u_int height,u_int bytes_per_pixel)178 static int resize_sixel(Pixmap pixmap, u_int width, u_int height, u_int bytes_per_pixel) {
179 void *p;
180 size_t line_len;
181 size_t old_line_len;
182 size_t image_len;
183 size_t old_image_len;
184 u_char *dst;
185 u_char *src;
186 int y;
187 u_int min_height;
188
189 p = NULL;
190
191 if ((width == 0 || width == pixmap->width) && (height == 0 || height == pixmap->height)) {
192 goto end;
193 }
194
195 if (width > SSIZE_MAX / bytes_per_pixel / height) {
196 goto error;
197 }
198
199 old_line_len = pixmap->width * bytes_per_pixel;
200 line_len = width * bytes_per_pixel;
201 image_len = line_len * height;
202 old_image_len = old_line_len * pixmap->height;
203
204 if (image_len > old_image_len) {
205 if (!(p = realloc(pixmap->image, image_len))) {
206 goto error;
207 }
208
209 pixmap->image = p;
210 }
211
212 /* Tiling */
213
214 min_height = BL_MIN(height, pixmap->height);
215
216 if (width > pixmap->width) {
217 size_t surplus;
218 u_int num_copy;
219 u_int count;
220 u_char *dst_next;
221
222 y = min_height - 1;
223 src = pixmap->image + old_line_len * y;
224 dst = pixmap->image + line_len * y;
225
226 surplus = line_len % old_line_len;
227 num_copy = line_len / old_line_len - 1;
228
229 for (; y >= 0; y--) {
230 dst_next = memmove(dst, src, old_line_len);
231
232 for (count = num_copy; count > 0; count--) {
233 memcpy((dst_next += old_line_len), dst, old_line_len);
234 }
235 memcpy(dst_next + old_line_len, dst, surplus);
236
237 dst -= line_len;
238 src -= old_line_len;
239 }
240 } else if (width < pixmap->width) {
241 src = pixmap->image + old_line_len;
242 dst = pixmap->image + line_len;
243
244 for (y = 1; y < min_height; y++) {
245 memmove(dst, src, old_line_len);
246 dst += line_len;
247 src += old_line_len;
248 }
249 }
250
251 if (height > pixmap->height) {
252 y = pixmap->height;
253 src = pixmap->image;
254 dst = src + line_len * y;
255
256 for (; y < height; y++) {
257 memcpy(dst, src, line_len);
258 dst += line_len;
259 src += line_len;
260 }
261 }
262
263 bl_msg_printf("Resize sixel from %dx%d to %dx%d\n", pixmap->width, pixmap->height, width, height);
264
265 pixmap->width = width;
266 pixmap->height = height;
267
268 end:
269 /* Always realloate pixmap->image according to its width, height and
270 * bytes_per_pixel. */
271 if (!p && (p = realloc(pixmap->image, pixmap->width * pixmap->height * bytes_per_pixel))) {
272 pixmap->image = p;
273 }
274
275 return 1;
276
277 error:
278 free(pixmap->image);
279
280 return 0;
281 }
282
283 #define CARD_HEAD_SIZE 0
284 #include "../../common/c_sixel.c"
285
286
287 /* For old machines (not to use mlimgloader) */
288 #if (defined(__NetBSD__) || defined(__OpenBSD__)) && !defined(USE_GRF)
289
290 #define SIXEL_1BPP
291 #include "../../common/c_sixel.c"
292 #undef SIXEL_1BPP
293
294 /* depth should be checked by the caller. */
load_sixel_with_mask_from_data_1bpp(char * file_data,u_int width,u_int height,Pixmap * pixmap,PixmapMask * mask)295 static int load_sixel_with_mask_from_data_1bpp(char *file_data, u_int width, u_int height,
296 Pixmap *pixmap, PixmapMask *mask) {
297 int x;
298 int y;
299 u_char *src;
300 #if 0
301 u_char *dst;
302 #endif
303
304 if (!(*pixmap = calloc(1, sizeof(**pixmap)))) {
305 return 0;
306 }
307
308 if (!((*pixmap)->image =
309 load_sixel_from_data_1bpp(file_data, &(*pixmap)->width, &(*pixmap)->height)) ||
310 /* resize_sixel() frees pixmap->image in failure. */
311 !resize_sixel(*pixmap, width, height, 1)) {
312 free(*pixmap);
313
314 return 0;
315 }
316
317 src = (*pixmap)->image;
318
319 #if 0
320 if (mask && (dst = *mask = calloc(1, (*pixmap)->width * (*pixmap)->height))) {
321 int has_tp;
322
323 has_tp = 0;
324
325 for (y = 0; y < (*pixmap)->height; y++) {
326 for (x = 0; x < (*pixmap)->width; x++) {
327 if (*src >= 0x80) {
328 *dst = 1;
329 /* clear opaque mark */
330 *src &= 0x7f;
331 } else {
332 has_tp = 1;
333 }
334
335 src++;
336 dst++;
337 }
338 }
339
340 if (!has_tp) {
341 free(*mask);
342 *mask = None;
343 }
344 } else {
345 for (y = 0; y < (*pixmap)->height; y++) {
346 for (x = 0; x < (*pixmap)->width; x++) {
347 /* clear opaque mark */
348 *(src++) &= 0x7f;
349 }
350 }
351 }
352 #else
353 {
354 u_char bg_color;
355 u_char *p;
356
357 if (mask) {
358 *mask = None;
359 }
360
361 bg_color = 0;
362 p = src;
363
364 /* Guess the current screen background color. */
365 for (y = 0; y < (*pixmap)->height; y++) {
366 for (x = 0; x < (*pixmap)->width; x++) {
367 if (*p >= 0x80) {
368 bg_color = (((*p) & 0x7f) == 1) ? 0 : 1;
369 break;
370 }
371
372 p++;
373 }
374 }
375
376 for (y = 0; y < (*pixmap)->height; y++) {
377 for (x = 0; x < (*pixmap)->width; x++) {
378 if (*src >= 0x80) {
379 /* clear opaque mark */
380 *(src++) &= 0x7f;
381 } else {
382 /* replace transparent pixel by the background color */
383 *(src++) = bg_color;
384 }
385 }
386 }
387 }
388 #endif
389
390 return 1;
391 }
392 #endif
393 #endif /* BUILTIN_SIXEL */
394
395 #define SIXEL_SHAREPALETTE
396 #include "../../common/c_sixel.c"
397 #undef SIXEL_SHAREPALETTE
398
399 #if defined(USE_WIN32API)
400 #include <windows.h>
401
exec_mlimgloader(char * path,u_int width,u_int height,int keep_aspect,Pixmap * pixmap)402 static int exec_mlimgloader(char *path, u_int width, u_int height, int keep_aspect,
403 Pixmap *pixmap) {
404 HANDLE input_write;
405 HANDLE input_read_tmp;
406 HANDLE input_read;
407 SECURITY_ATTRIBUTES sa;
408 PROCESS_INFORMATION pi;
409 STARTUPINFO si;
410 char *cmd_line;
411 DWORD len;
412 ssize_t size;
413 u_int32_t tmp;
414
415 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
416 sa.lpSecurityDescriptor = NULL;
417 sa.bInheritHandle = TRUE;
418
419 if (!CreatePipe(&input_read_tmp, &input_write, &sa, 0)) {
420 #ifdef DEBUG
421 bl_warn_printf(BL_DEBUG_TAG " CreatePipe() failed.\n");
422 #endif
423
424 return 0;
425 }
426
427 if (!DuplicateHandle(GetCurrentProcess(), input_read_tmp, GetCurrentProcess(),
428 &input_read /* Address of new handle. */,
429 0, FALSE /* Make it uninheritable. */,
430 DUPLICATE_SAME_ACCESS)) {
431 #ifdef DEBUG
432 bl_warn_printf(BL_DEBUG_TAG " DuplicateHandle() failed.\n");
433 #endif
434
435 CloseHandle(input_read_tmp);
436
437 goto error1;
438 }
439
440 CloseHandle(input_read_tmp);
441
442 ZeroMemory(&si, sizeof(STARTUPINFO));
443 si.cb = sizeof(STARTUPINFO);
444 si.dwFlags = STARTF_USESTDHANDLES | STARTF_FORCEOFFFEEDBACK;
445 si.hStdOutput = input_write;
446 si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
447 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
448 /*
449 * Use this if you want to hide the child:
450 * si.wShowWindow = SW_HIDE;
451 * Note that dwFlags must include STARTF_USESHOWWINDOW if you want to
452 * use the wShowWindow flags.
453 */
454
455 if ((cmd_line = alloca(23 + DIGIT_STR_LEN(u_int) * 2 + strlen(path) + 1)) == NULL) {
456 #ifdef DEBUG
457 bl_warn_printf(BL_DEBUG_TAG " alloca failed.\n");
458 #endif
459
460 goto error1;
461 }
462
463 sprintf(cmd_line, "%s 0 %d %d %s stdout%s", "mlimgloader.exe", width, height, path,
464 keep_aspect ? " -a" : "");
465
466 if (!CreateProcess("mlimgloader.exe", cmd_line, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL,
467 &si, &pi)) {
468 #ifdef DEBUG
469 bl_warn_printf(BL_DEBUG_TAG " CreateProcess() failed.\n");
470 #endif
471
472 goto error1;
473 }
474
475 CloseHandle(pi.hProcess);
476 CloseHandle(pi.hThread);
477
478 CloseHandle(input_write);
479
480 if (!(*pixmap = calloc(1, sizeof(**pixmap)))) {
481 goto error2;
482 }
483
484 if (!ReadFile(input_read, &tmp, sizeof(u_int32_t), &len, NULL) || len != sizeof(u_int32_t)) {
485 goto error2;
486 }
487
488 size = ((*pixmap)->width = tmp) * sizeof(u_int32_t);
489
490 if (!ReadFile(input_read, &tmp, sizeof(u_int32_t), &len, NULL) || len != sizeof(u_int32_t)) {
491 goto error2;
492 }
493
494 size *= ((*pixmap)->height = tmp);
495
496 if (!((*pixmap)->image = malloc(size))) {
497 goto error2;
498 } else {
499 u_char *p;
500
501 p = (*pixmap)->image;
502 do {
503 if (!ReadFile(input_read, p, size, &len, NULL)) {
504 free((*pixmap)->image);
505 goto error2;
506 }
507 p += len;
508 } while ((size -= len) > 0);
509 }
510
511 CloseHandle(input_read);
512
513 return 1;
514
515 error1:
516 CloseHandle(input_write);
517 CloseHandle(input_read);
518
519 return 0;
520
521 error2:
522 free(*pixmap);
523 CloseHandle(input_read);
524
525 return 0;
526 }
527
528 #elif defined(__ANDROID__)
529
exec_mlimgloader(char * path,u_int width,u_int height,int keep_aspect,Pixmap * pixmap)530 static int exec_mlimgloader(char *path, u_int width, u_int height, int keep_aspect,
531 Pixmap *pixmap) {
532 if (!(*pixmap = calloc(1, sizeof(**pixmap)))) {
533 return 0;
534 }
535
536 (*pixmap)->width = width;
537 (*pixmap)->height = height;
538
539 if (!((*pixmap)->image = ui_display_get_bitmap(path, &(*pixmap)->width, &(*pixmap)->height))) {
540 free(*pixmap);
541
542 return 0;
543 }
544
545 return 1;
546 }
547
548 #else
549
exec_mlimgloader(char * path,u_int width,u_int height,int keep_aspect,Pixmap * pixmap)550 static int exec_mlimgloader(char *path, u_int width, u_int height, int keep_aspect,
551 Pixmap *pixmap) {
552 pid_t pid;
553 int fds[2];
554 ssize_t size;
555 u_int32_t tmp;
556
557 if (pipe(fds) == -1) {
558 return 0;
559 }
560
561 pid = fork();
562 if (pid == -1) {
563 close(fds[0]);
564 close(fds[0]);
565
566 return 0;
567 }
568
569 if (pid == 0) {
570 /* child process */
571
572 char *args[8];
573 char width_str[DIGIT_STR_LEN(u_int) + 1];
574 char height_str[DIGIT_STR_LEN(u_int) + 1];
575
576 args[0] = BL_LIBEXECDIR("mlterm") "/mlimgloader";
577 args[1] = "0";
578 sprintf(width_str, "%u", width);
579 args[2] = width_str;
580 sprintf(height_str, "%u", height);
581 args[3] = height_str;
582 args[4] = path;
583 args[5] = "stdout";
584 if (keep_aspect) {
585 args[6] = "-a";
586 args[7] = NULL;
587 } else {
588 args[6] = NULL;
589 }
590
591 close(fds[0]);
592 if (dup2(fds[1], STDOUT_FILENO) != -1) {
593 execv(args[0], args);
594 }
595
596 bl_msg_printf("Failed to exec %s.\n", args[0]);
597
598 exit(1);
599 }
600
601 close(fds[1]);
602
603 if (!(*pixmap = calloc(1, sizeof(**pixmap)))) {
604 goto error;
605 }
606
607 if (read(fds[0], &tmp, sizeof(u_int32_t)) != sizeof(u_int32_t)) {
608 goto error;
609 }
610
611 size = ((*pixmap)->width = tmp) * sizeof(u_int32_t);
612
613 if (read(fds[0], &tmp, sizeof(u_int32_t)) != sizeof(u_int32_t)) {
614 goto error;
615 }
616
617 size *= ((*pixmap)->height = tmp);
618
619 if (!((*pixmap)->image = malloc(size))) {
620 goto error;
621 } else {
622 u_char *p;
623 ssize_t n_rd;
624
625 p = (*pixmap)->image;
626 while ((n_rd = read(fds[0], p, size)) > 0) {
627 p += n_rd;
628 size -= n_rd;
629 }
630
631 if (size > 0) {
632 goto error;
633 }
634 }
635
636 close(fds[0]);
637
638 /* bl_pty_fork() in vt_pty_unix_new() may block without this in startup. */
639 #if 1
640 waitpid(pid, NULL, 0);
641 #endif
642
643 return 1;
644
645 error:
646 #ifdef DEBUG
647 bl_debug_printf(BL_DEBUG_TAG " Failed to load %s\n", path);
648 #endif
649
650 if (*pixmap) {
651 free((*pixmap)->image);
652 free(*pixmap);
653 }
654
655 close(fds[0]);
656
657 return 0;
658 }
659
660 #endif
661
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)662 static int load_file(Display *display, char *path, u_int width, u_int height, int keep_aspect,
663 ui_picture_modifier_t *pic_mod, u_int depth, Pixmap *pixmap,
664 PixmapMask *mask) {
665 if (!path || !*path) {
666 return 0;
667 }
668
669 #ifdef BUILTIN_SIXEL
670 if (strcasecmp(path + strlen(path) - 4, ".six") == 0) {
671 char *file_data;
672
673 if (!(file_data = read_sixel_file(path))) {
674 return 0;
675 }
676
677 /* For old machines */
678 #if (defined(__NetBSD__) || defined(__OpenBSD__)) && !defined(USE_GRF)
679 if (depth == 1) {
680 /* pic_mod is ignored. */
681 if (load_sixel_with_mask_from_data_1bpp(file_data, width, height, pixmap, mask)) {
682 free(file_data);
683 return 1;
684 }
685 } else
686 #endif
687 if (
688 /* For old machines and Android (not to use mlimgloader) */
689 #if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && \
690 (!defined(__FreeBSD__) || !defined(PC98))
691 width == 0 && height == 0 &&
692 #endif
693 (*pixmap = calloc(1, sizeof(**pixmap)))) {
694 #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE
695 u_int32_t *sixel_cmap;
696
697 if (ui_display_is_changeable_cmap()) {
698 goto skip_sharepalette;
699 }
700 #endif
701
702 if (depth <= 8) {
703 if (ui_picture_modifier_is_normal(pic_mod) /* see modify_pixmap() */) {
704 if (((*pixmap)->image = load_sixel_from_data_sharepalette(file_data, &(*pixmap)->width,
705 &(*pixmap)->height)) &&
706 resize_sixel(*pixmap, width, height, BPP_PSEUDO)) {
707 if (mask) {
708 *mask = NULL;
709 }
710 free(file_data);
711
712 goto loaded_nomodify;
713 }
714 }
715
716 bl_msg_printf("Use closest colors for %s.\n", path);
717 }
718
719 #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE
720 skip_sharepalette:
721 if (!(sixel_cmap = custom_palette) &&
722 (sixel_cmap = alloca(sizeof(*sixel_cmap) * (SIXEL_PALETTE_SIZE + 1)))) {
723 sixel_cmap[SIXEL_PALETTE_SIZE] = 0; /* No active palette */
724 custom_palette = sixel_cmap;
725 }
726 #endif
727
728 if (((*pixmap)->image = load_sixel_from_data(file_data, &(*pixmap)->width,
729 &(*pixmap)->height)) &&
730 /* resize_sixel() frees pixmap->image in failure. */
731 resize_sixel(*pixmap, width, height, 4)) {
732 #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE
733 if (sixel_cmap) {
734 /* see set_wall_picture() in ui_screen.c */
735 ui_display_set_cmap(sixel_cmap, sixel_cmap[SIXEL_PALETTE_SIZE]);
736 }
737 #endif
738 free(file_data);
739
740 goto loaded;
741 } else {
742 free(*pixmap);
743 }
744 }
745
746 free(file_data);
747 }
748 #endif /* BUILTIN_SIXEL */
749
750 if (!exec_mlimgloader(path, width, height, keep_aspect, pixmap)) {
751 return 0;
752 }
753
754 loaded:
755 if (mask) {
756 u_char *dst;
757
758 if ((dst = *mask = calloc(1, (*pixmap)->width * (*pixmap)->height))) {
759 int x;
760 int y;
761 int has_tp;
762 u_int32_t *src;
763
764 has_tp = 0;
765 src = (u_int32_t *)(*pixmap)->image;
766
767 for (y = 0; y < (*pixmap)->height; y++) {
768 for (x = 0; x < (*pixmap)->width; x++) {
769 if (*(src++) >= 0x80000000) {
770 *dst = 1;
771 } else {
772 has_tp = 1;
773 }
774
775 dst++;
776 }
777 }
778
779 if (!has_tp) {
780 free(*mask);
781 *mask = None;
782 }
783 }
784 }
785
786 modify_pixmap(display, *pixmap, pic_mod, depth);
787
788 loaded_nomodify:
789 #ifdef DEBUG
790 bl_debug_printf(BL_DEBUG_TAG " %s(w %d h %d) is loaded%s.\n", path, (*pixmap)->width,
791 (*pixmap)->height, (mask && *mask) ? " (has mask)" : "");
792 #endif
793
794 return 1;
795 }
796
797 /* --- global functions --- */
798
ui_imagelib_display_opened(Display * display)799 void ui_imagelib_display_opened(Display *display) {}
800
ui_imagelib_display_closed(Display * display)801 void ui_imagelib_display_closed(Display *display) {}
802
ui_imagelib_load_file_for_background(ui_window_t * win,char * path,ui_picture_modifier_t * pic_mod)803 Pixmap ui_imagelib_load_file_for_background(ui_window_t *win, char *path,
804 ui_picture_modifier_t *pic_mod) {
805 Pixmap pixmap;
806
807 #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE
808 ui_display_enable_to_change_cmap(1);
809 #endif
810
811 if (!load_file(win->disp->display, path, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win), 0, pic_mod,
812 win->disp->depth, &pixmap, NULL)) {
813 pixmap = None;
814 }
815
816 #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE
817 ui_display_enable_to_change_cmap(0);
818 #endif
819
820 return pixmap;
821 }
822
ui_imagelib_root_pixmap_available(Display * display)823 int ui_imagelib_root_pixmap_available(Display *display) { return 0; }
824
ui_imagelib_get_transparent_background(ui_window_t * win,ui_picture_modifier_t * pic_mod)825 Pixmap ui_imagelib_get_transparent_background(ui_window_t *win, ui_picture_modifier_t *pic_mod) {
826 return None;
827 }
828
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)829 int ui_imagelib_load_file(ui_display_t *disp, char *path, u_int32_t **cardinal, Pixmap *pixmap,
830 PixmapMask *mask, u_int *width, u_int *height, int keep_aspect) {
831 if (cardinal) {
832 return 0;
833 }
834
835 if (!load_file(disp->display, path, *width, *height, keep_aspect, NULL, disp->depth,
836 pixmap, mask)) {
837 return 0;
838 }
839
840 if (*width == 0 || *height == 0 || keep_aspect) {
841 *width = (*pixmap)->width;
842 *height = (*pixmap)->height;
843 }
844
845 return 1;
846 }
847
ui_destroy_image(Display * display,Pixmap pixmap)848 void ui_destroy_image(Display *display, Pixmap pixmap) {
849 free(pixmap->image);
850 free(pixmap);
851 }
852
ui_destroy_mask(Display * display,PixmapMask mask)853 void ui_destroy_mask(Display *display, PixmapMask mask /* can be NULL */) {
854 if (mask) {
855 free(mask);
856 }
857 }
858
859 #endif /* NO_IMAGE */
860