summaryrefslogtreecommitdiff
path: root/src/image.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/image.c')
-rw-r--r--src/image.c245
1 files changed, 179 insertions, 66 deletions
diff --git a/src/image.c b/src/image.c
index a124cf91ba0..bcd45eb4514 100644
--- a/src/image.c
+++ b/src/image.c
@@ -511,7 +511,7 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file)
/* Search bitmap-file-path for the file, if appropriate. */
if (openp (Vx_bitmap_file_path, file, Qnil, &found,
- make_fixnum (R_OK), false)
+ make_fixnum (R_OK), false, false)
< 0)
return -1;
@@ -1199,6 +1199,7 @@ free_image (struct frame *f, struct image *img)
/* Free resources, then free IMG. */
img->type->free_img (f, img);
+ xfree (img->face_font_family);
xfree (img);
}
}
@@ -1597,7 +1598,7 @@ make_image_cache (void)
static struct image *
search_image_cache (struct frame *f, Lisp_Object spec, EMACS_UINT hash,
unsigned long foreground, unsigned long background,
- bool ignore_colors)
+ int font_size, char *font_family, bool ignore_colors)
{
struct image *img;
struct image_cache *c = FRAME_IMAGE_CACHE (f);
@@ -1621,7 +1622,10 @@ search_image_cache (struct frame *f, Lisp_Object spec, EMACS_UINT hash,
if (img->hash == hash
&& !NILP (Fequal (img->spec, spec))
&& (ignore_colors || (img->face_foreground == foreground
- && img->face_background == background)))
+ && img->face_background == background
+ && img->face_font_size == font_size
+ && (font_family
+ &&!strcmp (font_family, img->face_font_family)))))
break;
return img;
}
@@ -1639,7 +1643,7 @@ uncache_image (struct frame *f, Lisp_Object spec)
can have multiple copies of an image with the same spec. We want
to remove them all to ensure the user doesn't see an old version
of the image when the face changes. */
- while ((img = search_image_cache (f, spec, hash, 0, 0, true)))
+ while ((img = search_image_cache (f, spec, hash, 0, 0, 0, NULL, true)))
{
free_image (f, img);
/* As display glyphs may still be referring to the image ID, we
@@ -1983,46 +1987,68 @@ scale_image_size (int size, size_t divisor, size_t multiplier)
return INT_MAX;
}
+/* Return a size, in pixels, from the value specified by SYMBOL, which
+ may be an integer or a pair of the form (VALUE . 'em) where VALUE
+ is a float that is multiplied by the font size to get the final
+ dimension.
+
+ If the value doesn't exist in the image spec, or is invalid, return
+ -1.
+*/
+static int
+image_get_dimension (struct image *img, Lisp_Object symbol)
+{
+ Lisp_Object value = image_spec_value (img->spec, symbol, NULL);
+
+ if (FIXNATP (value))
+ return min (XFIXNAT (value), INT_MAX);
+ if (CONSP (value) && NUMBERP (CAR (value)) && EQ (Qem, CDR (value)))
+ return min (img->face_font_size * XFLOATINT (CAR (value)), INT_MAX);
+
+ return -1;
+}
+
/* Compute the desired size of an image with native size WIDTH x HEIGHT.
Use SPEC to deduce the size. Store the desired size into
*D_WIDTH x *D_HEIGHT. Store -1 x -1 if the native size is OK. */
static void
compute_image_size (size_t width, size_t height,
- Lisp_Object spec,
+ struct image *img,
int *d_width, int *d_height)
{
Lisp_Object value;
+ int int_value;
int desired_width = -1, desired_height = -1, max_width = -1, max_height = -1;
double scale = 1;
- value = image_spec_value (spec, QCscale, NULL);
+ value = image_spec_value (img->spec, QCscale, NULL);
if (NUMBERP (value))
scale = XFLOATINT (value);
- value = image_spec_value (spec, QCmax_width, NULL);
- if (FIXNATP (value))
- max_width = min (XFIXNAT (value), INT_MAX);
+ int_value = image_get_dimension (img, QCmax_width);
+ if (int_value >= 0)
+ max_width = int_value;
- value = image_spec_value (spec, QCmax_height, NULL);
- if (FIXNATP (value))
- max_height = min (XFIXNAT (value), INT_MAX);
+ int_value = image_get_dimension (img, QCmax_height);
+ if (int_value >= 0)
+ max_height = int_value;
/* If width and/or height is set in the display spec assume we want
to scale to those values. If either h or w is unspecified, the
unspecified should be calculated from the specified to preserve
aspect ratio. */
- value = image_spec_value (spec, QCwidth, NULL);
- if (FIXNATP (value))
+ int_value = image_get_dimension (img, QCwidth);
+ if (int_value >= 0)
{
- desired_width = min (XFIXNAT (value) * scale, INT_MAX);
+ desired_width = int_value * scale;
/* :width overrides :max-width. */
max_width = -1;
}
- value = image_spec_value (spec, QCheight, NULL);
- if (FIXNATP (value))
+ int_value = image_get_dimension (img, QCheight);
+ if (int_value >= 0)
{
- desired_height = min (XFIXNAT (value) * scale, INT_MAX);
+ desired_height = int_value * scale;
/* :height overrides :max-height. */
max_height = -1;
}
@@ -2207,24 +2233,29 @@ image_set_transform (struct frame *f, struct image *img)
/* SVGs are pre-scaled to the correct size. */
if (EQ (image_spec_value (img->spec, QCtype, NULL), Qsvg))
{
- width = img->width;
- height = img->height;
+ width = img->width / FRAME_SCALE_FACTOR (f);
+ height = img->height / FRAME_SCALE_FACTOR (f);
}
else
#endif
- compute_image_size (img->width, img->height, img->spec, &width, &height);
+ compute_image_size (img->width, img->height, img, &width, &height);
/* Determine rotation. */
double rotation = 0.0;
compute_image_rotation (img, &rotation);
# if defined USE_CAIRO || defined HAVE_XRENDER || defined HAVE_NS
- /* We want scale up operations to use a nearest neighbour filter to
+ /* We want scale up operations to use a nearest neighbor filter to
show real pixels instead of munging them, but scale down
operations to use a blended filter, to avoid aliasing and the like.
TODO: implement for Windows. */
- bool scale_down = (width < img->width) || (height < img->height);
+ bool smoothing;
+ Lisp_Object s = image_spec_value (img->spec, QCtransform_smoothing, NULL);
+ if (NILP (s))
+ smoothing = (width < img->width) || (height < img->height);
+ else
+ smoothing = !NILP (s);
# endif
/* Perform scale transformation. */
@@ -2338,13 +2369,13 @@ image_set_transform (struct frame *f, struct image *img)
/* Under NS the transform is applied to the drawing surface at
drawing time, so store it for later. */
ns_image_set_transform (img->pixmap, matrix);
- ns_image_set_smoothing (img->pixmap, scale_down);
+ ns_image_set_smoothing (img->pixmap, smoothing);
# elif defined USE_CAIRO
cairo_matrix_t cr_matrix = {matrix[0][0], matrix[0][1], matrix[1][0],
matrix[1][1], matrix[2][0], matrix[2][1]};
cairo_pattern_t *pattern = cairo_pattern_create_rgb (0, 0, 0);
cairo_pattern_set_matrix (pattern, &cr_matrix);
- cairo_pattern_set_filter (pattern, scale_down
+ cairo_pattern_set_filter (pattern, smoothing
? CAIRO_FILTER_BEST : CAIRO_FILTER_NEAREST);
/* Dummy solid color pattern just to record pattern matrix. */
img->cr_data = pattern;
@@ -2363,13 +2394,13 @@ image_set_transform (struct frame *f, struct image *img)
XDoubleToFixed (matrix[2][2])}}};
XRenderSetPictureFilter (FRAME_X_DISPLAY (f), img->picture,
- scale_down ? FilterBest : FilterNearest, 0, 0);
+ smoothing ? FilterBest : FilterNearest, 0, 0);
XRenderSetPictureTransform (FRAME_X_DISPLAY (f), img->picture, &tmat);
if (img->mask_picture)
{
XRenderSetPictureFilter (FRAME_X_DISPLAY (f), img->mask_picture,
- scale_down ? FilterBest : FilterNearest, 0, 0);
+ smoothing ? FilterBest : FilterNearest, 0, 0);
XRenderSetPictureTransform (FRAME_X_DISPLAY (f), img->mask_picture,
&tmat);
}
@@ -2406,6 +2437,8 @@ lookup_image (struct frame *f, Lisp_Object spec, int face_id)
struct face *face = FACE_FROM_ID (f, face_id);
unsigned long foreground = FACE_COLOR_TO_PIXEL (face->foreground, f);
unsigned long background = FACE_COLOR_TO_PIXEL (face->background, f);
+ int font_size = face->font->pixel_size;
+ char *font_family = SSDATA (face->lface[LFACE_FAMILY_INDEX]);
/* F must be a window-system frame, and SPEC must be a valid image
specification. */
@@ -2414,7 +2447,8 @@ lookup_image (struct frame *f, Lisp_Object spec, int face_id)
/* Look up SPEC in the hash table of the image cache. */
hash = sxhash (spec);
- img = search_image_cache (f, spec, hash, foreground, background, false);
+ img = search_image_cache (f, spec, hash, foreground, background,
+ font_size, font_family, false);
if (img && img->load_failed_p)
{
free_image (f, img);
@@ -2429,6 +2463,9 @@ lookup_image (struct frame *f, Lisp_Object spec, int face_id)
cache_image (f, img);
img->face_foreground = foreground;
img->face_background = background;
+ img->face_font_size = font_size;
+ img->face_font_family = xmalloc (strlen (font_family) + 1);
+ strcpy (img->face_font_family, font_family);
img->load_failed_p = ! img->type->load_img (f, img);
/* If we can't load the image, and we don't have a width and
@@ -3115,20 +3152,17 @@ image_find_image_fd (Lisp_Object file, int *pfd)
/* Try to find FILE in data-directory/images, then x-bitmap-file-path. */
fd = openp (search_path, file, Qnil, &file_found,
- pfd ? Qt : make_fixnum (R_OK), false);
- if (fd >= 0 || fd == -2)
+ pfd ? Qt : make_fixnum (R_OK), false, false);
+ if (fd == -2)
{
- file_found = ENCODE_FILE (file_found);
- if (fd == -2)
- {
- /* The file exists locally, but has a file name handler.
- (This happens, e.g., under Auto Image File Mode.)
- 'openp' didn't open the file, so we should, because the
- caller expects that. */
- fd = emacs_open (SSDATA (file_found), O_RDONLY, 0);
- }
+ /* The file exists locally, but has a file name handler.
+ (This happens, e.g., under Auto Image File Mode.)
+ 'openp' didn't open the file, so we should, because the
+ caller expects that. */
+ Lisp_Object encoded_name = ENCODE_FILE (file_found);
+ fd = emacs_open (SSDATA (encoded_name), O_RDONLY, 0);
}
- else /* fd < 0, but not -2 */
+ else if (fd < 0)
return Qnil;
if (pfd)
*pfd = fd;
@@ -3136,8 +3170,8 @@ image_find_image_fd (Lisp_Object file, int *pfd)
}
/* Find image file FILE. Look in data-directory/images, then
- x-bitmap-file-path. Value is the encoded full name of the file
- found, or nil if not found. */
+ x-bitmap-file-path. Value is the full name of the file found, or
+ nil if not found. */
Lisp_Object
image_find_image_file (Lisp_Object file)
@@ -3379,6 +3413,7 @@ static int
xbm_scan (char **s, char *end, char *sval, int *ival)
{
unsigned char c UNINIT;
+ char *sval_end = sval + BUFSIZ;
loop:
@@ -3438,7 +3473,7 @@ xbm_scan (char **s, char *end, char *sval, int *ival)
else if (c_isalpha (c) || c == '_')
{
*sval++ = c;
- while (*s < end
+ while (*s < end && sval < sval_end
&& (c = *(*s)++, (c_isalnum (c) || c == '_')))
*sval++ = c;
*sval = 0;
@@ -4023,6 +4058,7 @@ enum xpm_keyword_index
XPM_LAST
};
+#if defined HAVE_XPM || defined HAVE_NS
/* Vector of image_keyword structures describing the format
of valid XPM image specifications. */
@@ -4040,6 +4076,7 @@ static const struct image_keyword xpm_format[XPM_LAST] =
{":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":background", IMAGE_STRING_OR_NIL_VALUE, 0}
};
+#endif /* HAVE_XPM || HAVE_NS */
#if defined HAVE_X_WINDOWS && !defined USE_CAIRO
@@ -4263,6 +4300,7 @@ init_xpm_functions (void)
#endif /* WINDOWSNT */
+#if defined HAVE_XPM || defined HAVE_NS
/* Value is true if COLOR_SYMBOLS is a valid color symbols list
for XPM images. Such a list must consist of conses whose car and
cdr are strings. */
@@ -4283,7 +4321,6 @@ xpm_valid_color_symbols_p (Lisp_Object color_symbols)
return NILP (color_symbols);
}
-
/* Value is true if OBJECT is a valid XPM image specification. */
static bool
@@ -4299,6 +4336,7 @@ xpm_image_p (Lisp_Object object)
&& (! fmt[XPM_COLOR_SYMBOLS].count
|| xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
}
+#endif /* HAVE_XPM || HAVE_NS */
#endif /* HAVE_XPM || USE_CAIRO || HAVE_NS */
@@ -4668,10 +4706,11 @@ xpm_load (struct frame *f, struct image *img)
#endif /* HAVE_XPM && !USE_CAIRO */
-#if defined USE_CAIRO || (defined HAVE_NS && !defined HAVE_XPM)
+#if (defined USE_CAIRO && defined HAVE_XPM) \
+ || (defined HAVE_NS && !defined HAVE_XPM)
-/* XPM support functions for NS where libxpm is not available.
- Only XPM version 3 (without any extensions) is supported. */
+/* XPM support functions for NS where libxpm is not available, and for
+ Cairo. Only XPM version 3 (without any extensions) is supported. */
static void xpm_put_color_table_v (Lisp_Object, const char *,
int, Lisp_Object);
@@ -4952,7 +4991,7 @@ xpm_load_image (struct frame *f,
while (num_colors-- > 0)
{
- char *color, *max_color;
+ char *color, *max_color = NULL;
int key, next_key, max_key = 0;
Lisp_Object symbol_color = Qnil, color_val;
Emacs_Color cdef;
@@ -5013,7 +5052,7 @@ xpm_load_image (struct frame *f,
cdef.blue));
}
}
- if (NILP (color_val) && max_key > 0)
+ if (NILP (color_val) && max_color)
{
if (xstrcasecmp (max_color, "None") == 0)
color_val = Qt;
@@ -7735,6 +7774,13 @@ tiff_image_p (Lisp_Object object)
# include <tiffio.h>
+/* libtiff version 4.3.0 deprecated uint32 typedef. */
+#if TIFFLIB_VERSION >= 20210416
+# define UINT32 uint32_t
+#else
+# define UINT32 uint32
+#endif
+
# ifdef WINDOWSNT
/* TIFF library details. */
@@ -7746,7 +7792,7 @@ DEF_DLL_FN (TIFF *, TIFFClientOpen,
TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc,
TIFFMapFileProc, TIFFUnmapFileProc));
DEF_DLL_FN (int, TIFFGetField, (TIFF *, ttag_t, ...));
-DEF_DLL_FN (int, TIFFReadRGBAImage, (TIFF *, uint32, uint32, uint32 *, int));
+DEF_DLL_FN (int, TIFFReadRGBAImage, (TIFF *, UINT32, UINT32, UINT32 *, int));
DEF_DLL_FN (void, TIFFClose, (TIFF *));
DEF_DLL_FN (int, TIFFSetDirectory, (TIFF *, tdir_t));
@@ -7938,7 +7984,7 @@ tiff_load (struct frame *f, struct image *img)
Lisp_Object specified_data;
TIFF *tiff;
int width, height, x, y, count;
- uint32 *buf;
+ UINT32 *buf;
int rc;
Emacs_Pix_Container ximg;
tiff_memory_source memsrc;
@@ -8064,11 +8110,11 @@ tiff_load (struct frame *f, struct image *img)
/* Process the pixel raster. Origin is in the lower-left corner. */
for (y = 0; y < height; ++y)
{
- uint32 *row = buf + y * width;
+ UINT32 *row = buf + y * width;
for (x = 0; x < width; ++x)
{
- uint32 abgr = row[x];
+ UINT32 abgr = row[x];
int r = TIFFGetR (abgr) << 8;
int g = TIFFGetG (abgr) << 8;
int b = TIFFGetB (abgr) << 8;
@@ -9194,7 +9240,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
compute_image_size (MagickGetImageWidth (image_wand),
MagickGetImageHeight (image_wand),
- img->spec, &desired_width, &desired_height);
+ img, &desired_width, &desired_height);
if (desired_width != -1 && desired_height != -1)
{
@@ -9526,6 +9572,7 @@ enum svg_keyword_index
SVG_DATA,
SVG_FILE,
SVG_BASE_URI,
+ SVG_CSS,
SVG_ASCENT,
SVG_MARGIN,
SVG_RELIEF,
@@ -9546,6 +9593,7 @@ static const struct image_keyword svg_format[SVG_LAST] =
{":data", IMAGE_STRING_VALUE, 0},
{":file", IMAGE_STRING_VALUE, 0},
{":base-uri", IMAGE_STRING_VALUE, 0},
+ {":css", IMAGE_STRING_VALUE, 0},
{":ascent", IMAGE_ASCENT_VALUE, 0},
{":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
{":relief", IMAGE_INTEGER_VALUE, 0},
@@ -9629,6 +9677,11 @@ DEF_DLL_FN (gboolean, rsvg_handle_get_geometry_for_layer,
(RsvgHandle *, const char *, const RsvgRectangle *,
RsvgRectangle *, RsvgRectangle *, GError **));
# endif
+
+# if LIBRSVG_CHECK_VERSION (2, 48, 0)
+DEF_DLL_FN (gboolean, rsvg_handle_set_stylesheet,
+ (RsvgHandle *, const guint8 *, gsize, GError **));
+# endif
DEF_DLL_FN (void, rsvg_handle_get_dimensions,
(RsvgHandle *, RsvgDimensionData *));
DEF_DLL_FN (GdkPixbuf *, rsvg_handle_get_pixbuf, (RsvgHandle *));
@@ -9682,6 +9735,9 @@ init_svg_functions (void)
LOAD_DLL_FN (library, rsvg_handle_get_intrinsic_dimensions);
LOAD_DLL_FN (library, rsvg_handle_get_geometry_for_layer);
#endif
+#if LIBRSVG_CHECK_VERSION (2, 48, 0)
+ LOAD_DLL_FN (library, rsvg_handle_set_stylesheet);
+#endif
LOAD_DLL_FN (library, rsvg_handle_get_dimensions);
LOAD_DLL_FN (library, rsvg_handle_get_pixbuf);
@@ -9722,6 +9778,9 @@ init_svg_functions (void)
# undef rsvg_handle_get_geometry_for_layer
# endif
# undef rsvg_handle_get_dimensions
+# if LIBRSVG_CHECK_VERSION (2, 48, 0)
+# undef rsvg_handle_set_stylesheet
+# endif
# undef rsvg_handle_get_pixbuf
# if LIBRSVG_CHECK_VERSION (2, 32, 0)
# undef g_file_new_for_path
@@ -9755,6 +9814,9 @@ init_svg_functions (void)
fn_rsvg_handle_get_geometry_for_layer
# endif
# define rsvg_handle_get_dimensions fn_rsvg_handle_get_dimensions
+# if LIBRSVG_CHECK_VERSION (2, 48, 0)
+# define rsvg_handle_set_stylesheet fn_rsvg_handle_set_stylesheet
+# endif
# define rsvg_handle_get_pixbuf fn_rsvg_handle_get_pixbuf
# if LIBRSVG_CHECK_VERSION (2, 32, 0)
# define g_file_new_for_path fn_g_file_new_for_path
@@ -9832,7 +9894,7 @@ svg_load (struct frame *f, struct image *img)
#if LIBRSVG_CHECK_VERSION (2, 46, 0)
static double
-svg_css_length_to_pixels (RsvgLength length, double dpi)
+svg_css_length_to_pixels (RsvgLength length, double dpi, int font_size)
{
double value = length.length;
@@ -9860,9 +9922,16 @@ svg_css_length_to_pixels (RsvgLength length, double dpi)
case RSVG_UNIT_IN:
value *= dpi;
break;
+#if LIBRSVG_CHECK_VERSION (2, 48, 0)
+ /* We don't know exactly what font size is used on older librsvg
+ versions. */
+ case RSVG_UNIT_EM:
+ value *= font_size;
+ break;
+#endif
default:
- /* Probably one of em, ex, or %. We can't know what the pixel
- value is without more information. */
+ /* Probably ex or %. We can't know what the pixel value is
+ without more information. */
value = 0;
}
@@ -9892,6 +9961,10 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
char *wrapped_contents = NULL;
ptrdiff_t wrapped_size;
+#if LIBRSVG_CHECK_VERSION (2, 48, 0)
+ char *css = NULL;
+#endif
+
#if ! GLIB_CHECK_VERSION (2, 36, 0)
/* g_type_init is a glib function that must be called prior to
using gnome type library functions (obsolete since 2.36.0). */
@@ -9917,6 +9990,26 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
rsvg_handle_set_dpi_x_y (rsvg_handle, FRAME_DISPLAY_INFO (f)->resx,
FRAME_DISPLAY_INFO (f)->resy);
+
+#if LIBRSVG_CHECK_VERSION (2, 48, 0)
+ Lisp_Object lcss = image_spec_value (img->spec, QCcss, NULL);
+ if (!STRINGP (lcss))
+ {
+ /* Generate the CSS for the SVG image. */
+ const char *css_spec = "svg{font-family:\"%s\";font-size:%4dpx}";
+ int css_len = strlen (css_spec) + strlen (img->face_font_family);
+ css = xmalloc (css_len);
+ snprintf (css, css_len, css_spec, img->face_font_family, img->face_font_size);
+ rsvg_handle_set_stylesheet (rsvg_handle, (guint8 *)css, strlen (css), NULL);
+ }
+ else
+ {
+ css = xmalloc (SBYTES (lcss) + 1);
+ strncpy (css, SSDATA (lcss), SBYTES (lcss));
+ *(css + SBYTES (lcss) + 1) = 0;
+ }
+#endif
+
#else
/* Make a handle to a new rsvg object. */
rsvg_handle = rsvg_handle_new ();
@@ -9959,20 +10052,20 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
if (has_width && has_height)
{
/* Success! We can use these values directly. */
- viewbox_width = svg_css_length_to_pixels (iwidth, dpi);
- viewbox_height = svg_css_length_to_pixels (iheight, dpi);
+ viewbox_width = svg_css_length_to_pixels (iwidth, dpi, img->face_font_size);
+ viewbox_height = svg_css_length_to_pixels (iheight, dpi, img->face_font_size);
}
else if (has_width && has_viewbox)
{
- viewbox_width = svg_css_length_to_pixels (iwidth, dpi);
- viewbox_height = svg_css_length_to_pixels (iwidth, dpi)
- * viewbox.width / viewbox.height;
+ viewbox_width = svg_css_length_to_pixels (iwidth, dpi, img->face_font_size);
+ viewbox_height = svg_css_length_to_pixels (iwidth, dpi, img->face_font_size)
+ * viewbox.height / viewbox.width;
}
else if (has_height && has_viewbox)
{
- viewbox_height = svg_css_length_to_pixels (iheight, dpi);
- viewbox_width = svg_css_length_to_pixels (iheight, dpi)
- * viewbox.height / viewbox.width;
+ viewbox_height = svg_css_length_to_pixels (iheight, dpi, img->face_font_size);
+ viewbox_width = svg_css_length_to_pixels (iheight, dpi, img->face_font_size)
+ * viewbox.width / viewbox.height;
}
else if (has_viewbox)
{
@@ -10005,9 +10098,12 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
viewbox_height = dimension_data.height;
}
- compute_image_size (viewbox_width, viewbox_height, img->spec,
+ compute_image_size (viewbox_width, viewbox_height, img,
&width, &height);
+ width *= FRAME_SCALE_FACTOR (f);
+ height *= FRAME_SCALE_FACTOR (f);
+
if (! check_image_size (f, width, height))
{
image_size_error ();
@@ -10090,6 +10186,10 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
rsvg_handle_set_dpi_x_y (rsvg_handle, FRAME_DISPLAY_INFO (f)->resx,
FRAME_DISPLAY_INFO (f)->resy);
+
+#if LIBRSVG_CHECK_VERSION (2, 48, 0)
+ rsvg_handle_set_stylesheet (rsvg_handle, (guint8 *)css, strlen (css), NULL);
+#endif
#else
/* Make a handle to a new rsvg object. */
rsvg_handle = rsvg_handle_new ();
@@ -10123,6 +10223,11 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
g_object_unref (rsvg_handle);
xfree (wrapped_contents);
+#if LIBRSVG_CHECK_VERSION (2, 48, 0)
+ if (!STRINGP (lcss))
+ xfree (css);
+#endif
+
/* Extract some meta data from the svg handle. */
width = gdk_pixbuf_get_width (pixbuf);
height = gdk_pixbuf_get_height (pixbuf);
@@ -10193,6 +10298,10 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
g_object_unref (rsvg_handle);
if (wrapped_contents)
xfree (wrapped_contents);
+#if LIBRSVG_CHECK_VERSION (2, 48, 0)
+ if (css && !STRINGP (lcss))
+ xfree (css);
+#endif
/* FIXME: Use error->message so the user knows what is the actual
problem with the image. */
image_error ("Error parsing SVG image `%s'", img->spec);
@@ -10684,6 +10793,7 @@ non-numeric, there is no explicit limit on the size of images. */);
DEFSYM (QCrotation, ":rotation");
DEFSYM (QCmatrix, ":matrix");
DEFSYM (QCscale, ":scale");
+ DEFSYM (QCtransform_smoothing, ":transform-smoothing");
DEFSYM (QCcolor_adjustment, ":color-adjustment");
DEFSYM (QCmask, ":mask");
@@ -10697,6 +10807,8 @@ non-numeric, there is no explicit limit on the size of images. */);
DEFSYM (QCmax_width, ":max-width");
DEFSYM (QCmax_height, ":max-height");
+ DEFSYM (Qem, "em");
+
#ifdef HAVE_NATIVE_TRANSFORMS
DEFSYM (Qscale, "scale");
DEFSYM (Qrotate, "rotate");
@@ -10783,6 +10895,7 @@ non-numeric, there is no explicit limit on the size of images. */);
#if defined (HAVE_RSVG)
DEFSYM (Qsvg, "svg");
DEFSYM (QCbase_uri, ":base-uri");
+ DEFSYM (QCcss, ":css");
add_image_type (Qsvg);
#ifdef HAVE_NTGUI
/* Other libraries used directly by svg code. */