[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
GDI+ take 3
From: |
Juan José García-Ripoll |
Subject: |
GDI+ take 3 |
Date: |
Sat, 04 Apr 2020 23:25:09 +0200 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/26.3 (windows-nt) |
After some consideration and washing off the feeling that I am wasting
my time, I have reworked my previous patch to test at boot time whether
GDI+ is available (gdiplus_v3.diff). It implements a generic
"native-image-api" option which can be extended to OSX (I have a patch,
but I have no machines to test it so it is not attached).
It does not implement a new image type. Instead, it places the native
backends at the front and continues searching the image list when those
backends are not active. I find that treating the native backend as a
second class citizen, as ImageMagick, is not ok. But most important, I
find that the abstraction of backend = image-type is broken.
Regarding previous discussions, I believe the concerns about GDI+
becoming deprecated are irrelevant in comparison to the fact that Emacs
is using already a deprecated API, namely GDI, which is older and
equally prone to disappear in favor of Direct2d/WIC.
Regarding unicode, GDI+ requires WCHAR. Therefore the backend refuses to
initialize if w32-unicode-filenames is NIL, defaulting to other
backends. However, if the user changes this variable from T to NIL after
the backend has been initialized, the backend will remain active but
refuse to load images.
I have fixed the use of terminal hooks, due to insistance. However, that
meant one function declaration had to be added to w32term.h
I have not changed the use of SSDATA in the :data field of images. If
this is a problem, it is so in all of image.c.
I have touch my Emacs installation to avoid removing the double spaces
after a dot, but I am not 100% sure all is Kosher.
I go to bed. If you still find that this patch is not acceptable, I am
not going to work any more on it. I developed it to minimize the number
of dependencies of Emacs on the Windows platform, but that does not seem
to be a priority around here.
Best,
--
Juan José García Ripoll
http://juanjose.garciaripoll.com
http://quinfog.hbar.es
diff --git a/src/image.c b/src/image.c
index 65d59254f0..2ef51a87f2 100644
--- a/src/image.c
+++ b/src/image.c
@@ -751,7 +751,7 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id)
/* Check that SPEC is a valid image specification for the given
image type. Value is true if SPEC is valid. */
- bool (*valid_p) (Lisp_Object spec);
+ bool (*valid_p) (Lisp_Object spec, Lisp_Object type);
/* Load IMG which is used on frame F from information contained in
IMG->spec. Value is true if successful. */
@@ -807,7 +807,7 @@ valid_image_p (Lisp_Object object)
{
struct image_type const *type = lookup_image_type (XCAR (tail));
if (type)
- return type->valid_p (object);
+ return type->valid_p (object, builtin_lisp_symbol
(type->type));
}
break;
}
@@ -3144,12 +3144,12 @@ slurp_file (int fd, ptrdiff_t *size)
displayed is used. */
static bool
-xbm_image_p (Lisp_Object object)
+xbm_image_p (Lisp_Object object, Lisp_Object type)
{
struct image_keyword kw[XBM_LAST];
memcpy (kw, xbm_format, sizeof kw);
- if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
+ if (!parse_image_spec (object, kw, XBM_LAST, type))
return 0;
eassert (EQ (kw[XBM_TYPE].value, Qxbm));
@@ -3697,7 +3697,7 @@ xbm_load (struct frame *f, struct image *img)
bool success_p = 0;
Lisp_Object file_name;
- eassert (xbm_image_p (img->spec));
+ eassert (xbm_image_p (img->spec, Qxbm));
/* If IMG->spec specifies a file name, create a non-file spec from it. */
file_name = image_spec_value (img->spec, QCfile, NULL);
@@ -4155,11 +4155,11 @@ xpm_valid_color_symbols_p (Lisp_Object color_symbols)
/* Value is true if OBJECT is a valid XPM image specification. */
static bool
-xpm_image_p (Lisp_Object object)
+xpm_image_p (Lisp_Object object, Lisp_Object type)
{
struct image_keyword fmt[XPM_LAST];
memcpy (fmt, xpm_format, sizeof fmt);
- return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
+ return (parse_image_spec (object, fmt, XPM_LAST, type)
/* Either `:file' or `:data' must be present. */
&& fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
/* Either no `:color-symbols' or it's a list of conses
@@ -5882,13 +5882,13 @@ image_build_heuristic_mask (struct frame *f, struct
image *img,
/* Return true if OBJECT is a valid PBM image specification. */
static bool
-pbm_image_p (Lisp_Object object)
+pbm_image_p (Lisp_Object object, Lisp_Object type)
{
struct image_keyword fmt[PBM_LAST];
memcpy (fmt, pbm_format, sizeof fmt);
- if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
+ if (!parse_image_spec (object, fmt, PBM_LAST, type))
return 0;
/* Must specify either :data or :file. */
@@ -6230,6 +6230,83 @@ pbm_load (struct frame *f, struct image *img)
return 1;
}
+
+/***********************************************************************
+ NATIVE IMAGE HANDLING
+ ***********************************************************************/
+#if defined(HAVE_NATIVE_IMAGE_API) && defined(HAVE_NTGUI)
+/*
+ * These functions are actually defined in the OS-native implementation
+ * file. Currently, for Windows GDI+ interface, w32image.c, but other
+ * operating systems can follow suit.
+ */
+
+static bool
+init_native_image_functions (void)
+{
+ return w32_gdiplus_startup ();
+}
+
+/* Indices of image specification fields in native format, below. */
+
+enum native_image_keyword_index
+{
+ NATIVE_IMAGE_TYPE,
+ NATIVE_IMAGE_DATA,
+ NATIVE_IMAGE_FILE,
+ NATIVE_IMAGE_ASCENT,
+ NATIVE_IMAGE_MARGIN,
+ NATIVE_IMAGE_RELIEF,
+ NATIVE_IMAGE_ALGORITHM,
+ NATIVE_IMAGE_HEURISTIC_MASK,
+ NATIVE_IMAGE_MASK,
+ NATIVE_IMAGE_BACKGROUND,
+ NATIVE_IMAGE_INDEX,
+ NATIVE_IMAGE_LAST
+};
+
+/* Vector of image_keyword structures describing the format
+ of valid user-defined image specifications. */
+
+static const struct image_keyword native_image_format[] =
+{
+ {":type", IMAGE_SYMBOL_VALUE, 1},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":file", IMAGE_STRING_VALUE, 0},
+ {":ascent", IMAGE_ASCENT_VALUE, 0},
+ {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
+ {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
+};
+
+/* Return true if OBJECT is a valid native API image specification. */
+
+static bool
+native_image_p (Lisp_Object object, Lisp_Object type)
+{
+ struct image_keyword fmt[NATIVE_IMAGE_LAST];
+ memcpy (fmt, native_image_format, sizeof fmt);
+
+ if (!parse_image_spec (object, fmt, 10, type))
+ return 0;
+
+ /* Must specify either the :data or :file keyword. */
+ return fmt[NATIVE_IMAGE_FILE].count + fmt[NATIVE_IMAGE_DATA].count == 1;
+}
+
+static bool
+native_image_load (struct frame *f, struct image *img)
+{
+ return w32_load_image (f, img,
+ image_spec_value (img->spec, QCfile, NULL),
+ image_spec_value (img->spec, QCdata, NULL));
+}
+#endif
+
/***********************************************************************
PNG
@@ -6274,12 +6351,12 @@ pbm_load (struct frame *f, struct image *img)
/* Return true if OBJECT is a valid PNG image specification. */
static bool
-png_image_p (Lisp_Object object)
+png_image_p (Lisp_Object object, Lisp_Object type)
{
struct image_keyword fmt[PNG_LAST];
memcpy (fmt, png_format, sizeof fmt);
- if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
+ if (!parse_image_spec (object, fmt, PNG_LAST, type))
return 0;
/* Must specify either the :data or :file keyword. */
@@ -6889,7 +6966,6 @@ png_load (struct frame *f, struct image *img)
image_spec_value (img->spec, QCdata, NULL));
}
-
#endif /* HAVE_NS */
@@ -6937,13 +7013,13 @@ png_load (struct frame *f, struct image *img)
/* Return true if OBJECT is a valid JPEG image specification. */
static bool
-jpeg_image_p (Lisp_Object object)
+jpeg_image_p (Lisp_Object object, Lisp_Object type)
{
struct image_keyword fmt[JPEG_LAST];
memcpy (fmt, jpeg_format, sizeof fmt);
- if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
+ if (!parse_image_spec (object, fmt, JPEG_LAST, type))
return 0;
/* Must specify either the :data or :file keyword. */
@@ -7513,12 +7589,12 @@ jpeg_load (struct frame *f, struct image *img)
/* Return true if OBJECT is a valid TIFF image specification. */
static bool
-tiff_image_p (Lisp_Object object)
+tiff_image_p (Lisp_Object object, Lisp_Object type)
{
struct image_keyword fmt[TIFF_LAST];
memcpy (fmt, tiff_format, sizeof fmt);
- if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
+ if (!parse_image_spec (object, fmt, TIFF_LAST, type))
return 0;
/* Must specify either the :data or :file keyword. */
@@ -7961,19 +8037,19 @@ gif_clear_image (struct frame *f, struct image *img)
/* Return true if OBJECT is a valid GIF image specification. */
static bool
-gif_image_p (Lisp_Object object)
+gif_image_p (Lisp_Object object, Lisp_Object type)
{
struct image_keyword fmt[GIF_LAST];
memcpy (fmt, gif_format, sizeof fmt);
- if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
+ if (!parse_image_spec (object, fmt, GIF_LAST, type))
return 0;
/* Must specify either the :data or :file keyword. */
return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
}
-#endif /* HAVE_GIF */
+#endif /* HAVE_GIF || HAVE_NS */
#ifdef HAVE_GIF
@@ -8573,12 +8649,12 @@ imagemagick_clear_image (struct frame *f,
identify the IMAGEMAGICK format. */
static bool
-imagemagick_image_p (Lisp_Object object)
+imagemagick_image_p (Lisp_Object object, Lisp_Object type)
{
struct image_keyword fmt[IMAGEMAGICK_LAST];
memcpy (fmt, imagemagick_format, sizeof fmt);
- if (!parse_image_spec (object, fmt, IMAGEMAGICK_LAST, Qimagemagick))
+ if (!parse_image_spec (object, fmt, IMAGEMAGICK_LAST, type))
return 0;
/* Must specify either the :data or :file keyword. */
@@ -9368,12 +9444,12 @@ DEFUN ("imagemagick-types", Fimagemagick_types,
Simagemagick_types, 0, 0, 0,
identify the SVG format. */
static bool
-svg_image_p (Lisp_Object object)
+svg_image_p (Lisp_Object object, Lisp_Object type)
{
struct image_keyword fmt[SVG_LAST];
memcpy (fmt, svg_format, sizeof fmt);
- if (!parse_image_spec (object, fmt, SVG_LAST, Qsvg))
+ if (!parse_image_spec (object, fmt, SVG_LAST, type))
return 0;
/* Must specify either the :data or :file keyword. */
@@ -9836,7 +9912,7 @@ #define HAVE_GHOSTSCRIPT 1
specification. */
static bool
-gs_image_p (Lisp_Object object)
+gs_image_p (Lisp_Object object, Lisp_Object type)
{
struct image_keyword fmt[GS_LAST];
Lisp_Object tem;
@@ -9844,7 +9920,7 @@ gs_image_p (Lisp_Object object)
memcpy (fmt, gs_format, sizeof fmt);
- if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
+ if (!parse_image_spec (object, fmt, GS_LAST, type))
return 0;
/* Bounding box must be a list or vector containing 4 integers. */
@@ -10131,13 +10207,20 @@ DEFUN ("init-image-library", Finit_image_library,
Sinit_image_library, 1, 1, 0,
initialize_image_type (struct image_type const *type)
{
#ifdef WINDOWSNT
- Lisp_Object typesym = builtin_lisp_symbol (type->type);
- Lisp_Object tested = Fassq (typesym, Vlibrary_cache);
+ Lisp_Object typesym, tested;
+ bool (*init) (void) = type->init;
+
+#ifdef HAVE_NATIVE_IMAGE_API
+ if (init == init_native_image_functions)
+ return init();
+#endif
+
+ typesym = builtin_lisp_symbol (type->type);
+ tested = Fassq (typesym, Vlibrary_cache);
/* If we failed to load the library before, don't try again. */
if (CONSP (tested))
return !NILP (XCDR (tested)) ? true : false;
- bool (*init) (void) = type->init;
if (init)
{
bool type_valid = init ();
@@ -10164,6 +10247,16 @@ initialize_image_type (struct image_type const *type)
{ SYMBOL_INDEX (Qsvg), svg_image_p, svg_load, image_clear_image,
IMAGE_TYPE_INIT (init_svg_functions) },
#endif
+#if defined HAVE_NATIVE_IMAGE_API
+ { SYMBOL_INDEX (Qjpeg), native_image_p, native_image_load, image_clear_image,
+ IMAGE_TYPE_INIT (init_native_image_functions) },
+ { SYMBOL_INDEX (Qpng), native_image_p, native_image_load, image_clear_image,
+ IMAGE_TYPE_INIT (init_native_image_functions) },
+ { SYMBOL_INDEX (Qgif), native_image_p, native_image_load, image_clear_image,
+ IMAGE_TYPE_INIT (init_native_image_functions) },
+ { SYMBOL_INDEX (Qtiff), native_image_p, native_image_load, image_clear_image,
+ IMAGE_TYPE_INIT (init_native_image_functions) },
+#endif
#if defined HAVE_PNG || defined HAVE_NS
{ SYMBOL_INDEX (Qpng), png_image_p, png_load, image_clear_image,
IMAGE_TYPE_INIT (init_png_functions) },
@@ -10198,7 +10291,13 @@ lookup_image_type (Lisp_Object type)
{
struct image_type const *r = &image_types[i];
if (EQ (type, builtin_lisp_symbol (r->type)))
+#ifdef HAVE_NATIVE_IMAGE_API
+ /* We can have more than one backend for one image type. */
+ if (initialize_image_type (r))
+ return r;
+#else
return initialize_image_type (r) ? r : NULL;
+#endif
}
return NULL;
}
@@ -10315,22 +10414,22 @@ syms_of_image (void)
add_image_type (Qxpm);
#endif
-#if defined (HAVE_JPEG) || defined (HAVE_NS)
+#if defined (HAVE_JPEG) || defined (HAVE_NS) || defined (HAVE_NATIVE_IMAGE_API)
DEFSYM (Qjpeg, "jpeg");
add_image_type (Qjpeg);
#endif
-#if defined (HAVE_TIFF) || defined (HAVE_NS)
+#if defined (HAVE_TIFF) || defined (HAVE_NS) || defined (HAVE_NATIVE_IMAGE_API)
DEFSYM (Qtiff, "tiff");
add_image_type (Qtiff);
#endif
-#if defined (HAVE_GIF) || defined (HAVE_NS)
+#if defined (HAVE_GIF) || defined (HAVE_NS) || defined (HAVE_NATIVE_IMAGE_API)
DEFSYM (Qgif, "gif");
add_image_type (Qgif);
#endif
-#if defined (HAVE_PNG) || defined (HAVE_NS)
+#if defined (HAVE_PNG) || defined (HAVE_NS) || defined(HAVE_NATIVE_IMAGE_API)
DEFSYM (Qpng, "png");
add_image_type (Qpng);
#endif
diff --git a/src/w32.c b/src/w32.c
index 698e10e234..1d2a52b6df 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -10225,6 +10225,10 @@ term_ntproc (int ignored)
term_winsock ();
term_w32select ();
+
+#ifdef HAVE_GDIPLUS
+ w32_gdiplus_shutdown ();
+#endif
}
void
diff --git a/src/w32term.c b/src/w32term.c
index 5fa77d58e1..f19754df02 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -1529,7 +1529,7 @@ w32_query_colors (struct frame *f, Emacs_Color *colors,
int ncolors)
/* Store F's background color into *BGCOLOR. */
-static void
+void
w32_query_frame_background_color (struct frame *f, Emacs_Color *bgcolor)
{
bgcolor->pixel = FRAME_BACKGROUND_PIXEL (f);
diff --git a/src/w32term.h b/src/w32term.h
index f8a8a727e8..d44c6f9b83 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -75,7 +75,10 @@ #define CP_DEFAULT 1004
extern void w32_regenerate_palette (struct frame *f);
extern void w32_fullscreen_rect (HWND hwnd, int fsmode, RECT normal,
RECT *rect);
-
+extern int w32_load_image (struct frame *f, struct image *img,
+ Lisp_Object spec_file, Lisp_Object spec_data);
+extern bool w32_gdiplus_startup (void);
+extern void w32_gdiplus_shutdown (void);
/* For each display (currently only one on w32), we have a structure that
records information about it. */
@@ -248,6 +251,8 @@ #define CP_DEFAULT 1004
extern int w32_display_pixel_width (struct w32_display_info *);
extern void initialize_frame_menubar (struct frame *);
extern void w32_dialog_in_progress (Lisp_Object in_progress);
+extern void w32_query_frame_background_color (struct frame *f,
+ Emacs_Color *bgcolor);
extern void w32_make_frame_visible (struct frame *f);
extern void w32_make_frame_invisible (struct frame *f);
- GDI+ take 3,
Juan José García-Ripoll <=
- Re: GDI+ take 3, Eli Zaretskii, 2020/04/05
- Re: GDI+ take 3, Eli Zaretskii, 2020/04/13
- Re: GDI+ take 3, Juan José García-Ripoll, 2020/04/13
- Re: GDI+ take 3, Eli Zaretskii, 2020/04/14
- Re: GDI+ take 3, Eli Zaretskii, 2020/04/14
- Re: GDI+ take 3, Alan Third, 2020/04/16
- Re: GDI+ take 3, Eli Zaretskii, 2020/04/16
- Re: GDI+ take 3, Dmitry Gutov, 2020/04/14
- Re: GDI+ take 3, Eli Zaretskii, 2020/04/14
- Re: GDI+ take 3, Dmitry Gutov, 2020/04/14