diff options
| author | Po Lu | 2023-08-01 10:34:33 +0800 |
|---|---|---|
| committer | Po Lu | 2023-08-01 10:34:33 +0800 |
| commit | 74d6604eaa2d770626309181ac4bc4f2598e63e7 (patch) | |
| tree | da81fdaabe8e41afa9b5518bdbee8ecdaa605a79 /src | |
| parent | bfb7c58ac5c322d6363e83f68afa88fc88ba2a0f (diff) | |
| download | emacs-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.c | 187 | ||||
| -rw-r--r-- | src/pgtkterm.c | 26 | ||||
| -rw-r--r-- | src/pgtkterm.h | 1 |
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 | |||
| 444 | static cairo_pattern_t * | 450 | static cairo_pattern_t * |
| 445 | image_create_pattern_from_pixbuf (struct frame *f, GdkPixbuf * pixbuf) | 451 | image_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 |
| 620 | static char *slurp_file (int, ptrdiff_t *); | 650 | static char *slurp_file (int, ptrdiff_t *); |
| 621 | static Lisp_Object image_find_image_fd (Lisp_Object, int *); | 651 | static Lisp_Object image_find_image_fd (Lisp_Object, int *); |
| 622 | static bool xbm_read_bitmap_data (struct frame *, char *, char *, | 652 | static 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 | |||
| 3152 | static bool | 3150 | static bool |
| 3153 | pgtk_bitmap_icon (struct frame *f, Lisp_Object file) | 3151 | pgtk_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 | ||
| 43 | struct pgtk_bitmap_record | 43 | struct 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; |