bohoomil / fontconfig-ultimate

freetype2-infinality run-time settings => infinality compatible fontconfig => infinality-bundle
453 stars 38 forks source link

User settings not overriding /etc/fonts/conf.d #51

Closed alexoj closed 9 years ago

alexoj commented 9 years ago

Shouldn't /etc/fonts/conf.avail.infinality/28-user.conf be /etc/fonts/conf.avail/infinality/98-user.conf and /etc/fonts/conf.avail.infinality/29-local.conf be /etc/fonts/conf.avail.infinality/99-local.conf ?

Right now I can't override system settings (for example overriding no-embedded-bitmaps for one font) from my home directory.

I tried working around it renaming the file locally to 98-user, 99-local, but it results in the 28-user,29-local files appearing every time infinality updates, which makes fontconfig ignore my identical 98-user,99-local files.

bohoomil commented 9 years ago

Thank you for the feedback.

Renaming files isn't a good idea: you can modify the content of some which are meant to be customized, but any changes to fontconfig/conf.d layout needs to be introduced globally in order to work for all users in a predictable manner.

I never thought about a user case where this sort of feature would be useful: yours makes sense, though. I will change the current layout of conf.d as follows:

94-no-synthetic.conf
96-reject.conf
97-local.conf
98-user.conf

Positions 95 and 99 will remain empty just in case we may need them in the future. Of course, respective templates in conf.avail.infinality will be renumbered, too.

Don't forget to assist pacman on next fontconfig-iu update, if necessary (possible errors: "file exists in the file system", broken symlinks to targets not existing any more, etc.).

jbernhard commented 9 years ago

I actually have the opposite problem: prior to the most recent update, my user file ~/.config/fontconfig/fonts.conf worked as expected and took precedence over /etc/fonts. Now, the user file has no effect and I must edit the system files to achieve any customization.

bohoomil commented 9 years ago

@jbernhard Would you mind sharing a snippet that has ceased to work after the upgrade?

jbernhard commented 9 years ago

Yeah, here's my config for the default monospace font.

<fontconfig>
  <alias>
    <family>monospace</family>
    <prefer>
      <family>Inconsolatazi4</family>
    </prefer>
  </alias>
</fontconfig>

It almost seems like my fontconfig is loading files in opposite order... Shouldn't 98-user have precedence over 60-latin-free?

alexoj commented 9 years ago

Okay, since I proposed this change in the first place I went and found out what's wrong.

This is what the docs say:

Alias elements provide a shorthand notation for the set of common match
operations needed to substitute one font family for another.  They contain a
<family> element followed by optional <prefer>, <accept> and <default>
elements.  Fonts matching the <family> element are edited to prepend the
list of <prefer>ed families before the matching <family>, append the
<accept>able families after the matching <family> and append the <default>
families to the end of the family list.

I went and read the fontconfig source and it does exactly that: fontconfig maintains a list of directives, in order of appearance. Then the list is prepended to the requested name ("monospace") and they are tried one by one. The first one that succeeds (that is, the font exists) wins. Thus since 60-latin-free goes first it always wins.

The real problem is that there isn't a consistent way to override settings in fontconfig, for some settings you override them by setting them after the defaults and for some others you override them by setting them before.

I suppose a way to solve this problem would be to split 98-user in two files, 00-user and 98-user, each one reading something like ~/.config/fontconfig/conf.d.head and ~/.config/fontconfig/conf.d.tail respectively, but it sounds really hacky.

jbernhard commented 9 years ago

@alexoj thanks for looking into it! That makes perfect sense.

@bohoomil maybe I am doing this wrong. My goal is essentially to keep the "free" preset but change the default fonts (I really don't like Liberation Mono). How would you recommend doing that?

bohoomil commented 9 years ago

@alexoj & @jbernhard

Yes, it does sound too hacky... ;-) I remember we were playing quite a bit with xx-user.conf and xx-local.conf in the past and eventually we decided to stick with the 28/29 layout. This particular one is IMO pretty versatile as far as per-user configuration is concerned. What it doesn't offer is the possibility to alter rendering settings, but this is actually a feature that wasn't meant to be accessible for the user (see the stock fontconfig).

Let's take a glance at customization options available for the user now:

  1. On the system wide level, we have 35-repl-custom.conf, which provides custom font substitutions, including default aliases (sans, serif, mono, etc.). Originally, it was supposed to be used as an extension for fixed presets, free and ms, which shouldn't be changed directly (they serve as a sort of a 'reset' button: if your font tweaking goes wrong, you can always reset 'custom' presets and set back either of the two, which will get the system back to the working state). 35-repl-custom.conf overrides both 60- and 65- groups of files, as well as everything in the 36-40 range, which lets you set custom font replacements for wonky web fonts with @font-face:web_font_name string, among other things. Hence if all you need is swapping a couple of fonts for another for whatever reason, and do it for all user accounts, this is the config file you should look into.
  2. Next we have the combi preset. You can think of it as the 35's big brother becase not only it lets you replace a few typefaces, but first of all you can create a completely unique font layout with it which neither free nor ms provides. A typical user scenario here would be merging free and ms in any way you want, adding totally new font families for Latin and non-Latin scripts, etc. In most cases it offers too much to bother with it: if you are generally happy with free or MS fonts and only want to introduce a few changes to satisfy your taste or needs, 35-repl-custom.conf is the way to go. However, if you have plenty of fonts you want to use instead of "plenty of fonts" supported by default and mix all of them in a wild way -- combi is here to help.
  3. Both 1) and 2) can be overriden on a per-user level via 28/29 links. For example, I'm using my local fontconfig directory to set a few font replacements for websites I visit (I try to keep /etc/fonts/conf.d compatible with infinality-bundle defaults, 37-repl-webfonts.conf in this case, and avoid placing there anything other users might never need), sometimes for testing optional global substitutions and the like.

These are the options which work as expected and IMO should be left as were prior to the recent update.

Now, what can be done about tweaking rendering settings.

  1. If a font is new and has no ready to use fontconfig configuration files, we should simply add them: 40 or 45 should be used to add a typeface to the serif / sans / mono groups, sometimes 65 may be handy if we want to create additional aliases, finally either 90-non-tt-font_name.conf or 90-tt-font_name.conf files will be needed to specify rendering options and further tweak the font's look.
  2. If rendering parameters for a font are already defined and we want to change them, we should climb up to 92-selective-rendering-foo.conf and introduce any changes there. For instance, we can enable embedded bitmaps in it, change default lcd type, turn antialiasing on and of, and so forth.

What we should IMO do in order to break the customization deadlock and never get back to it:

  1. Let's stay with the previous 28/29 layout because it does what it should and more than the stock fontconfig offers by default. It's reliable and safe, giving you plenty of options to customize the font collection to fit most needs.
  2. Let's leave rendering tweaks where they belong, i.e. in the system wide config directory (/etc/fonts/conf.d). For users who want or need to alter a couple of settings, we may use a separate config file, 93-selective-rendering-custom.conf, as a pair for 35-repl-custom.conf, which won't be overwritten on fontconfig updates and will always take precedence over 92 and 90 files.

Sounds sane?

jbernhard commented 9 years ago

Works for me. Thanks for taking the time to write such a detailed response.

alexoj commented 9 years ago

The only problem with the previous layout is that root access becomes necessary to install a bitmap-inside-ttf font, because the default configuration explicitly disables embedded bitmaps in all fonts.

What about leaving the 28/29 layout as it was before, but adding a new config file named 98-user-font-tweak.conf file that includes the user font directory, that is:

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>

  <include ignore_missing="yes">~/.fonts</include>

</fontconfig>

This way the configurations that always worked, for family selectors, etc, are available in the standard directory ~/.config/fontconfig/conf.d so compatibility is not broken, and if you want to add a font that needs tweaks to work properly, you can add it to ~/.fonts like before and add an accompanying file fontname.conf that sets its settings properly.

What do you think?

bohoomil commented 9 years ago

Let me repeat what I think:

Let's leave rendering tweaks where they belong, i.e. in the system wide config directory (/etc/fonts/conf.d). For users who want or need to alter a couple of settings, we may use a separate config file, 93-selective-rendering-custom.conf, as a pair for 35-repl-custom.conf, which won't be overwritten on fontconfig updates and will always take precedence over 92 and 90 files.

More or less. :-)

If 93-selective-rendering-custom.conf (actually, 97, so custom font rejections can also be defined) is going to be kept intact, which means that anything you put in it will live there as long as your HDD surface, I can't really find a good reason for opening yet another security hole in the fontconfig tree. What's the big deal with editing a file in a different location of your own system that does exactly what you want? I can't predict possible consequences of forcing a single user scenario on hundreds of other users, quite possibly breaking stability of fontconfig and producing one heck of potential maintenance problems, though.

Frankly speaking, in the original project I was planning to get rid of the local fontconfig configuration altogether. It was a justified solution in the old days in multi user, client-server environments, but even there the scope of options available for the user was limited to a few very basic ones (like adding custom fonts that weren't installed on the server by default due to license restrictions for instance). Today this isn't the case any longer, so keeping such extra functionality is highly dubious at best: most often it's a source of PEBKAC rather than greater versatility. Neither Windows nor Mac OS has ever needed it, too, because in modern (i.e. post-mainframe era) computing a personal terminal was replaced by a personal PC with all its benefits, while sharing resources would more and more often mean sharing data. But OK, let's keep the *NIX tradition alive for a while yet, even though in certain situations it seems more like keeping up appearances...

All in all, the more holes in the wall and the more loops breaking the consistency of a data flow, the more reasons for the structure to eventually become unstable and/or insecure. Better yet: the more complex the data you're going to inject into the loops from the outside is, the less consistent and reliable the entire configuration becomes. I started to play with fontconfig-infinality and rethinking the idea behind it because out of the box it was too complex and hence too prone to user errors to be useful at all. Couple it with fontconfig's own complexity and in a critical moment you'll end up banging your head against your desk. One of the key features of the new fontconfig-infinality became its easily recoverable operability: if a user fails in her/his customization attempts, they can effortlessly 'reset' their configuration and get back to work right then, in zero time. It was actually done by limiting the number of user entry points to the global configuration and preventing it this way from being overflown by numerous hypothetical errors that are customization's frequent side effects. Customization itself wasn't restricted in any way, though: it was merely put back where its place should be, i.e. where it was in the original fontconfig blueprint. Now that we were to put 98-font-tweak.conf at the other end of the configuration tree, we'd actually let the old headache in under a different name.

Excuse me my answering with yet another "story", but I'd like to make it clear and valid why your solution isn't the right one in terms of its being a standard for everyone. This is a hack that makes sense in one scenario, but it's still a hack, substantially a pretty idiosyncratic one. It's not really needed as a feature (because the same can be achieved in a safer way), it doesn't eliminate real limitations imposed on a user (because we're usually our own system administrators and can access any part of the system we want), finally it doesn't improve in any obvious way fontconfig's usability. What it does for sure is breeding potential problems and security issues that I don't necessarily want to know by name. ;-)

I will implement a couple of extra xx-foo-custom.conf files anyway, so this feature request will have positive impact on fontconfig-iu. If you still don't feel convinced and would rather walk your own path, just do what you want:

  1. Move 97/98 back to 28/29 (I will revert the change on next fontconfig-iu update).
  2. Create a custom 98-font-tweak.conf.

This way you probably won't miss any important update, which at the same time won't touch your private configuration files.

bohoomil commented 9 years ago

Reverting d839ee0 (see #58 for details).

alexoj commented 9 years ago

Fair enough, sorry for the trouble caused.