Tuesday, October 21, 2025

CapyPDF 1.8.0 released

I have just released CapyPDF 1.8. It's mostly minor fixes and tweaks but there are two notable things. The first one is that CapyPDF now supports variable axis fonts. The other one is that CapyPDF will now produce PDF version 2.0 files instead of 1.7 by default. This might seem like a big leap but really isn't. PDF 2.0 is pretty much the same as 1.7, just with documentation updates and deprecating (but not removing) a bunch of things. People using PDF have a tendency to be quite conservative in their versions, but PDF 2.0 has been out since 2017 with most of it being PDF 1.7 from 2008.

It is still possible to create version with older PDF specs. If you specify, say, PDF/X3, CapyPDF will output PDF 1.3 as the spec requires that version and no other even though, for example, Adobe's PDF tools accept PDF/X3 whose version later than 1.3.

The PDF specification is currently undergoing major changes and future versions are expected to have backwards incompatible features such as HDR imaging. But 2.0 does not have those yet.

Things CapyPDF supports

CapyPDF has implemented a fair chunk of the various PDF specs:

  • All paint and text operations
  • Color management
  • Optional content groups
  • PDF/X and PDF/A support
  • Tagged PDF (i.e. document structure and semantic information)
  • TTF, OTF, TTC and CFF fonts
  • Forms (preliminary)
  • Annotations
  • File attachments
  • Outlines
  • Page naming
In theory this should be enough to support things like XRechnung and documents with full accessibility information as per PDF/UA. These have not been actually tested as I don't have personal experience in German electronic invoicing or document accessibility.

Wednesday, October 15, 2025

Building Android apps with native code using Meson

Building code for Android with Meson has long been possible, but a bit hacky and not particularly well documented. Recently some new features have landed in Meson main, which make the experience quite a bit nicer. To demonstrate, I have updated the Platypus sample project to build and run on Android. The project itself aims demonstrate how you'd build a GUI application with shared native code on multiple platforms using native widget toolkits on each of them. Currently it supports GTK, Win32, Cocoa, WASM and Android. In addition to building the code it also generates native packages and installers.

It would be nice if you could build full Android applications with just a toolchain directly from the command line. As you start looking into how Android builds work you realize that this is not really the way to go if you want to preserve your sanity. Google has tied app building very tightly into Android Studio. Thus the simple way is to build the native code with Meson, Java/Kotlin code with Android Studio and then merge the two together.

The Platypus repo has a script called build_android.py, which does exactly this. The steps needed to get a working build are the following:

  1. Use Meson's env2mfile to introspect the current Android Studio installation and create cross files for all discovered Android toolchains
  2. Set up a build directory for the toolchain version/ABI/CPU combination given, defaulting to the newest toolchain and arm64-v8a
  3. Compile the code.
  4. Install the generated shared library in the source tree under <app source dir>/jniLibs/<cpu>.
  5. Android Studio will then automatically install the built libs when deploying the project.

Here is a picture of the end result. The same application is running both in an emulator (x86_64) and a physical device (arm64-v8a).

The main downside is that you have to run the native build step by hand. It should be possible to make this a custom build step in Gradle but I've never actually written Gradle code so I don't know how to do it.