Native SVG support for Apache OpenOffice 3.4 (Incubating)
Apache OpenOffice 3.4 supports embedding SVG graphics using a newly created native SVG interpreter implementation. I want to talk about the advantages and some internals of this solution and the necessary changes done.
One reason to do this was IP clearance. It allowed removal of six GPL/LGPL libraries, namely
librsvg, libcroco, libgsf, gdk-pixbuf, glib, and pango gettext. These
were used as an external pixel-based renderer. The new SVG uses an own internal
interpreter in a new library and some new UNO API services. IP clearance was no interesting task to do, but it leaded to effects like here with SVG; the install sets get smaller (less libraries to deliver), the app needs less libraries (startup, memory, runtime) and the internal handling of SVG vector data is completely vector-graphic oriented.
There were also ODF-compatible File Format adaptions needed, more concrete the in ODF already contained and described multi-image support. In ODF, the original SVG is now embedded to the 'Pictures' folder inside the ODF file as one
would expect from such a feature and can be easily extracted (unzip the ODF file and there you are). There is also a Png file
written as replacement image. The draw:frame is now multi-image
capable (as the spec allows). In the case of a SVG it writes a good
quality Png and the original SVG as draw:image elements. Since older
(and other) office versions are only capable of loading a single (and
thus the first) image, the Png is written first. This allows file
exchange with other and older offices without breaking backward compatibility and/or ODF file exchange. At load time, multi-image support
will choose the best quality graphic available for further work, e.g.
preferring vector format over pixel format, pixel format with
alpha over non-alpha and lossless formats over those with
losing info (you get the idea). Other ODF implementations (e.g. a
viewer) may just use the pixel graphic available. Multi-image support is
independent from SVG in principle and will work with all image file
formats. This is implemented for the Drawinglayer graphic object (used
in Draw/Impress/Calc) and the Writer graphic object (used in Writer).
SVG is no longer interpreted each time it needs to be
rendered (unavoidable by an external renderer), but only once transformed to a
sequence of primitives (UNO API graphic atoms). That sequence is then used for all outputs,
transformed to the graphic object's form and viewport. The
sequence itself is completely view-independent. Internally, it is reused
and thus it makes no difference if you have your SVG graphic added once
or multiple times to your document. This is also true for saving, so always only one copy of your added SVG will be written (the same is true for the replacement
Png image). Both, the sequence of primitives and the replacement
image, are created using new UNO API services. One is capable of
converting an io::XInputStream with SVG content to a sequence of primitives, the other is
able to convert every sequence of primitives to a rendering::XBitmap
with given DPI and discrete sizes (pixels, with automatic resolution
reduction to a given maximum square pixel count to be on the safe side). This will be useful
for other purposes, too, since it creates a fully alpha-capable
representation of anything in primitive format to use as e.g. sprite.
For all graphic processing the created vector graphic in form
of a sequence of primitives is used. This means that you will get best
quality in all zoom situations and all resolutions. This is also true
for all exports, e.g. printing or PDF export which also uses the vector
format. With an external renderer, it is unavoidable to use bitmaps with
discrete solution in those cases, looking bad when zooming and needing more space in most cases as vector data. There is one caveat since not all
program paths already use primitives; some will use the internal MetaFile
format in-between (One more reason for more reworks to primitive usages
in the future).
I implemented most SVG features from SVG 1.1, but not yet
using animations or interactions (but possible in the future due to an
own interpreter, impossible with an external SVG renderer). It supports
all geometric SVG forms. It supports SVG gradients (using a new primitive
for this which will be reused when we add SVG gradients to
SdrObjects one day), these have a resolution-dependent low-level format
to not waste runtime on low resolutions. It supports masks, clipPath, markers, linked content, embedded graphics or SVG (intern, extern,
base64), SVG use nodes, text, text on curve and patterns. It does not yet
support filters, color profiles, embedded scripts, interactions and
linking. These can be added when needed, most of them will need to
implement new primitive types (e.g. filtering) which would be useful for the future
anyways.
Especially interesting is the possibility to later add SVG animation import to GraphicObjects for Impress.
Some side effects: I had to fix cropping (unified with new primitive) which
works now also for mirrored graphics (never worked) and quite some other
stuff. We are prepared for SVG gradients as possible future feature (we
can already render them now). You can work with an added SVG as with a normal GraphicObject; crop it, break it (to SdrObjects, currently limited to the
transfer over the old MetaFile format, though). You can convert an
inserted Tux to 3D, you can bend the SVG in vector quality in Draw. It
is possible to directly export the original SVG again by selecting the
object and using 'Save as Picture...' from the context menu. You can add text, line style, fill
style, pretty much the same as most other graphic objects. You can add
shadow which casts shadow for the SVG graphic itself as expected (also not possible with an
external renderer).
This is a bigger change, but most stuff is isolated in the
two mentioned services. There will be errors (I'm too long a programmer
to deny that :-)), but I tried to be as careful as possible. I already got some help from other community members and fixed some reported bugs (kudos to all testers and bug writers), but to find
the rest, your help is appreciated. Please feel free to play around with any
SVG you can find in current AOO 3.4 builds and report problems early in the Apache bugtracker!
Here is another blog entry about an early version of this feature.
And here are some developer snapshots of AOO 3.4 when you want to check it out. Be aware that these are AOO 3.4 Unofficial Developer Snapshots; these are intended to be used for early testing by other community volunteers.
They have no release quality and should not be installed in a
production environment. Developer snapshots can be unstable and are
expected to have bugs.
Regards,
Armin