GSoC/2023/StatusReports/ShivoditGill
Improve Okular For Android
Okular has an Android version, but it has some issues. PDFs without embedded fonts don’t display properly due to the lack of an Android-specific font API in the Poppler backend. Icons also do not render, due to problems in KDE Frameworks or the Kirigami UI framework.
This project aims to implement an Android-specific font API in the Poppler backend, as well as solving the issue of icon rendering in Okular’s Android version.
Links to Blogs and other writing
Blog
I will be writing about my progress on my blog. It can be found at: https://shivoditg.hashnode.dev
The blog posts in chronological order:
- First blog: https://shivoditg.hashnode.dev/first-blog-for-gsoc-23
- Second blog detailing work done during the first coding period: https://shivoditg.hashnode.dev/gsoc-23-summary-of-work-done-over-first-coding-period
Merge Requests
- Main merge request for font-matching functionality in Poppler
- Fix icon rendering in Okular on Android
- Package the Okular icon when building for Android
- Replace Kirigami.AboutPage with MobileForm.AboutPage for mobile build
- Port to the newer FormCard API from the MobileForm API
- Cherry picked commit from Qt6 in order to fix black screen issue in Okular Android
Work Reports
Week 1 and 2
- Work begins on font-matching functionality for Android version of Poppler
- Understood what is to be done
- Implement GlobalParams::findSystemFontFile() and GlobalParams::findBase14FontFile() for Android version of Poppler
- Set up development environment
- Use
kde-android
docker image for building Poppler - Use CMake script incliuded in the android build for Poppler project CI
- Use invent-registry.kde.org/sysadmin/ci-images/android-qt515 docker image for building Okular
- To test changes in Poppler:
- First make necessary changes to poppler
- Build poppler in kde-android docker container
- replace the poppler library in the android-qt515 docker container
- Build okular again so that it gets built with the new poppler library
- Package Okular and install it on android device/emulator to test changes
- Use
Week 2
- Added conditional compilation for Android version of Poppler, to get the correct libraries and set the correct environment variables
- Environment variables included pre-processor variables which would compile the Android specific implementation of Poppler's font-matching backend when building for Android.
- THe android libraries included the
android
library and thelog
library provided by the Android NDK.
Week 3
- Forked Poppler's repository hosted at gitlab.freedesktop.org after acquiring the relevant permissions
- Successfully implemented a crude version of GlobalParams::findSystemFontFile() using AFontMatcher functionality which only returns sans-serif fonts.
- Accomplished this by adding the
android
library in the CMake - Still needs implementation for:
- Fetching the correct style of the required font (bold, italic, bold + italic, etc.)
- Fetching the font having the correct font weight
- Getting other generic font styles such as serif, fixed-width
- Accomplished this by adding the
Week 4
- Since AFontMatcher uses the pre-installed fonts found on Android, and only matches fonts based on the generic font-family (sans-serif, serif, fixed-width, fantasy, etc.). It was inadequate for matching the base 14 fonts.
- The base 14 fonts are a set of 14 fonts that are expected to be supported by every PDF reader. These include:
- Times (v3) (in regular, italic, bold, and bold italic)
- Courier (in regular, oblique, bold and bold oblique)
- Helvetica (v3) (in regular, oblique, bold and bold oblique)
- Symbol
- Zapf Dingbats
- However, these fonts have proprietary licenses, so instead we use some substitute fonts that closely match the base-14 fonts in appearance. In Poppler's case, these fonts are:
- NimbusMonoPS-Regular.otf
- NimbusMonoPS-Bold.otf
- NimbusMonoPS-BoldItalic.otf
- NimbusMonoPS-Italic.otf
- NimbusSans-Regular.otf
- NimbusSans-Bold.otf
- NimbusSans-BoldItalic.otf
- NimbusSans-Italic.otf
- StandardSymbolsPS.otf
- NimbusRoman-Bold.otf
- NimbusRoman-BoldItalic.otf
- NimbusRoman-Italic.otf
- NimbusRoman-Regular.otf
- D050000L.otf
- However, Android devices do not come with these base-14 fonts installed by default, so we must provide our own.
- Luckily, OKular already packages these fonts inside the assets folder of its apk. To access and use these files, we first transfer them to the internal storage of the app (Okular in this case) and then set the path where the font files can be found, so that Poppler can load and use the font files.
- However, as a sanity test, I first placed the font files in a directory inside the /data/local/tmp folder of android, which is read/write and has execute permissions, and specified the path in GlobalParams.cc myself. It worked, so I got to work on implementing a mechanism for copying the font files and setting the font file path.
Week 5
- I implemented a mechanism to copy all the font files contained in the
assets/share/fonts
folder of the Okular APK. - This code uses the QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) functionality of Qt to quickly find the internal storage directory of the app.
- Within this folder, another folder called fonts is created, and the font files in the
assets/share/fonts
folder of the APK are copied over to the fonts folder one-by-one - This code was originally written in the mobile/app/main.cpp file of Okular, however I could not call GlobalParams functions, since they are private to Poppler. This presented a blocker to setting the path for the font directory in GlobalParams.
- I later shifted the code to the qt backend of Poppler, as I could access QStandardPaths and other Qt functions, while also being able to call GlobalParams functions. More specifically, the code was added in the DocumentData::init() method.
- I then created a static method in GlobalParams,
GlobalParams::setFontDir()
, which takes a file path as a string input, and sets it as the path where font files should be searched.
Week 6
- The midterm deadline was fast approaching, so I got to work on finalizing my work and created a Merge Request on Poppler's gitlab.
- I cleaned up the code by removing several print debugging statements, organising the code properly, and adding comments to detail what a piece of code does.
- I then created the MR, and fixed any issues that were found in my code by my mentor, and also fixed the code so that all the CI jobs for Poppler would pass. For example, I forgot to add some conditional compilation statements, which resulted in every CI besides clang-format and android failing to build. I also fixed some memory leak issues with AFontMatcher and AFont objects using unique_ptrs (thanks to Sune Vuorela for suggesting unique_ptrs!).
- I also wrote my blog entry detailing the work done in the first coding period: Link to blog