diff options
| author | Yuuki Harano | 2019-07-05 22:37:18 +0900 |
|---|---|---|
| committer | Jeff Walsh | 2020-11-22 14:46:55 +1100 |
| commit | 85441c96d74f82ca368b950aa0f5334297bf4fa0 (patch) | |
| tree | 0bdc7d96aa602594cb18ba364e7f12347d7c8a76 /src | |
| parent | 1d549fa0690d174446ff139bece6db5decd25eba (diff) | |
| download | emacs-85441c96d74f82ca368b950aa0f5334297bf4fa0.tar.gz emacs-85441c96d74f82ca368b950aa0f5334297bf4fa0.zip | |
Add Stipple support for PGTK
* ../src/pgtkterm.c (create_background_surface_by_face)
(create_background_surface, x_draw_glyph_string_background)
(x_draw_glyph_string_bg_rect, x_draw_image_glyph_string)
(x_draw_stretch_glyph_string, pgtk_draw_fringe_bitmap): handle stipple
* ../src/image.c (image_create_bitmap_from_file, )
(syms_of_image): Add pgtk support
* ../lisp/faces.el (face-valid-attribute-values): add pgtk support
stipple 対応。
stipple がまともに動いてなかったので修正。
Diffstat (limited to 'src')
| -rw-r--r-- | src/image.c | 8 | ||||
| -rw-r--r-- | src/pgtkterm.c | 199 |
2 files changed, 126 insertions, 81 deletions
diff --git a/src/image.c b/src/image.c index 9beb35c484b..0242b502581 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -507,12 +507,14 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) | |||
| 507 | #endif | 507 | #endif |
| 508 | 508 | ||
| 509 | #ifdef HAVE_PGTK | 509 | #ifdef HAVE_PGTK |
| 510 | GError *err; | 510 | GError *err = NULL; |
| 511 | ptrdiff_t id; | 511 | ptrdiff_t id; |
| 512 | void * bitmap = gdk_pixbuf_new_from_file(SSDATA(file), &err); | 512 | void * bitmap = gdk_pixbuf_new_from_file(SSDATA(file), &err); |
| 513 | 513 | ||
| 514 | if (!bitmap) | 514 | if (!bitmap) { |
| 515 | g_error_free(err); | ||
| 515 | return -1; | 516 | return -1; |
| 517 | } | ||
| 516 | 518 | ||
| 517 | id = image_allocate_bitmap_record(f); | 519 | id = image_allocate_bitmap_record(f); |
| 518 | 520 | ||
| @@ -10698,7 +10700,7 @@ non-numeric, there is no explicit limit on the size of images. */); | |||
| 10698 | DEFSYM (Qxbm, "xbm"); | 10700 | DEFSYM (Qxbm, "xbm"); |
| 10699 | add_image_type (Qxbm); | 10701 | add_image_type (Qxbm); |
| 10700 | 10702 | ||
| 10701 | #if defined (HAVE_XPM) || defined (HAVE_NS) | 10703 | #if defined (HAVE_XPM) || defined (HAVE_NS) || defined (USE_CAIRO) |
| 10702 | DEFSYM (Qxpm, "xpm"); | 10704 | DEFSYM (Qxpm, "xpm"); |
| 10703 | add_image_type (Qxpm); | 10705 | add_image_type (Qxpm); |
| 10704 | #endif | 10706 | #endif |
diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 3e3c73ce503..fb2520614f2 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c | |||
| @@ -984,6 +984,66 @@ x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h) | |||
| 984 | } | 984 | } |
| 985 | 985 | ||
| 986 | 986 | ||
| 987 | static cairo_surface_t * | ||
| 988 | create_background_surface_by_face (struct frame *f, struct face *face, int x, int y, int width, int height) | ||
| 989 | { | ||
| 990 | cairo_surface_t *surface = cairo_surface_create_similar (FRAME_CR_SURFACE (f), | ||
| 991 | CAIRO_CONTENT_COLOR, | ||
| 992 | width, | ||
| 993 | height); | ||
| 994 | |||
| 995 | { | ||
| 996 | cairo_t *cr = cairo_create (surface); | ||
| 997 | |||
| 998 | double r = ((face->background >> 16) & 0xff) / 255.0; | ||
| 999 | double g = ((face->background >> 8) & 0xff) / 255.0; | ||
| 1000 | double b = ((face->background >> 0) & 0xff) / 255.0; | ||
| 1001 | cairo_set_source_rgb (cr, r, g, b); | ||
| 1002 | cairo_paint (cr); | ||
| 1003 | |||
| 1004 | cairo_destroy (cr); | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | if (face->stipple != 0) { | ||
| 1008 | GdkPixbuf *pixbuf = FRAME_DISPLAY_INFO (f)->bitmaps[face->stipple - 1].img; | ||
| 1009 | GdkPixbuf *pb = gdk_pixbuf_add_alpha (pixbuf, TRUE, 255, 255, 255); | ||
| 1010 | cairo_surface_t *mask = cairo_surface_create_similar_image (FRAME_CR_SURFACE (f), | ||
| 1011 | CAIRO_FORMAT_A1, | ||
| 1012 | width, | ||
| 1013 | height); | ||
| 1014 | |||
| 1015 | { | ||
| 1016 | cairo_t *cr = cairo_create (mask); | ||
| 1017 | gdk_cairo_set_source_pixbuf (cr, pb, 0, 0); | ||
| 1018 | cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT); | ||
| 1019 | cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); | ||
| 1020 | cairo_paint (cr); | ||
| 1021 | cairo_destroy (cr); | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | { | ||
| 1025 | cairo_t *cr = cairo_create (surface); | ||
| 1026 | double r = ((face->foreground >> 16) & 0xff) / 255.0; | ||
| 1027 | double g = ((face->foreground >> 8) & 0xff) / 255.0; | ||
| 1028 | double b = ((face->foreground >> 0) & 0xff) / 255.0; | ||
| 1029 | cairo_set_source_rgb (cr, r, g, b); | ||
| 1030 | cairo_mask_surface (cr, mask, 0, 0); | ||
| 1031 | cairo_destroy (cr); | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | cairo_surface_destroy (mask); | ||
| 1035 | g_object_unref (pb); | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | return surface; | ||
| 1039 | } | ||
| 1040 | |||
| 1041 | static cairo_surface_t * | ||
| 1042 | create_background_surface (struct glyph_string *s, int x, int y, int width, int height) | ||
| 1043 | { | ||
| 1044 | return create_background_surface_by_face (s->f, s->face, x, y, width, height); | ||
| 1045 | } | ||
| 1046 | |||
| 987 | /* Draw the background of glyph_string S. If S->background_filled_p | 1047 | /* Draw the background of glyph_string S. If S->background_filled_p |
| 988 | is non-zero don't draw it. FORCE_P non-zero means draw the | 1048 | is non-zero don't draw it. FORCE_P non-zero means draw the |
| 989 | background even if it wouldn't be drawn normally. This is used | 1049 | background even if it wouldn't be drawn normally. This is used |
| @@ -1007,20 +1067,28 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p) | |||
| 1007 | PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", s->font_not_found_p); | 1067 | PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", s->font_not_found_p); |
| 1008 | PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", s->extends_to_end_of_line_p); | 1068 | PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", s->extends_to_end_of_line_p); |
| 1009 | PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", force_p); | 1069 | PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", force_p); |
| 1010 | #if 0 | 1070 | |
| 1011 | if (s->stippled_p) | 1071 | if (s->stippled_p) |
| 1012 | { | 1072 | { |
| 1013 | /* Fill background with a stipple pattern. */ | 1073 | /* Fill background with a stipple pattern. */ |
| 1014 | XSetFillStyle (s->display, s->gc, FillOpaqueStippled); | 1074 | |
| 1015 | x_fill_rectangle (s->f, s->gc, s->x, | 1075 | cairo_surface_t *bg = create_background_surface (s, |
| 1016 | s->y + box_line_width, | 1076 | s->x, s->y + box_line_width, |
| 1017 | s->background_width, | 1077 | s->background_width, s->height - 2 * box_line_width); |
| 1018 | s->height - 2 * box_line_width); | 1078 | |
| 1019 | XSetFillStyle (s->display, s->gc, FillSolid); | 1079 | cairo_t *cr = pgtk_begin_cr_clip (s->f); |
| 1080 | cairo_set_source_surface (cr, bg, s->x, s->y + box_line_width); | ||
| 1081 | cairo_rectangle (cr, | ||
| 1082 | s->x, s->y + box_line_width, | ||
| 1083 | s->background_width, s->height - 2 * box_line_width); | ||
| 1084 | cairo_fill (cr); | ||
| 1085 | pgtk_end_cr_clip (s->f); | ||
| 1086 | |||
| 1087 | cairo_surface_destroy (bg); | ||
| 1088 | |||
| 1020 | s->background_filled_p = true; | 1089 | s->background_filled_p = true; |
| 1021 | } | 1090 | } |
| 1022 | else | 1091 | else |
| 1023 | #endif | ||
| 1024 | if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width | 1092 | if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width |
| 1025 | /* When xdisp.c ignores FONT_HEIGHT, we cannot trust | 1093 | /* When xdisp.c ignores FONT_HEIGHT, we cannot trust |
| 1026 | font dimensions, since the actual glyphs might be | 1094 | font dimensions, since the actual glyphs might be |
| @@ -1821,16 +1889,21 @@ x_draw_image_relief (struct glyph_string *s) | |||
| 1821 | static void | 1889 | static void |
| 1822 | x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h) | 1890 | x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h) |
| 1823 | { | 1891 | { |
| 1824 | #if 0 | ||
| 1825 | if (s->stippled_p) | 1892 | if (s->stippled_p) |
| 1826 | { | 1893 | { |
| 1827 | /* Fill background with a stipple pattern. */ | 1894 | /* Fill background with a stipple pattern. */ |
| 1828 | XSetFillStyle (s->display, s->gc, FillOpaqueStippled); | 1895 | |
| 1829 | x_fill_rectangle (s->f, s->gc, x, y, w, h); | 1896 | cairo_surface_t *bg = create_background_surface (s, x, y, w, h); |
| 1830 | XSetFillStyle (s->display, s->gc, FillSolid); | 1897 | |
| 1898 | cairo_t *cr = pgtk_begin_cr_clip (s->f); | ||
| 1899 | cairo_set_source_surface (cr, bg, x, y); | ||
| 1900 | cairo_rectangle (cr, x, y, w, h); | ||
| 1901 | cairo_fill (cr); | ||
| 1902 | pgtk_end_cr_clip (s->f); | ||
| 1903 | |||
| 1904 | cairo_surface_destroy (bg); | ||
| 1831 | } | 1905 | } |
| 1832 | else | 1906 | else |
| 1833 | #endif | ||
| 1834 | x_clear_glyph_string_rect (s, x, y, w, h); | 1907 | x_clear_glyph_string_rect (s, x, y, w, h); |
| 1835 | } | 1908 | } |
| 1836 | 1909 | ||
| @@ -1881,7 +1954,6 @@ x_draw_image_glyph_string (struct glyph_string *s) | |||
| 1881 | int box_line_hwidth = eabs (s->face->box_line_width); | 1954 | int box_line_hwidth = eabs (s->face->box_line_width); |
| 1882 | int box_line_vwidth = max (s->face->box_line_width, 0); | 1955 | int box_line_vwidth = max (s->face->box_line_width, 0); |
| 1883 | int height; | 1956 | int height; |
| 1884 | cairo_surface_t *surface = NULL; | ||
| 1885 | 1957 | ||
| 1886 | height = s->height; | 1958 | height = s->height; |
| 1887 | if (s->slice.y == 0) | 1959 | if (s->slice.y == 0) |
| @@ -1903,43 +1975,15 @@ x_draw_image_glyph_string (struct glyph_string *s) | |||
| 1903 | { | 1975 | { |
| 1904 | if (s->img->mask) | 1976 | if (s->img->mask) |
| 1905 | { | 1977 | { |
| 1906 | /* Create a pixmap as large as the glyph string. Fill it | 1978 | cairo_surface_t *bg = create_background_surface (s, s->x, s->y, s->background_width, s->height); |
| 1907 | with the background color. Copy the image to it, using | ||
| 1908 | its mask. Copy the temporary pixmap to the display. */ | ||
| 1909 | |||
| 1910 | /* Create a pixmap as large as the glyph string. */ | ||
| 1911 | surface = cairo_surface_create_similar(FRAME_CR_SURFACE(s->f), CAIRO_CONTENT_COLOR_ALPHA, | ||
| 1912 | s->background_width, | ||
| 1913 | s->height); | ||
| 1914 | 1979 | ||
| 1915 | /* Don't clip in the following because we're working on the | 1980 | cairo_t *cr = pgtk_begin_cr_clip (s->f); |
| 1916 | pixmap. */ | 1981 | cairo_set_source_surface (cr, bg, s->x, s->y); |
| 1917 | // XSetClipMask (s->display, s->gc, None); | 1982 | cairo_rectangle (cr, s->x, s->y, s->background_width, s->height); |
| 1983 | cairo_fill (cr); | ||
| 1984 | pgtk_end_cr_clip (s->f); | ||
| 1918 | 1985 | ||
| 1919 | /* Fill the pixmap with the background color/stipple. */ | 1986 | cairo_surface_destroy (bg); |
| 1920 | #if 0 | ||
| 1921 | if (s->stippled_p) | ||
| 1922 | { | ||
| 1923 | /* Fill background with a stipple pattern. */ | ||
| 1924 | XSetFillStyle (s->display, s->gc, FillOpaqueStippled); | ||
| 1925 | XSetTSOrigin (s->display, s->gc, - s->x, - s->y); | ||
| 1926 | XFillRectangle (s->display, pixmap, s->gc, | ||
| 1927 | 0, 0, s->background_width, s->height); | ||
| 1928 | XSetFillStyle (s->display, s->gc, FillSolid); | ||
| 1929 | XSetTSOrigin (s->display, s->gc, 0, 0); | ||
| 1930 | } | ||
| 1931 | else | ||
| 1932 | #endif | ||
| 1933 | { | ||
| 1934 | cairo_t *cr = cairo_create(surface); | ||
| 1935 | int red = (s->xgcv.background >> 16) & 0xff; | ||
| 1936 | int green = (s->xgcv.background >> 8) & 0xff; | ||
| 1937 | int blue = (s->xgcv.background >> 0) & 0xff; | ||
| 1938 | cairo_set_source_rgb (cr, red / 255.0, green / 255.0, blue / 255.0); | ||
| 1939 | cairo_rectangle(cr, 0, 0, s->background_width, s->height); | ||
| 1940 | cairo_fill(cr); | ||
| 1941 | cairo_destroy(cr); | ||
| 1942 | } | ||
| 1943 | } | 1987 | } |
| 1944 | else | 1988 | else |
| 1945 | { | 1989 | { |
| @@ -1957,7 +2001,15 @@ x_draw_image_glyph_string (struct glyph_string *s) | |||
| 1957 | if (s->slice.y == 0) | 2001 | if (s->slice.y == 0) |
| 1958 | y += box_line_vwidth; | 2002 | y += box_line_vwidth; |
| 1959 | 2003 | ||
| 1960 | x_draw_glyph_string_bg_rect (s, x, y, width, height); | 2004 | cairo_surface_t *bg = create_background_surface (s, x, y, width, height); |
| 2005 | |||
| 2006 | cairo_t *cr = pgtk_begin_cr_clip (s->f); | ||
| 2007 | cairo_set_source_surface (cr, bg, x, y); | ||
| 2008 | cairo_rectangle (cr, x, y, width, height); | ||
| 2009 | cairo_fill (cr); | ||
| 2010 | pgtk_end_cr_clip (s->f); | ||
| 2011 | |||
| 2012 | cairo_surface_destroy (bg); | ||
| 1961 | } | 2013 | } |
| 1962 | 2014 | ||
| 1963 | s->background_filled_p = true; | 2015 | s->background_filled_p = true; |
| @@ -1979,18 +2031,6 @@ x_draw_image_glyph_string (struct glyph_string *s) | |||
| 1979 | pgtk_end_cr_clip (s->f); | 2031 | pgtk_end_cr_clip (s->f); |
| 1980 | } | 2032 | } |
| 1981 | else | 2033 | else |
| 1982 | if (surface != NULL) | ||
| 1983 | { | ||
| 1984 | cairo_t *cr = pgtk_begin_cr_clip(s->f); | ||
| 1985 | |||
| 1986 | x_draw_image_foreground_1 (s, surface); | ||
| 1987 | x_set_glyph_string_clipping (s, cr); | ||
| 1988 | |||
| 1989 | cairo_set_source_surface(cr, surface, 0, 0); | ||
| 1990 | cairo_rectangle(cr, s->x, s->y, s->background_width, s->height); | ||
| 1991 | pgtk_end_cr_clip(s->f); | ||
| 1992 | } | ||
| 1993 | else | ||
| 1994 | x_draw_image_foreground (s); | 2034 | x_draw_image_foreground (s); |
| 1995 | 2035 | ||
| 1996 | /* If we must draw a relief around the image, do it. */ | 2036 | /* If we must draw a relief around the image, do it. */ |
| @@ -1998,9 +2038,6 @@ x_draw_image_glyph_string (struct glyph_string *s) | |||
| 1998 | || s->hl == DRAW_IMAGE_RAISED | 2038 | || s->hl == DRAW_IMAGE_RAISED |
| 1999 | || s->hl == DRAW_IMAGE_SUNKEN) | 2039 | || s->hl == DRAW_IMAGE_SUNKEN) |
| 2000 | x_draw_image_relief (s); | 2040 | x_draw_image_relief (s); |
| 2001 | |||
| 2002 | if (surface != NULL) | ||
| 2003 | cairo_surface_destroy(surface); | ||
| 2004 | } | 2041 | } |
| 2005 | 2042 | ||
| 2006 | /* Draw stretch glyph string S. */ | 2043 | /* Draw stretch glyph string S. */ |
| @@ -2071,16 +2108,18 @@ x_draw_stretch_glyph_string (struct glyph_string *s) | |||
| 2071 | get_glyph_string_clip_rect (s, &r); | 2108 | get_glyph_string_clip_rect (s, &r); |
| 2072 | x_set_clip_rectangles (s->f, cr, &r, 1); | 2109 | x_set_clip_rectangles (s->f, cr, &r, 1); |
| 2073 | 2110 | ||
| 2074 | #if 0 | ||
| 2075 | if (s->face->stipple) | 2111 | if (s->face->stipple) |
| 2076 | { | 2112 | { |
| 2077 | /* Fill background with a stipple pattern. */ | 2113 | /* Fill background with a stipple pattern. */ |
| 2078 | XSetFillStyle (s->display, gc, FillOpaqueStippled); | 2114 | cairo_surface_t *bg = create_background_surface (s, x, y, w, h); |
| 2079 | x_fill_rectangle (s->f, gc, x, y, w, h); | 2115 | cairo_t *cr = pgtk_begin_cr_clip (s->f); |
| 2080 | XSetFillStyle (s->display, gc, FillSolid); | 2116 | cairo_set_source_surface (cr, bg, x, y); |
| 2117 | cairo_rectangle (cr, x, y, w, h); | ||
| 2118 | cairo_fill (cr); | ||
| 2119 | pgtk_end_cr_clip (s->f); | ||
| 2120 | cairo_surface_destroy (bg); | ||
| 2081 | } | 2121 | } |
| 2082 | else | 2122 | else |
| 2083 | #endif | ||
| 2084 | { | 2123 | { |
| 2085 | pgtk_fill_rectangle(s->f, color, x, y, w, h); | 2124 | pgtk_fill_rectangle(s->f, color, x, y, w, h); |
| 2086 | } | 2125 | } |
| @@ -3195,15 +3234,19 @@ pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fr | |||
| 3195 | for something displayed in the text (e.g. face `region' on | 3234 | for something displayed in the text (e.g. face `region' on |
| 3196 | mono-displays, the fill style may have been changed to | 3235 | mono-displays, the fill style may have been changed to |
| 3197 | FillSolid in x_draw_glyph_string_background. */ | 3236 | FillSolid in x_draw_glyph_string_background. */ |
| 3198 | #if 0 | 3237 | if (face->stipple) { |
| 3199 | if (face->stipple) | 3238 | cairo_surface_t *bg = create_background_surface_by_face(f, face, p->bx, p->by, p->nx, p->ny); |
| 3200 | XSetFillStyle (display, face->gc, FillOpaqueStippled); | 3239 | cairo_t *cr = pgtk_begin_cr_clip (f); |
| 3201 | else | 3240 | cairo_set_source_surface (cr, bg, p->bx, p->by); |
| 3202 | #endif | 3241 | cairo_rectangle (cr, p->bx, p->by, p->nx, p->ny); |
| 3242 | cairo_fill (cr); | ||
| 3243 | pgtk_end_cr_clip (f); | ||
| 3244 | cairo_surface_destroy (bg); | ||
| 3245 | } else { | ||
| 3203 | pgtk_set_cr_source_with_color(f, face->background); | 3246 | pgtk_set_cr_source_with_color(f, face->background); |
| 3204 | 3247 | cairo_rectangle(cr, p->bx, p->by, p->nx, p->ny); | |
| 3205 | cairo_rectangle(cr, p->bx, p->by, p->nx, p->ny); | 3248 | cairo_fill(cr); |
| 3206 | cairo_fill(cr); | 3249 | } |
| 3207 | } | 3250 | } |
| 3208 | 3251 | ||
| 3209 | PGTK_TRACE("which: %d, max_fringe_bmp: %d.", p->which, max_fringe_bmp); | 3252 | PGTK_TRACE("which: %d, max_fringe_bmp: %d.", p->which, max_fringe_bmp); |