INKMACS - Inkscape Emacs fusion
What is Inkmacs?
Inkmacs is a fusion between Inkscape and Emacs. Well, in the far future at least. But its kind of cool right now also.
Inkscape is a very capable free software vector drawing tool. Emacs is the One True Editor.
With Inkmacs you can use Emacs to do interesting things with Inkscape using DBUS IPC.
Inkmacs lives here:https://github.com/jave/inkmacs
Real world usability
Currently I use Inkmacs for a very large technical poster at a Client. It has lots of text so Inkmacs is a very suitable tool.
The Emacs/Inkscape combo is actually surprisingly robust. I experience few crashes now.
I have some issues but they are in unexpected areas such as Inkscape generated PDF isn’t well handled at the printshop. The free PDF renderers such as Poppler used by Evince are in fact more robust than Adobes so I hadn’t noticed any issues at home.
Synchronize Inkscape text nodes with Org mode text nodes.
Edit an Org mode file as usual.
‘m-x inkmacs-edit’ starts a linked inkscape instance. The svg file name is derived from the root node. inkorg-minor-mode is enabled, which in turn enables the inkorg mode map detailed below.
Each root node can have its own inkscape document.
‘c-m-x’ creates or syncs the text of the current org node with an inkscape node.
‘c-u c-m-x’ creates or syncs the whole tree.
You can move the nodes and format the text in inkscape. only the text is kept in the org tree.
Since Inkscape is a drawing tool it has different notions of text somewhat alien to an Emacs user. Text objects can be bound to ‘flow frames’ which are graphic shapes that bounds the flow of text. By default Inkmacs creates rectangles, but its possible to use any shape.
The Inkscape representation of an Org node is thus two objects. One flow frame and one text object.
It can be a little tricky to select the object you want to work with. inkorg-mode has (embryonic) support:
‘m-x inkorg-select-tree’ selects all corresponding inkscape nodes. With argument, define a filter: ‘keep-siblings ‘keep-sibling-subtrees ‘keep-subtree
Image mode support
Create Elisp macros that perform Inkscape edit operations
‘m-x inkmacs-edit’ opens the svg file in the current emacs buffer in inkscape. A dbus link is established.
dbus linked inkscape control
When a dbus link is established from an emacs buffer to an Inkscape desktop, it is then possible to call inkdoc or inkverb methods on Inkscape.
The inkverb-* methods are interactive and theres a lot of them. So ‘m-x inkverb-calligraphic-prefs’ in a buffer using inkorg-minor-mode for example, will bring up the calligraphy preference ui.
The inkverb-* methods are mostly ui related and take no arguments.
The inkdoc-* methods are related to object creation and manipulation and are not (yet) declared interactive.
Finding the right Inkscape operation in Emacs can actualy be much more efficient than using the menus in Inkscape. Especialy if you use some M-x booster such as Anything or Icicles.
Currently needs bleeding edge versions of a number of components.
- trunk version of inkscape with dbus enabled
- trunk version of Eieio(needs a change which hasnt been merged downstream)
- trunk version of Jan Moringen dbus-proxy
- Emacs 23. I use Emacs 24 from trunk, but 23 should be ok. but since everything else is bleeding edge you might as well use a bleeding edge Emacs also. You know you want to.
get Inkmacs bugfixes merged
please note that there is an Inkscape branch where I have some bugfixes for the dbus support: lp:~joakim-verona/inkscape/dbus-fixes In particular the ink-org integration wont work at all without the fixes
the long term goal is to make an Emacs that does things quickly that currently inhibits creative flow with inkscape. In particular I want to make a framework that supports specialized workflows, such as producing sketches for blog entries and web comics. so, when inspiration hits you: m-x inkscape-blog-sketch, rather than fiddling about in menus etc until you loose inspiration.
I am also interested in building a presentation tool on top of the inkmacs org integration. This is currently based on org-mode and is called inkorg minor mode in inkmacs. Inkorg seems to be pretty good for the purposes mentioned and is currently the flagsdip UI of Inkmacs.
For this we want to:
make the xwidget Emacs branch usable, so inkscape can be embedded
in Emacs. I’ve done some initial experiments with a xembed patch for Inkscape and the xwidget branch for emacs. It is possible to embedded Inkscape in Emacs with this particular stack. There are a number of problems that are documented in the xwdiget readme. Briefly:
- xwidgets can’t support emacs split window paradigm with sockets easily.
- the xembed patch for inkscape is just proof of concept. Some more support like creating new xembed windows using perhaps the dbus api would be useful
- inkscape doesn’t seem able to create several views for the same document. investigate.
make inkscape support xembed, so it can be embedded in Emacs.
I have a branch on launchpad for this but it has issues and is long term. see above also.
maybe using inkview. I noticed Inkscape has a shift-F11 mode which should do the trick. CANCELLED make an inkscape mode that shows just the canvas.
make an Emacs inkscape control mode that implements a proper Emacs
ui on top of inkscape. the foundation for this is done. Whats lacking is good bindings.
somehow implement the Emacs buffer model with inkscape
implement a form of OLE.
display svg images inline muse-mode org org mode for example. this is already mostly possible. this requires working xembed xwidgets.
edit the svg inside inkscape when desired
very important is to support text editing in Emacs.
nodes in an outline-mode document should preferably be bound to nodes in the inkscape document.
an annoying extra inkscape window appears
happens when the proxies are registered. theres seemingly no straightforward way around it. introspection of a live instance appears needed.
some test code snippets
check alive (dbus-ping :session “org.inkscape” 100)
(dbus-introspect-xml :session “org.inkscape” “/”)
(dbus-introspect-get-all-nodes :session “org.inkscape” “/org/inkscape”)
(dbus-introspect-get-interface :session “org.inkscape” “/org/inkscape/application” “org.inkscape.application”) (dbus-introspect-get-method-names :session “org.inkscape” “/org/inkscape/application” “org.inkscape.application”) (dbus-introspect-get-method-names :session “org.inkscape” “/org/inkscape/desktop_24” “org.inkscape.document”) (dbus-introspect-get-method :session “org.inkscape” “/org/inkscape/desktop_24” “org.inkscape.document” “rectangle”)
(dbus-introspect :session “org.inkscape” “/org/inkscape”)
the verb proxies
inkscape doesnt export all functionality through proper dbus interfaces atm. there is an older “verb” interface, and a dbus bridge. here is some code that tries to aproximate the dbus-proxy api for the verb api
the dbus proxies
creating the dbus proxies, using Jan Moringen fantastic dbus-proxy library. The way emacs dbus integration was meant to be
inkdoc load issue
BUG funnily crashes if called twice on the same desktop object(not reproducible) inkdoc-load is awkward:
- 1st open happens inside “virgin” desktop
- subsequent opens happen in new desktops
- the resulting desktop name isnt returned
inkscape org integration
inkscape org integration - the pride of inkmacs
- tree level 1 represents the file
- tree level 2 is a column heading
- tree level 3 and lower are placed in the column
inkscape text is a little bit unintuitive: text objects are realy a set of text span objects with separate prperties but tde api doesnt ouite reflect that because its inconvenient anyway furthermore the spans dont change after you create them
for the purpose of inkorg, its nicer if we handle formating and wordwrap inside inkscape. to get that we need a text object and another linked object which determines the shape. they are both handled separately.
Also note that svg 1.2 isn’t finalized: http://wiki.inkscape.org/wiki/index.php/FAQ#What_about_flowed_text.3F
In practice this means that early 2011 the flow text nodes won’t show up if you try to render the image in Firefox or Webkit based browsers. librsvg2 which is used in Emacs won’t work either. This is hardly convenient. I’m investigating two non-mutex ways forward:
- rendering the svg image to another image format on demand
- optionaly use the textspan object rather than the flowroot. Then you would have to handle text line break in Emacs which might be okay for some cases.
tip: create a special text layer before inkorg-create-text-group
strategy for orphaned nodes
if a node has been removed from the org doc it should also be
removed from the ink doc. this is however a bit tricky. naive method to find orphan nodes:
- build a list A of all inkscape objects using select-all
- build a list B of all inkorg nodes by iterating the org tree and extracting the id
oh wait - I dont know which A:s used to be inkorg nodes. aargh! inkscape groups cant really be used because it changes behaviourp the only reasonable alternative seems to be to use a naming convention: inkmacs-<type>-<orgid>
inkorg mode works sort of like org export but its not always entirely the same. Nevertheless inkorg should reuse org export code when possible. A big difference is that the svg file is used in tandem with org. it is not generated from org like other org exports. subtree export support
doesnt really work because the name is used to link to the svg file. a property can be added to override the file name. a better error is needed to show the error is unlinked file. changing name of root inkorg node.
could be used to override the default file name.
org mode does this already. CANCELLED [#B] some form ov planner/outline integration that works with ecb
look at org-ascii
to replace my text extractor
For this we need: support formatted text
- support to apply styles to text via ibus in inkscape.
My dbusfixes branch has this and the prospect of inclusion are good.
- inkorg support for extracting the org formatting.
The way things work atm this will be a 2 step process. create text, then apply styles.
I now support bold headings which is good enough for now
better file import wrapper
Emacs is a great file selecor I’d like to use in order to import clip art into a technical drawing for instance.
inkverb-file-import triggers the inkscape import dialogue. I need to figure out a way to send the file name as a parameter instead. It might turn out I need another dbus interface function.
An interface to openclipart.organisation on top of this would be useful. Inkscape has support for openclipart which is good but in think Nkmacs can do better:)
- fetch the query result to a buffer with url-get
- parse the xml using the emacs 24 xml parser
- fetch thumbnails and display asynchronously
- each thumbnail is a button with an interface to inkmacs-file-import
- download the svg and imort it when button clicked
resize flowframe from text size
the frame holding a flowed text is often too small. currently it needs to be resized by hand. it appears possible to find the height of the flowtext and set the height of the flowframe accordingly.
note that the ontire point of flowframes is that the frame sets the size of the text. so its not meaningful to set more than either height or width from the text.
Its a little difficult to get the sizes for rendered flowtext. I’ve implemented the dbus parent/child accessors needed as a first step. parent child accessors
cleanup flowroot transforms
When you move things around and scale, it can happen that flowroots get their own transforms. Then all layout breaks. In those cases it would be useful to reset the transforms so text flows inside their flow frame again. If you really want the text to have an offset or something you are probably out of luck.
remove these attributes: flowroot.transform flowroot/flowregion/use.tranform
help to export clean interchange formats like svg 1.1 and PDF that actually works in acroread.
inkscape has pdf export but it sometimes creates pdf:s which arent readable by acroread.
batix also has issues with the corresponding svg.
- filter:url(#filter2573-3). the filter was undefined. It had gotten removed during editing
- svg version 1.2
one workaround was using evince to filter the inkscape pdf.
another way is checking the SVG with Batik and edit the XML in Emacs. it would work by parsing objoct references of type url and report.
batik pdf transcode: java -jar /home/joakim/batik-1.7/batik-rasterizer.jar -m application/pdf tst.svg
Emacs suffer from regexp overflow atm.
https://bugs.launchpad.net/inkscape/+bug/780335 contains good inforrmation:
one particular gradient type causes problems. “reflected”. identify and remove.
iterate all flowtext and convert to text
flowtext is good when you work with your document. text flows nicely in your shapes. OTOH flowtext sucks when publishing your SVG because only SVG 1.1 is finalized flowtext requires 1.2.
So it would be nice to convert back and forth.
THe SVG renderer in Emacs is librsvg. It’s robust but not fast because it renders to a deep bitmap and doesn’t seem to clip. Anyway, its not fast enough to pan around and zoom in and out of a SVG. Things to investigate: faster SVG renderer in Emacs
- make the librsvg usage faster by cleverer clipping and less bitmap copying
- try anether svg renderer like Cairo thats new and shiny
the end result would be a dual screen display which lets you select a region inside an SVG in one window and zoom into that region in another window, on a separate projector for instance.
The emacs xwidget branch allows for webkit rendering of SVG in Emacs, so I’ll consider this done.
recover if the first inkscape dies
if you try to redo proxies then it crashes.
attach to existing inkscape
(defun inkscape-document-dbus-proxy-create (desktop &optional session) useful for debugging. some more stuff is needed:
- list existing inkscape dbus sessions
- provide interactively
jessyink is an inkscape extension that creates portable presentations in svg. I want inkmacs to be compatile. I think it should be mostly already.
works like this: focus on particular area during presentations
- make a special layer with named rectangles. these are your focus areas
- make layer invisible during presentation
- bind “inkmacs-zoom-id” to something convenient during your presentation
the last part is the only tricky thing since Inkscape will be in focus and Emacs won’t have kbd focus. you will need a bridge at the WM level. dbus or emacsclient.
also you will need to know the ids of your focus objects.
this is mostly implemented now
poster print tiling
https://bugs.launchpad.net/inkscape/+bug/170274 poster -v jira.eps > jira.poster.ps && evince jira.poster.ps
poster unexpectedly didn’t work for my simple test.
another strategy could be to automate tilling from inkmacs via dbus.
suppose you want to create a template object, like a speech bubble. you want to create clones of this bubble filled with different text. furthermore you want to be able to know the ID of the text nodes you want to change such that you can update them again later.
There are some annoyances with this:
- Emacs is a bit limited when modifying xml. There is an xml parser in Emacs 24, but there is no convenient xslt like functionality other than traversing the sexp tree and changing it, which would be okay except I don’t feel like reinventing the wheel yet again
- there is no way of injecting the instantiated template into the inkscape DOM other than using a temporary file. and the template would need to be trimmed before injecting. and the existing inkscape important verb requires to use an interacive dialogue.
so, these add up to be quite annoying. path of least resistance seems to be a dbus file import function.
really funny layer resize bug
If you create a document from scratch with ink-org and create nodes they will go to unnamed “root layer”. If you then resize the document flowtexts will move separately from flowroots!
If you create layers and cut/paste all nodes into the new layer this behaviour goes away.
- is my empty init doc wrong? should it have a layer?
- does nodes get created with wrong attribs?
better org mode text extraction
currently I have my own org-entry-to-plain-text function. I couldnt find anything in org. surely there must be.
whatever the solution it should:
- export plain text
- newlines only on new paragraph
- support bullet lists
anything-colors has a pretty nice color picker that could be used. But I would like to be able to also select the palette, frem the set of palettes Inkscape offers.
better flowframe shape support
by default ugly rects get created
- provide facility to select shape on creation
- also be able to swap shape ID:s
[#C] try adding black bottom rectangle by svg file manipulation for drawings
this is wanted because some rendeerers see the bg as transparent, while some dont. a bg rect fixes this, but you need to add it explicitly.
configurable text mode support
either ordinary svg text or svg 1.2 flowframe text. I’ve implemented flowframe text but Inkscape has a number of issues with it such as that its inconvenient to handle two objects for one text object.
If you are sattisfied with Emacs dictating the linebreaks rather than a separate Inkscape flowframe object, an ordinary svg text object would be less hassle.
to make it easier to keep track of the objects which is the main source of trouble at the moment. separate text and flow object layers
- inkmacs-text layer
- inkmacs-text-flow layer
the flow objects should simply be semi-transparent rectangles with frames. hide the layer when you don’t want to see it.
done, but the inkscape dbus layer functions are somewhat fragile still.
support multiple page
http://sourceforge.net/projects/inkscape-pages the current imkmacs code care about layer names so would need to check.
support org attachments
the svg file could be an attachment to the org tree.
inkmacs ease of use
should work: (require ‘inkmacs) this inkscape is too old: (setq inkscape-path “/home/joakim/build_myprojs/inkscape/inkscape.dbus/src/inkscape”)
- recognize if inkscape lacks dbus. currently it just fails.