diff options
| author | YAMAMOTO Mitsuharu | 2019-06-08 13:05:15 +0900 |
|---|---|---|
| committer | YAMAMOTO Mitsuharu | 2019-06-08 13:05:15 +0900 |
| commit | 88c49ac31898e7b2c29338ca55cae292c450f7be (patch) | |
| tree | 6130d1732acceaf2eef70327acb724c14171934d /src/image.c | |
| parent | 890a0826f3f68f4476f6ec0b56fe96c6bc047142 (diff) | |
| download | emacs-88c49ac31898e7b2c29338ca55cae292c450f7be.tar.gz emacs-88c49ac31898e7b2c29338ca55cae292c450f7be.zip | |
Implement native image rotation and cropping on cairo
* src/dispextern.h (struct image) [USE_CAIRO]:
* src/image.c (free_image, image_clear_image_1)
(image_set_crop, image_set_size, image_set_rotation)
(image_create_x_image_and_pixmap) [USE_CAIRO]: #ifdef out HAVE_XRENDER part.
* src/image.c (cr_create_surface_from_pix_containers) [USE_CAIRO]: Rename
from cr_create_surface_from_pix_containers. Change arguments to pair of
Emacs_Pix_Container:s. Move block_input and unblock_input to caller.
(cr_put_image_to_cr_data) [USE_CAIRO]: New function.
(prepare_image_for_display) [USE_CAIRO]: Use it.
(image_set_transform) [USE_CAIRO]: Create dummy solid color pattern equipped
with transformation matrix and set it to img->cr_data.
* src/xterm.c (fringe_bmp) [USE_CAIRO]: Change type to cairo_pattern_t **.
(x_cr_define_fringe_bitmap, x_cr_destroy_fringe_bitmap) [USE_CAIRO]: Create
or destroy cairo pattern.
(x_cr_draw_image) [USE_CAIRO]: Remove arguments image_width and image_height.
Change type of image to cairo pattern. All callers changed.
* src/gtkutil.c (xg_get_image_for_pixmap) [USE_CAIRO]: Get cairo surface
from img->cr_data, which is of cairo pattern now.
Diffstat (limited to 'src/image.c')
| -rw-r--r-- | src/image.c | 74 |
1 files changed, 53 insertions, 21 deletions
diff --git a/src/image.c b/src/image.c index 30f4f4b0bc5..86f8e8f4bb7 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -207,12 +207,12 @@ image_pix_container_create_from_bitmap_data (struct frame *f, | |||
| 207 | } | 207 | } |
| 208 | 208 | ||
| 209 | static cairo_surface_t * | 209 | static cairo_surface_t * |
| 210 | cr_create_cr_surface_from_image (struct frame *f, struct image *img) | 210 | cr_create_surface_from_pix_containers (Emacs_Pix_Container pimg, |
| 211 | Emacs_Pix_Container mask) | ||
| 211 | { | 212 | { |
| 212 | Emacs_Pix_Container pimg = img->pixmap; | ||
| 213 | cairo_surface_t *surface; | 213 | cairo_surface_t *surface; |
| 214 | 214 | ||
| 215 | if (img->mask) | 215 | if (mask) |
| 216 | { | 216 | { |
| 217 | int x, y; | 217 | int x, y; |
| 218 | 218 | ||
| @@ -223,30 +223,49 @@ cr_create_cr_surface_from_image (struct frame *f, struct image *img) | |||
| 223 | int r, g, b; | 223 | int r, g, b; |
| 224 | 224 | ||
| 225 | color = GET_PIXEL (pimg, x, y); | 225 | color = GET_PIXEL (pimg, x, y); |
| 226 | alpha = GET_PIXEL (img->mask, x, y); | 226 | alpha = GET_PIXEL (mask, x, y); |
| 227 | r = (RED_FROM_ULONG (color) * alpha + 0x7f) / 0xff; | 227 | r = (RED_FROM_ULONG (color) * alpha + 0x7f) / 0xff; |
| 228 | g = (GREEN_FROM_ULONG (color) * alpha + 0x7f) / 0xff; | 228 | g = (GREEN_FROM_ULONG (color) * alpha + 0x7f) / 0xff; |
| 229 | b = (BLUE_FROM_ULONG (color) * alpha + 0x7f) / 0xff; | 229 | b = (BLUE_FROM_ULONG (color) * alpha + 0x7f) / 0xff; |
| 230 | PUT_PIXEL (pimg, x, y, ARGB_TO_ULONG (alpha, r, g, b)); | 230 | PUT_PIXEL (pimg, x, y, ARGB_TO_ULONG (alpha, r, g, b)); |
| 231 | } | 231 | } |
| 232 | xfree (img->mask->data); | 232 | xfree (mask->data); |
| 233 | img->mask->data = NULL; | 233 | mask->data = NULL; |
| 234 | } | 234 | } |
| 235 | block_input (); | ||
| 236 | surface = cairo_image_surface_create_for_data ((unsigned char *) pimg->data, | 235 | surface = cairo_image_surface_create_for_data ((unsigned char *) pimg->data, |
| 237 | (img->mask | 236 | (mask ? CAIRO_FORMAT_ARGB32 |
| 238 | ? CAIRO_FORMAT_ARGB32 | ||
| 239 | : CAIRO_FORMAT_RGB24), | 237 | : CAIRO_FORMAT_RGB24), |
| 240 | pimg->width, pimg->height, | 238 | pimg->width, pimg->height, |
| 241 | pimg->bytes_per_line); | 239 | pimg->bytes_per_line); |
| 242 | static const cairo_user_data_key_t key; | 240 | static const cairo_user_data_key_t key; |
| 243 | cairo_surface_set_user_data (surface, &key, pimg->data, xfree); | 241 | cairo_surface_set_user_data (surface, &key, pimg->data, xfree); |
| 244 | unblock_input (); | ||
| 245 | pimg->data = NULL; | 242 | pimg->data = NULL; |
| 246 | 243 | ||
| 247 | return surface; | 244 | return surface; |
| 248 | } | 245 | } |
| 249 | 246 | ||
| 247 | static void | ||
| 248 | cr_put_image_to_cr_data (struct image *img) | ||
| 249 | { | ||
| 250 | cairo_pattern_t *pattern = NULL; | ||
| 251 | cairo_surface_t *surface = cr_create_surface_from_pix_containers (img->pixmap, | ||
| 252 | img->mask); | ||
| 253 | if (surface) | ||
| 254 | { | ||
| 255 | pattern = cairo_pattern_create_for_surface (surface); | ||
| 256 | if (img->cr_data) | ||
| 257 | { | ||
| 258 | cairo_matrix_t matrix; | ||
| 259 | cairo_pattern_get_matrix (img->cr_data, &matrix); | ||
| 260 | cairo_pattern_set_matrix (pattern, &matrix); | ||
| 261 | cairo_pattern_destroy (img->cr_data); | ||
| 262 | } | ||
| 263 | cairo_surface_destroy (surface); | ||
| 264 | } | ||
| 265 | |||
| 266 | img->cr_data = pattern; | ||
| 267 | } | ||
| 268 | |||
| 250 | #endif /* USE_CAIRO */ | 269 | #endif /* USE_CAIRO */ |
| 251 | 270 | ||
| 252 | #ifdef HAVE_NS | 271 | #ifdef HAVE_NS |
| @@ -1150,7 +1169,7 @@ free_image (struct frame *f, struct image *img) | |||
| 1150 | 1169 | ||
| 1151 | c->images[img->id] = NULL; | 1170 | c->images[img->id] = NULL; |
| 1152 | 1171 | ||
| 1153 | #ifdef HAVE_XRENDER | 1172 | #if !defined USE_CAIRO && defined HAVE_XRENDER |
| 1154 | if (img->picture) | 1173 | if (img->picture) |
| 1155 | XRenderFreePicture (FRAME_X_DISPLAY (f), img->picture); | 1174 | XRenderFreePicture (FRAME_X_DISPLAY (f), img->picture); |
| 1156 | if (img->mask_picture) | 1175 | if (img->mask_picture) |
| @@ -1212,14 +1231,20 @@ prepare_image_for_display (struct frame *f, struct image *img) | |||
| 1212 | img->load_failed_p = ! img->type->load (f, img); | 1231 | img->load_failed_p = ! img->type->load (f, img); |
| 1213 | 1232 | ||
| 1214 | #ifdef USE_CAIRO | 1233 | #ifdef USE_CAIRO |
| 1215 | if (!img->load_failed_p && img->cr_data == NULL) | 1234 | if (!img->load_failed_p) |
| 1216 | { | 1235 | { |
| 1217 | img->cr_data = cr_create_cr_surface_from_image (f, img); | 1236 | block_input (); |
| 1218 | if (img->cr_data == NULL) | 1237 | if (img->cr_data == NULL || (cairo_pattern_get_type (img->cr_data) |
| 1238 | != CAIRO_PATTERN_TYPE_SURFACE)) | ||
| 1219 | { | 1239 | { |
| 1220 | img->load_failed_p = 1; | 1240 | cr_put_image_to_cr_data (img); |
| 1221 | img->type->free (f, img); | 1241 | if (img->cr_data == NULL) |
| 1242 | { | ||
| 1243 | img->load_failed_p = 1; | ||
| 1244 | img->type->free (f, img); | ||
| 1245 | } | ||
| 1222 | } | 1246 | } |
| 1247 | unblock_input (); | ||
| 1223 | } | 1248 | } |
| 1224 | #elif defined HAVE_X_WINDOWS | 1249 | #elif defined HAVE_X_WINDOWS |
| 1225 | if (!img->load_failed_p) | 1250 | if (!img->load_failed_p) |
| @@ -1470,7 +1495,7 @@ image_clear_image_1 (struct frame *f, struct image *img, int flags) | |||
| 1470 | #ifdef USE_CAIRO | 1495 | #ifdef USE_CAIRO |
| 1471 | if (img->cr_data) | 1496 | if (img->cr_data) |
| 1472 | { | 1497 | { |
| 1473 | cairo_surface_destroy ((cairo_surface_t *) img->cr_data); | 1498 | cairo_pattern_destroy (img->cr_data); |
| 1474 | img->cr_data = NULL; | 1499 | img->cr_data = NULL; |
| 1475 | } | 1500 | } |
| 1476 | #endif /* USE_CAIRO */ | 1501 | #endif /* USE_CAIRO */ |
| @@ -1973,7 +1998,7 @@ image_set_rotation (struct image *img, matrix3x3 tm) | |||
| 1973 | return; | 1998 | return; |
| 1974 | # endif | 1999 | # endif |
| 1975 | 2000 | ||
| 1976 | # ifdef HAVE_XRENDER | 2001 | # if !defined USE_CAIRO && defined HAVE_XRENDER |
| 1977 | if (!img->picture) | 2002 | if (!img->picture) |
| 1978 | return; | 2003 | return; |
| 1979 | # endif | 2004 | # endif |
| @@ -2064,7 +2089,7 @@ image_set_crop (struct image *img, matrix3x3 tm) | |||
| 2064 | return; | 2089 | return; |
| 2065 | # endif | 2090 | # endif |
| 2066 | 2091 | ||
| 2067 | # ifdef HAVE_XRENDER | 2092 | # if !defined USE_CAIRO && defined HAVE_XRENDER |
| 2068 | if (!img->picture) | 2093 | if (!img->picture) |
| 2069 | return; | 2094 | return; |
| 2070 | # endif | 2095 | # endif |
| @@ -2156,7 +2181,7 @@ image_set_size (struct image *img, matrix3x3 tm) | |||
| 2156 | return; | 2181 | return; |
| 2157 | # endif | 2182 | # endif |
| 2158 | 2183 | ||
| 2159 | # ifdef HAVE_XRENDER | 2184 | # if !defined USE_CAIRO && defined HAVE_XRENDER |
| 2160 | if (!img->picture) | 2185 | if (!img->picture) |
| 2161 | return; | 2186 | return; |
| 2162 | # endif | 2187 | # endif |
| @@ -2186,6 +2211,13 @@ image_set_transform (struct frame *f, struct image *img, matrix3x3 matrix) | |||
| 2186 | /* Under NS the transform is applied to the drawing surface at | 2211 | /* Under NS the transform is applied to the drawing surface at |
| 2187 | drawing time, so store it for later. */ | 2212 | drawing time, so store it for later. */ |
| 2188 | ns_image_set_transform (img->pixmap, matrix); | 2213 | ns_image_set_transform (img->pixmap, matrix); |
| 2214 | # elif defined USE_CAIRO | ||
| 2215 | cairo_matrix_t cr_matrix = {matrix[0][0], matrix[0][1], matrix[1][0], | ||
| 2216 | matrix[1][1], matrix[2][0], matrix[2][1]}; | ||
| 2217 | cairo_pattern_t *pattern = cairo_pattern_create_rgb (0, 0, 0); | ||
| 2218 | cairo_pattern_set_matrix (pattern, &cr_matrix); | ||
| 2219 | /* Dummy solid color pattern just to record pattern matrix. */ | ||
| 2220 | img->cr_data = pattern; | ||
| 2189 | # elif defined (HAVE_XRENDER) | 2221 | # elif defined (HAVE_XRENDER) |
| 2190 | if (img->picture) | 2222 | if (img->picture) |
| 2191 | { | 2223 | { |
| @@ -2745,7 +2777,7 @@ image_create_x_image_and_pixmap (struct frame *f, struct image *img, | |||
| 2745 | eassert ((!mask_p ? img->pixmap : img->mask) == NO_PIXMAP); | 2777 | eassert ((!mask_p ? img->pixmap : img->mask) == NO_PIXMAP); |
| 2746 | 2778 | ||
| 2747 | Picture *picture = NULL; | 2779 | Picture *picture = NULL; |
| 2748 | #ifdef HAVE_XRENDER | 2780 | #if !defined USE_CAIRO && defined HAVE_XRENDER |
| 2749 | picture = !mask_p ? &img->picture : &img->mask_picture; | 2781 | picture = !mask_p ? &img->picture : &img->mask_picture; |
| 2750 | #endif | 2782 | #endif |
| 2751 | return image_create_x_image_and_pixmap_1 (f, width, height, depth, ximg, | 2783 | return image_create_x_image_and_pixmap_1 (f, width, height, depth, ximg, |