/* Functions for image support on window system.
-Copyright (C) 1989, 1992-2014 Free Software Foundation, Inc.
+Copyright (C) 1989, 1992-2015 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#define x_defined_color w32_defined_color
#define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
-/* Versions of libpng, libgif, and libjpeg that we were compiled with,
- or -1 if no PNG/GIF support was compiled in. This is tested by
- w32-win.el to correctly set up the alist used to search for the
- respective image libraries. */
-Lisp_Object Qlibpng_version, Qlibgif_version, Qlibjpeg_version;
-
#endif /* HAVE_NTGUI */
+#ifdef USE_CAIRO
+#undef COLOR_TABLE_SUPPORT
+#endif
+
#ifdef HAVE_NS
#undef COLOR_TABLE_SUPPORT
#define DefaultDepthOfScreen(screen) x_display_list->n_planes
#endif /* HAVE_NS */
-
-/* The symbol `postscript' identifying images of this type. */
-
-static Lisp_Object Qpostscript;
-
static void x_disable_image (struct frame *, struct image *);
static void x_edge_detection (struct frame *, struct image *, Lisp_Object,
Lisp_Object);
static unsigned long *colors_in_color_table (int *n);
#endif
-static Lisp_Object QCmax_width, QCmax_height;
-
/* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
id, which is just an int that this section returns. Bitmaps are
reference counted so they can be shared among frames.
#endif /* HAVE_NTGUI */
#ifdef HAVE_NS
- void *bitmap = ns_image_from_XBM (bits, width, height);
+ void *bitmap = ns_image_from_XBM (bits, width, height, 0, 0);
if (!bitmap)
return -1;
#endif
#endif /* HAVE_X_WINDOWS */
-
/***********************************************************************
Image types
***********************************************************************/
static struct image_type *image_types;
-/* The symbol `xbm' which is used as the type symbol for XBM images. */
-
-static Lisp_Object Qxbm;
-
-/* Keywords. */
-
-Lisp_Object QCascent, QCmargin, QCrelief;
-Lisp_Object QCconversion;
-static Lisp_Object QCheuristic_mask;
-static Lisp_Object QCcolor_symbols;
-static Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask, QCgeometry;
-static Lisp_Object QCcrop, QCrotation;
-
-/* Other symbols. */
-
-static Lisp_Object Qcount, Qextension_data, Qdelay;
-static Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
-
/* Forward function prototypes. */
static struct image_type *lookup_image_type (Lisp_Object);
define_image_type (struct image_type *type)
{
struct image_type *p = NULL;
- Lisp_Object target_type = *type->type;
- bool type_valid = 1;
+ int new_type = type->type;
+ bool type_valid = true;
block_input ();
for (p = image_types; p; p = p->next)
- if (EQ (*p->type, target_type))
+ if (p->type == new_type)
goto done;
if (type->init)
{
#if defined HAVE_NTGUI && defined WINDOWSNT
/* If we failed to load the library before, don't try again. */
- Lisp_Object tested = Fassq (target_type, Vlibrary_cache);
+ Lisp_Object tested = Fassq (builtin_lisp_symbol (new_type),
+ Vlibrary_cache);
if (CONSP (tested) && NILP (XCDR (tested)))
- type_valid = 0;
+ type_valid = false;
else
#endif
{
type_valid = type->init ();
- CACHE_IMAGE_TYPE (target_type, type_valid ? Qt : Qnil);
+ CACHE_IMAGE_TYPE (builtin_lisp_symbol (new_type),
+ type_valid ? Qt : Qnil);
}
}
/* We're about to display IMG, so set its timestamp to `now'. */
img->timestamp = current_timespec ();
+#ifndef USE_CAIRO
/* If IMG doesn't have a pixmap yet, load it now, using the image
type dependent loader function. */
if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
unblock_input ();
}
#endif
+#endif
}
return ascent;
}
+#ifdef USE_CAIRO
+static uint32_t
+xcolor_to_argb32 (XColor xc)
+{
+ return (0xff << 24) | ((xc.red / 256) << 16)
+ | ((xc.green / 256) << 8) | (xc.blue / 256);
+}
+
+static uint32_t
+get_spec_bg_or_alpha_as_argb (struct image *img,
+ struct frame *f)
+{
+ uint32_t bgcolor = 0;
+ XColor xbgcolor;
+ Lisp_Object bg = image_spec_value (img->spec, QCbackground, NULL);
+
+ if (STRINGP (bg) && XParseColor (FRAME_X_DISPLAY (f),
+ FRAME_X_COLORMAP (f),
+ SSDATA (bg),
+ &xbgcolor))
+ bgcolor = xcolor_to_argb32 (xbgcolor);
+
+ return bgcolor;
+}
+
+static void
+create_cairo_image_surface (struct image *img,
+ unsigned char *data,
+ int width,
+ int height)
+{
+ cairo_surface_t *surface;
+ cairo_format_t format = CAIRO_FORMAT_ARGB32;
+ int stride = cairo_format_stride_for_width (format, width);
+ surface = cairo_image_surface_create_for_data (data,
+ format,
+ width,
+ height,
+ stride);
+ img->width = width;
+ img->height = height;
+ img->cr_data = surface;
+ img->cr_data2 = data;
+ img->pixmap = 0;
+}
+#endif
+
+
\f
/* Image background colors. */
x_clear_image (struct frame *f, struct image *img)
{
block_input ();
+#ifdef USE_CAIRO
+ if (img->cr_data)
+ cairo_surface_destroy ((cairo_surface_t *)img->cr_data);
+ if (img->cr_data2) xfree (img->cr_data2);
+#endif
x_clear_image_1 (f, img,
CLEAR_IMAGE_PIXMAP | CLEAR_IMAGE_MASK | CLEAR_IMAGE_COLORS);
unblock_input ();
/* Do image transformations and compute masks, unless we
don't have the image yet. */
- if (!EQ (*img->type->type, Qpostscript))
+ if (!EQ (builtin_lisp_symbol (img->type->type), Qpostscript))
postprocess_image (f, img);
}
static struct image_type xbm_type =
{
- &Qxbm,
+ SYMBOL_INDEX (Qxbm),
xbm_image_p,
xbm_load,
x_clear_image,
convert_mono_to_color_image (f, img, fg, bg);
#elif defined (HAVE_NS)
- img->pixmap = ns_image_from_XBM (data, img->width, img->height);
+ img->pixmap = ns_image_from_XBM (data, img->width, img->height, fg, bg);
#else
img->pixmap =
#endif /* HAVE_XPM */
#if defined (HAVE_XPM) || defined (HAVE_NS)
-/* The symbol `xpm' identifying XPM-format images. */
-
-static Lisp_Object Qxpm;
/* Indices of image specification fields in xpm_format, below. */
static struct image_type xpm_type =
{
- &Qxpm,
+ SYMBOL_INDEX (Qxpm),
xpm_image_p,
xpm_load,
x_clear_image,
color allocation failures more gracefully than the ones on the XPM
lib. */
+#ifndef USE_CAIRO
#if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
#define ALLOC_XPM_COLORS
#endif
+#endif /* USE_CAIRO */
#endif /* HAVE_X_WINDOWS */
#ifdef ALLOC_XPM_COLORS
#endif /* HAVE_NTGUI */
}
+#ifdef USE_CAIRO
+ // Load very specific Xpm:s.
+ if (rc == XpmSuccess
+ && img->ximg->format == ZPixmap
+ && img->ximg->bits_per_pixel == 32
+ && (! img->mask_img || img->mask_img->bits_per_pixel == 1))
+ {
+ int width = img->ximg->width;
+ int height = img->ximg->height;
+ unsigned char *data = (unsigned char *) xmalloc (width*height*4);
+ int i;
+ uint32_t *od = (uint32_t *)data;
+ uint32_t *id = (uint32_t *)img->ximg->data;
+ char *mid = img->mask_img ? img->mask_img->data : 0;
+ uint32_t bgcolor = get_spec_bg_or_alpha_as_argb (img, f);
+
+ for (i = 0; i < height; ++i)
+ {
+ int k;
+ for (k = 0; k < width; ++k)
+ {
+ int idx = i * img->ximg->bytes_per_line/4 + k;
+ int maskidx = mid ? i * img->mask_img->bytes_per_line + k/8 : 0;
+ int mask = mid ? mid[maskidx] & (1 << (k % 8)) : 1;
+
+ if (mask) od[idx] = id[idx] + 0xff000000; // ff => full alpha
+ else od[idx] = bgcolor;
+ }
+ }
+
+ create_cairo_image_surface (img, data, width, height);
+ }
+ else
+ {
+ rc = XpmFileInvalid;
+ x_clear_image (f, img);
+ }
+#else
#ifdef HAVE_X_WINDOWS
if (rc == XpmSuccess)
{
}
}
#endif
+#endif /* ! USE_CAIRO */
if (rc == XpmSuccess)
{
Colormap cmap;
bool rc;
- if (ct_colors_allocated_max <= ct_colors_allocated)
+ if (ct_colors_allocated >= ct_colors_allocated_max)
return FRAME_FOREGROUND_PIXEL (f);
#ifdef HAVE_X_WINDOWS
HGDIOBJ prev;
#endif /* HAVE_NTGUI */
- if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *colors / img->width < img->height)
+ if (img->height > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *colors / img->width)
memory_full (SIZE_MAX);
colors = xmalloc (sizeof *colors * img->width * img->height);
#define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
- if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *new / img->width < img->height)
+ if (img->height > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *new / img->width)
memory_full (SIZE_MAX);
new = xmalloc (sizeof *new * img->width * img->height);
if (i == 3 && NILP (how))
{
char color_name[30];
- sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
+ sprintf (color_name, "#%04x%04x%04x",
+ rgb[0] + 0u, rgb[1] + 0u, rgb[2] + 0u);
bg = (
#ifdef HAVE_NTGUI
0x00ffffff & /* Filter out palette info. */
static bool pbm_image_p (Lisp_Object object);
static bool pbm_load (struct frame *f, struct image *img);
-/* The symbol `pbm' identifying images of this type. */
-
-static Lisp_Object Qpbm;
-
/* Indices of image specification fields in gs_format, below. */
enum pbm_keyword_index
static struct image_type pbm_type =
{
- &Qpbm,
+ SYMBOL_INDEX (Qpbm),
pbm_image_p,
pbm_load,
x_clear_image,
bool raw_p;
int x, y;
int width, height, max_color_idx = 0;
- XImagePtr ximg;
Lisp_Object file, specified_file;
enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
unsigned char *contents = NULL;
unsigned char *end, *p;
ptrdiff_t size;
+#ifdef USE_CAIRO
+ unsigned char *data = 0;
+ uint32_t *dataptr;
+#else
+ XImagePtr ximg;
+#endif
specified_file = image_spec_value (img->spec, QCfile, NULL);
width = pbm_scan_number (&p, end);
height = pbm_scan_number (&p, end);
+#ifdef USE_CAIRO
+ data = (unsigned char *) xmalloc (width * height * 4);
+ dataptr = (uint32_t *) data;
+#endif
+
if (type != PBM_MONO)
{
max_color_idx = pbm_scan_number (&p, end);
goto error;
}
+#ifndef USE_CAIRO
if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
goto error;
+#endif
/* Initialize the color hash table. */
init_color_table ();
struct image_keyword fmt[PBM_LAST];
unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
-
+#ifdef USE_CAIRO
+ XColor xfg, xbg;
+ int fga32, bga32;
+#endif
/* Parse the image specification. */
memcpy (fmt, pbm_format, sizeof fmt);
parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
/* Get foreground and background colors, maybe allocate colors. */
+#ifdef USE_CAIRO
+ if (! fmt[PBM_FOREGROUND].count
+ || ! STRINGP (fmt[PBM_FOREGROUND].value)
+ || ! x_defined_color (f, SSDATA (fmt[PBM_FOREGROUND].value), &xfg, 0))
+ {
+ xfg.pixel = fg;
+ x_query_color (f, &xfg);
+ }
+ fga32 = xcolor_to_argb32 (xfg);
+
+ if (! fmt[PBM_BACKGROUND].count
+ || ! STRINGP (fmt[PBM_BACKGROUND].value)
+ || ! x_defined_color (f, SSDATA (fmt[PBM_BACKGROUND].value), &xbg, 0))
+ {
+ xbg.pixel = bg;
+ x_query_color (f, &xbg);
+ }
+ bga32 = xcolor_to_argb32 (xbg);
+#else
if (fmt[PBM_FOREGROUND].count
&& STRINGP (fmt[PBM_FOREGROUND].value))
fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
img->background = bg;
img->background_valid = 1;
}
+#endif
for (y = 0; y < height; ++y)
for (x = 0; x < width; ++x)
{
if (p >= end)
{
+#ifdef USE_CAIRO
+ xfree (data);
+#else
x_destroy_x_image (ximg);
+#endif
x_clear_image (f, img);
image_error ("Invalid image size in image `%s'",
img->spec, Qnil);
else
g = pbm_scan_number (&p, end);
+#ifdef USE_CAIRO
+ *dataptr++ = g ? fga32 : bga32;
+#else
XPutPixel (ximg, x, y, g ? fg : bg);
+#endif
}
}
else
if (raw_p && p + expected_size > end)
{
+#ifdef USE_CAIRO
+ xfree (data);
+#else
x_destroy_x_image (ximg);
+#endif
x_clear_image (f, img);
image_error ("Invalid image size in image `%s'",
img->spec, Qnil);
if (r < 0 || g < 0 || b < 0)
{
+#ifdef USE_CAIRO
+ xfree (data);
+#else
x_destroy_x_image (ximg);
+#endif
image_error ("Invalid pixel value in image `%s'",
img->spec, Qnil);
goto error;
}
+#ifdef USE_CAIRO
+ r = (double) r * 255 / max_color_idx;
+ g = (double) g * 255 / max_color_idx;
+ b = (double) b * 255 / max_color_idx;
+ *dataptr++ = (0xff << 24) | (r << 16) | (g << 8) | b;
+#else
/* RGB values are now in the range 0..max_color_idx.
Scale this to the range 0..0xffff supported by X. */
r = (double) r * 65535 / max_color_idx;
g = (double) g * 65535 / max_color_idx;
b = (double) b * 65535 / max_color_idx;
XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
+#endif
}
}
/* Maybe fill in the background field while we have ximg handy. */
+#ifdef USE_CAIRO
+ create_cairo_image_surface (img, data, width, height);
+#else
if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
/* Casting avoids a GCC warning. */
IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
/* Put ximg into the image. */
image_put_x_image (f, img, ximg, 0);
+#endif
/* X and W32 versions did it here, MAC version above. ++kfs
img->width = width;
PNG
***********************************************************************/
-#if defined (HAVE_PNG) || defined (HAVE_NS)
+#if defined (HAVE_PNG) || defined (HAVE_NS) || defined (USE_CAIRO)
/* Function prototypes. */
static bool png_image_p (Lisp_Object object);
static bool png_load (struct frame *f, struct image *img);
-/* The symbol `png' identifying images of this type. */
-
-static Lisp_Object Qpng;
-
/* Indices of image specification fields in png_format, below. */
enum png_keyword_index
static struct image_type png_type =
{
- &Qpng,
+ SYMBOL_INDEX (Qpng),
png_image_p,
png_load,
x_clear_image,
return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
}
-#endif /* HAVE_PNG || HAVE_NS */
+#endif /* HAVE_PNG || HAVE_NS || USE_CAIRO */
-#if defined HAVE_PNG && !defined HAVE_NS
+#if (defined HAVE_PNG && !defined HAVE_NS) || defined USE_CAIRO
# ifdef WINDOWSNT
/* PNG library details. */
Lisp_Object specified_data;
int x, y;
ptrdiff_t i;
- XImagePtr ximg, mask_img = NULL;
png_struct *png_ptr;
png_info *info_ptr = NULL, *end_info = NULL;
FILE *fp = NULL;
bool transparent_p;
struct png_memory_storage tbr; /* Data to be read */
+#ifdef USE_CAIRO
+ unsigned char *data = 0;
+ uint32_t *dataptr;
+#else
+ XImagePtr ximg, mask_img = NULL;
+#endif
+
/* Find out what file to load. */
specified_file = image_spec_value (img->spec, QCfile, NULL);
specified_data = image_spec_value (img->spec, QCdata, NULL);
+ IF_LINT (Lisp_Object volatile specified_data_volatile = specified_data);
if (NILP (specified_data))
{
/* Silence a bogus diagnostic; see GCC bug 54561. */
IF_LINT (fp = c->fp);
+ IF_LINT (specified_data = specified_data_volatile);
/* Read image info. */
if (!NILP (specified_data))
goto error;
}
+#ifndef USE_CAIRO
/* Create the X image and pixmap now, so that the work below can be
omitted if the image is too large for X. */
if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
goto error;
+#endif
/* If image contains simply transparency data, we prefer to
construct a clipping mask. */
row_bytes = png_get_rowbytes (png_ptr, info_ptr);
/* Allocate memory for the image. */
- if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *rows < height
- || min (PTRDIFF_MAX, SIZE_MAX) / sizeof *pixels / height < row_bytes)
+ if (height > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *rows
+ || row_bytes > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *pixels / height)
memory_full (SIZE_MAX);
c->pixels = pixels = xmalloc (sizeof *pixels * row_bytes * height);
c->rows = rows = xmalloc (height * sizeof *rows);
c->fp = NULL;
}
+#ifdef USE_CAIRO
+ data = (unsigned char *) xmalloc (width * height * 4);
+ dataptr = (uint32_t *) data;
+#else
/* Create an image and pixmap serving as mask if the PNG image
contains an alpha channel. */
if (channels == 4
x_clear_image_1 (f, img, CLEAR_IMAGE_PIXMAP);
goto error;
}
+#endif
/* Fill the X image and mask from PNG data. */
init_color_table ();
{
int r, g, b;
+#ifdef USE_CAIRO
+ int a = 0xff;
+ r = *p++;
+ g = *p++;
+ b = *p++;
+ if (channels == 4) a = *p++;
+ *dataptr++ = (a << 24) | (r << 16) | (g << 8) | b;
+#else
r = *p++ << 8;
g = *p++ << 8;
b = *p++ << 8;
XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN);
++p;
}
+#endif
}
}
img->width = width;
img->height = height;
+#ifdef USE_CAIRO
+ create_cairo_image_surface (img, data, width, height);
+#else
/* Maybe fill in the background field while we have ximg handy.
Casting avoids a GCC warning. */
IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
image_put_x_image (f, img, mask_img, 1);
}
+#endif
return 1;
}
image_spec_value (img->spec, QCdata, NULL));
}
+
#endif /* HAVE_NS */
static bool jpeg_image_p (Lisp_Object object);
static bool jpeg_load (struct frame *f, struct image *img);
-/* The symbol `jpeg' identifying images of this type. */
-
-static Lisp_Object Qjpeg;
-
/* Indices of image specification fields in gs_format, below. */
enum jpeg_keyword_index
static struct image_type jpeg_type =
{
- &Qjpeg,
+ SYMBOL_INDEX (Qjpeg),
jpeg_image_p,
jpeg_load,
x_clear_image,
FILE * IF_LINT (volatile) fp = NULL;
JSAMPARRAY buffer;
int row_stride, x, y;
- XImagePtr ximg = NULL;
unsigned long *colors;
int width, height;
+ int i, ir, ig, ib;
+#ifndef USE_CAIRO
+ XImagePtr ximg = NULL;
+#endif
/* Open the JPEG file. */
specified_file = image_spec_value (img->spec, QCfile, NULL);
specified_data = image_spec_value (img->spec, QCdata, NULL);
+ IF_LINT (Lisp_Object volatile specified_data_volatile = specified_data);
if (NILP (specified_data))
{
jpeg_destroy_decompress (&mgr->cinfo);
/* If we already have an XImage, free that. */
+#ifndef USE_CAIRO
x_destroy_x_image (ximg);
-
+#endif
/* Free pixmap and colors. */
x_clear_image (f, img);
return 0;
}
+ /* Silence a bogus diagnostic; see GCC bug 54561. */
+ IF_LINT (specified_data = specified_data_volatile);
+
/* Create the JPEG decompression object. Let it read from fp.
Read the JPEG image header. */
jpeg_CreateDecompress (&mgr->cinfo, JPEG_LIB_VERSION, sizeof *&mgr->cinfo);
sys_longjmp (mgr->setjmp_buffer, 1);
}
+#ifndef USE_CAIRO
/* Create X image and pixmap. */
if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
{
mgr->failure_code = MY_JPEG_CANNOT_CREATE_X;
sys_longjmp (mgr->setjmp_buffer, 1);
}
+#endif
/* Allocate colors. When color quantization is used,
mgr->cinfo.actual_number_of_colors has been set with the number of
No more than 255 colors will be generated. */
USE_SAFE_ALLOCA;
{
- int i, ir, ig, ib;
-
if (mgr->cinfo.out_color_components > 2)
ir = 0, ig = 1, ib = 2;
else if (mgr->cinfo.out_color_components > 1)
else
ir = 0, ig = 0, ib = 0;
+#ifndef CAIRO
/* Use the color table mechanism because it handles colors that
cannot be allocated nicely. Such colors will be replaced with
a default color, and we don't have to care about which colors
int b = mgr->cinfo.colormap[ib][i] << 8;
colors[i] = lookup_rgb_color (f, r, g, b);
}
+#endif
#ifdef COLOR_TABLE_SUPPORT
/* Remember those colors actually allocated. */
row_stride = width * mgr->cinfo.output_components;
buffer = mgr->cinfo.mem->alloc_sarray ((j_common_ptr) &mgr->cinfo,
JPOOL_IMAGE, row_stride, 1);
+#ifdef USE_CAIRO
+ {
+ unsigned char *data = (unsigned char *) xmalloc (width*height*4);
+ uint32_t *dataptr = (uint32_t *) data;
+ int r, g, b;
+
+ for (y = 0; y < height; ++y)
+ {
+ jpeg_read_scanlines (&mgr->cinfo, buffer, 1);
+
+ for (x = 0; x < width; ++x)
+ {
+ i = buffer[0][x];
+ r = mgr->cinfo.colormap[ir][i];
+ g = mgr->cinfo.colormap[ig][i];
+ b = mgr->cinfo.colormap[ib][i];
+ *dataptr++ = (0xff << 24) | (r << 16) | (g << 8) | b;
+ }
+ }
+
+ create_cairo_image_surface (img, data, width, height);
+ }
+#else
for (y = 0; y < height; ++y)
{
jpeg_read_scanlines (&mgr->cinfo, buffer, 1);
for (x = 0; x < mgr->cinfo.output_width; ++x)
XPutPixel (ximg, x, y, colors[buffer[0][x]]);
}
+#endif
/* Clean up. */
jpeg_finish_decompress (&mgr->cinfo);
if (fp)
fclose (fp);
+#ifndef USE_CAIRO
/* Maybe fill in the background field while we have ximg handy. */
if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
/* Casting avoids a GCC warning. */
/* Put ximg into the image. */
image_put_x_image (f, img, ximg, 0);
+#endif
SAFE_FREE ();
return 1;
}
static bool tiff_image_p (Lisp_Object object);
static bool tiff_load (struct frame *f, struct image *img);
-/* The symbol `tiff' identifying images of this type. */
-
-static Lisp_Object Qtiff;
-
/* Indices of image specification fields in tiff_format, below. */
enum tiff_keyword_index
static struct image_type tiff_type =
{
- &Qtiff,
+ SYMBOL_INDEX (Qtiff),
tiff_image_p,
tiff_load,
x_clear_image,
return 0;
}
+#ifdef USE_CAIRO
+ {
+ unsigned char *data = (unsigned char *) xmalloc (width*height*4);
+ uint32_t *dataptr = (uint32_t *) data;
+ int r, g, b, a;
+
+ for (y = 0; y < height; ++y)
+ {
+ uint32 *row = buf + (height - 1 - y) * width;
+ for (x = 0; x < width; ++x)
+ {
+ uint32 abgr = row[x];
+ int r = TIFFGetR (abgr);
+ int g = TIFFGetG (abgr);
+ int b = TIFFGetB (abgr);
+ int a = TIFFGetA (abgr);
+ *dataptr++ = (a << 24) | (r << 16) | (g << 8) | b;
+ }
+ }
+
+ create_cairo_image_surface (img, data, width, height);
+ }
+#else
/* Initialize the color table. */
init_color_table ();
/* Put ximg into the image. */
image_put_x_image (f, img, ximg, 0);
- xfree (buf);
+#endif /* ! USE_CAIRO */
+
+ xfree (buf);
return 1;
}
static bool gif_load (struct frame *f, struct image *img);
static void gif_clear_image (struct frame *f, struct image *img);
-/* The symbol `gif' identifying images of this type. */
-
-static Lisp_Object Qgif;
-
/* Indices of image specification fields in gif_format, below. */
enum gif_keyword_index
static struct image_type gif_type =
{
- &Qgif,
+ SYMBOL_INDEX (Qgif),
gif_image_p,
gif_load,
gif_clear_image,
# ifdef WINDOWSNT
/* GIF library details. */
-# if 5 < GIFLIB_MAJOR + (1 <= GIFLIB_MINOR)
+# if GIFLIB_MAJOR + (GIFLIB_MINOR >= 1) > 5
DEF_DLL_FN (int, DGifCloseFile, (GifFileType *, int *));
# else
DEF_DLL_FN (int, DGifCloseFile, (GifFileType *));
{
int retval;
-#if 5 < GIFLIB_MAJOR + (1 <= GIFLIB_MINOR)
+#if GIFLIB_MAJOR + (GIFLIB_MINOR >= 1) > 5
retval = DGifCloseFile (gif, err);
#else
retval = DGifCloseFile (gif);
{
Lisp_Object file;
int rc, width, height, x, y, i, j;
- XImagePtr ximg;
ColorMapObject *gif_color_map;
unsigned long pixel_colors[256];
GifFileType *gif;
EMACS_INT idx;
int gif_err;
+#ifdef USE_CAIRO
+ unsigned char *data = 0;
+#else
+ XImagePtr ximg;
+#endif
+
if (NILP (specified_data))
{
file = x_find_image_file (specified_file);
int subimg_height = subimage->ImageDesc.Height;
int subimg_top = subimage->ImageDesc.Top;
int subimg_left = subimage->ImageDesc.Left;
- if (! (0 <= subimg_width && 0 <= subimg_height
+ if (! (subimg_width >= 0 && subimg_height >= 0
&& 0 <= subimg_top && subimg_top <= height - subimg_height
&& 0 <= subimg_left && subimg_left <= width - subimg_width))
{
}
}
+#ifdef USE_CAIRO
+ /* xzalloc so data is zero => transparent */
+ data = (unsigned char *) xzalloc (width * height * 4);
+ if (STRINGP (specified_bg))
+ {
+ XColor color;
+ if (x_defined_color (f, SSDATA (specified_bg), &color, 0))
+ {
+ uint32_t *dataptr = (uint32_t *)data;
+ int r = color.red/256;
+ int g = color.green/256;
+ int b = color.blue/256;
+
+ for (y = 0; y < height; ++y)
+ for (x = 0; x < width; ++x)
+ *dataptr++ = (0xff << 24) | (r << 16) | (g << 8) | b;
+ }
+ }
+#else
/* Create the X image and pixmap. */
if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
{
for (x = img->corners[RIGHT_CORNER]; x < width; ++x)
XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
}
+#endif
/* Read the GIF image into the X image. */
if (disposal == 0)
disposal = 1;
- /* Allocate subimage colors. */
- memset (pixel_colors, 0, sizeof pixel_colors);
gif_color_map = subimage->ImageDesc.ColorMap;
if (!gif_color_map)
gif_color_map = gif->SColorMap;
+#ifndef USE_CAIRO
+ /* Allocate subimage colors. */
+ memset (pixel_colors, 0, sizeof pixel_colors);
+
if (gif_color_map)
for (i = 0; i < gif_color_map->ColorCount; ++i)
{
pixel_colors[i] = lookup_rgb_color (f, r, g, b);
}
}
+#endif
/* Apply the pixel values. */
if (GIFLIB_MAJOR < 5 && gif->SavedImages[j].ImageDesc.Interlace)
{
int c = raster[y * subimg_width + x];
if (transparency_color_index != c || disposal != 1)
- XPutPixel (ximg, x + subimg_left, row + subimg_top,
- pixel_colors[c]);
+ {
+#ifdef USE_CAIRO
+ uint32_t *dataptr =
+ ((uint32_t*)data + ((row + subimg_top) * subimg_width
+ + x + subimg_left));
+ int r = gif_color_map->Colors[c].Red;
+ int g = gif_color_map->Colors[c].Green;
+ int b = gif_color_map->Colors[c].Blue;
+
+ if (transparency_color_index != c)
+ *dataptr = (0xff << 24) | (r << 16) | (g << 8) | b;
+#else
+ XPutPixel (ximg, x + subimg_left, row + subimg_top,
+ pixel_colors[c]);
+#endif
+ }
}
}
}
else
{
- for (y = 0; y < subimg_height; ++y)
+ for (y = 0; y < subimg_height; ++y)
for (x = 0; x < subimg_width; ++x)
{
int c = raster[y * subimg_width + x];
if (transparency_color_index != c || disposal != 1)
- XPutPixel (ximg, x + subimg_left, y + subimg_top,
- pixel_colors[c]);
+ {
+#ifdef USE_CAIRO
+ uint32_t *dataptr =
+ ((uint32_t*)data + ((y + subimg_top) * subimg_width
+ + x + subimg_left));
+ int r = gif_color_map->Colors[c].Red;
+ int g = gif_color_map->Colors[c].Green;
+ int b = gif_color_map->Colors[c].Blue;
+ if (transparency_color_index != c)
+ *dataptr = (0xff << 24) | (r << 16) | (g << 8) | b;
+#else
+ XPutPixel (ximg, x + subimg_left, y + subimg_top,
+ pixel_colors[c]);
+#endif
+ }
}
}
}
#endif
}
+#ifdef USE_CAIRO
+ create_cairo_image_surface (img, data, width, height);
+#else
/* Maybe fill in the background field while we have ximg handy. */
if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
/* Casting avoids a GCC warning. */
/* Put ximg into the image. */
image_put_x_image (f, img, ximg, 0);
+#endif
return 1;
}
*d_height = desired_height;
}
-static Lisp_Object Qimagemagick;
-
static bool imagemagick_image_p (Lisp_Object);
static bool imagemagick_load (struct frame *, struct image *);
static void imagemagick_clear_image (struct frame *, struct image *);
static struct image_type imagemagick_type =
{
- &Qimagemagick,
+ SYMBOL_INDEX (Qimagemagick),
imagemagick_image_p,
imagemagick_load,
imagemagick_clear_image,
static bool svg_load_image (struct frame *, struct image *,
unsigned char *, ptrdiff_t, char *);
-/* The symbol `svg' identifying images of this type. */
-
-static Lisp_Object Qsvg;
-
/* Indices of image specification fields in svg_format, below. */
enum svg_keyword_index
static struct image_type svg_type =
{
- &Qsvg,
+ SYMBOL_INDEX (Qsvg),
svg_image_p,
svg_load,
x_clear_image,
DEF_DLL_FN (void, g_object_unref, (gpointer));
DEF_DLL_FN (void, g_error_free, (GError *));
-Lisp_Object Qgdk_pixbuf, Qglib, Qgobject;
-
static bool
init_svg_functions (void)
{
eassert (gdk_pixbuf_get_has_alpha (pixbuf));
eassert (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
+#ifdef USE_CAIRO
+ {
+ unsigned char *data = (unsigned char *) xmalloc (width*height*4);
+ int y;
+ uint32_t bgcolor = get_spec_bg_or_alpha_as_argb (img, f);
+
+ for (y = 0; y < height; ++y)
+ {
+ const guchar *iconptr = pixels + y * rowstride;
+ uint32_t *dataptr = (uint32_t *) (data + y * rowstride);
+ int x;
+
+ for (x = 0; x < width; ++x)
+ {
+ if (iconptr[3] == 0)
+ *dataptr = bgcolor;
+ else
+ *dataptr = (iconptr[0] << 16)
+ | (iconptr[1] << 8)
+ | iconptr[2]
+ | (iconptr[3] << 24);
+
+ iconptr += 4;
+ ++dataptr;
+ }
+ }
+
+ create_cairo_image_surface (img, data, width, height);
+ g_object_unref (pixbuf);
+ }
+#else
/* Try to create a x pixmap to hold the svg pixmap. */
if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
{
/* Put ximg into the image. */
image_put_x_image (f, img, ximg, 0);
+#endif /* ! USE_CAIRO */
return 1;
static bool gs_load (struct frame *f, struct image *img);
static void gs_clear_image (struct frame *f, struct image *img);
-/* Keyword symbols. */
-
-static Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
-
/* Indices of image specification fields in gs_format, below. */
enum gs_keyword_index
static struct image_type gs_type =
{
- &Qpostscript,
+ SYMBOL_INDEX (Qpostscript),
gs_image_p,
gs_load,
gs_clear_image,
/* For each pixel of the image, look its color up in the
color table. After having done so, the color table will
contain an entry for each color used by the image. */
+#ifdef COLOR_TABLE_SUPPORT
for (y = 0; y < img->height; ++y)
for (x = 0; x < img->width; ++x)
{
unsigned long pixel = XGetPixel (ximg, x, y);
+
lookup_pixel_color (f, pixel);
}
/* Record colors in the image. Free color table and XImage. */
-#ifdef COLOR_TABLE_SUPPORT
img->colors = colors_in_color_table (&img->ncolors);
free_color_table ();
#endif
}
-DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
+DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0,
+ doc: /* */)
(Lisp_Object spec)
{
ptrdiff_t id = -1;
return define_image_type (&gif_type);
#endif
-#if defined (HAVE_PNG) || defined (HAVE_NS)
+#if defined (HAVE_PNG) || defined (HAVE_NS) || defined (USE_CAIRO)
if (EQ (type, Qpng))
return define_image_type (&png_type);
#endif
non-numeric, there is no explicit limit on the size of images. */);
Vmax_image_size = make_float (MAX_IMAGE_SIZE);
+ /* Other symbols. */
DEFSYM (Qcount, "count");
DEFSYM (Qextension_data, "extension-data");
DEFSYM (Qdelay, "delay");
+ /* Keywords. */
DEFSYM (QCascent, ":ascent");
DEFSYM (QCmargin, ":margin");
DEFSYM (QCrelief, ":relief");
DEFSYM (QCcolor_symbols, ":color-symbols");
DEFSYM (QCheuristic_mask, ":heuristic-mask");
DEFSYM (QCindex, ":index");
- DEFSYM (QCgeometry, ":geometry");
DEFSYM (QCcrop, ":crop");
DEFSYM (QCrotation, ":rotation");
DEFSYM (QCmatrix, ":matrix");
DEFSYM (QCcolor_adjustment, ":color-adjustment");
DEFSYM (QCmask, ":mask");
+ /* Other symbols. */
DEFSYM (Qlaplace, "laplace");
DEFSYM (Qemboss, "emboss");
DEFSYM (Qedge_detection, "edge-detection");
#ifdef HAVE_GHOSTSCRIPT
ADD_IMAGE_TYPE (Qpostscript);
DEFSYM (QCloader, ":loader");
- DEFSYM (QCbounding_box, ":bounding-box");
DEFSYM (QCpt_width, ":pt-width");
DEFSYM (QCpt_height, ":pt-height");
#endif /* HAVE_GHOSTSCRIPT */
#ifdef HAVE_NTGUI
+ /* Versions of libpng, libgif, and libjpeg that we were compiled with,
+ or -1 if no PNG/GIF support was compiled in. This is tested by
+ w32-win.el to correctly set up the alist used to search for the
+ respective image libraries. */
DEFSYM (Qlibpng_version, "libpng-version");
Fset (Qlibpng_version,
#if HAVE_PNG