# HG changeset patch # User Jason Rumney # Date 1016659076 0 # Node ID 73645cbc79a72a3be1860f83d234bc2731119438 # Parent 994f2deaa5bc236faff473727ae34d09e015e422 (x_set_cursor_color): Set foreground of cursor, not frame. (Fimage_size, Fimage_mask_p, XPutPixel): New functions. (four_corners_best, x_clear_image_1, x_clear_image) (x_alloc_image_color, postprocess_image) (x_create_x_image_and_pixmap, x_destroy_x_image, xbm_load_image) (x_from_x_colors, x_disable_image, pbm_load): Adapt for Windows. (init_xfns, syms_of_w32fns): Initialize image functions and constants. diff -r 994f2deaa5bc -r 73645cbc79a7 src/w32fns.c --- a/src/w32fns.c Wed Mar 20 21:00:50 2002 +0000 +++ b/src/w32fns.c Wed Mar 20 21:17:56 2002 +0000 @@ -2287,7 +2287,7 @@ fore_pixel = FRAME_BACKGROUND_PIXEL (f); } - FRAME_FOREGROUND_PIXEL (f) = fore_pixel; + f->output_data.w32->cursor_foreground_pixel = fore_pixel; f->output_data.w32->cursor_pixel = pixel; if (FRAME_W32_WINDOW (f) != 0) @@ -6640,8 +6640,8 @@ char height_dpi[8]; char width_pixels[8]; char *fontname_dash; - int display_resy = one_w32_display_info.resy; - int display_resx = one_w32_display_info.resx; + int display_resy = (int) one_w32_display_info.resy; + int display_resx = (int) one_w32_display_info.resx; int bufsz; struct coding_system coding; @@ -6757,7 +6757,7 @@ char name[50], weight[20], slant, pitch, pixels[10], height[10], width[10], resy[10], remainder[50]; char * encoding; - int dpi = one_w32_display_info.resy; + int dpi = (int) one_w32_display_info.resy; fields = sscanf (lpxstr, "-%*[^-]-%49[^-]-%19[^-]-%c-%*[^-]-%*[^-]-%9[^-]-%9[^-]-%*[^-]-%9[^-]-%c-%9[^-]-%49s", @@ -8499,6 +8499,64 @@ } +#ifdef HAVE_IMAGES +DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0, + doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT). +PIXELS non-nil means return the size in pixels, otherwise return the +size in canonical character units. +FRAME is the frame on which the image will be displayed. FRAME nil +or omitted means use the selected frame. */) + (spec, pixels, frame) + Lisp_Object spec, pixels, frame; +{ + Lisp_Object size; + + size = Qnil; + if (valid_image_p (spec)) + { + struct frame *f = check_x_frame (frame); + int id = lookup_image (f, spec); + struct image *img = IMAGE_FROM_ID (f, id); + int width = img->width + 2 * img->hmargin; + int height = img->height + 2 * img->vmargin; + + if (NILP (pixels)) + size = Fcons (make_float ((double) width / CANON_X_UNIT (f)), + make_float ((double) height / CANON_Y_UNIT (f))); + else + size = Fcons (make_number (width), make_number (height)); + } + else + error ("Invalid image specification"); + + return size; +} + + +DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0, + doc: /* Return t if image SPEC has a mask bitmap. +FRAME is the frame on which the image will be displayed. FRAME nil +or omitted means use the selected frame. */) + (spec, frame) + Lisp_Object spec, frame; +{ + Lisp_Object mask; + + mask = Qnil; + if (valid_image_p (spec)) + { + struct frame *f = check_x_frame (frame); + int id = lookup_image (f, spec); + struct image *img = IMAGE_FROM_ID (f, id); + if (img->mask) + mask = Qt; + } + else + error ("Invalid image specification"); + + return mask; +} +#endif /*********************************************************************** @@ -8601,7 +8659,7 @@ ascent = height / 2; } else - ascent = height * img->ascent / 100.0; + ascent = (int) (height * img->ascent / 100.0); return ascent; } @@ -8610,20 +8668,21 @@ /* Image background colors. */ -static unsigned long +/* Find the "best" corner color of a bitmap. XIMG is assumed to a device + context with the bitmap selected. */ +static COLORREF four_corners_best (ximg, width, height) - XImage *ximg; + HDC ximg; unsigned long width, height; { -#if 0 /* TODO: Image support. */ - unsigned long corners[4], best; + COLORREF corners[4], best; int i, best_count; /* Get the colors at the corners of ximg. */ - corners[0] = XGetPixel (ximg, 0, 0); - corners[1] = XGetPixel (ximg, width - 1, 0); - corners[2] = XGetPixel (ximg, width - 1, height - 1); - corners[3] = XGetPixel (ximg, 0, height - 1); + corners[0] = GetPixel (ximg, 0, 0); + corners[1] = GetPixel (ximg, width - 1, 0); + corners[2] = GetPixel (ximg, width - 1, height - 1); + corners[3] = GetPixel (ximg, 0, height - 1); /* Choose the most frequently found color as background. */ for (i = best_count = 0; i < 4; ++i) @@ -8639,9 +8698,6 @@ } return best; -#else - return 0; -#endif } /* Return the `background' field of IMG. If IMG doesn't have one yet, @@ -8739,18 +8795,17 @@ struct image *img; int pixmap_p, mask_p, colors_p; { -#if 0 /* TODO: W32 image support */ if (pixmap_p && img->pixmap) { - XFreePixmap (FRAME_X_DISPLAY (f), img->pixmap); - img->pixmap = None; + DeleteObject (img->pixmap); + img->pixmap = NULL; img->background_valid = 0; } if (mask_p && img->mask) { - XFreePixmap (FRAME_X_DISPLAY (f), img->mask); - img->mask = None; + DeleteObject (img->mask); + img->mask = NULL; img->background_transparent_valid = 0; } @@ -8761,7 +8816,6 @@ img->colors = NULL; img->ncolors = 0; } -#endif } /* Free X resources of image IMG which is used on frame F. */ @@ -8771,18 +8825,18 @@ struct frame *f; struct image *img; { -#if 0 /* TODO: W32 image support */ - if (img->pixmap) { BLOCK_INPUT; - XFreePixmap (NULL, img->pixmap); + DeleteObject (img->pixmap); img->pixmap = 0; UNBLOCK_INPUT; } if (img->ncolors) { +#if 0 /* TODO: color table support */ + int class = FRAME_W32_DISPLAY_INFO (f)->visual->class; /* If display has an immutable color map, freeing colors is not @@ -8798,12 +8852,12 @@ img->ncolors, 0); UNBLOCK_INPUT; } +#endif xfree (img->colors); img->colors = NULL; img->ncolors = 0; } -#endif } @@ -8819,7 +8873,6 @@ Lisp_Object color_name; unsigned long dflt; { -#if 0 /* TODO: allocing colors. */ XColor color; unsigned long result; @@ -8839,8 +8892,6 @@ else result = dflt; return result; -#endif - return 0; } @@ -9016,7 +9067,7 @@ } else if (NILP (mask) && found_p && img->mask) { - XFreePixmap (FRAME_X_DISPLAY (f), img->mask); + DeleteObject (img->mask); img->mask = NULL; } } @@ -9231,8 +9282,6 @@ W32 support code ***********************************************************************/ -#if 0 /* TODO: W32 specific image code. */ - static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int, XImage **, Pixmap *)); static void x_destroy_x_image P_ ((XImage *)); @@ -9242,8 +9291,10 @@ /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created. Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated - via xmalloc. Print error messages via image_error if an error - occurs. Value is non-zero if successful. */ + via xmalloc. DEPTH of zero signifies a 24 bit image, otherwise + DEPTH should indicate the bit depth of the image. Print error + messages via image_error if an error occurs. Value is non-zero if + successful. */ static int x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap) @@ -9252,37 +9303,71 @@ XImage **ximg; Pixmap *pixmap; { -#if 0 /* TODO: Image support for W32 */ - Display *display = FRAME_W32_DISPLAY (f); - Screen *screen = FRAME_X_SCREEN (f); - Window window = FRAME_W32_WINDOW (f); - - xassert (interrupt_input_blocked); - - if (depth <= 0) - depth = one_w32_display_info.n_cbits; - *ximg = XCreateImage (display, DefaultVisualOfScreen (screen), - depth, ZPixmap, 0, NULL, width, height, - depth > 16 ? 32 : depth > 8 ? 16 : 8, 0); + BITMAPINFOHEADER *header; + HDC hdc; + int scanline_width_bits; + int remainder; + int palette_colors = 0; + + if (depth == 0) + depth = 24; + + if (depth != 1 && depth != 4 && depth != 8 + && depth != 16 && depth != 24 && depth != 32) + { + image_error ("Invalid image bit depth specified", Qnil, Qnil); + return 0; + } + + scanline_width_bits = width * depth; + remainder = scanline_width_bits % 32; + + if (remainder) + scanline_width_bits += 32 - remainder; + + /* Bitmaps with a depth less than 16 need a palette. */ + /* BITMAPINFO structure already contains the first RGBQUAD. */ + if (depth < 16) + palette_colors = 1 << depth - 1; + + *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD)); if (*ximg == NULL) { - image_error ("Unable to allocate X image", Qnil, Qnil); + image_error ("Unable to allocate memory for XImage", Qnil, Qnil); return 0; } - /* Allocate image raster. */ - (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height); - - /* Allocate a pixmap of the same size. */ - *pixmap = XCreatePixmap (display, window, width, height, depth); - if (*pixmap == 0) - { + header = &((*ximg)->info.bmiHeader); + bzero (&((*ximg)->info), sizeof (BITMAPINFO)); + header->biSize = sizeof (*header); + header->biWidth = width; + header->biHeight = -height; /* negative indicates a top-down bitmap. */ + header->biPlanes = 1; + header->biBitCount = depth; + header->biCompression = BI_RGB; + header->biClrUsed = palette_colors; + + hdc = get_frame_dc (f); + + /* Create a DIBSection and raster array for the bitmap, + and store its handle in *pixmap. */ + *pixmap = CreateDIBSection (hdc, &((*ximg)->info), DIB_RGB_COLORS, + &((*ximg)->data), NULL, 0); + + /* Realize display palette and garbage all frames. */ + release_frame_dc (f, hdc); + + if (*pixmap == NULL) + { + DWORD err = GetLastError(); + Lisp_Object errcode; + /* All system errors are < 10000, so the following is safe. */ + XSETINT (errcode, (int) err); + image_error ("Unable to create bitmap, error code %d", errcode, Qnil); x_destroy_x_image (*ximg); - *ximg = NULL; - image_error ("Unable to create X pixmap", Qnil, Qnil); return 0; } -#endif + return 1; } @@ -9296,9 +9381,9 @@ xassert (interrupt_input_blocked); if (ximg) { - xfree (ximg->data); + /* Data will be freed by DestroyObject. */ ximg->data = NULL; - XDestroyImage (ximg); + xfree (ximg); } } @@ -9312,15 +9397,16 @@ XImage *ximg; Pixmap pixmap; { + +#if TODO /* W32 specific image code. */ GC gc; - + xassert (interrupt_input_blocked); gc = XCreateGC (NULL, pixmap, 0, NULL); XPutImage (NULL, pixmap, gc, ximg, 0, 0, 0, 0, width, height); XFreeGC (NULL, gc); -} - -#endif +#endif +} /*********************************************************************** @@ -9844,6 +9930,8 @@ if (rc) { int depth = one_w32_display_info.n_cbits; + int planes = one_w32_display_info.n_planes; + unsigned long foreground = FRAME_FOREGROUND_PIXEL (f); unsigned long background = FRAME_BACKGROUND_PIXEL (f); Lisp_Object value; @@ -9861,16 +9949,9 @@ img->background = background; img->background_valid = 1; } - -#if 0 /* TODO : Port image display to W32 */ img->pixmap - = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f), - FRAME_W32_WINDOW (f), - data, - img->width, img->height, - foreground, background, - depth); -#endif + = CreateBitmap (img->width, img->height, planes, depth, data); + xfree (data); if (img->pixmap == 0) @@ -10478,13 +10559,14 @@ #endif /* TODO */ +#ifdef HAVE_IMAGES /* TODO */ /*********************************************************************** Algorithms ***********************************************************************/ -#if 0 /* TODO: image support. */ static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int)); static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *)); static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int)); +static void XPutPixel (XImage *, int, int, COLORREF); /* Non-zero means draw a cross on images having `:conversion disabled'. */ @@ -10531,7 +10613,7 @@ XImage *ximg; colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors); - +#if 0 /* TODO: implement image colors. */ /* Get the X image IMG->pixmap. */ ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0, img->width, img->height, ~0, ZPixmap); @@ -10551,9 +10633,37 @@ } XDestroyImage (ximg); +#endif return colors; } +/* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been + created with CreateDIBSection, with the pointer to the bit values + stored in ximg->data. */ + +static void XPutPixel (ximg, x, y, color) + XImage * ximg; + int x, y; + COLORREF color; +{ + int width = ximg->info.bmiHeader.biWidth; + int height = ximg->info.bmiHeader.biHeight; + int rowbytes = width * 3; + unsigned char * pixel; + + /* Don't support putting pixels in images with palettes. */ + xassert (ximg->info.bmiHeader.biBitCount == 24); + + /* Ensure scanlines are aligned on 4 byte boundaries. */ + if (rowbytes % 4) + rowbytes += 4 - (rowbytes % 4); + + pixel = ximg->data + y * rowbytes + x * 3; + *pixel = 255 - GetRValue (color); + *(pixel + 1) = 255 - GetGValue (color); + *(pixel + 2) = 255 - GetBValue (color); +} + /* Create IMG->pixmap from an array COLORS of XColor structures, whose RGB members are set. F is the frame on which this all happens. @@ -10569,9 +10679,9 @@ XImage *oimg; Pixmap pixmap; XColor *p; - +#if 0 /* TODO: color tables. */ init_color_table (); - +#endif x_create_x_image_and_pixmap (f, img->width, img->height, 0, &oimg, &pixmap); p = colors; @@ -10579,7 +10689,11 @@ for (x = 0; x < img->width; ++x, ++p) { unsigned long pixel; +#if 0 /* TODO: color tables. */ pixel = lookup_rgb_color (f, p->red, p->green, p->blue); +#else + pixel = PALETTERGB (p->red, p->green, p->blue); +#endif XPutPixel (oimg, x, y, pixel); } @@ -10589,8 +10703,10 @@ x_put_x_image (f, oimg, pixmap, img->width, img->height); x_destroy_x_image (oimg); img->pixmap = pixmap; +#if 0 /* TODO: color tables. */ img->colors = colors_in_color_table (&img->ncolors); free_color_table (); +#endif } @@ -10741,9 +10857,9 @@ struct frame *f; struct image *img; { - struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); - - if (dpyinfo->n_planes >= 2) + struct w32_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + + if (dpyinfo->n_planes * dpyinfo->n_cbits >= 2) { /* Color (or grayscale). Convert to gray, and equalize. Just drawing such images with a stipple can look very odd, so @@ -10767,8 +10883,9 @@ /* Draw a cross over the disabled image, if we must or if we should. */ - if (dpyinfo->n_planes < 2 || cross_disabled_images) - { + if (dpyinfo->n_planes * dpyinfo->n_cbits < 2 || cross_disabled_images) + { +#if 0 /* TODO: full image support */ Display *dpy = FRAME_X_DISPLAY (f); GC gc; @@ -10790,6 +10907,7 @@ img->width - 1, 0); XFreeGC (dpy, gc); } +#endif } } @@ -10807,6 +10925,7 @@ struct image *img; Lisp_Object how; { +#if 0 /* TODO: full image support. */ Display *dpy = FRAME_W32_DISPLAY (f); XImage *ximg, *mask_img; int x, y, rc, use_img_background; @@ -10870,9 +10989,11 @@ XDestroyImage (ximg); return 1; -} -#endif /* TODO */ - +#else + return 0; +#endif +} +#endif /*********************************************************************** PBM (mono, gray, color) @@ -11137,12 +11258,13 @@ || (type != PBM_MONO && max_color_idx < 0)) goto error; - if (!x_create_x_image_and_pixmap (f, width, height, 0, - &ximg, &img->pixmap)) + if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) goto error; +#if 0 /* TODO: color tables. */ /* Initialize the color hash table. */ init_color_table (); +#endif if (type == PBM_MONO) { @@ -11207,28 +11329,32 @@ if (r < 0 || g < 0 || b < 0) { - xfree (ximg->data); - ximg->data = NULL; - XDestroyImage (ximg); + x_destroy_x_image (ximg); image_error ("Invalid pixel value in image `%s'", img->spec, Qnil); goto error; } /* 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)); + Scale this to the range 0..0xff supported by W32. */ + r = (int) ((double) r * 255 / max_color_idx); + g = (int) ((double) g * 255 / max_color_idx); + b = (int) ((double) b * 255 / max_color_idx); + XPutPixel (ximg, x, y, +#if 0 /* TODO: color tables. */ + lookup_rgb_color (f, r, g, b)); +#else + PALETTERGB (r, g, b)); +#endif } } - + +#if 0 /* TODO: color tables. */ /* Store in IMG->colors the colors allocated for the image, and free the color table. */ img->colors = colors_in_color_table (&img->ncolors); free_color_table (); - +#endif /* Maybe fill in the background field while we have ximg handy. */ if (NILP (image_spec_value (img->spec, QCbackground, NULL))) IMAGE_BACKGROUND (img, f, ximg); @@ -14550,14 +14676,16 @@ if (pfn_GetDiskFreeSpaceEx) { + /* Unsigned large integers cannot be cast to double, so + use signed ones instead. */ LARGE_INTEGER availbytes; LARGE_INTEGER freebytes; LARGE_INTEGER totalbytes; if (pfn_GetDiskFreeSpaceEx(rootname, - &availbytes, - &totalbytes, - &freebytes)) + (ULARGE_INTEGER *)&availbytes, + (ULARGE_INTEGER *)&totalbytes, + (ULARGE_INTEGER *)&freebytes)) value = list3 (make_float ((double) totalbytes.QuadPart), make_float ((double) freebytes.QuadPart), make_float ((double) availbytes.QuadPart)); @@ -15106,7 +15234,7 @@ set_frame_fontset_func = x_set_font; check_window_system_func = check_w32; -#if 0 /* TODO Image support for W32 */ +#ifdef IMAGES /* Images. */ Qxbm = intern ("xbm"); staticpro (&Qxbm); @@ -15126,6 +15254,7 @@ staticpro (&QCrelief); Qpostscript = intern ("postscript"); staticpro (&Qpostscript); +#if 0 /* TODO: These need entries at top of file. */ QCloader = intern (":loader"); staticpro (&QCloader); QCbounding_box = intern (":bounding-box"); @@ -15134,10 +15263,12 @@ staticpro (&QCpt_width); QCpt_height = intern (":pt-height"); staticpro (&QCpt_height); +#endif QCindex = intern (":index"); staticpro (&QCindex); Qpbm = intern ("pbm"); staticpro (&Qpbm); +#endif #if HAVE_XPM Qxpm = intern ("xpm"); @@ -15164,13 +15295,16 @@ staticpro (&Qpng); #endif +#ifdef HAVE_IMAGES defsubr (&Sclear_image_cache); + defsubr (&Simage_size); + defsubr (&Simage_mask_p); +#endif #if GLYPH_DEBUG defsubr (&Simagep); defsubr (&Slookup_image); #endif -#endif /* TODO */ hourglass_atimer = NULL; hourglass_shown_p = 0; @@ -15194,10 +15328,14 @@ image_types = NULL; Vimage_types = Qnil; +#if HAVE_PBM + define_image_type (&pbm_type); +#endif + #if 0 /* TODO : Image support for W32 */ define_image_type (&xbm_type); define_image_type (&gs_type); - define_image_type (&pbm_type); +#endif #if HAVE_XPM define_image_type (&xpm_type); @@ -15218,7 +15356,6 @@ #if HAVE_PNG define_image_type (&png_type); #endif -#endif /* TODO */ } #undef abort