unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: "Elijah G." <eg642616@gmail.com>
To: 71159@debbugs.gnu.org
Cc: luangruo@yahoo.com, eliz@gnu.org
Subject: bug#71159: [PATCH] Stipple support for MS Windows
Date: Sat, 01 Jun 2024 12:54:22 -0600	[thread overview]
Message-ID: <86r0dg4hpd.fsf@gmail.com> (raw)
In-Reply-To: <87ed9gkber.fsf@yahoo.com> (Po Lu via's message of "Sat, 01 Jun 2024 22:03:40 +0800")

[-- Attachment #1: Type: text/plain, Size: 2255 bytes --]

Po Lu via "Bug reports for GNU Emacs, the Swiss army knife of text
editors" <bug-gnu-emacs@gnu.org> writes:

> "Elijah G." <eg642616@gmail.com> writes:
>
>> I've updated the patch for delete all the conflicts generated by
>> ae7d0e86b37eabc434c48f85f56df0a221e0e7c7 commit.
>
> Thank you.  Please find several comments below:
>
>> * src/w32term.c:
>> (w32_fill_stipple_pattern): New function.
>> (w32_draw_glyph_string_background, w32_draw_glyph_string_bg_rect)
>> (w32_draw_stretch_glyph_string): Use new stipple function.
>
> Please delete the redundant colon after the file name.
>
>> * src/image.c:
>> (image_create_bitmap_from_data): Create stipple bitmap.
>> (image_create_bitmap_from_file): Add suuport for pixmap and create
>> stipple bitmap.
>
> Likewise.  This commit message is also excessively wide, and must be
> filled to remain within 64 columns.

It's now fixed, sorry about that i couldn't find how to insert
change-log skeleton or amend with vc.el, those where generated by
`diff-add-change-log-entries-other-window'.

>> +#ifdef HAVE_NTGUI
>> +static HBITMAP w32_create_pixmap_from_bitmap_data (int width,
>> +						   int height,
>> +						   char *data);
>> +
>> +#endif
>
> It should be aesthetically better if the parameter names were deleted
> from this declaration's type list, and all of the types placed on one
> line.

Done.

>> +    int nbytes, i;
>> +    ptrdiff_t sa_avail; /* Used only for SAFE_NALLOCA.  */
>
> ??? Please insert this boilerplate by means of the `USE_SAFE_ALLOCA'
> macro.
>
>> +    invertedBits = bits;
>> +    nbytes = (width + CHAR_BIT - 1) / CHAR_BIT * height;
>> +    sa_avail = MAX_ALLOCA
>> +
>> +    SAFE_NALLOCA (bits, 1, nbytes);
>
> Shouldn't you subsequently call SAFE_FREE?

Thank you, i forgot calling SAFE_FREE, i only defined sa_avail instead
using USE_SAFE_ALLOCA because i was getting an unused variable warning.

It's now fixed.

>> +    for (i = 0; i < nbytes; i++)
>> +      bits[i] = XBM_BIT_SHUFFLE(invertedBits[i]);
>
> Absent space between macro name and parameters.
>
>> +      data[i] = XBM_BIT_SHUFFLE(data[i]);
>
> Here also.

Done.

>> +  Emacs_Pixmap stipple;
>
> Should not the object in this field be released in `free_bitmap_record'?

Yes, i forgot about it, it's fixed.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Stipple-support-for-MS-Windows.patch --]
[-- Type: text/x-patch, Size: 9602 bytes --]

From 6db0266a99dff476eb66ff00b310f650bd3ad0ea Mon Sep 17 00:00:00 2001
From: "Elias G. Perez" <eg642616@gmail.com>
Date: Fri, 10 May 2024 20:36:42 -0600
Subject: [PATCH] Stipple support for MS Windows

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

* src/w32term.h (w32_bitmap_record): Add stipple value.

* src/w32term.c (w32_fill_stipple_pattern): New function.
(w32_draw_glyph_string_background)
(w32_draw_glyph_string_bg_rect w32_draw_stretch_glyph_string):
Use new stipple function.

* 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      |   3 ++
 src/image.c   | 101 ++++++++++++++++++++++++++++++++++++++++++--------
 src/w32term.c |  55 +++++++++++++++++----------
 src/w32term.h |   1 +
 4 files changed, 125 insertions(+), 35 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 3c672ffed8f..f0aec17371f 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2827,6 +2827,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.
diff --git a/src/image.c b/src/image.c
index 3138ef25a63..42f72780c24 100644
--- a/src/image.c
+++ b/src/image.c
@@ -130,6 +130,12 @@ #define NO_PIXMAP 0
 #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 @@ #define n_planes n_image_planes
 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,34 @@ 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;
+  Emacs_Pixmap stipple, bitmap;
   bitmap = CreateBitmap (width, height,
-			 FRAME_DISPLAY_INFO (XFRAME (frame))->n_planes,
-			 FRAME_DISPLAY_INFO (XFRAME (frame))->n_cbits,
+			 dpyinfo->n_planes,
+			 dpyinfo->n_cbits,
 			 bits);
-  if (! bitmap)
+
+  /* Convert X bitmap to W32 bitmap.  */
+  /* Windows mono bitmaps are reversed compared with X.  */
+  USE_SAFE_ALLOCA;
+
+  {
+    char *invertedBits;
+    int nbytes, i;
+
+    invertedBits = bits;
+    nbytes = (width + CHAR_BIT - 1) / CHAR_BIT * height;
+
+    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 +713,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 +732,7 @@ image_create_bitmap_from_data (struct frame *f, char *bits,
 #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 +744,53 @@ image_create_bitmap_from_data (struct frame *f, char *bits,
 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 +1113,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 +4877,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 */
 
 
diff --git a/src/w32term.c b/src/w32term.c
index 2bcd5d86a38..3ef6d0f11f1 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -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);
             }
diff --git a/src/w32term.h b/src/w32term.h
index a19be1a9e6a..38eac4230dd 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -58,6 +58,7 @@ #define CP_DEFAULT 1004
 {
   Emacs_Pixmap pixmap;
   char *file;
+  Emacs_Pixmap stipple;
   HINSTANCE hinst; /* Used to load the file */
   int refcount;
   /* Record some info about this pixmap.  */
-- 
2.44.0.windows.1


  reply	other threads:[~2024-06-01 18:54 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-24  1:27 bug#71159: [PATCH] Stipple support for MS Windows Elijah G.
2024-05-29 23:25 ` Elijah G.
2024-05-31  0:12   ` Elijah G.
2024-06-01 14:03     ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-01 18:54       ` Elijah G. [this message]
2024-06-02  1:34         ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-02  1:40           ` Elijah G.
2024-06-02  1:49             ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-02  4:54               ` Eli Zaretskii
2024-06-02  7:56                 ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-06-02  4:54         ` Eli Zaretskii
2024-06-02  5:27           ` Elijah G.
2024-06-02  6:37             ` Eli Zaretskii
2024-06-01 14:28     ` Eli Zaretskii
2024-06-01 19:04       ` Elijah G.

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=86r0dg4hpd.fsf@gmail.com \
    --to=eg642616@gmail.com \
    --cc=71159@debbugs.gnu.org \
    --cc=eliz@gnu.org \
    --cc=luangruo@yahoo.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).