aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2023-08-01 10:34:33 +0800
committerPo Lu2023-08-01 10:34:33 +0800
commit74d6604eaa2d770626309181ac4bc4f2598e63e7 (patch)
treeda81fdaabe8e41afa9b5518bdbee8ecdaa605a79 /src
parentbfb7c58ac5c322d6363e83f68afa88fc88ba2a0f (diff)
downloademacs-74d6604eaa2d770626309181ac4bc4f2598e63e7.tar.gz
emacs-74d6604eaa2d770626309181ac4bc4f2598e63e7.zip
Fix stipple support on PGTK
* src/image.c (image_create_pattern_from_pixbuf): Remove function. (image_bitmap_to_cr_pattern): New function. (image_create_bitmap_from_data): (image_create_bitmap_from_file): Create patterns with the correct mask values directly from bitmap data. Also, don't rely on GDK to read XPMs, as that format isn't supported anymore. * src/pgtkterm.c (pgtk_bitmap_icon): Disable already nonfunctional code. (pgtk_display_x_warning): Wrap warning message. * src/pgtkterm.h (struct pgtk_bitmap_record): Remove `img' field. (bug#64969)
Diffstat (limited to 'src')
-rw-r--r--src/image.c187
-rw-r--r--src/pgtkterm.c26
-rw-r--r--src/pgtkterm.h1
3 files changed, 128 insertions, 86 deletions
diff --git a/src/image.c b/src/image.c
index c9420b48f4a..cb9725892d1 100644
--- a/src/image.c
+++ b/src/image.c
@@ -441,32 +441,101 @@ image_reference_bitmap (struct frame *f, ptrdiff_t id)
441} 441}
442 442
443#ifdef HAVE_PGTK 443#ifdef HAVE_PGTK
444
445/* Create a Cairo pattern from the bitmap BITS, which should be WIDTH
446 and HEIGHT in size. BITS's fill order is LSB first, meaning that
447 the value of the left most pixel within a byte is its least
448 significant bit. */
449
444static cairo_pattern_t * 450static cairo_pattern_t *
445image_create_pattern_from_pixbuf (struct frame *f, GdkPixbuf * pixbuf) 451image_bitmap_to_cr_pattern (char *bits, int width, int height)
446{ 452{
447 GdkPixbuf *pb = gdk_pixbuf_add_alpha (pixbuf, TRUE, 255, 255, 255); 453 cairo_surface_t *surface;
448 cairo_surface_t *surface = 454 unsigned char *data;
449 cairo_surface_create_similar_image (cairo_get_target 455 int stride;
450 (f->output_data.pgtk->cr_context), 456 cairo_pattern_t *pattern;
451 CAIRO_FORMAT_A1, 457#ifdef WORDS_BIGENDIAN
452 gdk_pixbuf_get_width (pb), 458 int x;
453 gdk_pixbuf_get_height (pb)); 459 static const unsigned char table[] = {
460 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
461 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
462 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
463 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
464 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
465 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
466 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
467 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
468 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
469 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
470 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
471 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
472 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
473 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
474 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
475 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
476 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
477 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
478 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
479 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
480 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
481 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
482 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
483 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
484 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
485 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
486 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
487 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
488 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
489 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
490 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
491 };
492#endif /* WORDS_BIGENDIAN */
454 493
455 cairo_t *cr = cairo_create (surface); 494 surface = cairo_image_surface_create (CAIRO_FORMAT_A1, width,
456 gdk_cairo_set_source_pixbuf (cr, pb, 0, 0); 495 height);
457 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
458 cairo_paint (cr);
459 cairo_destroy (cr);
460 496
461 cairo_pattern_t *pat = cairo_pattern_create_for_surface (surface); 497 if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
462 cairo_pattern_set_extend (pat, CAIRO_EXTEND_REPEAT); 498 memory_full (0);
463 499
464 cairo_surface_destroy (surface); 500 cairo_surface_flush (surface);
465 g_object_unref (pb); 501 data = cairo_image_surface_get_data (surface);
502 stride = cairo_image_surface_get_stride (surface);
466 503
467 return pat; 504#ifdef WORDS_BIGENDIAN
505 /* Big endian systems require that individual bytes be inverted to
506 compensate for the different fill order used by Cairo. */
507 while (height--)
508 {
509 memcpy (data, bits, (width + 7) / 8);
510 for (x = 0; x < (width + 7) / 8; ++x)
511 data[x] = table[data[x]];
512 data += stride;
513 bits += (width + 7) / 8;
514 }
515#else /* !WORDS_BIGENDIAN */
516 /* Cairo uses LSB first fill order for bitmaps on little-endian
517 systems, so copy each row over. */
518
519 while (height--)
520 {
521 memcpy (data, bits, (width + 7) / 8);
522 data += stride;
523 bits += (width + 7) / 8;
524 }
525#endif /* WORDS_BIGENDIAN */
526
527 cairo_surface_mark_dirty (surface);
528 pattern = cairo_pattern_create_for_surface (surface);
529 if (cairo_pattern_status (pattern) != CAIRO_STATUS_SUCCESS)
530 memory_full (0);
531
532 /* The pattern now holds a reference to the surface. */
533 cairo_surface_destroy (surface);
534 cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
535 return pattern;
468} 536}
469#endif 537
538#endif /* HAVE_PGTK */
470 539
471/* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */ 540/* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
472 541
@@ -504,46 +573,9 @@ image_create_bitmap_from_data (struct frame *f, char *bits,
504#endif 573#endif
505 574
506#ifdef HAVE_PGTK 575#ifdef HAVE_PGTK
507 GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 576 cairo_pattern_t *pattern;
508 FALSE, 577
509 8, 578 pattern = image_bitmap_to_cr_pattern (bits, width, height);
510 width,
511 height);
512 {
513 char *sp = bits;
514 int mask = 0x01;
515 unsigned char *buf = gdk_pixbuf_get_pixels (pixbuf);
516 int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
517 for (int y = 0; y < height; y++)
518 {
519 unsigned char *dp = buf + rowstride * y;
520 for (int x = 0; x < width; x++)
521 {
522 if (*sp & mask)
523 {
524 *dp++ = 0xff;
525 *dp++ = 0xff;
526 *dp++ = 0xff;
527 }
528 else
529 {
530 *dp++ = 0x00;
531 *dp++ = 0x00;
532 *dp++ = 0x00;
533 }
534 if ((mask <<= 1) >= 0x100)
535 {
536 mask = 0x01;
537 sp++;
538 }
539 }
540 if (mask != 0x01)
541 {
542 mask = 0x01;
543 sp++;
544 }
545 }
546 }
547#endif /* HAVE_PGTK */ 579#endif /* HAVE_PGTK */
548 580
549#ifdef HAVE_HAIKU 581#ifdef HAVE_HAIKU
@@ -577,10 +609,8 @@ image_create_bitmap_from_data (struct frame *f, char *bits,
577#endif 609#endif
578 610
579#ifdef HAVE_PGTK 611#ifdef HAVE_PGTK
580 dpyinfo->bitmaps[id - 1].img = pixbuf;
581 dpyinfo->bitmaps[id - 1].depth = 1; 612 dpyinfo->bitmaps[id - 1].depth = 1;
582 dpyinfo->bitmaps[id - 1].pattern = 613 dpyinfo->bitmaps[id - 1].pattern = pattern;
583 image_create_pattern_from_pixbuf (f, pixbuf);
584#endif 614#endif
585 615
586#ifdef HAVE_HAIKU 616#ifdef HAVE_HAIKU
@@ -616,7 +646,7 @@ image_create_bitmap_from_data (struct frame *f, char *bits,
616 return id; 646 return id;
617} 647}
618 648
619#if defined HAVE_HAIKU || defined HAVE_NS 649#if defined HAVE_HAIKU || defined HAVE_NS || defined HAVE_PGTK
620static char *slurp_file (int, ptrdiff_t *); 650static char *slurp_file (int, ptrdiff_t *);
621static Lisp_Object image_find_image_fd (Lisp_Object, int *); 651static Lisp_Object image_find_image_fd (Lisp_Object, int *);
622static bool xbm_read_bitmap_data (struct frame *, char *, char *, 652static bool xbm_read_bitmap_data (struct frame *, char *, char *,
@@ -680,25 +710,38 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file)
680#endif 710#endif
681 711
682#ifdef HAVE_PGTK 712#ifdef HAVE_PGTK
683 GError *err = NULL; 713 ptrdiff_t id, size;
684 ptrdiff_t id; 714 int fd, width, height, rc;
685 void * bitmap = gdk_pixbuf_new_from_file (SSDATA (file), &err); 715 char *contents, *data;
716 void *bitmap;
686 717
687 if (!bitmap) 718 if (!STRINGP (image_find_image_fd (file, &fd)))
719 return -1;
720
721 contents = slurp_file (fd, &size);
722
723 if (!contents)
724 return -1;
725
726 rc = xbm_read_bitmap_data (f, contents, contents + size,
727 &width, &height, &data, 0);
728
729 if (!rc)
688 { 730 {
689 g_error_free (err); 731 xfree (contents);
690 return -1; 732 return -1;
691 } 733 }
692 734
693 id = image_allocate_bitmap_record (f); 735 id = image_allocate_bitmap_record (f);
694 736
695 dpyinfo->bitmaps[id - 1].img = bitmap;
696 dpyinfo->bitmaps[id - 1].refcount = 1; 737 dpyinfo->bitmaps[id - 1].refcount = 1;
697 dpyinfo->bitmaps[id - 1].file = xlispstrdup (file); 738 dpyinfo->bitmaps[id - 1].file = xlispstrdup (file);
698 dpyinfo->bitmaps[id - 1].height = gdk_pixbuf_get_width (bitmap); 739 dpyinfo->bitmaps[id - 1].height = width;
699 dpyinfo->bitmaps[id - 1].width = gdk_pixbuf_get_height (bitmap); 740 dpyinfo->bitmaps[id - 1].width = height;
700 dpyinfo->bitmaps[id - 1].pattern 741 dpyinfo->bitmaps[id - 1].pattern
701 = image_create_pattern_from_pixbuf (f, bitmap); 742 = image_bitmap_to_cr_pattern (data, width, height);
743 xfree (contents);
744 xfree (data);
702 return id; 745 return id;
703#endif 746#endif
704 747
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index dc2d6477bb5..9c1fc7bef4e 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -3147,11 +3147,15 @@ pgtk_scroll_run (struct window *w, struct run *run)
3147 3147
3148/* Icons. */ 3148/* Icons. */
3149 3149
3150/* Make the x-window of frame F use the gnu icon bitmap. */
3151
3152static bool 3150static bool
3153pgtk_bitmap_icon (struct frame *f, Lisp_Object file) 3151pgtk_bitmap_icon (struct frame *f, Lisp_Object file)
3154{ 3152{
3153 /* This code has never worked anyway for the reason that Wayland
3154 uses icons set within desktop files, and has been disabled
3155 because leaving it intact would require image.c to retain a
3156 reference to a GdkPixbuf (which are no longer used) within new
3157 bitmaps. */
3158#if 0
3155 ptrdiff_t bitmap_id; 3159 ptrdiff_t bitmap_id;
3156 3160
3157 if (FRAME_GTK_WIDGET (f) == 0) 3161 if (FRAME_GTK_WIDGET (f) == 0)
@@ -3207,12 +3211,8 @@ pgtk_bitmap_icon (struct frame *f, Lisp_Object file)
3207 bitmap_id = FRAME_DISPLAY_INFO (f)->icon_bitmap_id; 3211 bitmap_id = FRAME_DISPLAY_INFO (f)->icon_bitmap_id;
3208 } 3212 }
3209 3213
3210 if (FRAME_DISPLAY_INFO (f)->bitmaps[bitmap_id - 1].img != NULL)
3211 gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
3212 FRAME_DISPLAY_INFO (f)->bitmaps[bitmap_id - 1].img);
3213
3214 f->output_data.pgtk->icon_bitmap = bitmap_id; 3214 f->output_data.pgtk->icon_bitmap = bitmap_id;
3215 3215#endif /* 0 */
3216 return false; 3216 return false;
3217} 3217}
3218 3218
@@ -6685,12 +6685,12 @@ pgtk_display_x_warning (GdkDisplay *display)
6685 gtk_window_set_title (window, "Warning"); 6685 gtk_window_set_title (window, "Warning");
6686 gtk_window_set_screen (window, screen); 6686 gtk_window_set_screen (window, screen);
6687 6687
6688 label = gtk_label_new ("You are trying to run Emacs configured with" 6688 label = gtk_label_new ("You are trying to run Emacs configured with\n"
6689 " the \"pure-GTK\" interface under the X Window" 6689 " the \"pure-GTK\" interface under the X Window\n"
6690 " System. That configuration is unsupported and" 6690 " System. That configuration is unsupported and\n"
6691 " will lead to sporadic crashes during transfer of" 6691 " will lead to sporadic crashes during transfer of\n"
6692 " large selection data. It will also lead to" 6692 " large selection data. It will also lead to\n"
6693 " various problems with keyboard input."); 6693 " various problems with keyboard input.\n");
6694 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); 6694 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
6695 gtk_container_add (GTK_CONTAINER (content_area), label); 6695 gtk_container_add (GTK_CONTAINER (content_area), label);
6696 gtk_widget_show (label); 6696 gtk_widget_show (label);
diff --git a/src/pgtkterm.h b/src/pgtkterm.h
index 8f2f00efdad..069e425fd9c 100644
--- a/src/pgtkterm.h
+++ b/src/pgtkterm.h
@@ -42,7 +42,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
42 42
43struct pgtk_bitmap_record 43struct pgtk_bitmap_record
44{ 44{
45 void *img;
46 char *file; 45 char *file;
47 int refcount; 46 int refcount;
48 int height, width, depth; 47 int height, width, depth;