unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Pip Cet <pipcet@gmail.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: cpitclaudel@gmail.com, 40845@debbugs.gnu.org
Subject: bug#40845: SVG rendering issues
Date: Sat, 25 Apr 2020 19:41:31 +0000	[thread overview]
Message-ID: <CAOqdjBcX0WgmJenStzb-4s0pnnTWm3rzxHiXFJSzMUM-H4zULQ@mail.gmail.com> (raw)
In-Reply-To: <83eesb7833.fsf@gnu.org>

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

On Sat, Apr 25, 2020 at 6:07 PM Eli Zaretskii <eliz@gnu.org> wrote:
or these
> Then I guess I don't understand your implementation at all.

My use case is to include a glyph which is supposed to look like a
character, but doesn't actually have a unicode codepoint. (I'm sorry
if this differs from the use cases you're exclusively concerned with,
but it appeared to be relevant enough to Clément's problem that I
assumed he was having a similar issue).

That means that we want to use an image spec, not a character in a
font; but that image spec depends on face/font properties, because we
want to blend in with surrounding text. The most obvious ones are
foreground and background color and size, but slant and weight would
also affect properly-rendered character-like images.

It seems fairly obvious to me that it's a bad idea to do all the work
in the display engine or in C code: sub-pixel rendering and
anti-aliasing are hard to get right. A character-like glyph might need
a third color which provides sufficient contrast to the foreground and
background colors, and that color space calculation is complicated
enough to be moved to Lisp.

So I moved it to Lisp: there's Lisp code which is passed the font/face
properties, and returns an image spec that's appropriate for that.

The attached patch actually applies to and works with master, and
includes an example. It can no longer easily be demonstrated to do the
right thing when the same buffer is displayed in different frames,
because Emacs currently applies text scaling per buffer rather than
per frame (IMHO, that's a bug). It also doesn't properly display the
cursor as a block cursor when it's over the glyph, because I can no
longer find the code which allowed me to tell, from Lisp, whether that
was the case.

And of course it doesn't use the right font metrics, because these
currently aren't exposed to Lisp.

But all these limitations are fixable.

[-- Attachment #2: 0001-support-generated-display-specs.patch --]
[-- Type: text/x-patch, Size: 4818 bytes --]

From 8e7aa38e098bd044a71fa20df1593d2b37347f1c Mon Sep 17 00:00:00 2001
From: Pip Cet <pipcet@gmail.com>
Date: Sat, 25 Apr 2020 18:41:02 +0000
Subject: [PATCH] support generated display specs

---
 generated-image-specs.el | 31 ++++++++++++++++++++++++++++
 src/callint.c            |  1 +
 src/xdisp.c              | 44 ++++++++++++++++++++++++++++++++++++++++
 src/xfaces.c             |  2 +-
 4 files changed, 77 insertions(+), 1 deletion(-)
 create mode 100644 generated-image-specs.el

diff --git a/generated-image-specs.el b/generated-image-specs.el
new file mode 100644
index 0000000000..b764d1999d
--- /dev/null
+++ b/generated-image-specs.el
@@ -0,0 +1,31 @@
+(require 'svg)
+
+(defun generate-circle-image (alist)
+  (let* ((vsize (font-get (alist-get :font alist) :size))
+         (foreground (apply #'color-rgb-to-hex (nconc (color-name-to-rgb (alist-get :foreground alist)) (list 2))))
+         (background (apply #'color-rgb-to-hex (nconc (color-name-to-rgb (alist-get :background alist)) (list 2))))
+         (hsize (* vsize .8))
+         (svg (svg-create hsize vsize))
+         (sw (* .1 hsize)))
+    (svg-rectangle svg 0 0 hsize vsize :fill background)
+    (svg-circle svg (* hsize .5)
+                (- (* .8 vsize) (* .5 hsize))
+                (- (* hsize .5) sw)
+                :fill "none"
+                :stroke foreground
+                :stroke-width sw)
+    (svg-line svg
+              (* hsize .5) (- (* .8 vsize) (* .5 hsize))
+              (* hsize .5) (- (* .8 vsize) sw)
+              :stroke foreground
+              :stroke-width sw)
+    (svg-circle svg (* hsize .5) (- (* .8 vsize) (* (/ 2.0 3.0) hsize))
+                sw
+                :fill foreground
+                :stroke "none")
+    (let ((ret (svg-image svg)))
+      (setcdr ret (plist-put (cdr ret) :scale 1.0))
+      (setcdr ret (plist-put (cdr ret) :ascent 80))
+      ret)))
+
+(insert (propertize " " 'display `(generated-spec ,#'generate-circle-image)))
diff --git a/src/callint.c b/src/callint.c
index eb916353a0..2c34dddbe4 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -826,6 +826,7 @@ syms_of_callint (void)
   DEFSYM (Qlet, "let");
   DEFSYM (Qif, "if");
   DEFSYM (Qwhen, "when");
+  DEFSYM (Qgenerated_spec, "generated-spec");
   DEFSYM (Qletx, "let*");
   DEFSYM (Qsave_excursion, "save-excursion");
   DEFSYM (Qprogn, "progn");
diff --git a/src/xdisp.c b/src/xdisp.c
index 3258893956..b341cbb735 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -5050,6 +5050,7 @@ handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
 #endif
       && !EQ (XCAR (spec), Qspace)
       && !EQ (XCAR (spec), Qwhen)
+      && !EQ (XCAR (spec), Qgenerated_spec)
       && !EQ (XCAR (spec), Qslice)
       && !EQ (XCAR (spec), Qspace_width)
       && !EQ (XCAR (spec), Qheight)
@@ -5148,6 +5149,8 @@ display_prop_end (struct it *it, Lisp_Object object, struct text_pos start_pos)
    Value is non-zero if something was found which replaces the display
    of buffer or string text.  */
 
+extern Lisp_Object *lface_id_to_name;
+
 static int
 handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
 			    Lisp_Object overlay, struct text_pos *position,
@@ -5159,6 +5162,47 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
   struct text_pos start_pos = *position;
   void *itdata = NULL;
 
+  if (it != NULL &&
+      CONSP (spec) &&
+      EQ (XCAR (spec), Qgenerated_spec))
+    {
+      spec = XCDR (spec);
+      if (!CONSP (spec))
+	return 0;
+      Lisp_Object gen = XCAR (spec);
+      struct face *face = FACE_FROM_ID (it->f, it->face_id);
+      Lisp_Object lface = Qnil;
+      Lisp_Object props[] = {
+	QCtype,
+	QCfamily,
+	QCfoundry,
+	QCwidth,
+	QCheight,
+	QCweight,
+	QCslant,
+	QCunderline,
+	QCinverse_video,
+	QCforeground,
+	QCbackground,
+	QCstipple,
+	QCoverline,
+	QCstrike_through,
+	QCbox,
+	QCfont,
+	QCinherit,
+	QCfontset,
+	QCdistant_foreground,
+	QCextend,
+      };
+      for (int i = 0; i < LFACE_VECTOR_SIZE; i++)
+	lface = Fcons (Fcons (props[i], face->lface[i]),
+		       lface);
+      Lisp_Object font = Qnil;
+      XSETFONT (font, face->font);
+      lface = Fcons (Fcons (QCfont, font), lface);
+      spec = safe_call1 (gen, lface);
+    }
+
   /* If SPEC is a list of the form `(when FORM . VALUE)', evaluate FORM.
      If the result is non-nil, use VALUE instead of SPEC.  */
   form = Qt;
diff --git a/src/xfaces.c b/src/xfaces.c
index bab142ade0..01429ac86e 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -310,7 +310,7 @@ #define FACE_CACHE_BUCKETS_SIZE 1001
 
 /* A vector mapping Lisp face Id's to face names.  */
 
-static Lisp_Object *lface_id_to_name;
+Lisp_Object *lface_id_to_name;
 static ptrdiff_t lface_id_to_name_size;
 
 #ifdef HAVE_WINDOW_SYSTEM
-- 
2.26.2


  reply	other threads:[~2020-04-25 19:41 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-25 12:19 bug#40845: SVG rendering issues Clément Pit-Claudel
2020-04-25 14:34 ` Pip Cet
2020-04-25 15:30   ` Eli Zaretskii
2020-04-25 15:48     ` Pip Cet
2020-04-25 16:10       ` Eli Zaretskii
2020-04-25 17:38         ` Pip Cet
2020-04-25 18:07           ` Eli Zaretskii
2020-04-25 19:41             ` Pip Cet [this message]
2020-04-25 20:11               ` Eli Zaretskii
2020-04-26 10:15                 ` Pip Cet
2020-04-26 14:38                   ` Eli Zaretskii
2020-04-26 19:00                     ` Pip Cet
2020-04-27 15:47                       ` Eli Zaretskii
2020-04-25 15:46   ` Eli Zaretskii
2020-04-25 16:42     ` Clément Pit-Claudel
2020-04-25 17:02       ` Eli Zaretskii
2020-04-25 17:24         ` Clément Pit-Claudel
2020-04-25 17:46           ` Alan Third
2020-04-25 18:07             ` Pip Cet
2020-04-26 21:17             ` Alan Third
2020-04-26 22:48               ` Clément Pit-Claudel
2020-04-27 15:22                 ` Alan Third
2020-04-27 16:04                   ` Clément Pit-Claudel
2020-05-03 14:13                 ` Alan Third
2020-05-03 14:18                   ` Lars Ingebrigtsen
2020-05-03 16:07                   ` Eli Zaretskii
2020-05-03 16:24                     ` Alan Third
2020-05-03 16:49                       ` Eli Zaretskii
2020-05-03 18:38                         ` Alan Third
2020-05-03 19:17                           ` Eli Zaretskii
2020-05-09 14:27                       ` Alan Third
2020-05-09 19:54                         ` Alan Third
2020-05-15 11:09                           ` Eli Zaretskii
2020-05-15 21:40                             ` Alan Third
2020-08-22 16:15                               ` Alan Third
2020-08-22 16:28                                 ` Lars Ingebrigtsen
2020-08-22 16:54                                 ` Eli Zaretskii
2020-08-22 18:57                                   ` Alan Third
2020-08-22 19:17                                     ` Eli Zaretskii
2020-08-22 21:35                                       ` Alan Third
2020-08-23  5:47                                         ` Eli Zaretskii
2020-08-23  9:09                                           ` Alan Third
2020-08-23  9:11                                             ` Eli Zaretskii
2020-08-23 11:48                                               ` Alan Third
2020-08-23 12:05                                                 ` Eli Zaretskii
2020-08-23 12:19                                                   ` Alan Third
2020-08-23 12:23                                                     ` Eli Zaretskii
2020-08-23 15:29                                                       ` Alan Third
2020-08-23 15:43                                                         ` Lars Ingebrigtsen
2020-08-23 16:08                                                           ` Alan Third
2020-08-23 16:38                                                             ` Lars Ingebrigtsen
2020-04-27  2:27               ` Eli Zaretskii

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=CAOqdjBcX0WgmJenStzb-4s0pnnTWm3rzxHiXFJSzMUM-H4zULQ@mail.gmail.com \
    --to=pipcet@gmail.com \
    --cc=40845@debbugs.gnu.org \
    --cc=cpitclaudel@gmail.com \
    --cc=eliz@gnu.org \
    /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).