SVG Hack for Emacs Display Engine

 

 

Here's throwing an idea into the wild (Emacs mailing list, Reddit). How about using SVG for rendering in the Emacs display engine? The attached image shows the rendering as a proof of concept for feasibility. The top window shows the SVG rendering of the buffer shown in the bottom window. One obvious advantage is precise positioning of content including inline popups for auto-completion. This also precludes any major changes to the display engine data structures. Other use cases include feature filled tooltips, inline completion popup, multi-column layouts, watermarks etc

In this hack, the elisp code navigates from (window-start) to (window-end) reading a line of text from associated buffer and displaying the same in SVG. I've used (read-event) and (lookup-key) to allow for key translations for navigation commands. Hopefully with a tighter integration, all of this will not be required.

Positioning of point is one open area. We would need the bounding box of text for accurate positioning. We have three sources for this - librsvg, pango or the current display engine.

Though I'm not sure about the practicality at this point of time. I'd love to hear your thoughts.


Here's some details on how I think it might work. Emacs exposes two Lisp APIs:
- svg-render (svg x y width height)
svg is a Lisp DOM object as returned by (dom-node). This should use librsvg to generate a bitmap image of svg of size (width x height) and superimpose it at position (x, y) on the current bitmap being displayed by Emacs. The current image API takes either a filename or XML string for SVG. This can be avoided if svg is a Lisp DOM.

- svg-bbox (node)
This returns the bounding box of the DOM node. This is basically a wrapper around librsvg API.

Emacs also adds a hook, say, display-svg-hook which runs only on a graphical display. Any mode can use this hook to display the SVG content using the above API. Emacs would define a new data structure {svg, x, y, w, h} and two new variables with this type - new_svg and prev_svg. Then the sequence of operations would be:
 
- Display engine refreshes the view bitmap with current logic - full or partial refresh as the case may be.
- If it's a graphical display
- prev_svg = new_svg
- new_svg = null
- Run display-svg-hook. The registered user function will call (svg-render) function passing required information. This API sets the value in new_svg.
- If the bounding box of new_svg < the bounding box of prev_svg, display engine refreshes the area of prev_svg in the view bitmap. Basically, refresh the area covered by prev_svg which is not covered by new_svg.
- Generate a bitmap for new_svg and superimpose it on the view bitmap.
- Display the view bitmap to the user.


Comments

  1. You can look my project https://github.com/manateelazycat/popweb and https://github.com/emacs-eaf/emacs-application-framework

    ReplyDelete

Post a Comment

Popular posts from this blog

GNU Emacs as a Comic Book Reader

Data Visualization with GNU Emacs

Mozilla Readability in GNU Emacs