]> git.eshelyaron.com Git - emacs.git/commitdiff
Stipple support for MS Windows (bug#71159)
authorElias G. Perez <eg642616@gmail.com>
Sat, 11 May 2024 02:36:42 +0000 (20:36 -0600)
committerEshel Yaron <me@eshelyaron.com>
Sun, 2 Jun 2024 11:18:11 +0000 (13:18 +0200)
* src/w32term.c (w32_fill_stipple_pattern): New function.
(w32_draw_glyph_string_bg_rect w32_draw_stretch_glyph_string)
(w32_draw_glyph_string_background): Use new stipple function.
* src/w32term.h (w32_bitmap_record): Add stipple value.
* src/image.c (image_create_bitmap_from_data): Create stipple
bitmap.
(image_create_bitmap_from_file): Add suuport for pixmap and
create stipple bitmap.
(free_bitmap_record): Release stipple.

* etc/NEWS: Announce support for stipples in MS-Windows.

(cherry picked from commit 48bb25c0e37f8489b06b82a4c32f0c6dcc0856e9)

etc/NEWS
src/image.c
src/w32term.c
src/w32term.h

index 0985fe8e96a0729e6fe8ea9c69f66d8e6522bb7b..11f572d325442b08baa9be6a3e4ba37f59016c97 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2986,6 +2986,9 @@ thumbnail images and show them in the thumbnail buffer.  Unlike with
 using 'convert', this fallback method is synchronous, so Emacs will wait
 until all the thumbnails are created and displayed, before showing them.
 
+---
+*** Emacs on MS-Windows now supports the ':stipple' face attribute.
+
 \f
 ----------------------------------------------------------------------
 This file is part of GNU Emacs.
index 3138ef25a639b60c400b4083c9b23b9fdf882af6..321073a4fd98e85fd7b885598e5569dc3fc49a65 100644 (file)
@@ -130,6 +130,12 @@ typedef struct w32_bitmap_record Bitmap_Record;
 #define PIX_MASK_RETAIN        0
 #define PIX_MASK_DRAW  1
 
+#define XBM_BIT_SHUFFLE(b) (~(b))
+
+#else
+
+#define XBM_BIT_SHUFFLE(b) (b)
+
 #endif /* HAVE_NTGUI */
 
 #ifdef HAVE_NS
@@ -214,6 +220,11 @@ static void free_color_table (void);
 static unsigned long *colors_in_color_table (int *n);
 #endif
 
+#ifdef HAVE_NTGUI
+static HBITMAP w32_create_pixmap_from_bitmap_data (int, int, char *);
+
+#endif
+
 #if defined (HAVE_WEBP) || defined (HAVE_GIF)
 static void anim_prune_animation_cache (Lisp_Object);
 #endif
@@ -596,13 +607,31 @@ image_create_bitmap_from_data (struct frame *f, char *bits,
 #endif /* HAVE_ANDROID && !defined ANDROID_STUBIFY */
 
 #ifdef HAVE_NTGUI
-  Lisp_Object frame UNINIT;    /* The value is not used.  */
-  Emacs_Pixmap bitmap;
-  bitmap = CreateBitmap (width, height,
-                        FRAME_DISPLAY_INFO (XFRAME (frame))->n_planes,
-                        FRAME_DISPLAY_INFO (XFRAME (frame))->n_cbits,
-                        bits);
-  if (! bitmap)
+  Emacs_Pixmap stipple;
+  Emacs_Pixmap bitmap = CreateBitmap (width, height, dpyinfo->n_planes,
+                                     dpyinfo->n_cbits, bits);
+
+  /* Convert X bitmap to W32 bitmap.  */
+  /* Windows mono bitmaps are reversed compared with X.  */
+  USE_SAFE_ALLOCA;
+
+  {
+    char *invertedBits;
+    int nbytes = (width + CHAR_BIT - 1) / CHAR_BIT * height, i;
+
+    invertedBits = bits;
+
+    SAFE_NALLOCA (bits, 1, nbytes);
+
+    for (i = 0; i < nbytes; i++)
+      bits[i] = XBM_BIT_SHUFFLE (invertedBits[i]);
+  }
+
+  stipple = w32_create_pixmap_from_bitmap_data (width, height, bits);
+
+  SAFE_FREE ();
+
+  if (!bitmap || !stipple)
     return -1;
 #endif /* HAVE_NTGUI */
 
@@ -681,6 +710,7 @@ image_create_bitmap_from_data (struct frame *f, char *bits,
 
 #ifdef HAVE_NTGUI
   dpyinfo->bitmaps[id - 1].pixmap = bitmap;
+  dpyinfo->bitmaps[id - 1].stipple = stipple;
   dpyinfo->bitmaps[id - 1].hinst = NULL;
   dpyinfo->bitmaps[id - 1].depth = 1;
 #endif /* HAVE_NTGUI */
@@ -699,7 +729,7 @@ typedef int image_fd;
 #endif /* defined HAVE_ANDROID && !defined ANDROID_STUBIFY */
 
 #if defined HAVE_HAIKU || defined HAVE_NS || defined HAVE_PGTK \
-  || defined HAVE_ANDROID
+  || defined HAVE_ANDROID || defined HAVE_NTGUI
 static char *slurp_file (image_fd, ptrdiff_t *);
 static Lisp_Object image_find_image_fd (Lisp_Object, image_fd *);
 static bool xbm_read_bitmap_data (struct frame *, char *, char *,
@@ -711,10 +741,53 @@ static bool xbm_read_bitmap_data (struct frame *, char *, char *,
 ptrdiff_t
 image_create_bitmap_from_file (struct frame *f, Lisp_Object file)
 {
-#if defined (HAVE_NTGUI)
-  return -1;  /* W32_TODO : bitmap support */
-#else
   Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
+
+#ifdef HAVE_NTGUI
+  ptrdiff_t id, size;
+  int width, height, rc;
+  image_fd fd;
+  char *contents, *data;
+  Emacs_Pixmap bitmap;
+
+  if (!STRINGP (image_find_image_fd (file, &fd)))
+    return -1;
+
+  contents = slurp_file (fd, &size);
+
+  if (!contents)
+    return -1;
+
+  rc = xbm_read_bitmap_data (f, contents, contents + size,
+                            &width, &height, &data, 0);
+
+  if (!rc)
+    {
+      xfree (contents);
+      return -1;
+    }
+
+  {
+    /* Windows mono bitmaps are reversed compared with X.  */
+
+    int nbytes, i;
+    nbytes = (width + CHAR_BIT - 1) / CHAR_BIT * height;
+
+    for (i = 0; i < nbytes; i++)
+      data[i] = XBM_BIT_SHUFFLE (data[i]);
+  }
+
+  id = image_allocate_bitmap_record (f);
+  bitmap = w32_create_pixmap_from_bitmap_data (width, height, data);
+
+  dpyinfo->bitmaps[id - 1].height = width;
+  dpyinfo->bitmaps[id - 1].width = height;
+  dpyinfo->bitmaps[id - 1].stipple = bitmap;
+  dpyinfo->bitmaps[id - 1].file = xlispstrdup (file);
+
+  xfree (contents);
+  xfree (data);
+  return id;
 #endif
 
 #ifdef HAVE_NS
@@ -1037,6 +1110,7 @@ free_bitmap_record (Display_Info *dpyinfo, Bitmap_Record *bm)
 
 #ifdef HAVE_NTGUI
   DeleteObject (bm->pixmap);
+  DeleteObject (bm->stipple);
 #endif /* HAVE_NTGUI */
 
 #ifdef HAVE_NS
@@ -4800,12 +4874,6 @@ convert_mono_to_color_image (struct frame *f, struct image *img,
     img->pixmap = new_pixmap;
 }
 
-#define XBM_BIT_SHUFFLE(b) (~(b))
-
-#else
-
-#define XBM_BIT_SHUFFLE(b) (b)
-
 #endif /* HAVE_NTGUI */
 
 
index 2bcd5d86a3863f27259e6b2a87fe81374714e680..3ef6d0f11f14cdee51a10ac5964cef046ab41ebe 100644 (file)
@@ -1248,6 +1248,34 @@ w32_clear_glyph_string_rect (struct glyph_string *s,
                  real_w, real_h);
 }
 
+/* Fill background with bitmap pattern from S at specified position
+   given by X and Y.  WIDTH and HEIGHT specifies bitmap size, GC is
+   used to get foreground and background color context and HDC where
+   fill it.  */
+
+static void
+w32_fill_stipple_pattern (HDC hdc, struct glyph_string *s, Emacs_GC *gc,
+                         int x, int y, unsigned int width, unsigned int height)
+{
+  SetTextColor (hdc, gc->foreground);
+  SetBkColor (hdc, gc->background);
+
+  RECT r;
+  Emacs_Pixmap bm;
+  HBRUSH hb;
+
+  r.left = x;
+  r.top = y;
+  r.right = x + width;
+  r.bottom = y + height;
+
+  bm = FRAME_DISPLAY_INFO (s->f)->bitmaps[s->face->stipple - 1].stipple;
+
+  hb = CreatePatternBrush (bm);
+  FillRect (hdc, &r, hb);
+
+  DeleteObject (hb);
+}
 
 /* Draw the background of glyph_string S.  If S->background_filled_p
    is non-zero don't draw it.  FORCE_P non-zero means draw the
@@ -1264,21 +1292,16 @@ w32_draw_glyph_string_background (struct glyph_string *s, bool force_p)
     {
       int box_line_width = max (s->face->box_horizontal_line_width, 0);
 
-#if 0 /* TODO: stipple */
       if (s->stippled_p)
        {
          /* Fill background with a stipple pattern.  */
-         XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
-         XFillRectangle (s->display, FRAME_W32_WINDOW (s->f), s->gc, s->x,
-                         s->y + box_line_width,
-                         s->background_width,
-                         s->height - 2 * box_line_width);
-         XSetFillStyle (s->display, s->gc, FillSolid);
+         w32_fill_stipple_pattern (s->hdc, s, s->gc, s->x,
+                                   s->y + box_line_width,
+                                   s->background_width,
+                                   s->height - 2 * box_line_width);
          s->background_filled_p = true;
        }
-      else
-#endif
-           if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
+      else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
               /* When xdisp.c ignores FONT_HEIGHT, we cannot trust
                  font dimensions, since the actual glyphs might be
                  much smaller.  So in that case we always clear the
@@ -2286,16 +2309,12 @@ w32_draw_image_foreground_1 (struct glyph_string *s, HBITMAP pixmap)
 static void
 w32_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
 {
-#if 0 /* TODO: stipple */
   if (s->stippled_p)
     {
       /* Fill background with a stipple pattern.  */
-      XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
-      XFillRectangle (s->display, FRAME_W32_WINDOW (s->f), s->gc, x, y, w, h);
-      XSetFillStyle (s->display, s->gc, FillSolid);
+      w32_fill_stipple_pattern (s->hdc, s, s->gc, x, y, w, h);
     }
   else
-#endif
     w32_clear_glyph_string_rect (s, x, y, w, h);
 }
 
@@ -2500,16 +2519,12 @@ w32_draw_stretch_glyph_string (struct glyph_string *s)
          get_glyph_string_clip_rect (s, &r);
          w32_set_clip_rectangle (hdc, &r);
 
-#if 0 /* TODO: stipple */
          if (s->face->stipple)
            {
              /* Fill background with a stipple pattern.  */
-             XSetFillStyle (s->display, gc, FillOpaqueStippled);
-             XFillRectangle (s->display, FRAME_W32_WINDOW (s->f), gc, x, y, w, h);
-             XSetFillStyle (s->display, gc, FillSolid);
+             w32_fill_stipple_pattern (s->hdc, s, gc, x, y, w, h);
            }
          else
-#endif
             {
               w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h);
             }
index a19be1a9e6a604c1925fd9fe7cfec0c9f672164c..38eac4230dd5f73c4e847160763700f665263563 100644 (file)
@@ -58,6 +58,7 @@ struct w32_bitmap_record
 {
   Emacs_Pixmap pixmap;
   char *file;
+  Emacs_Pixmap stipple;
   HINSTANCE hinst; /* Used to load the file */
   int refcount;
   /* Record some info about this pixmap.  */