Inkmacs, Emacs and Inkscape fusion

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.

Inkorg-mode

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.

Technical Discussion

Dependencies

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.

DONE 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

long-term goal

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:

TODO 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.
  • TODO 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.

  • CANCELLED make an inkscape mode that shows just the canvas.

    maybe using inkview. I noticed Inkscape has a shift-F11 mode which should do the trick.

TODO 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.

DONE somehow implement the Emacs buffer model with inkscape

TODO 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.

DONE edit the svg inside inkscape when desired

DONE 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.

TODO 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")

DONE 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

DONE the dbus proxies

creating the dbus proxies, using Jan Moringen fantastic dbus-proxy library. The way emacs dbus integration was meant to be

TODO 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

DONE inkscape org integration

inkscape org integration - the pride of inkmacs

m-x inkorg-mode

strategy:

  • 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

inkverb-file-export

  • 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

TODO strategy for orphaned nodes

TODO 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>

DONE subtree export support

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.

DONE changing name of root inkorg node.

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.

`EXPORT_FILE_NAME', `EXPORT_TITLE',

could be used to override the default file name.

`#+TITLE:' compatibility

CANCELLED [#B] some form ov planner/outline integration that works with ecb

org mode does this already.

TODO look at org-ascii

to replace my text extractor

DONE support formatted text

For this we need:

  • 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

TODO 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.

TODO openclipart interface

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:)

http://www.openclipart.org/detail/90145

http://www.openclipart.org/wiki/API example search for a server image: http://www.openclipart.org/media/feed/rss/server

Plan:

  • 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

TODO 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.

DONE parent child accessors

Its a little difficult to get the sizes for rendered flowtext. I've implemented the dbus parent/child accessors needed as a first step.

TODO 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

TODO clean exports

help to export clean interchange formats like svg 1.1 and PDF that actually works in acroread.

TODO pdf

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:

  • scour
    • vacuum

one particular gradient type causes problems. "reflected". identify and remove.

TODO 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.

DONE faster SVG renderer in Emacs

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:

  • 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.

TODO recover if the first inkscape dies

if you try to redo proxies then it crashes.

TODO 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

TODO jessyink support

jessyink is an inkscape extension that creates portable presentations in svg. I want inkmacs to be compatile. I think it should be mostly already.

DONE focus on particular area during presentations

works like this:

  • 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

TODO 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.

TODO template instantiation

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.

TODO 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.

investigate:

  • is my empty init doc wrong? should it have a layer?
  • does nodes get created with wrong attribs?

TODO 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

TODO palette support

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.

TODO 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

TODO 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.

TODO 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.

DONE separate text and flow object layers

to make it easier to keep track of the objects which is the main source of trouble at the moment.

  • 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.

TODO support multiple page

http://sourceforge.net/projects/inkscape-pages the current imkmacs code care about layer names so would need to check.

TODO support org attachments

the svg file could be an attachment to the org tree.

TODO 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.