Skip to content

GitLab

  • Menu
Projects Groups Snippets
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • F fontconfig
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 170
    • Issues 170
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 20
    • Merge requests 20
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Monitor
    • Monitor
    • Incidents
  • Packages & Registries
    • Packages & Registries
    • Container Registry
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • fontconfig
  • fontconfig
  • Issues
  • #200

Closed
Open
Created Nov 23, 2019 by Nicolas Mailhot@nim

Please add <group>

Preamble

The fontconfig configuration language was intended as a way to perform declarative configuration. It has since morphed in a complete low-level xml programming language.

The result does not scale to human capabilities or to the level of complexity of current font projects. As a result, humans and apps are giving up on fontconfig as a way to manage their font files, and are reverting to manual assemblage based on human interpretation of font names.

Please add the group top-level configuration element, to help assembling simply and safely modern complex font families.

Purpose

The group element is intended to be complete enough a single group declaration is sufficient to describe:

  • how to assemble a font family
  • and how this family relates with other font families,
  • in a syntax as compact and simple as possible

The main objective is to eradicate the maintenance problems created by the current spread of low-level declaration blocks, over multiple files, that are never properly prioritized and synchronized.

It has the same objective as ISO 14496-28 in issue #33, in fonctonfig-friendly syntax. Since issue #33 was requested by Google for Noto, the interest in such a construct is shared by distributions, foundries and app downstreams.

Exemples

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<!-- SPDX-License-Identifier: MIT -->
<fontconfig>
  <group>
    <target>Tribun ADF Std</target>
    <like>
      <family>serif</family>
    </like>
  </group>
</fontconfig>
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<!-- SPDX-License-Identifier: MIT -->
<fontconfig>
  <group>
    <generic>serif</generic>
    <like>
      <family>DejaVu Serif</family>
      <family>Noto Serif</family>
    </like>
  </group>
</fontconfig>
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<!-- SPDX-License-Identifier: MIT -->
<fontconfig>
  <group>
    <target>GFS Didot</target>
    <fullname>GFS Didot Bold Italic</fullname>
    <fullname>GFS Didot Bold</fullname>
    <fullname>GFS Didot Italic</fullname>
    <fullname>GFS Didot Regular</fullname>
    <like>
      <family>GFS Didot Classic</family>
      <family>serif</family>
    </like>
  </group>
</fontconfig>
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<!-- SPDX-License-Identifier: MIT -->
<fontconfig>
  <group>
    <target>DejaVu Serif</target>
    <match>
       <family>DejaVu Serif</family>
       <change>
         <style>Book</style>
         <into>Regular</into>
       </change>
    </match>
    <family>DejaVu Math TeX Gyre</family>
    <like>
      <family>Bitstream Prima Serif</family>
      <family>BPG 2017 DejaVu Serif</family>
      <family>DejaVu LGC Serif</family>
      <family>Verajja Serif</family>
      <family>Olwen Serif</family>
      <family>SUSE Serif</family>
      <family>Bitstream Vera Serif</family>
      <family>serif</family>
    </like>
  </group>
</fontconfig>
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<!-- SPDX-License-Identifier: MIT -->
<fontconfig>
  <group>
    <target>Droid Sans</target>
    <match>
      <family>Droid Sans Hebrew</family>
      <good-lang>he</good-lang>
      <good-lang>yi</good-lang>
    </match>
    <match>
      <family>Droid Sans Armenian</family>
      <good-lang>hy</good-lang>
    </match>
    <match>
      <family>Droid Sans Georgian</family>
      <good-lang>ka</good-lang>
    </match>
    <match>
      <family>Droid Sans Ethiopic</family>
      <good-lang>am</good-lang>
      <good-lang>byn</good-lang>
      <good-lang>gez</good-lang>
      <good-lang>sid</good-lang>
      <good-lang>ti-er</good-lang>
      <good-lang>ti-et</good-lang>
      <good-lang>tig</good-lang>
      <good-lang>wal</good-lang>
    </match>
    <match>
      <family>Droid Sans Devanagari</family>
      <good-lang>hi</good-lang>
      <good-lang>mr</good-lang>
      <good-lang>kok</good-lang>
      <good-lang>ks@devanagari</good-lang>
      <good-lang>sd@devanagari</good-lang>
      <good-lang>mai</good-lang>
      <good-lang>ne</good-lang>
      <good-lang>bh</good-lang>
      <good-lang>bho</good-lang>
      <good-lang>brx</good-lang>
      <good-lang>doi</good-lang>
      <good-lang>hne</good-lang>
      <good-lang>sa</good-lang>
      <good-lang>sat</good-lang>
    </match>
    <match>
      <family>Droid Sans Tamil</family>
      <good-lang>ta</good-lang>
    </match>
    <match>
      <family>Droid Sans Thai</family>
      <good-lang>th</good-lang>
    </match>
    <match>
      <family>Droid Arabic Kufi</family>
      <good-lang>ar</good-lang>
    </match>
    <match>
      <family>Droid Sans Japanese</family>
      <good-lang>ja</good-lang>
    </match>
    <match>
      <family>Droid Sans Fallback</family>
    </match>
    <like>
      <family>Droid Sans Arabic</family>
      <family>Noto Sans</family>
      <family>sans-serif</family>
    </like>
  </group>
</fontconfig>
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<!-- SPDX-License-Identifier: MIT -->
<fontconfig>
  <group>
    <target>IBM Plex Sans</target>
    <match>
      <family>IBM Plex Sans Condensed</family>
      <style-prefix>Condensed</style-prefix>
    </match>
    <family>IBM Plex Sans Var</family>
    <match>
      <family>IBM Plex Sans Arabic</family>
      <good-lang>ar</good-lang>
    </match>
    <match>
      <family>IBM Plex Sans Hebrew</family>
      <good-lang>he</good-lang>
      <good-lang>yi</good-lang>
    </match>
    <match>
      <family>IBM Plex Sans Thai</family>
      <good-lang>th</good-lang>
    </match>
    <match>
      <family>IBM Plex Sans Devanagari</family>
      <good-lang>hi</good-lang>
      <good-lang>mr</good-lang>
      <good-lang>kok</good-lang>
      <good-lang>ks@devanagari</good-lang>
      <good-lang>sd@devanagari</good-lang>
      <good-lang>mai</good-lang>
      <good-lang>ne</good-lang>
      <good-lang>bh</good-lang>
      <good-lang>bho</good-lang>
      <good-lang>brx</good-lang>
      <good-lang>doi</good-lang>
      <good-lang>hne</good-lang>
      <good-lang>sa</good-lang>
      <good-lang>sat</good-lang>
    </match>
    <axis>
      <name>width</name>
      <step>
        <name>Condensed</name>
        <value>85</value>
      </step>
      <step>
        <name>Regular</name>
        <value>100</value>
      </step>
    </axis>
    <axis>
      <name>weight</name>
      <step>
        <name>Thin</name>
        <value>0</value>
      </step>
      <step>
        <name>ExtraLight</name>
        <value>40</value>
      </step>
      <step>
        <name>Light</name>
        <value>50</value>
      </step>
      <step>
        <name>Regular</name>
        <value>80</value>
      </step>
      <step>
        <name>Text</name>
        <value>90</value>
      </step>
      <step>
        <name>Medium</name>
        <value>100</value>
      </step>
      <step>
        <name>SemiBold</name>
        <value>180</value>
      </step>
      <step>
        <name>Bold</name>
        <value>200</value>
      </step>
    </axis>
    <axis>
      <name>slant</name>
      <step>
        <name>Regular</name>
        <value>0</value>
      </step>
      <step>
        <name>Italic</name>
        <value>100</value>
      </step>
    </axis>
    <like>
      <family>IBM Plex Sans Thai Looped</family>
      <family>sans-serif</family>
    </like>
  </group>
</fontconfig>
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<!-- SPDX-License-Identifier: MIT -->
<fontconfig>
  <group>
    <target>PT Sans</target>
    <match>
      <family>PT Sans</family>
      <good-lang>ru</good-lang>
    </match>
    <match>
      <family>PT Sans Narrow</family>
      <style-prefix>Narrow</style-prefix>
      <good-lang>ru</good-lang>
    </match>
    <axis>
      <name>optical size</name>
      <step>
        <name>Caption</name>
        <value>8</name>
        <match>
          <family>PT Sans Caption</family>
          <good-lang>ru</good-lang>
        </match>
      </step>
    </axis>
    <like>
      <family>sans-serif</family>
    </like>
  </group>
</fontconfig>

YAML examples

Since this is a new autonomous top-level element, it might be smarter to skip the XML step and define it directly in YAML. That would be easier on humans, and easier to integrate (for example, in Ansible-driven tests).

Here are the same examples in YAML syntax

---
# SPDX-License-Identifier: MIT
- family: Tribun ADF Std:
  - like:
    - serif
...
---
# SPDX-License-Identifier: MIT
- serif:
  - generic
  - like:
    - DejaVu Serif
    - Noto Serif
...
---
# SPDX-License-Identifier: MIT
- GFS Didot:
  - fullname: GFS Didot Bold Italic
  - fullname: GFS Didot Bold
  - fullname: GFS Didot Italic
  - fullname: GFS Didot Regular
  - like:
    - GFS Didot Classic
    - serif
...
---
# SPDX-License-Identifier: MIT
- DejaVu Serif:
  - family: DejaVu Serif
    new-styles: {Book: Regular}
  - family: DejaVu Math TeX Gyre
  - like:
    - Prima Serif
    - BPG 2017 DejaVu Serif
    - DejaVu LGC Serif
    - Verajja Serif
    - Olwen Serif
    - SUSE Serif
    - Bitstream Vera Serif
    - serif
...
---
# SPDX-License-Identifier: MIT
---
- Droid Sans:
  - family: Droid Sans Hebrew
    good-langs: [he, yi]
  - family: Droid Sans Armenian
    good-langs: [hy]
  - family: Droid Sans Georgian
    good-langs: [ka]
  - family: Droid Sans Ethiopic
    good-langs: [am, byn, gez, sid, ti-er, ti-et, tig, wal]
  - family: Droid Sans Devanagari
    good-langs: [hi, mr, kok, ks@devanagari, sd@devanagari, mai, ne, bh, bho,
               brx, doi, hne, sa, sat]
  - family: Droid Sans Tamil
    good-langs: [ta]
  - family: Droid Sans Thai
    good-langs: [th]
  - family: Droid Arabic Kufi
    good-langs: [ar]
  - family: Droid Sans Japanese
    good-langs: [ja]
  - family: Droid Sans Fallback
  - like:
    - Droid Sans Arabic
    - Noto Sans
    - sans-serif
...
---
# SPDX-License-Identifier: MIT
- IBM Plex Sans:
  - family: IBM Plex Sans Condensed
    style-prefix: Condensed
  - family: IBM Plex Sans Var
  - family: IBM Plex Sans Arabic
    good-langs: [ar]
  - family: IBM Plex Sans Hebrew
    good-langs: [he, yi]
  - family: IBM Plex Sans Thai
    good-langs: [th]
  - family: IBM Plex Sans Devanagari
    good-langs: [hi, mr, kok, ks@devanagari, sd@devanagari, mai, ne, bh, bho,
               brx, doi, hne, sa, sat]
  - axes:
    - width: {Condensed: 85, Regular: 100}
    - weight: {Thin: 0, ExtraLight: 40, Light: 50, Regular: 80, Text: 90,
              Medium: 100, SemiBold: 180, Bold: 200 }
    - slant: {Regular: 0, Italic: 100}
  - like:
    - IBM Plex Sans Thai Looped
    - sans-serif
...
---
# SPDX-License-Identifier: MIT
- PT Sans:
  - family: PT Sans
    good-langs: [ru]
  - family: PT Sans Narrow
    style-prefix: Narrow
    good-langs: [ru]
  - axes:
    - optical size:
      - Caption:
        - 8
        - family: PT Sans Caption
          good-langs: [ru]
  - like:
    - sans-serif
...

Complete Grammar

grammar {
  start = Fontconfig
  Fontconfig = element fontconfig { Group* }
  Group = element group {
    (Target | Generic) &
    Family* & Fullname* & Match* &
    Axis* &
    Like?
  }
  Target = element target { text }
  Generic = element generic { text }
  Family = element family { text }
  FullName = element fullname { text }
  Match = element match { MatchContent }
  MatchContent = {
    (Fullname | Family | Style | Styles)+ &
    (Change | StylePrefix)? &
    GoodLang* &
    BadLang*
  }
  Style = element style { text }
  Styles = element styles { Style+ }
  Change = element change { Style, Into }
  Into = element into { text }
  StylePrefix = element style-prefix { text }
  GoodLang = element good-lang { text }
  BadLang = element bad-lang { text }
  Axis = element axis { AxisContent }
  AxisContent = {
    (Name | Tag) &
    Step+
  }
  Name = element name { text }
  Tag = element tag { text }
  Step = element step { StepContent }
  StepContent = {
    Name &
    Value? &
    Family* & FullName* & Match*
  }
  Value = element value { text }
  Like = element like { Family* }
}

Edited Feb 10, 2020 by Nicolas Mailhot
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking