aboutsummaryrefslogtreecommitdiffstats
path: root/src/image.c
diff options
context:
space:
mode:
authorJuan José García-Ripoll2020-04-13 12:04:39 +0200
committerEli Zaretskii2020-04-14 09:52:55 +0300
commitdf254a7445a86dc25d133f2d79be8096190a8b96 (patch)
treec6094f663793c61f4243483c0c6d310205005a83 /src/image.c
parent7a9fb5d55c9bf612a38348d59e769ee915175e28 (diff)
downloademacs-df254a7445a86dc25d133f2d79be8096190a8b96.tar.gz
emacs-df254a7445a86dc25d133f2d79be8096190a8b96.zip
Initial version of native image API support for MS-Windows
* src/w32image.c: New file. * src/w32term.h: Add prototypes of 'w32_load_image', 'w32_gdiplus_startup', 'w32_gdiplus_shutdown', and 'w32_query_frame_background_color'. * src/w32term.c (w32_query_frame_background_color): No longer static. * src/w32.c (term_ntproc) [HAVE_GDIPLUS]: Call 'w32_gdiplus_shutdown'. * src/image.c (struct image_type) <valid_p>: Accept an additional argument, the image type. All implementations changed. (init_native_image_functions, native_image_p, native_image_load) [HAVE_NATIVE_IMAGE_API]: New methods for "native image type". (initialize_image_type) [HAVE_NATIVE_IMAGE_API]: Call 'init_native_image_functions'. (image_types) [HAVE_NATIVE_IMAGE_API]: Add settings for native image API. (lookup_image_type) [HAVE_NATIVE_IMAGE_API]: Initialize native functions if needed. * lisp/term/w32-win.el (dynamic-library-alist): Add gdiplus and shlwapi. * etc/NEWS: Announce the new feature. * configure.ac (native-image-api): New option, OFF by default. (HAVE_NATIVE_IMAGE_API): If native-image-api is selected, add w32image.o to W32_OBJ.
Diffstat (limited to 'src/image.c')
-rw-r--r--src/image.c163
1 files changed, 131 insertions, 32 deletions
diff --git a/src/image.c b/src/image.c
index c98ca291ca5..ff2d12fa1a1 100644
--- a/src/image.c
+++ b/src/image.c
@@ -751,7 +751,7 @@ struct image_type
751 751
752 /* Check that SPEC is a valid image specification for the given 752 /* Check that SPEC is a valid image specification for the given
753 image type. Value is true if SPEC is valid. */ 753 image type. Value is true if SPEC is valid. */
754 bool (*valid_p) (Lisp_Object spec); 754 bool (*valid_p) (Lisp_Object spec, Lisp_Object type);
755 755
756 /* Load IMG which is used on frame F from information contained in 756 /* Load IMG which is used on frame F from information contained in
757 IMG->spec. Value is true if successful. */ 757 IMG->spec. Value is true if successful. */
@@ -807,7 +807,7 @@ valid_image_p (Lisp_Object object)
807 { 807 {
808 struct image_type const *type = lookup_image_type (XCAR (tail)); 808 struct image_type const *type = lookup_image_type (XCAR (tail));
809 if (type) 809 if (type)
810 return type->valid_p (object); 810 return type->valid_p (object, builtin_lisp_symbol (type->type));
811 } 811 }
812 break; 812 break;
813 } 813 }
@@ -3144,12 +3144,12 @@ enum xbm_token
3144 displayed is used. */ 3144 displayed is used. */
3145 3145
3146static bool 3146static bool
3147xbm_image_p (Lisp_Object object) 3147xbm_image_p (Lisp_Object object, Lisp_Object type)
3148{ 3148{
3149 struct image_keyword kw[XBM_LAST]; 3149 struct image_keyword kw[XBM_LAST];
3150 3150
3151 memcpy (kw, xbm_format, sizeof kw); 3151 memcpy (kw, xbm_format, sizeof kw);
3152 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm)) 3152 if (!parse_image_spec (object, kw, XBM_LAST, type))
3153 return 0; 3153 return 0;
3154 3154
3155 eassert (EQ (kw[XBM_TYPE].value, Qxbm)); 3155 eassert (EQ (kw[XBM_TYPE].value, Qxbm));
@@ -3697,7 +3697,7 @@ xbm_load (struct frame *f, struct image *img)
3697 bool success_p = 0; 3697 bool success_p = 0;
3698 Lisp_Object file_name; 3698 Lisp_Object file_name;
3699 3699
3700 eassert (xbm_image_p (img->spec)); 3700 eassert (xbm_image_p (img->spec, Qxbm));
3701 3701
3702 /* If IMG->spec specifies a file name, create a non-file spec from it. */ 3702 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3703 file_name = image_spec_value (img->spec, QCfile, NULL); 3703 file_name = image_spec_value (img->spec, QCfile, NULL);
@@ -4155,11 +4155,11 @@ xpm_valid_color_symbols_p (Lisp_Object color_symbols)
4155/* Value is true if OBJECT is a valid XPM image specification. */ 4155/* Value is true if OBJECT is a valid XPM image specification. */
4156 4156
4157static bool 4157static bool
4158xpm_image_p (Lisp_Object object) 4158xpm_image_p (Lisp_Object object, Lisp_Object type)
4159{ 4159{
4160 struct image_keyword fmt[XPM_LAST]; 4160 struct image_keyword fmt[XPM_LAST];
4161 memcpy (fmt, xpm_format, sizeof fmt); 4161 memcpy (fmt, xpm_format, sizeof fmt);
4162 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm) 4162 return (parse_image_spec (object, fmt, XPM_LAST, type)
4163 /* Either `:file' or `:data' must be present. */ 4163 /* Either `:file' or `:data' must be present. */
4164 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1 4164 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
4165 /* Either no `:color-symbols' or it's a list of conses 4165 /* Either no `:color-symbols' or it's a list of conses
@@ -5883,13 +5883,13 @@ static const struct image_keyword pbm_format[PBM_LAST] =
5883/* Return true if OBJECT is a valid PBM image specification. */ 5883/* Return true if OBJECT is a valid PBM image specification. */
5884 5884
5885static bool 5885static bool
5886pbm_image_p (Lisp_Object object) 5886pbm_image_p (Lisp_Object object, Lisp_Object type)
5887{ 5887{
5888 struct image_keyword fmt[PBM_LAST]; 5888 struct image_keyword fmt[PBM_LAST];
5889 5889
5890 memcpy (fmt, pbm_format, sizeof fmt); 5890 memcpy (fmt, pbm_format, sizeof fmt);
5891 5891
5892 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm)) 5892 if (!parse_image_spec (object, fmt, PBM_LAST, type))
5893 return 0; 5893 return 0;
5894 5894
5895 /* Must specify either :data or :file. */ 5895 /* Must specify either :data or :file. */
@@ -6233,6 +6233,83 @@ pbm_load (struct frame *f, struct image *img)
6233 6233
6234 6234
6235/*********************************************************************** 6235/***********************************************************************
6236 NATIVE IMAGE HANDLING
6237 ***********************************************************************/
6238#if defined(HAVE_NATIVE_IMAGE_API) && defined(HAVE_NTGUI)
6239/*
6240 * These functions are actually defined in the OS-native implementation
6241 * file. Currently, for Windows GDI+ interface, w32image.c, but other
6242 * operating systems can follow suit.
6243 */
6244
6245static bool
6246init_native_image_functions (void)
6247{
6248 return w32_gdiplus_startup ();
6249}
6250
6251/* Indices of image specification fields in native format, below. */
6252
6253enum native_image_keyword_index
6254{
6255 NATIVE_IMAGE_TYPE,
6256 NATIVE_IMAGE_DATA,
6257 NATIVE_IMAGE_FILE,
6258 NATIVE_IMAGE_ASCENT,
6259 NATIVE_IMAGE_MARGIN,
6260 NATIVE_IMAGE_RELIEF,
6261 NATIVE_IMAGE_ALGORITHM,
6262 NATIVE_IMAGE_HEURISTIC_MASK,
6263 NATIVE_IMAGE_MASK,
6264 NATIVE_IMAGE_BACKGROUND,
6265 NATIVE_IMAGE_INDEX,
6266 NATIVE_IMAGE_LAST
6267};
6268
6269/* Vector of image_keyword structures describing the format
6270 of valid user-defined image specifications. */
6271
6272static const struct image_keyword native_image_format[] =
6273{
6274 {":type", IMAGE_SYMBOL_VALUE, 1},
6275 {":data", IMAGE_STRING_VALUE, 0},
6276 {":file", IMAGE_STRING_VALUE, 0},
6277 {":ascent", IMAGE_ASCENT_VALUE, 0},
6278 {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
6279 {":relief", IMAGE_INTEGER_VALUE, 0},
6280 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6281 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6282 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6283 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
6284 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
6285};
6286
6287/* Return true if OBJECT is a valid native API image specification. */
6288
6289static bool
6290native_image_p (Lisp_Object object, Lisp_Object type)
6291{
6292 struct image_keyword fmt[NATIVE_IMAGE_LAST];
6293 memcpy (fmt, native_image_format, sizeof fmt);
6294
6295 if (!parse_image_spec (object, fmt, 10, type))
6296 return 0;
6297
6298 /* Must specify either the :data or :file keyword. */
6299 return fmt[NATIVE_IMAGE_FILE].count + fmt[NATIVE_IMAGE_DATA].count == 1;
6300}
6301
6302static bool
6303native_image_load (struct frame *f, struct image *img)
6304{
6305 return w32_load_image (f, img,
6306 image_spec_value (img->spec, QCfile, NULL),
6307 image_spec_value (img->spec, QCdata, NULL));
6308}
6309#endif
6310
6311
6312/***********************************************************************
6236 PNG 6313 PNG
6237 ***********************************************************************/ 6314 ***********************************************************************/
6238 6315
@@ -6275,12 +6352,12 @@ static const struct image_keyword png_format[PNG_LAST] =
6275/* Return true if OBJECT is a valid PNG image specification. */ 6352/* Return true if OBJECT is a valid PNG image specification. */
6276 6353
6277static bool 6354static bool
6278png_image_p (Lisp_Object object) 6355png_image_p (Lisp_Object object, Lisp_Object type)
6279{ 6356{
6280 struct image_keyword fmt[PNG_LAST]; 6357 struct image_keyword fmt[PNG_LAST];
6281 memcpy (fmt, png_format, sizeof fmt); 6358 memcpy (fmt, png_format, sizeof fmt);
6282 6359
6283 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng)) 6360 if (!parse_image_spec (object, fmt, PNG_LAST, type))
6284 return 0; 6361 return 0;
6285 6362
6286 /* Must specify either the :data or :file keyword. */ 6363 /* Must specify either the :data or :file keyword. */
@@ -6890,7 +6967,6 @@ png_load (struct frame *f, struct image *img)
6890 image_spec_value (img->spec, QCdata, NULL)); 6967 image_spec_value (img->spec, QCdata, NULL));
6891} 6968}
6892 6969
6893
6894#endif /* HAVE_NS */ 6970#endif /* HAVE_NS */
6895 6971
6896 6972
@@ -6938,13 +7014,13 @@ static const struct image_keyword jpeg_format[JPEG_LAST] =
6938/* Return true if OBJECT is a valid JPEG image specification. */ 7014/* Return true if OBJECT is a valid JPEG image specification. */
6939 7015
6940static bool 7016static bool
6941jpeg_image_p (Lisp_Object object) 7017jpeg_image_p (Lisp_Object object, Lisp_Object type)
6942{ 7018{
6943 struct image_keyword fmt[JPEG_LAST]; 7019 struct image_keyword fmt[JPEG_LAST];
6944 7020
6945 memcpy (fmt, jpeg_format, sizeof fmt); 7021 memcpy (fmt, jpeg_format, sizeof fmt);
6946 7022
6947 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)) 7023 if (!parse_image_spec (object, fmt, JPEG_LAST, type))
6948 return 0; 7024 return 0;
6949 7025
6950 /* Must specify either the :data or :file keyword. */ 7026 /* Must specify either the :data or :file keyword. */
@@ -7514,12 +7590,12 @@ static const struct image_keyword tiff_format[TIFF_LAST] =
7514/* Return true if OBJECT is a valid TIFF image specification. */ 7590/* Return true if OBJECT is a valid TIFF image specification. */
7515 7591
7516static bool 7592static bool
7517tiff_image_p (Lisp_Object object) 7593tiff_image_p (Lisp_Object object, Lisp_Object type)
7518{ 7594{
7519 struct image_keyword fmt[TIFF_LAST]; 7595 struct image_keyword fmt[TIFF_LAST];
7520 memcpy (fmt, tiff_format, sizeof fmt); 7596 memcpy (fmt, tiff_format, sizeof fmt);
7521 7597
7522 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff)) 7598 if (!parse_image_spec (object, fmt, TIFF_LAST, type))
7523 return 0; 7599 return 0;
7524 7600
7525 /* Must specify either the :data or :file keyword. */ 7601 /* Must specify either the :data or :file keyword. */
@@ -7962,19 +8038,19 @@ gif_clear_image (struct frame *f, struct image *img)
7962/* Return true if OBJECT is a valid GIF image specification. */ 8038/* Return true if OBJECT is a valid GIF image specification. */
7963 8039
7964static bool 8040static bool
7965gif_image_p (Lisp_Object object) 8041gif_image_p (Lisp_Object object, Lisp_Object type)
7966{ 8042{
7967 struct image_keyword fmt[GIF_LAST]; 8043 struct image_keyword fmt[GIF_LAST];
7968 memcpy (fmt, gif_format, sizeof fmt); 8044 memcpy (fmt, gif_format, sizeof fmt);
7969 8045
7970 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif)) 8046 if (!parse_image_spec (object, fmt, GIF_LAST, type))
7971 return 0; 8047 return 0;
7972 8048
7973 /* Must specify either the :data or :file keyword. */ 8049 /* Must specify either the :data or :file keyword. */
7974 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1; 8050 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
7975} 8051}
7976 8052
7977#endif /* HAVE_GIF */ 8053#endif /* HAVE_GIF || HAVE_NS */
7978 8054
7979#ifdef HAVE_GIF 8055#ifdef HAVE_GIF
7980 8056
@@ -8574,12 +8650,12 @@ imagemagick_clear_image (struct frame *f,
8574 identify the IMAGEMAGICK format. */ 8650 identify the IMAGEMAGICK format. */
8575 8651
8576static bool 8652static bool
8577imagemagick_image_p (Lisp_Object object) 8653imagemagick_image_p (Lisp_Object object, Lisp_Object type)
8578{ 8654{
8579 struct image_keyword fmt[IMAGEMAGICK_LAST]; 8655 struct image_keyword fmt[IMAGEMAGICK_LAST];
8580 memcpy (fmt, imagemagick_format, sizeof fmt); 8656 memcpy (fmt, imagemagick_format, sizeof fmt);
8581 8657
8582 if (!parse_image_spec (object, fmt, IMAGEMAGICK_LAST, Qimagemagick)) 8658 if (!parse_image_spec (object, fmt, IMAGEMAGICK_LAST, type))
8583 return 0; 8659 return 0;
8584 8660
8585 /* Must specify either the :data or :file keyword. */ 8661 /* Must specify either the :data or :file keyword. */
@@ -9369,12 +9445,12 @@ static const struct image_keyword svg_format[SVG_LAST] =
9369 identify the SVG format. */ 9445 identify the SVG format. */
9370 9446
9371static bool 9447static bool
9372svg_image_p (Lisp_Object object) 9448svg_image_p (Lisp_Object object, Lisp_Object type)
9373{ 9449{
9374 struct image_keyword fmt[SVG_LAST]; 9450 struct image_keyword fmt[SVG_LAST];
9375 memcpy (fmt, svg_format, sizeof fmt); 9451 memcpy (fmt, svg_format, sizeof fmt);
9376 9452
9377 if (!parse_image_spec (object, fmt, SVG_LAST, Qsvg)) 9453 if (!parse_image_spec (object, fmt, SVG_LAST, type))
9378 return 0; 9454 return 0;
9379 9455
9380 /* Must specify either the :data or :file keyword. */ 9456 /* Must specify either the :data or :file keyword. */
@@ -9837,7 +9913,7 @@ static const struct image_keyword gs_format[GS_LAST] =
9837 specification. */ 9913 specification. */
9838 9914
9839static bool 9915static bool
9840gs_image_p (Lisp_Object object) 9916gs_image_p (Lisp_Object object, Lisp_Object type)
9841{ 9917{
9842 struct image_keyword fmt[GS_LAST]; 9918 struct image_keyword fmt[GS_LAST];
9843 Lisp_Object tem; 9919 Lisp_Object tem;
@@ -9845,7 +9921,7 @@ gs_image_p (Lisp_Object object)
9845 9921
9846 memcpy (fmt, gs_format, sizeof fmt); 9922 memcpy (fmt, gs_format, sizeof fmt);
9847 9923
9848 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript)) 9924 if (!parse_image_spec (object, fmt, GS_LAST, type))
9849 return 0; 9925 return 0;
9850 9926
9851 /* Bounding box must be a list or vector containing 4 integers. */ 9927 /* Bounding box must be a list or vector containing 4 integers. */
@@ -10132,13 +10208,20 @@ static bool
10132initialize_image_type (struct image_type const *type) 10208initialize_image_type (struct image_type const *type)
10133{ 10209{
10134#ifdef WINDOWSNT 10210#ifdef WINDOWSNT
10135 Lisp_Object typesym = builtin_lisp_symbol (type->type); 10211 Lisp_Object typesym, tested;
10136 Lisp_Object tested = Fassq (typesym, Vlibrary_cache); 10212 bool (*init) (void) = type->init;
10213
10214#ifdef HAVE_NATIVE_IMAGE_API
10215 if (init == init_native_image_functions)
10216 return init();
10217#endif
10218
10219 typesym = builtin_lisp_symbol (type->type);
10220 tested = Fassq (typesym, Vlibrary_cache);
10137 /* If we failed to load the library before, don't try again. */ 10221 /* If we failed to load the library before, don't try again. */
10138 if (CONSP (tested)) 10222 if (CONSP (tested))
10139 return !NILP (XCDR (tested)) ? true : false; 10223 return !NILP (XCDR (tested)) ? true : false;
10140 10224
10141 bool (*init) (void) = type->init;
10142 if (init) 10225 if (init)
10143 { 10226 {
10144 bool type_valid = init (); 10227 bool type_valid = init ();
@@ -10165,6 +10248,16 @@ static struct image_type const image_types[] =
10165 { SYMBOL_INDEX (Qsvg), svg_image_p, svg_load, image_clear_image, 10248 { SYMBOL_INDEX (Qsvg), svg_image_p, svg_load, image_clear_image,
10166 IMAGE_TYPE_INIT (init_svg_functions) }, 10249 IMAGE_TYPE_INIT (init_svg_functions) },
10167#endif 10250#endif
10251#if defined HAVE_NATIVE_IMAGE_API
10252 { SYMBOL_INDEX (Qjpeg), native_image_p, native_image_load, image_clear_image,
10253 IMAGE_TYPE_INIT (init_native_image_functions) },
10254 { SYMBOL_INDEX (Qpng), native_image_p, native_image_load, image_clear_image,
10255 IMAGE_TYPE_INIT (init_native_image_functions) },
10256 { SYMBOL_INDEX (Qgif), native_image_p, native_image_load, image_clear_image,
10257 IMAGE_TYPE_INIT (init_native_image_functions) },
10258 { SYMBOL_INDEX (Qtiff), native_image_p, native_image_load, image_clear_image,
10259 IMAGE_TYPE_INIT (init_native_image_functions) },
10260#endif
10168#if defined HAVE_PNG || defined HAVE_NS 10261#if defined HAVE_PNG || defined HAVE_NS
10169 { SYMBOL_INDEX (Qpng), png_image_p, png_load, image_clear_image, 10262 { SYMBOL_INDEX (Qpng), png_image_p, png_load, image_clear_image,
10170 IMAGE_TYPE_INIT (init_png_functions) }, 10263 IMAGE_TYPE_INIT (init_png_functions) },
@@ -10199,7 +10292,13 @@ lookup_image_type (Lisp_Object type)
10199 { 10292 {
10200 struct image_type const *r = &image_types[i]; 10293 struct image_type const *r = &image_types[i];
10201 if (EQ (type, builtin_lisp_symbol (r->type))) 10294 if (EQ (type, builtin_lisp_symbol (r->type)))
10295#ifdef HAVE_NATIVE_IMAGE_API
10296 /* We can have more than one backend for one image type. */
10297 if (initialize_image_type (r))
10298 return r;
10299#else
10202 return initialize_image_type (r) ? r : NULL; 10300 return initialize_image_type (r) ? r : NULL;
10301#endif
10203 } 10302 }
10204 return NULL; 10303 return NULL;
10205} 10304}
@@ -10316,22 +10415,22 @@ non-numeric, there is no explicit limit on the size of images. */);
10316 add_image_type (Qxpm); 10415 add_image_type (Qxpm);
10317#endif 10416#endif
10318 10417
10319#if defined (HAVE_JPEG) || defined (HAVE_NS) 10418#if defined (HAVE_JPEG) || defined (HAVE_NS) || defined (HAVE_NATIVE_IMAGE_API)
10320 DEFSYM (Qjpeg, "jpeg"); 10419 DEFSYM (Qjpeg, "jpeg");
10321 add_image_type (Qjpeg); 10420 add_image_type (Qjpeg);
10322#endif 10421#endif
10323 10422
10324#if defined (HAVE_TIFF) || defined (HAVE_NS) 10423#if defined (HAVE_TIFF) || defined (HAVE_NS) || defined (HAVE_NATIVE_IMAGE_API)
10325 DEFSYM (Qtiff, "tiff"); 10424 DEFSYM (Qtiff, "tiff");
10326 add_image_type (Qtiff); 10425 add_image_type (Qtiff);
10327#endif 10426#endif
10328 10427
10329#if defined (HAVE_GIF) || defined (HAVE_NS) 10428#if defined (HAVE_GIF) || defined (HAVE_NS) || defined (HAVE_NATIVE_IMAGE_API)
10330 DEFSYM (Qgif, "gif"); 10429 DEFSYM (Qgif, "gif");
10331 add_image_type (Qgif); 10430 add_image_type (Qgif);
10332#endif 10431#endif
10333 10432
10334#if defined (HAVE_PNG) || defined (HAVE_NS) 10433#if defined (HAVE_PNG) || defined (HAVE_NS) || defined(HAVE_NATIVE_IMAGE_API)
10335 DEFSYM (Qpng, "png"); 10434 DEFSYM (Qpng, "png");
10336 add_image_type (Qpng); 10435 add_image_type (Qpng);
10337#endif 10436#endif