Fun with VectorDrawable’s (or: how to make them work everywhere)

We recently started trying to use VectorDrawable’s – this is as part of an effort to reduce and minimise app size. VectorDrawable’s are a vector image format, based on SVG. Reliably using them across multiple Android versions, and a diverse medley of devices, has proven somewhat tricky – this blog post is a compilation of what we’ve done to get them rendering acceptably and consistently.

What’s a VectorDrawable

VectorDrawable‘s are an xml vector graphics format, with some similarities to SVG. They’re much smaller than the equivalent png or webp. They are scaleable, so you only need to ship one file, as opposed to 3+ when using raster images (i.e. png or webp).

When should you use them

On supported devices (we’ve tested Android 4+), for all images up to 200 x 200 dp (Google recommend not using them for larger images to avoid performance and memory-consumption issues), so long as you are using support library 23.2 or newer OR you only support Android 5 and newer.

If your app is extremely small there’s little advantage to using VectorDrawable’s, so it’s probably best to just stick to raster images to avoid the various issues detailed below.

Where can you use them

Pretty much anywhere: on Android 5 and newer VectorDrawable’s are supported everywhere by default. On older devices you’ll still be able to get them working, as long as you’re willing to get your hands dirty.

For 4.4 and older you need support library 23.2 or newer. Officially, as detailed in the release notes, VectorDrawable’s are only supported in some components: this includes AppCompat components. We’ve had no issues using them in design support library components, including NavigationView.

But it’s also possible to load VectorDrawable’s directly – which I’ll describe below. (Note: there was a temporarily supported feature for overriding all drawable loading when VectorDrawable’s were placed within a Drawable container, but that was disabled again, apparently due to issues in handling Configuration changes, and increased memory consumption.)

Build system changes

If you’re building for Android 5+, no changes should be needed. If you’re building for lower versions with use of the support library, and using gradle, follow the release note instructions. If you happen to have your own build system that invokes aapt directly (but who would do that?), you’ll need to add “–no-version-vectors” to your aapt invocation.

VectorDrawable loading with 23.4 (and possibly 23.2 – 24.1)

Instead of loading Drawable’s via context.getResources(), you can use AppCompatDrawableManager:

-    final Drawable d = context.getResources().getDrawable(drawableID); // This only loads system-supported resources
+    final Drawable d = AppCompatDrawableManager.get().getDrawable(context, drawableID); // This loads <vector> too!

This doesn’t seem to be documented anywhere, and is therefore essentially unsupported. However it uses the exact same Drawable loading code as the rest of AppCompat, and leads to the same code paths as the (newer/official) 24.2 code. This is what we use for most of our Drawable loading.

VectorDrawable loading with 24.2 and newer

24.2 finally introduces official VectorDrawable support, see the release notes and API docs:

-    final Drawable d = context.getResources().getDrawable(drawableID); // This only loads system-supported resources
+    final Drawable d = AppCompatResources.getDrawable(context, drawableID); // This loads <vector> too!

Version specific bugs

Android 4: corrupted drawable’s (Proguard)

Screenshot of VectorDrawable's exhibiting corruption on Android 4

Plenty of corrupted drawables. You’ll never get the same corruption twice!

This can be fixed with some proguard tweaks:

-keepclassmembers class$* {
   void set*(***);
   *** get*();

-keepattributes LocalVariableTable

This issue has been filed in the Android bug tracker, it doesn’t look like a fix has been landed yet.

Android 4 and 6: missing drawable’s on 4, artifacts on 6 (Arc curves)

On Android 4, drawable’s with arc curves might randomly disappear (this is easy to test if you have a navigationview that you can hide and reopen repeatedly, e.g. in a BottomSheet context menu). On Android 6, such drawable’s can display artifacts (this is a different kind of corruption to what we saw on Android 4: on Android 6, arc curves seem to result in some points in the image being misplaced, as opposed to true corruption).

Image of icons being rendered with artifacts visible.

The bottom 3 icons all exhibit some rendering issues on Android 6

Screenshot of some VectorDrawable's not being rendered on Android 4

Some icons will occasionally disappear on Android 4 (ignore the blurry pin icon, that’s just an excessively scaled png that we’ve since replaced with another VectorDrawable)

After some experimenting, I discovered this only happens for Drawable’s with arc curves. You can check if these are present by looking for the letter “a” or “A” being present in the “android:pathData” part of your VectorDrawable. Or within the <path> if you’re looking at the source SVG.

screenshot of an editor, pointing to where an arc curve is defined

You can spot an arc curve wherever ‘a’ or ‘A’ is used in a vector path

One simple way of getting rid of these is:

  1. Import the source SVG into an SVG editor
  2. Perform an “ungroup”
  3. Export again.

Boxy SVG is fairly lightweight option for doing this. If you’re processing a large number of drawable’s, scripting inkscape might be a more efficient choice. (Make sure to double check the output, there’s no guarantee that any edits will result in purging of arc curves.)

A warning for the road

Our QA team has done some good testing, which meant that we discovered the corruption issues described above early during development. Our release audience is significantly more diverse than what we can test ourselves – and we’ve only been using VectorDrawable’s for an as-of-yet unreleased feature – so we can’t actually guarantee that there won’t be more issues in the wild. The usual culprits have all been tested (every Android version, x86 devices, Asus 4.X devices, some other odd tablets), which makes me more confident that we’ve ironed out most of the kinks.

Our first universally-visible VectorDrawable landed recently, which should let us verify that VectorDrawable’s really are truly ready to ship everywhere.

Other size reduction tips

For larger images (larger than 200 x 200dp), or even just as a quicker fix (getting SVG versions of images is laborious), I recommend looking into webp conversion. Webp provides somewhat better compression than png (although you need to be careful to not compromise image quality), with 30% size savings commonly reported. Android 4.0 only supports non-transparent images (i.e. no alpha-channel), you need Android 4.3 for full support – nevertheless we converted a fair number of images recently. I’ve written a small wiki page detailing some png optimisation commands, and webp conversion tips.


Tagged with: , ,
Posted in Firefox for Android

Some Impress Remote Improvements

Over the course of the summer I’ve been adding some minor improvements to various parts of the Impress Remote — both on the Server and Android components.

Remote Deauthorisation & Dialog Improvements (for WiFi connected remotes)

(Implemented at the Paris Hackfest.)

Impress Remote Removal

Prior to this, authorising a remote was a permanent and irreversible action — now you can remove them again (this only applies to WiFi/network based remotes — Bluetooth remotes are managed using system utilities).

At the same time some further improvement work was carried out on the dialog to remove some other annoyances (e.g. occasional flickering), in addition to the fixing of an (admittedly minor) memory leak (shhh, apparently I wasn’t aware that C++ didn’t have a garbage collector when I first started working on LO), and finally improving the pin-entry (i.e. auto-focus on the pin-entry box, and no useless/junk “0” in that pin box anymore).

Ultimately it would be cool to use fancy new widget layouting to assemble the list of remotes, instead of the current custom vcl widget (which would make it easier to add more functionality in future if desired, and there is certainly no lack of ideas in that department), but that’s a story for another day (and no idea how simple/complex the conversion would be).

Emulator auto-discovery

This actually existed in the early days of the Android Remote, but unfortunately got lost at some point. It’s the work of only a few lines but makes the lives of developers simpler — especially so for first time developers who may not be aware of the networking infrastructure around the emulator (the “real” host is reachable under from the emulator).

Emulator Autodetection

Emulator Autodetection

(This was implemented at the LibreOffice Conference Hack-Night, where I was wanting to work on the bugs/features below, but couldn’t actually test the remote on my phone as my laptop’s Bluetooth adapter was borked, and the University WiFi was blocking the remote too. I couldn’t actually remember the correct host IP, and had managed to type it incorrectly on the remote development wiki page back in 2012 too…)

Grid View Current Slide Highlighting

The grid view previously offered no hints as to which slide is selected, that is now remedied:

Impress Remote Grid Highlights

Impress Remote Grid Highlights

The design is far from final, and can easily be adapted in the resource files, but the functionality now exists.

Refactoring and Bugfixing

Over time the code has become a bit untamed — fixing a bug in the laser-pointer mode (where the displayed slide wouldn’t be updated when the slide is changed on a different device and/or server) involved some refactoring that not only deduplicated a chunk of slide-change listening code, but also allowed easier (and more correct/simpler) implementation of some of the above features, e.g. the grid-view highlighting.

The future

There’s never a shortage of ideas/bugs, just too little time. There’s no plan, but some things that might be cool would be features such as storage of presentations on the remote (to allow transfer between PCs), chromecasting of presentations (although that would be very complex / would require using the full LibreOffice on Android porting work + a good chunk more — a very pie in the sky idea), Android Wear integration (probably mainly for showing athestopwatch), in addition to just more polishing of the existing functionality.

Finally, a big thanks to Google for sponsoring the initial implementation of the Impress Remote as part of the Google Summer of Code 2012, Michael Meeks as my first GSOC mentor, and the LibreOffice development community in general for their support and advice.

Posted in LibreOffice

LibreOffice on Android #3 – Calc Documents

After a somewhat painful debugging experience*, it’s now possible to view Calc documents on Android too.

This combines the Calc Tiled Rendering work (thanks to the Google Summer of Code) with the LibreOffice Android Viewer developed by Collabora (thanks to Smoose):

Calc on Android

This work is still on a branch (as some of the changes affect Calc’s normal rendering, and still need to be fully verified as to not introduce unwanted bugs there), but should hopefully be mergeable soon.

* Using the r10-ndk it was possible to at least set (and make use of) breakpoints on methods, however gdb seemed to be blind to any other debug-info, making this a pointless exercise. With the r9d-ndk, gdb wasn’t even able to connect to the application. (Fortunately we can still get log output via adb logcat — resulting in slow but useable debugging.)

(Update: It’s also worth noting that we don’t use the standard ndk build system (the LO build system is hugely complex already), and we have problems with the standard android linker due to the sheer size of what we do, currently we therefore link all our (usually separate on a desktop) libraries into one huge library (but restrict building debug info to only a few modules so that we can still link that huge library without running out of memory), which might also not be so helpful for the ndk-gdb. I’ll be back on my main machine soon, so can experiment with a full debuginfo build there hopefully, but on my laptop that just isn’t feasible.)

Tagged with: , , ,
Posted in LibreOffice

Calc & Impress Tiled Rendering, and LOKDocView

At the Libreoffice Conference 2014 in Bern I gave some very brief talks, both related to my work this summer on tiled rendering (and the possibilities of reuse in external applications):

Calc and Impress Tiled Rendering

A shortish talk (as part of the GSOC Panel) on the implementation of Tiled Rendering for Calc and Impress:


(Click on image for Hybrid PDF)

LOKDocView: the LibreOfficeKit GTK+ Widget

A very brief lightning talk on how to use our shiny new LibreOfficeKit GTK+ Widget (named LOKDocView). Is hopefully easy to use, hence one slide of real content should hopefully be enough to explain how to use it.


(Click on image for Hybrid PDF)

Attending the conference was a very valuable experience; allowing me to see past and future work by fellow contributors in addition to useful technical advice from some of the most important LibreOffice developers.

Tagged with: , , ,
Posted in LibreOffice

Calc & Impress Tiled Rendering preview

Recently I’ve been working on Calc and Impress tiled rendering, with some results now becoming visible:


Impress Tiled Rendering is now integrated into master — there are still some issues, i.e. foreground images are not shown yet (this is a bug that’s shared with calc tiled rendering), and it’s not yet possible to select between rendering only slides, only notes, or both (i.e. we currently default to whatever mode the document was last opened in). However in general it seems to work quite well:

Impress Tiled

Impress Tiled Rendering: Unfortunately no Image rendered

In fact very little work had to be done to get tiled rendering working here — the hardest part was figuring out what part of Impress to plug into: once I’d gotten my head around Impress’s architecture, connecting up the rendering was a matter of a few lines of code.


The calc work is somewhat more substantial, primarily due to the way that scaling for cell rendering works: calc calculates on-screen pixel based sizings in a number of steps using its own scaling methods, which can sum up to noticeable errors between expected and rendered content (which would result in discrepancies when later compositing tiles). This means that there is a significant amount of work needed in rewriting parts of the scaling: while the tiled rendering itself is beginning to look acceptable, the normal UI for Calc is now partly broken, primarily in that scrolling is rather glitchy (however this is being fixed bit by bit, and it is hoped will be mergeable in a useable state soon). This work is still staying on a branch for now — i.e. until it doesn’t break the usual way of using Calc.

Similarly to Impress, images in the foreground aren’t being rendered yet — this as far as I can tell is the same underlying issue, and is what I’m currently working on fixing.

Calc Tiled

Calc Tiled Rendering: charts work too!

Other Stuff

In addition to the work on actual tiled rendering, there have been some further additions in the surrounding code and testing tools:

  • “Zoom” Controls for the gtk tiled viewer. (Zooming is however quite slow as we’re repainting a huge tile…)
  • A part selector for the gtk tiled viewer, i.e. permits switching between tabs in a spreadsheet, or slides in a presentation (writer documents are however rendered all as one huge block).
  • Associated zoom and part selection methods for the LokDocView gtk+ widget.
  • A quad-tiled widget for testing (nothing to do with real tile composition…): this allows for inspecting tile transitions/borders (and was useful for finding some more glaring issues in the calc implementation).
  • Some automated tests that aren’t yet fully enabled due to some further bugs that have been uncovered (which would cause them to fail).
Tagged with: , , ,
Posted in LibreOffice

LibreOfficeKit GTK+ Viewer Widget

Easily integrating LibreOffice directly into any other application is now a step closer thanks to the new GTK+ lok_docview widget (currently only on the feature/gtkbmptiledviewer2 branch, API and naming liable to change, usual disclaimers, etc.).

It currently sports a very simple api, consisting of the following two methods:

GtkWidget*   lok_docview_new (LibreOfficeKit* pOffice);
gboolean     lok_docview_open_document (LOKDocView* pDocView,
                                        char* pPath);
The gtktiledviewer has been upgraded to use this widget, and looks much as it did before (although with some notable improvements, more below):
New and Improved

New and Improved (no more missing portions)

As mentioned above, there have been some further improvements to the tiled rendering in general:
  • All document content is now rendered, we don’t have missing text/images outside of the top-left section anymore.
  • Alpha channel is now set correctly in the tiled rendering output (less relevant for the widget where we could easily hide that, but useful for other uses of tiled rendering where additional manipulation of buffers can now be avoided).

I’m hoping to get started on tiled rendering support for calc next (currently only writer documents are supported). I’m also optimistic that we’ll be able to merge back onto master (allowing for more widespread experimentation) soon.

(For now we just dump one bitmap for the entire document within our widget — not hugely efficient, but simple and useable. Hopefully in the long run we’ll be able to move to having some form of proper tile compositing and also get rid of bitmap rendering — all of which can be hidden away within the widget implementation.)

Posted in LibreOffice

Tiled Rendering with LibreOfficeKit

This summer I’m going to be working on (hopefully) helping to add Tiled Rendering support to LibreOffice Calc and Impress.

As a first stage I’ve been experimenting with implementing a pure GTK+ tiled rendering app, to allow for active testing of tiled rendering work, i.e. using the existing tiled rendering in writer. (On desktop platforms we already do have a basic testing app, but that’s based on VCL — it shows a background window of the document in addition to wherever the tiled rendering happens.)

This application is being developed on the basis of LibreOfficeKit (formerly liblibreoffice)  — i.e. avoiding the need to interact with LO internals — which is being extended with the (currently experimental only) necessary API calls to allow rendering to a bitmap buffer (in the longer run OpenGL would probably be most appropriate, but bitmap rendering is still quite useful for some applications. More importantly support for this already exists whereas OpenGL would require a chunk of extra work). Hopefully we’ll soon also have a simple GTK+ viewer widget to allow for simple reuse in other applications (meaning we can then change the internal implementation at will and upgrade to faster rendering as appropriate), perhaps modelled on the basis of the WebViewGtk widget.

The current tiled viewer looks somewhat like this (there are still problems with document rendering, i.e. portions are not rendered in our test document in odk/examples/java/DocumentHandling/test/test1.odt ):


And if you get the rowstride (and colourspaces) mixed up you can get some more interesting effects such as:


Posted in LibreOffice

Bluez 5 support for LibreOffice Impress Remote

Recently some distros have started shipping Bluez 5 — this introduces a completely new DBus API, meaning that bluetooth support for Impress Remote was broken on such systems (openSuse and Fedora being the more notable distros now shipping Bluez 5, whereas e.g. Ubuntu still seems to be sticking with Bluez 4 for now).

LibreOffice has  gained Bluez 5 support — this is now available in LO 4.1.6, and will also be included in 4.2.4 (to be released soon).

API Changes: Bluez 4 -> Bluez 5

There is not a huge amount of documentation explaining the changes between Bluez 4 and 5. Fortunately the new API turns out to be fairly clean, and overall is much simpler to use than what we had to do for Bluez 4. However in LibreOffice we restrict ourselves to the low-level dbus library (“If you use this low-level API directly, you’re signing up for some pain.“) which makes things a bit harder and hugely verbose (this is primarily for buildability on older systems and to avoid new dependencies — there is hardly enough dbus use to warrant a slew of new dependencies). (Python however seems to be a much more elegant language for dbus work, as is evidenced by the Bluez 5 unit tests.)

The key differences between the Bluez 4 and 5 DBus APIs that are likely to be of interest to those wanting to add Bluez 5 support to their applications can be found in a document on the bluez homepage, however it’s probably worth adding:

  • In most cases you probably no longer need to retrieve any Bluetooth adapters, since Profile registration no longer happens via the devices (unless you want to fiddle with things like discoverability). This is good as the DefaultAdapter no longer exists, so to get hold of an adapter we need to retrieve all objects from the Bluez ObjectManger and filter that for adapters (a complete pain with the low-level library due to multiple levels of dicts which have to be traversed).
  • Trying to portray ourselves as a “server” (via the properties passed in to ProfileManager1.RegisterProfile) prevented connections from reaching LibreOffice — this still needs some investigation on my part… (Overall, profile registration is much simpler than with Bluez 4 since we can now just pass in a UUID and not have to construct our own XML SDP record as before.)
  • No need to detect Adapters appearing/disappearing (as happens on resume/suspend) in order to reregister profiles thanks to the ProfileManager doing this for us — much simpler main loop as a result.
  • New connections are passed to us via the org.bluez.Profile1 callback object which we (the application) have to implement (which provides a socket, connected to the remote device, ready to use in any pre-existing network code you may have, i.e. you can jump straight into send/recv’ing) — however you need to make sure to provide an (empty) reply when you receive the NewConnection call, or Bluez will simply shut down your connection after some timeout.

It’s worth noting that there is also a direct C library for bluez which appears to be quite stable (and as far as I can tell would’ve been the simplest way to do our SDP registration in combination with manual socket management as before — however as I’ve never used it I may be completely misguided on this) — however it is GPL’d and hence not of much use for LibreOffice.


Unfortunately Bluez 5 doesn’t seem fully reliable yet, i.e. it can seemingly randomly (but fortunately rarely) break after a suspend/resume cycle (no obvious reproduction recipe known yet, I’m still to get round to debugging in detail). The kde bluetooth management tools in openSuse 13.1 are also a bit crash-prone (but that is known and mentioned in the release notes — the relevant libraries are still in active development). If you are after a more reliable experience it is probably best to stick with Bluez 4 for a while longer.

(Bluez 4 support in LibreOffice continues to exists without change.)

Posted in LibreOffice

LO Embedded Firebird/HSQLDB performance comparison

One of the major motivations for my GSOC project this summer was to get rid of the somewhat inefficient use of Java from C++. One immediate difference noticeable from early on when working on Firebird integration is the disappearance of a large pause when loading a database caused by startup of the jvm. (Unfortunately we still need Java for various wizards within Base which still need rewriting in C++/Python/etc. — for now this pause just happens at a different point in time.)

However the main speedup to be expected was in actual manipulation of data. Hence a insertion/retrieval test was developed — currently we only test the insertion and retrieval of 120’000 strings (a dump of the aspell dictionary), the results of which show a significant advantage for Firebird:


It should be noted that this test is not an accurate comparison of Firebird and HSQLDB in their native environments, this is only an accurate comparison of the two databases accessed via SDBC drivers, i.e. going via C++ — I suspect the slowness of HSQLDB is mostly due to the use of JNI and the C++/Java transition.

It would probably be interesting to add further tests to compare the performance when working with numeric types, however the performance boost of using firebird should already be clear. The tests and documentation can currently be found in dbaccess/qa/unit/emeddeddb_performancetests.cxx.


Tagged with: , , ,
Posted in GSOC2013, LibreOffice

Embedded DB Selector for Base

It’s now possible to select the driver to use for embedded databases within Base thanks to the new selector:


The default database remains HSQLDB, however this change allows easy creation of new firebird based .odb files (mainly for testing purposes at the moment), whereas previously manual extraction and editing of the .odb file was necessary to create such a file. This also means that in future, once the default database can be changed to Firebird, it will still be possible to create HSQLDB files for compatibility with older version of LO/OO/etc.

Posted in GSOC2013, LibreOffice