It's been more than three weeks since the midterm summary, and the project is now nearing completion.
Currently, all the original features of Blinken have been fully implemented in the QML version. The remaining tasks involve UI adjustments, testing, and fixing potential bugs.
Over the past few weeks, I’ve been working on the following:
Integrating Blinken's Logic
The game logic of Blinken is handled by the BlinkenGame class from the original Blinken. The original code design is quite good, with most of the game logic encapsulated in this one class. The separation between the logic and the UI rendering is well done, so all I needed to do was connect the signals from this class in QML.
As for the audio playback in Blinken, the original code used the Phonon library, which is also open-source but does not support Android. Therefore, I replaced it with the QtMultimedia library, which provides cross-platform audio playback functionality.
Android Build for KF6 Applications
Some features of Blinken rely on libraries provided by the KF6 framework, such as KF6I18n and KF6Config. When cross-compiling to the Android platform, it's necessary to use the aarch64-linux versions of these libraries. If these libraries are not available on your system, you will encounter the following errors during compilation:
ld.lld: error: /usr/lib64/libKF6XmlGui.so.6.4.0 is incompatible with aarch64linux ld.lld: error: /usr/lib64/libKF6ConfigWidgets.so.6.4.0 is incompatible with aarch64linux ……
However, the package manager on my Fedora distribution does not provide these versions. Compiling and installing them one by one from source is too cumbersome. On the advice of the community, I used Craft to handle cross-compilation.
Important note: If you encounter installation failures, make sure to clear all contents under craft-kde-android before trying again, as leftover files may cause the installation to fail.
When installing, choose the Arm64 target architecture. If there are remnants from a previous failed installation, it may prevent the option to select the ARM64 architecture.
If you encounter issues like "Permission denied," you’ll need to disable SELinux:
Additionally, note that in the virtual machine invent-registry.kde.org/sysadmin/ci-images/android-qt67 provided by the community, the Java version is outdated, preventing the use of Gradle 8.6. You can either manually update the Java version in the docker or use an older version of Gradle.
To use Craft for building applications, you need to write a script called a Blueprint, which describes the libraries your application depends on. These scripts are relatively easy to write, and you can quickly get started by following the community documentation: Craft/Blueprints - KDE Community Wiki.
Using KF6 Framework Libraries
Some of the libraries originally used by Blinken are compatible with the Android platform, while others are not. By referring to the API Documentation, you can check which libraries are supported on Android. In Blinken, the following libraries are Android-compatible:
CoreAddons
GuiAddons
I18n
XmlGui
I needed to use these libraries in the QML version of Blinken.
The KF6 framework provides a convenient internationalization API, and the usage in QML is almost the same as in QWidget, which allowed me to directly reuse Blinken’s original multi-language support, saving a lot of time.
KConfig is used in Blinken to store high score information and settings. For the high scores, I needed to extract the HighScoreManager class from the original HighScoreDialog file, make some modifications, and then create a new high score interface in QML that connects the signals and slots of HighScoreManager. For the settings functionality, it’s as simple as registering a KConfig singleton in QML :
KF6XmlGui was used in the original Blinken to create the About Blinken Page, About KDE Page, and Handbook Page. Although this library is Android-compatible, it is based on QWidget, while the main interface of Blinken is built with QML. Bringing in QWidget just for these pages didn't seem like a good idea. Luckily, for the Android platform, kirigami-addons provides this functionality. By incorporating it, I also brought in Kirigami, which helps optimize the UI.
This post is written on behalf of the LabPlot team. It’s different compared to what we usually publish on our homepage but we feel we need to share this story with our community.
Introduction
You might already know this, but finalizing a release for a project with the complexity and scope like that of LabPlot can be hard and exhausting. After our latest recent 2.11 release, we decided to take a short break and distance ourselves from coding and take care of other non-coding related tasks, like discussions around the NLnet grant for LabPlot, our ongoing GSoC projects, the roadmap for the next release, improving our documentation, the gallery on the homepage and the article about LabPlot on Wikipedia. Don’t worry, we’re already back to coding and working on new features for the next release
The article about LabPlot on Wikipedia (we are talking about the ‘EN’ version here, but the situation is similar for other languages) was completely outdated and still containing the information about LabPlot1 from Qt3/KDE3 times. The article became largely wrong with the introduction of LabPlot2 and with further developments in recent years. Among other things, the feature set described on Wikipedia was very far from being correct and complete in comparison to the description for other applications of its type.
The current situation was clear for us and it was also evident what needed to be done. Let’s go ahead and improve the article, we thought. Hey! Being able to contribute and to share your knowledge with everybody is the advantage of Wikipedia, right? Easier said than done…
Key Takeaways
But before we begin:
Wikipedia itself points out that the purpose of Wikipedia is to benefit readers by acting as a comprehensive compendium that contains information on all branches of knowledge. For this purpose, as it is clearly stated on Wikipedia, “Wikipedia has many policies or what many consider “rules”. Instead of following every rule, it is acceptable to use common sense as you go about editing. Being too wrapped up in rules can cause a loss of perspective, so there are times when it is better to ignore a rule. Even if a contribution “violates” the precise wording of a rule, it might still be a good contribution.” Link: Use common sense.
According to Wikipedia there is no need to read any policy or guideline pages to start editing. The five pillars of Wikipedia are a popular summary of the most important principles. And the three of the pillars are formulated as follows: 1. Wikipedia is free content that anyone can use, edit, and distribute. 2. Wikipedia’s editors should treat each other with respect and civility. 3. Wikipedia has no firm rules. And If a rule prevents you from improving or maintaining Wikipedia, ignore it.
In this Wikipedia’s article on https://en.wikipedia.org/wiki/Wikipedia:Dispute_resolution it is stated that once sustained discussion begins, productively participating in it is a priority. Editors should focus on article content during discussions; comment on content, not the contributor. And when an editor finds a passage in an article that is biased, inaccurate, or unsourced the best practice is to improve it rather than deleting salvageable text.
I fully acknowledge these common-sense principles. I accept the fact that some phrases of the original version of the new content added by Dariusz, another core member of the LabPlot team, might have possibly infringed a less general rule on Wikipedia, and that’s why he asked for a constructive assistance, to no effect.
I can also accept the reality and the existence of different users with the various amount of expertise, goodwill and power. The worst case are people contributing in a subversive manner over long time to such an open project to achieve more power and authority and completely different and evil goals later, and this can also be related to users with granted power. See the recent XZ Utils backdoor. I also accept the fact that the amount of work behind the scenes on Wikipedia requires the usage of automated mechanisms and bots (“Meet the ‘bots’ that edit Wikipedia”).
However, I cannot accept the fact that the quality of knowledge on Wikipedia can be seriously undermined by power users heavily using algorithms and blindly enforcing some subjectively selected, narrow rules against the general principles outlined above, and at the same time not being open to any constructive discussion. The fact that complete content and comments are censored and removed by users with granted power or by their (semi-)automated tools, which deceives the reader and distorts the history of the discussion, is definitely not acceptable. And this is apparently not an exception, see the links here, here and here and many other similar discussions on the internet.
Keep the above in mind while you read what happened.
The incident I want to share with you is certainly not about LabPlot and its team. It’s about the negative impact of blindly invoking algorithms or quoting a single rule by Wikipedia’s users with granted power on the overall quality of the information stored on Wikipedia. As Dariusz noticed, in economics there is the observation that “bad money” drives out the “good money” from the market (Gresham’s Law “bad money drives out good”). We wonder whether the actions of the entities like MrOllie, some of which are described in the next parts of the article, are enough to justify the introduction of a new law for Wikipedia “bad information drives out good”?
Chain of events
In order to make the content correct and to provide an up-to-date description of the project, similar to the articles for other projects mentioned e.g. on https://en.wikipedia.org/wiki/List_of_information_graphics_software, Dariusz did multiple edits of the article over the course of two days using his Wikipedia account ‘Dlaska’. Very soon after that, the entity MrOllie became aware of his changes and reverted them completely with the suggestion that it was a promotional rewrite. Then, a “user talk” with Dariusz was initiated by MrOllie:
We are all volunteers, having no benefit other than satisfaction from developing LabPlot. But sticking to the principle of intellectual honesty, Dariusz himself fully disclosed to MrOllie that he is a LabPlot team member that felt obliged to step in to correct misleading information in the article and to make the content more complete and up-to-date, because no one has done it for a long time. Unable to get any suggestions from MrOllie despite Dariusz’ requests, Dariusz removed any phrases that could even potentially have promotional qualities (e.g. rename “strongly support” to “support”). Unfortunately, even this had no effect on the actions of MrOllie, resulting in the revert of the new content.
In parallel, I joined these activities and reverted the revert done by MrOllie and provided some explanations for this step. Another “user talk” with me (I don’t have any account, you see my IP address here) was initiated by MrOllie:
After multiple back-and-forth reverts, my IP was blocked and a “Conflict of Interest on the Noticeboard” was raised by MrOllie where he quickly got the support from his peers on Wikipedia. Dariusz’ comment didn’t change anything in the overall situation:
In parallel, more seasoned Wikipedia users jumped on the bandwagon and started ‘editing’ the article by first blindly reverting the article to the version containing potentially promotional content and then removing even more and more content and references with arguments that, in our perception, didn’t make sense arguing with anymore. Any discussion seemed completely ineffective. After most of the content had been removed from the article, to the point that the new version was more deprived of content than the old version, the user Smartse added a notability tag which was later turned into a notification box to the article stating this article “may not meet Wikipedia’s general notability guideline.”. Notability is a test used by editors to decide whether a given topic warrants its own article. So in our perception this could be interpreted as a threat of removing the article completely. The size and severity of the problem we were confronted with was already obvious at this point.
After my IP was unblocked (or maybe because I just got a new IP from my ISP), I was able to reply on this noticeboard. Since I was already foreseeing it’s going to be deleted, I took a screenshot (this is also the reason why I did screenshots for all other events):
Practically immediately my reply, red-highlighted above, was deleted without any comment or note and this is how this thread looks like afterwards:
Fortunately, Dariusz, who has an account in Wikipedia, got the notification about my added reply via email:
and after clicking within seconds on the link in the email he was informed that the comment might have been deleted, and it sure was, right after it had been added.
Immediately after this, another notification box with “A major contributor to this article appears to have a close connection with its subject.” was added to the article:
What seems to have happened here looks like a well coordinated or even (semi-) automated chain of events with a pre-defined replies, arguments and actions. MrOllie stands out for the incredible diligence and regularity of his activity. The chart below shows the number of edits he has made by day of the week and hour (in local time), from 2008 to the present (source of the chart: https://xtools.wmcloud.org):
Also, over 75% of MrOllie’s edits are done in a semi-automated way with the help of tools on Wikipedia like Twinkle. So, this account functions like a programmed algorithm or somebody who is heavily relying on them.
Seeing no reasonable chance of correcting this situation in the context of being deprived of the right to effectively discuss the matters with entities like MrOllie, we gave up on our initial idea to improve the article.
What’s next?
After reading more on this subject we realized that this problem is not new, but apparently it is not common knowledge either. Completely independent of who or what censored us – AI bots (is AI already winning over us?), good or bad editors etc. – trusting Wikipedia now is much harder than before. Still, the question remains about what to do next.
We can completely give up the idea of contributing to this platform and rather focus on other channels like our homepage and other online resources in the KDE and free world (Mastodon, etc) and provide more and more useful information.
Alternatively, we can ask for support from other people with more experience in editing and maybe even with more authority on Wikipedia to help us to get a reasonable description of the project on Wikipedia to the benefit of Wikipedia’s readers and LabPlot’s users.
Thoughts?
Links
For the sake of completeness and of easier usage, here are the links mentioned in my reply that were deleted:
Note, for the first two links above, the original posts in the Wikipedia related channels on Reddit about the same MrOllie account on Wikipedia were deleted, shame on those who think evil of this. The comments are still available, though, and the reader can get at least an idea about the original content of those posts.
Edit
We added a short post about the article to r/wikipedia on Reddit, but it was removed by the moderators just 2 hours later, without any comment.
If, after reading this article, you think MrOllie and his counterparts are capable of correcting their own actions, take a look at the exchange below. It’s also an indication of what the future may hold for the LabPlot article on Wikipedia… Source: https://en.wikipedia.org/w/index.php?title=User_talk:MrOllie&oldid=1240636433
Update (20.08.2024)
We’ve been informed that a Wikipedia’s editor (Smartse) has today nominated the article about LabPlot for deletion, so before making any hasty, not to say retaliative, decisions, we encourage Wikipedia editors to reach a sensible “consensus” in the context of information published on these websites:
The last three links refer to Wikipedia’s articles about other applications similar to LabPlot. As far as we know, none of them have been nominated for deletion. In the meantime the article has been given a “protected” status.
Update (21.08.2024)
So far we have provided a list of nearly 50 research papers from various scientific fields that show that LabPlot has been used for research and teaching purposes. It would be unreasonable to expect researchers dealing with domain problems to devote a significant part of their research papers to describing LabPlot. In contrast, the following article is devoted entirely to LabPlot. The professors Williams Morales González and Jesús Eleuterio Hernández-Ruíz described the program’s functionality and usage in detail [1]. This fits into the Wikipedia’s General notability guideline:
“A topic is presumed to be suitable for a stand-alone article or list when it has received significant coverage in reliable sources that are independent of the subject.”
“Sources do not have to be written in English” and “there is no fixed number of sources required.”
“Notability is based on the existence of suitable sources, not on the state of sourcing in an article.”
Below is a (semi-)automatic translation of the authors’ conclusions:
The experiences of the professors of the Experimental Physics group of the UCLV Physics program in the use of LabPlot as a tool for the analytical and graphical processing of experimental data were presented.
LabPlot is a free, open source, multiplatform software with KDE desktop design and similar characteristics to Origin. It is intended for interactive analysis of experimental data and includes a wide variety of operations for analytical and graphical data processing, including linear and nonlinear fitting and data extraction from external plots, without the need for licensed software.
LabPlot can be used as a tool for experimental data processing, not only in Experimental Physics, but also in the scientific work developed by students from the second year of the course and culminating with the diploma work.
Does this information have any real relevance to Wikipedia editors? Time will tell.
Most of the time programmers do not write new code. Instead, they read, try to understand, extend, and fix bugs in existing code. While some parts of KDE are pretty new and follow modern standards, many parts are more then two decades old -- following obsolete coding principles, using outdated ways of solving problems, and having additions from several persons with different styles. Often when we read code, we immediately spot things we could improve.
Kent Beck's approach is applying a series of small tidyings that leads to structural change and an overall better software design. In his new bookTidy First? he describes his idea in three parts: Tidyings, how to manage tidyings, and software design theory.
In the first part the author introduces generic tidyings like dead code removal, moving declaration and initialization together, introducing new interfaces, or explicit parameters. Most proposals are not new, but it is a good reminder to follow them and fix these things wherever you come across them in code you are working with. After reading the first part, I felt motivated to create some tidying commits right away. For KDE more specific tidying could be added: Fix deprecation warnings from Qt and KF, replace C-style code by C++, use modern C++ (range-base for loop, initialization lists), fix compiler warnings.
The second part gives hints on how to organize and commit tidyings. Separate tidyings from new features or behavioral changes. Find a balance between asking for review of your tidyings too often or with too extensive reviews.
In the third part Kent Beck offers some basic ideas from software design, especially future options and code coupling.
The book is worth reading for both commercial and open-source developers. Both are facing similar issues. Open-source developers are not worrying about costs, but precious spare time dedicated to coding for their pet project. Every projects has bit rot and profits from regular tidyings by their developers.
People interested in software design will recognize the ideas from classic books like Structured Design or Refactoring: Improving the Design of Existing Code. Nevertheless, Tidy First? makes the knowledge easily accessible. Most chapters are only one to three pages long and the book stays below a hundred pages.
This is the first book of a planned series of small books. Kent Beck develops his ideas in his blog (partially pay-walled) and discusses his views with his readers. Some blog post make it into Kevin's weekly web reviews.
The KIO Framework has gained support for de-facto standard, cross-desktop thumbnail generators.
This means that we have a support for thumbnails from 3rd party applications!
On Linux systems, many applications that produce some kind of output, such as a 3D file or text document,
ship a thumbnailer file that tells file managers how to create thumbnails of their files.
One specific example I've used here in the images are STL files, for which we don't have our own KDE-specific thumbnailer plugin.
These thumbnailer files are currently used by Nautilus and Thunar,
so we felt like we were missing out and wanted to join the party! :)
Thumbnailer files
Thumbnailer files are simple text files that tell the system what program we should run to generate
a thumbnail. You can check what thumbnailers you have installed by running ls /usr/share/thumbnailers
For example, the STL thumbnailer file looks like this:
It tells the software running the thumbnailer what commands to use to generate the thumbnail,
and what mimetypes it supports.
KDE Thumbnailer Plugins
On KDE side, we have used plugins for KIO, that reside in the kio-extras repository.
They work just fine for our usecase in KDE apps, but nobody should need to write a KIO specific plugin
for their application.
The changes to KIO
You can check the merge request for more
in-depth details, but here's a summary of how I made it work side-by-side with our plugin system:
We utilize the KIO plugins always first if possible, since we know for sure they work. This is to avoid
any possible regressions and oddities, and to keep the change as unintrusive as possible. When we encounter
a mimetype that is not supported by our plugins, like STL files, we utilize a thumbnailer file instead.
This also means that it's transparent to users. Users do not have to worry which one they have installed.
Why make support for thumbnailer files then?
As mentioned earlier, no application should need to create a plugin for KIO just to make their thumbnails
show up in our applications.
Thumbnailer files offer other benefits too, such as easing future transitions, (like from KF6 to KF7); working nicely with sandboxing, and being distributable in Flatpak bundles.
I am also working on moving our own plugins into thumbnailers,
so we get the benefits from that too.
The Freedesktop.org Specifications directory contains a list of common specifications that have accumulated over the decades and define how common desktop environment functionality works. The specifications are designed to increase interoperability between desktops. Common specifications make the life of both desktop-environment developers and especially application developers (who will almost always want to maximize the amount of Linux DEs their app can run on and behave as expected, to increase their apps target audience) a lot easier.
Unfortunately, building the HTML specifications and maintaining the directory of available specs has become a bit of a difficult chore, as the pipeline for building the site has become fairly old and unmaintained (parts of it still depended on Python 2). In order to make my life of maintaining this part of Freedesktop easier, I aimed to carefully modernize the website. I do have bigger plans to maybe eventually restructure the site to make it easier to navigate and not just a plain alphabetical list of specifications, and to integrate it with the Wiki, but in the interest of backwards compatibility and to get anything done in time (rather than taking on a mega-project that can’t be finished), I decided to just do the minimum modernization first to get a viable website, and do the rest later.
So, long story short: Most Freedesktop specs are written in DocBook XML. Some were plain HTML documents, some were DocBook SGML, a few were plaintext files. To make things easier to maintain, almost every specification is written in DocBook now. This also simplifies the review process and we may be able to switch to something else like AsciiDoc later if we want to. Of course, one could have switched to something else than DocBook, but that would have been a much bigger chore with a lot more broken links, and I did not want this to become an even bigger project than it already was and keep its scope somewhat narrow.
DocBook is a markup language for documentation which has been around for a very long time, and therefore has older tooling around it. But fortunately our friends at openSUSE created DAPS (DocBook Authoring and Publishing Suite) as a modern way to render DocBook documents to HTML and other file formats. DAPS is now used to generate all Freedesktop specifications on our website. The website index and the specification revisions are also now defined in structured TOML files, to make them easier to read and to extend. A bunch of specifications that had been missing from the original website are also added to the index and rendered on the website now.
Originally, I wanted to put the website live in a temporary location and solicit feedback, especially since some links have changed and not everything may have redirects. However, due to how GitLab Pages worked (and due to me not knowing GitLab CI well enough…) the changes went live before their MR was actually merged. Rather than reverting the change, I decided to keep it (as the old website did not build properly anymore) and to see if anything breaks. So far, no dead links or bad side effects have been observed, but:
If you notice any broken link to specifications.fd.o or anything else weird, please file a bug so that we can fix it!
Thank you, and I hope you enjoy reading the specifications in better rendering and more coherent look!
I like to call myself git “expert”, but I failed pretty badly few weeks ago I needed to bisect the kernel source code to figure out one bug.
General git bisect process is, You have two known commits, one is good and one is bad, and you keep searching for bad commit by splitting history in two. Lets say you have following changelog (not the actual changelog I was debugging, but example):
KStars v3.7.2 is released on 2024.08.03 for Windows, MacOS & Linux. It's a bi-monthly bug-fix release with a couple of exciting features.
A few members of the KStars development team were enjoying their summer holidays over the past few weeks, but we still have a couple of exciting features in this release!
Multi-Camera Support
Wolfgang Reissenberger devoted countless hours to bring this complex feature that required lots of architectural changes in Ekos. If you have double rigs (or even more), we have a new great feature: multi camera support! If you have more than one optical train on your mount, you now will be able to run capture sequences for each of your optical trains in parallel from the same KStars instance. You simply need to create an optical train for each of your telescopes on your mount, create camera tabs for each optical train, create their own sequence and let them run in parallel.
This new feature may also be used in combination with the scheduler: in this release, the scheduler itself will control the first camera. On top of that, you could configure additional cameras in the capture tab which could execute their own capture sequences. Enhancing the scheduler such that it could control multiple optical trains in parallel is already under development and will be part of one of the next releases. So stay tuned!
Focus Advisor v4
John Evans refactored the Focus Advisor to make it simpler while still offering a lot of insight on parameters tuning. It is now more accessible to new users and has added functionality to optimize values for 2 of the more difficult Focus parameters: Step Size and Backlash (or AF Overscan).
In addition, Focus Advisor contains a convenience tool to locate stars by searching the range of motion of the focuser and another convenience tool to highlight differences between current Focus parameter settings and those recommended by Focus Advisor.
Akademy 2023 was almost year ago and soon Akademy 2024 is coming. This is probably good time to talk about Akademy 2023. I know it was in way too past but some of those who know me personally/professionally know that last year has been rollar-coaster for me emotionally and did not manage to write about event while recovering from it.
But since this post was sitting in draft from long time, it is finally time to finish and publish it.
Coming three months after 3.0.0 and two months after the first bugfix release 3.0.1, the main development focus in 3.1 has been getting Qt6 / KDE Frameworks 6
based version closer. We are not quite there yet, but not that far away anymore. And there are some quite nice new features too! Amarok 3.1.0 brings in a refreshed Last.fm integration,
which uses more up-to-date account connection mechanisms, and is better at informing users of any Last.fm errors. Similar Artists context applet does a comeback,
and there's naturally also a nice bunch of smaller features and bug fixes; this time the oldest fulfilled feature request was filed just under 15 years ago.
Changes since 3.0.1
FEATURES:
Last.fm plugin updated to use token-based authentication method and to notify user of session key errors (BR 414826, BR 327547)
Reintroducing Last.fm Similar Artists context applet - a new Amarok 3 version
Remember the previous destination provider when saving playlist (BR 216528)
CHANGES:
Amarok now depends on KDE Frameworks 5.89.
Cleanup of unused code and various changes that improve Qt6 compatibility but shouldn't affect functionality. (n.b. one won't be able to compile a Qt6 Amarok with 3.1 yet, but perhaps with the eventual 3.2)
Remove old derelict openDesktop.org integrations from about dialog. This also removes the dependency to Attica framework.
Disable gapless playback if ReplayGain is active and the following track is not from same album, to avoid volume spikes due to delay in the applying of ReplayGain (BR 299461)
BUGFIXES:
Small UI and compilation fixes
Fix saving and restoring playlist queue on quit / restart (BR 338741)
Fix system tray icon menu reordering
Fix erroneous apparent zero track progresses on track changes, which caused playcount updates and scrobbles to get skipped (BR 337849, BR 406701)
Fix 'save playlist' button in playlist controls
Sort playlist sorting breadcrumb menu by localized names (BR 277146)
Miscellaneous fixes to saving and loading various playlist file formats, resulting also in improved compatibility with other software (including BR 435779, BR 333745)
Don't show false reordering visual hints on a sorted playlist (BR 254821)
Fix multiple instances of web services appearing in Internet menu after saving plugin config.
Show podcast provider actions for non-empty podcast categories, too (BR 371192)
Fix threading-related crashes in CoverManager (BR 490147)
In comparison to changes between 2.9 to 3.0, the git repository statistics between 3.0 and 3.1 are somewhat short:
However, this is an excellent spot to send a huge thank you out to everyone who has been on board outside the git history;
translators, packagers, bug reporters, writers, commenters, and of course: users - music fans all around the world!
Happy listening, everyone! You rok!
Getting Amarok
In addition to source code, Amarok is available for installation from many distributions' package
repositories, which are likely to update to 3.1.0 soon.
A flatpak is currently available on flathub-beta.
It’s been a while since my last blog post regarding text. Since then I’ve been working on the on-canvas text tool, as well as multiple reworks for rich text editing, the actual text properties docker for this rich text editing, and finally I’ve done a talk at the Libre Graphics Meeting about my work on the text tool.
I’m now at the point that I’m going over each property and thoroughly polish it. Because I’m also doing frequent updates on the krita-artists forum, I’m hoping to punctuate each polish session with an introduction to the property, and because I also have a lot of technical things to talk about, I’ll be making technical blog posts alongside that, of which this will be the first.
So the first thing that needed to be tackled after putting together the basic text properties docker and the related interaction is font selection. Krita’s text tool is based on SVG+CSS, and uses FontConfig to select fonts. Typically, a font selection widget will show the list fonts, and in some cases, it organises this in two dropdowns, where the first is the font family, and the second a sub family, like italic or bold. So obviously there’s meta data for this, right, and you should just plug that in the right places, and everything’s peachy? Well, we do have a lot of meta data…
Family Relations
For digital fonts, the OpenType format (in both ttf and otf flavours), is the most common digital format. For formats older than it, the family relations are usually limited to regular, italic, bold and bold-italic (‘RIBBI’), but OpenType also allows for weight/width/slant (‘WWS’) organisation, or even a completely arbitrary organisation under a single typographic family. All at once, too, because not all programs have the same font selection features. These are stored in OpenType names 1, 2, 16, 17 and 21, 22. You can model their relationship as a tree, as in the following example, where we have a single typographic family with a sans, a serif, both of which are WWS families, and each has a variety of RIBBI subfamilies, some of them (semibold) being a single font:
Typographic family (ids 16, 17)
Sans (WWS family, ids 21, 22)
Regular (RIBBI, ids 1 and 2)
Regular
Italic
Bold
Bold italic
Condensed (width variant)
Regular
Italic
Bold
Bold italic
Semi-bold
Regular
Serif
Regular
Regular
Italic
Etc…
This is of course not only stored in the names, it is also stored in the OS/2.fsSelection flags, and for WWS, there’s width and weight data in the OS/2 table. However for typographic family, there’s no way to identify separate WWS families besides the WWS name being present (besides a bit flag in fsSelection, which indicates there’s only one WWS family, but this too cannot be relied on). Furthermore, variable fonts don’t have subfamilies, but rather “axes”, and perhaps some “instances”, which are internal presets of those axes.
And that’s not all, not all fonts are required to have this data, only fonts that are not sufficiently described without all names present, so the default font of a given font family only needs names 1 and 2 to be present, the semibold only names 1, 2, 16 and 17, and so on.
FontConfig is somewhat build to handle this, the default ordering ( undocumented , of course) of the font family names being WWS, Typographic and finally the RIBBI family name. However, The WWS family name is quite recent, meaning there’s many fonts that only have a typographic and RIBBI name, despite having a difference in, say, optical size data, or one of those layer typefaces.
This works because many of these font selector widgets don’t select a family, but rather, they present a bit of ordering for you to select a font and finally store a specific identifier to that font, like the PostScript name, in the text object. Because we’re using CSS however, we store the font family, and specify the weight, width and slant. This has its benefits, as when a font is absent, we can still infer the intention that something was to be set bold or italic. But that does require that the font can be selected by family at all, so if FontConfig cannot associate a WWS family, that is kind of a problem.
Finally, some fonts have a STAT table, which gives even more info about those axes (if a variable font) and allows for non-variable families to describe their relations in an axis like manner. There’s no API to retrieve this info in Harfbuzz, however, FontConfig knows nothing about it either, and even the CSS working group hasn’t made any statements on whether to interpret the STAT table at all. Mind you, even with api for the STAT table, too many fonts don’t have it, so it is not a solution in itself.
Family Reunion
So, the best way to go about this is to sort the font families. This will require opening each font file up with FreeType or Harfbuzz, and retrieving the data you need, as fontconfig doesn’t store everything we need to identify the different families.
For this purpose, I created a struct to put the data in, and organized the structs inside KisForest, which is a templated container class that allows storing data in a tree, and provides a bunch of itterators to traverse said tree. This allows me to create a top level node (‘typographic family’ node) for each font as I find them, and then sort fonts into those. Then afterwards, go over each node again and sort them into individual WWS families, as WWS family names are in fact kind of rare, and the majority of fonts that need them don’t have them.
The second sort is done by going over each toplevel typographic node, and then take all the children. Of the children, you first select all “regular” fonts (the ones closest to width: 100%, weight: 400% and no italic or slant), and adding those first, each with their own WWS family, and then sort the rest into those. Care will need to be taken for fonts that have different optical sizes identified as well (there’s, of course, four ways this can be stored: OS/2 optical size range; size OpenType tag; ‘opsz’ variable axis and STAT table axis), as well as keeping track of situations where multiple formats of the same font are installed (The Nimbus family on many Linux distributions is often installed as OpenType font as well as two separate Postscript fonts, I’m currently sorting those into the same font family). For bitmap fonts, you want to sort the separate pixel sizes into the RIBBI family, depending on how you interpret bitmap pixel size.
Once that’s done, the CSS font matching algorithm needs to be implemented. CSS is explicitely vague about what it means by a font family (this whole blog has assumed up till now that if a give subfamily cannot be selected with CSS parameters, it needs to be in a separate WWS family), but it does specify that any localized names should be matched (localized names are rare and only really used for CJK fonts, but they do exist). So in practice, you end up testing all the possible names, that is, OpenType ids 1, 16, and 21, in the order of the lowest child node to the parent (because remember, the most default version of a given family only has id 1, so you want to test that first). Then comes the actual style testing, the algorithm of which is more or less the same along width, weight and slant, with weight being special for having a default range to test first, while slant needs to be multiplied by -1 first, which it needed anyhow to cohere the specs (CSS dictates that positive slant should skew to the right, while the OpenType spec requires negative slant to skew to the right).
After all of that, the filenames that rolled out of matching can be added to the FontConfig search pattern to prioritize them in the regular fallback search, which I am very thankful of.
While nowadays an example like this would be best off using a color font, there’s many examples of older fonts that are meant to be used layered (as in, two text shapes overlapped with the same text but different subfonts). This particular font, Sweetie Summer, predates any discussion about WWS, only having a typographic family and ribbi family, which lead it to be unselectable with fontconfig.
Presentation
But getting the matching to work for odd fonts wasn’t the only thing that was necessary. Fonts also needed to be displayed nicely. Even more, I really wanted to integrate them with Krita’s resource system, as that would allow tagging and search. These are important usability features as modern operating systems come with hundreds of fonts, so being able to tag fonts with “cursive” and “display” and then filter on that can make it much easier to find an appropriate font. Not all design programs have this feature, which has led to a number of designers to use a so-called font manager, which effectively allows installing and deinstalling fonts by user-defined group (KDE Plasma even has one of these build in, and I’d be suprised if there wasn’t one for Gnome somewhere). Inkscape has quite recently introduced font collections, whose purpose is similar, and given we spend 2 years reworking our resource system, which can do exactly this, it made sense to try and get this system working.
There’s some quibles however: vast majority of resources within Krita are tied to a file, while such a font family resource is an abstraction of a collection of files. This results in problems with getting a preview generated as well as updating an entry between restarts of Krita.
Then there’s selecting the style. This one is a bit abstract, so bear with me: So, as explained before, CSS selects the font file to use by using the user-defined font-family and a set of parameters (width, weight, slant, etc). This has both the benefit of having a certain intent (whether the text is condensed, or the weight is set heavy), as well as being a good abstraction that encompasses both regular font families and variable fonts.
This abstraction is implemented as each font family resource having a set of axes (for variable fonts these are the axes in the font, for non-variable, these are an accumulation of the different parameters associated with the subfamilies), and styles which form a sort of preset for those given parameters (encompassing the instances of variable fonts, and the actual subfamilies in non-variable fonts). This way, you can have fonts that use the OS/2.fsSelection bitflags for indicating bold and italic, you can have fonts that use the OS/2 table values, you can have fonts that have variable axes, and all these will have the same toggles in the same place. If in the future the STAT table is going to be read, the extra info for that will easily be integrated in the same system.
There’s some more toggles than the WWS parameters though, for example, toggles for synthesize slant and bold. Some people think that nowadays, these are not necessary, but that’s really only true for scripts with few glyphs. In fact, we had to implement synthesized slant and bold because CJK users were having missing it dearly in the new text layout. On the flip side, in European typesetting, synthesized versions are considered ‘dangerous’ as it can be hard to tell if the correct bold version was selected, so a toggle to turn it off is required. This needed some extra work with variable fonts, as active slant and italic axes are not testable in the usual manner. There’s also optical size, though this is only supported for variable fonts that have an ‘opsz’ axis, as the CSS Working Group doesn’t seem to have an opinion on the other three ways optical size can be indicated. Finally there’s the remaining axes, in case of a variable font with extra custom axes.
So, this sounds to work right? Where’s the issue with styles? Well, some might say that the split between a font-family and the style is unnecessary, it would be much better to just see all the styles at once. In fact, Inkscape has been implementing this recently. Which means I’ll be asked why I didn’t implement that, because obviously I should.
The main problem here is a philosophical one. The reason Inkscape is implementing this is because its user base wants this UI, and the reason the user base wants this UI is because other software they’re using has this UI. So far, so good.
However, other software has this UI because it has a different kind of text layout system. As noted before, the font selector in these programs is just a fancy way of selecting a specific font file. Within programming way of saying “select font file XYZ” is considered an ‘imperative’ way of programming. This is quite common in WYSIWYG (what you see is what you get) editors, as its easier to program. Markup based methods like CSS instead has a ‘declarative’ way of programming: “Select from this font family a font with these parameters, and otherwise these other font families”. A system like this usually tries to infer properties, which is harder to program, but also means less properties need to be set.
The philosophical difference here is that I don’t think it is wise to try to abstract away the underlying data structure, because I think it leads to bugs that are kind of hard to articulate if you don’t know the UI is not representing the underlying structure properly. This is also why it is weird to see people go “Well, UI should be completely decoupled from the business logic”, because even if you programmatically decouple UI and data, the fact remains that the UI can only do what the data structure allows. The data structure by itself belies a workflow, which in the case of mark-up based type setting general, is one that focuses on consistency, and that if you want to make a small modification, only a small modification is stored.
The importance of the underlying data structure is something that I always feel is missing from discussions about the UI of Free Open Source Software, which is why I am emphasizing it now. The main idea of “listening to your users” is not bad, and even for my own work I did talk to other artists on KA to try to get a feel of what artists using Krita prioritize. But text in particular is also far more tricky than this, because the main reason both the Inkscape folks and us went with an SVG+CSS based text layout is because it is a specification that is widely used (just not in graphics programs…) and has a lot of thought put into multi-lingual and non-European text handling (which is still quite rare today). And I think it is going to cause trouble if you try to apply UI conventions that belong to a different kind of text layout.
The main issue I foresee with this approach is that there’s no mind paid to font family fallback. In an online situation, font family fallback is mainly for what to do when a font family can be found. In a local situation like a graphics program, it is mostly useful in multi-script situations. Many fonts only have glyphs for a small subset of Unicode, often limited to a single script with supplementary punctuation and numbers. So in multi-script situations the CSS font matching algorithm requires you to check if a glyph can be represented, and if not, you must check other fonts on the system till you find one with the given glyph. Font family fallback allows you to have some control over this mechanism.
The font family list allows us to control the fallback. Many fonts only have glyphs for a subset of unicode, so controlling fallback can allow us to select fonts that seem to be in a similar tradition, like using a Serif Latin font for a Naskh Arabic font.Not all scripts have similar traditions, so control over the font fallback is also useful in selecting a font that may not fit within the same tradition, but might look good in terms of contrast, so the Latin text, in this case, stands out less.
Another thing that’s kind of difficult here is that it hides the fluidness of variable fonts. Because where before we could treat instances as a sort of preset for the parameters, they now are presented as a whole font to select. To further explain, one thing I’m fully expecting to happen for Krita is that we receive a bug report with “I turned off synthesis for weight, but still Krita is showing something for a weight value that doesn’t correspond to a style”, and I’ll have to reply with “Yes, that’s because you’re using a variable font”, expand on that, and then close the bug as RESOLVED, NOTABUG. By focusing too much on the styles as individual fonts to select, we’re inhibiting people from updating their mental model of how fonts can work.
Visuals
Of course, because there’s so much variation in what the different fonts can do, it is necessary to indicate the capabilities of a font. Many font selectors have at the very least an icon for the font type. Because there’s been a flurry of activity within OpenType in the last decade, there’s now also variable fonts to keep an eye on, and four (five?) different ways to do color font representation, and those can all be present at once. Krita only really supports the Bitmap and ClrV0 implementations, so we need to indicate which color font data is present.
Other than that, the font name should be present. As well as a preview for the given font. We could technically do the latter straight up with the text layout, by putting a KoSvgTextShape inside a QQuickPaintedItem, but I worry that might be slow on some systems. Instead, I’m laying out the text and converting the result to regular paths, storing the SVG, and then painting the path from that within a QQuickPaintedItem. The sample text chosen uses FontConfig supported languages list, though I am wondering if we’re not better off testing CharMap support instead, as to ensure we will always have some glyphs from the font available. Anyway, I’m quite pleased with the result, as it allows us to display the sample nice and sharp.
One thing that is also tricky is the localization. Basically all user-facing strings within OpenType can have localized variants within the font, and if those are present they should be displayed. In practice this means that these localized strings get stored in the KoResource as well. The models for tracking the styles and axes receive a ‘setLocales’ function, so that when the font name is requested within QML, the text label will receive the localized name. However, with the resource model this isn’t feasible, as the font family resource is the only one that holds localized names. Thankfully, a QVariantHash is treated as a javascript object/dict within QML, so the localized names could be stored into the metadata QVariantMap (note that QML does not support converting QVariantHash to a dict(!), and then tested against the KLocalizedString::languages() stringlist (though care must be taken to ensure the underscore is replaced with a dash).
Eventually, we’ll prolly need to do the same with the writing system samples. However, that should probably use the language the text shape is tagged with, as it is very common for multi-lingual artists to keep the software in English, so they won’t have to guess at a translation when doing an internet search for a given label. So in those cases where you’d need a different sample (like, a Arabic sample if you’re typesetting Arabic), it is probably combined with a different language being set on the text. Mind, there’s no language selector yet, because SVG+CSS uses BCP47 language tags, and I haven’t figured out how to capture the richness of those tags in a discovery friendly ui. Being able to limit the visible fonts based on whether fontconfig thinks they support the active language would also be useful in the same vein.
FontConfig Rescan Interval
When discussing the architecture of how to implement this, it was mentioned that FontConfig has a rescan mechanism. This is basically FontConfig checking if any changes had happened, and if so, updating the font list, and the default on most Linux systems for this is 30 seconds. I think most programs just turn this off, but the person I was talking with went “oh, yes, this is how you need to implement this”, which was a little confusing because our resource system doesn’t actually support refreshing resources during a session. I ended up implementing what they asked of me, as a show of good faith, but there’s multiple refresh problems with it (because our resource system was not build to handle this). It will probably be disabled in the end, unless the refresh problems turn out to be trivial to tackle.
Postamble
A returning theme in handling fonts, OpenType fonts in particular, is that there’s at the least 3-5 ways of doing one common thing. This is not unusual, and often happens when people need a certain function to be part of a specification so badly that there’s no time to standardize. Because of this complexity though, implementing a good font selector still took about a month. At the same time, I’m happy I spend time on this because it would otherwise hang like a thunderstorm over the whole text project, as it would be a matter of time we’d drown in bug reports about this-or-that font not being selectable. That is still going to happen, but at the least there’s a framework to deal with edge cases now.
The next topic I’ll be tackling is probably going to be font size and line height.
Appendix
TTF vs OTF
So an OpenType font should be in a file called the Open Type Format (otf), right? Then why are most of them in the True Type Format (ttf)? Aren’t these two the same?
ttf and oft are the same format, yes. The original spec was called TrueType, and the glyphs were outlined with quadratic bezier curves. One of the things that was added when the spec became OpenType, was that the glyphs could now also be outlined in CFF (compact font format, PostScript, basically), which uses cubic bezier curves. Since then, a font stored in a ttf file is an OpenType font with quadratic bezier curves, and a font stored in an otf file is a file with cubic bezier curves. I am unsure whether since the introduction of variable fonts this difference isn’t purely conventional however.
Italics and Obliques
Because blogpost is aimed at readers that are probably not typography (or lettering/calligraphy) nerds, let’s speed through the history of Latin script as to explain the difference between Italics and Obliques and why they’re sometimes confused:
The history of Latin script is basically the existence of a formal style of writing (a ‘ductus’), and then because clerics need to write a lot, them developing a less formal style that’s easier to write. That one then formalizes, and then a new style is developed. So if we start with Roman Square Capitals (like Trajan), it is followed by a variety of less formal styles like Uncial and Rustic Capitals. Around the middle ages however, the formal ductus and less formal ductus are unified into one system of capital (‘upper case’, also called ‘majuscule’) and miniscule (‘lower case’) letters. However, clerics needed a faster way of writing, so a given blackletter style would often be developed into a chancery or court style.
Fast forward to the Rennaisance. Italians are making their first printing fonts. For reasons I don’t want to get into, they choose Roman Square Capitals for the capitals of their typefaces and combine those with Carolingian miniscules. But they want more typographic richness, so the popular Italic chancery hand is turned into a printing font as well. There’s some notable difference between Carolingian miniscules and Italian miniscules, in particular, the ‘a’ and ‘g’ are written differently, as is the ‘f’:
Then, much later, in the nineteenth century, Sans-serif fonts were introduced, which find their origin in sign-painting. For some reason, these fonts don’t use an Italic ductus for their corresponding slanted style, in fact, the slanted style is just that: slanted (an ‘Oblique’). My best guess is that this is because this font style comes from sign painting and thus is optimized for legibility, and frequently uses an Italic ‘g’, combined with a Carolingian ‘a’ for this purpose. So they may have considered a simple slant much more distinguishable than trying to create a full Italic ductus compatible variant.
By the time computers get involved, a slanted version of the font is considered paramount, as many academic style guides require Italics to indicate quotes and book names. By this time, Oblique variants were considered acceptable, which is why ‘synthesized italic’ just ends up being a digitally slanted version of the original. Fonts that combine both a rare, but exist, so OpenType specifies an extra bit to indicate that a font is specifically an oblique version, but it seems that this didn’t catch on. Even now, with OpenType variable fonts and the STAT table making it much easier to define a slanted version, there’s still hesitance to use it as nobody knows which software supports selecting it.
Furthermore, many other writing systems use various script styles to indicate quotes and such, yet, these are not recognized as ‘Italics’ by computer software. There’s therefore something very arbitrary about Italics by themselves: There’s nothing stopping a font designer from creating a black letter or copperplate style for their font family, except how to handle the font files so that software can select these.
Slant
Slant, within variable OpenType fonts, is a different toggle from Italics. And it can go either way, similarly, there is such a thing as a ‘upright Italic’. So that begs the question: why are Italics usually slanted? This has to do with calligraphy, in particular, the reach of the right hand.
Because the right hand has a reach that goes from top-right to bottom-left, it is likely to skew vertical lines to the right.
If you write with a left hand the same as with a right hand, you get the same effect, but flipped.
For lefties like me, to do right-slanting calligraphy we need to either write with our hand over the line, or rotate the paper.
Now, for European scripts, this is usually for italics, but sometimes a slant doesn’t express a calligraphic quirk, but rather a feeling of forward motion. Which is why for right-to-left scripts, you will sometimes see a left-leaning font being used.