In migrating the font configuration mechanism out of Xft and into a 
separate library, I have an opportunity to redefine the configuration 
language to make it easier for external agents to parse and modify.

I've decided to give XML a try and see how it looks; other applications 
have started migrating to this for configuration and it has a lot of 
appeal.

Please find enclosed the proposed DTD and a sample font configuration file.
They have only been run through xmllint --valid; I have not started on any 
related C code.

For those of you with more XML experience than I (that shouldn't be hard, 
I just printed the XML spec this morning), please let me know if I'm doing 
things in silly or unconventional ways.  Also, please let me know if using 
libxml is a bad idea; it seems a bit easier to use than expat.

If this transition goes well, I may propose that the XFree86 server 
configuration file be transitioned to XML as well; the ability to have 
external agents edit the file without needing a complete understanding of 
the syntax should be very useful.

Keith Packard        XFree86 Core Team        Compaq Cambridge Research Lab

<!-- This is the Document Type Definition for font configuration files -->
<!ELEMENT fontconfig (dir | 
                      cache | 
                      include | 
                      include_if | 
                      match | 
                      alias)* >

<!-- 
    Add a directory that provides fonts
-->
<!ELEMENT dir EMPTY>
<!ATTLIST dir
          dir   CDATA       #REQUIRED>

<!--
    Define the per-user file that holds cache font information.

    If the filename begins with '~', it is replaced with the users
    home directory path.
-->
<!ELEMENT cache EMPTY>
<!ATTLIST cache 
          file  CDATA       #REQUIRED>

<!--
    Reference another configuration file; note that this
    is another complete font configuration file and not
    just a file included by the XML parser.

    Set 'ignore_missing' to 'yes' if errors are to be ignored.

    If the filename begins with '~', it is replaced with the users
    home directory path.
-->
<!ELEMENT include EMPTY>
<!ATTLIST include
          ignore_missing (no|yes) "no"
          file CDATA        #REQUIRED>

<!--
    Aliases are just a special case for multiple match elements

    They are syntactically equivalent to:

    <match>
        <test name="family">
            <string value=[family]/>
        </test>
        <edit name="family" mode="prepend">
            <string value=[prefer]/>
            ...
        </edit>
        <edit name="family" mode="append">
            <string value=[accept]/>
            ...
        </edit>
        <edit name="family" mode="append_last">
            <string value=[default]/>
            ...
        </edit>
    </match>
-->
<!ELEMENT alias (prefer?, accept?, default?)>
<!ATTLIST alias
          family CDATA      #REQUIRED>
<!ELEMENT prefer (family)*>
<!ELEMENT accept (family)*>
<!ELEMENT default (family)*>
<!ELEMENT family EMPTY>
<!ATTLIST family
          family CDATA      #REQUIRED>

<!ENTITY % expr 
'number|string|name|matrix|boolean_or|boolean_and|eq|not_eq|less|less_eq|more|more_eq|plus|minus|times|divide|not|if'>

<!--
    Match and edit patterns.

    If 'target' is 'pattern', execute the match before selecting a font.
    if 'target' is 'font', execute the match on the result of a font
    selection.
-->
<!ELEMENT match (test*, edit*)>
<!ATTLIST match
          target (pattern|font) "pattern">

<!--
    Match a field in a pattern

    if 'qual' is 'any', then the match succeeds if any value in the field matches.
    if 'qual' is 'all', then the match succeeds only if all values match.
-->
<!ELEMENT test (%expr;)>
<!ATTLIST test 
          qual (any|all)    "any"
          name CDATA        #REQUIRED
          compare (eq|not_eq|less|less_eq|more|more_eq) "eq">

<!--
    Edit a field in a pattern

    The enclosed values are used together to edit the list of values
    associated with 'name'.

    If 'name' matches one of those used in a test element for this match element:
        if 'mode' is 'assign', replace the matched value.
        if 'mode' is 'assign_replace', replace all of the values
        if 'mode' is 'prepend', insert before the matched value
        if 'mode' is 'append', insert after the matched value
        if 'mode' is 'prepend_first', insert before all of the values
        if 'mode' is 'append_last', insert after all of the values
    If 'name' doesn't match any of those used in a test element:
        if 'mode' is 'assign' or 'assign_replace, replace all of the values
        if 'mode' is 'prepend' or 'prepend_first', insert before all of the values
        if 'mode' is 'append' or 'append_last', insert after all of the values
-->
<!ELEMENT edit (%expr;)*>
<!ATTLIST edit
          name CDATA        #REQUIRED
          mode (assign|assign_replace|prepend|append|prepend_first|append_last) 
"assign">

<!--
    Elements of expressions follow
-->
<!ELEMENT number EMPTY>
<!ATTLIST number
          value CDATA       #REQUIRED>
<!ELEMENT string EMPTY>
<!ATTLIST string
          value CDATA       #REQUIRED>
<!ELEMENT name EMPTY>
<!ATTLIST name
          name CDATA        #REQUIRED>
<!ELEMENT matrix (number,number,number,number)>
<!ELEMENT boolean_or (%expr;)*>
<!ELEMENT boolean_and (%expr;)*>
<!ELEMENT eq (%expr;)*>
<!ELEMENT not_eq (%expr;)*>
<!ELEMENT less (%expr;)*>
<!ELEMENT less_eq (%expr;)*>
<!ELEMENT more (%expr;)*>
<!ELEMENT more_eq (%expr;)*>
<!ELEMENT plus (%expr;)*>
<!ELEMENT minus (%expr;)*>
<!ELEMENT times (%expr;)*>
<!ELEMENT divide (%expr;)*>
<!ELEMENT not (%expr;)>
<!ELEMENT if ((%expr;), (%expr;), (%expr;)?)>
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<!-- /etc/fonts.conf file to configure system font access -->
<fontconfig>
<!-- 
        Find true type fonts in this directory 
-->
<dir dir="/usr/X11R6/lib/X11/fonts/truetype"/>

<!--
        Accept deprecated 'mono' alias, replacing it with 'monospace'
-->
<match target="pattern">
        <test qual="any" name="family"><string value="mono"/></test>
        <edit name="family" mode="assign"><string value="monospace"/></edit>
</match>

<!--
        Load per-user customization file
-->
<include ignore_missing="yes" file="~/.fonts.conf"/>

<!--
        Alias well known font names to available TrueType fonts
-->
<alias family="Times">
        <prefer><family family="Times New Roman"/></prefer>
        <default><family family="serif"/></default>
</alias>
<alias family="Helvetica">
        <prefer><family family="Verdana"/></prefer>
        <default><family family="sans"/></default>
</alias>
<alias family="Courier">
        <prefer><family family="Courier New"/></prefer>
        <default><family family="monospace"/></default>
</alias>

<!--
        Provide required aliases for standard names
-->
<alias family="serif">
        <prefer><family family="Times New Roman"/></prefer>
</alias>
<alias family="sans">
        <prefer><family family="Verdana"/></prefer>
</alias>
<alias family="monospace">
        <prefer><family family="Andale Mono"/></prefer>
</alias>

</fontconfig>

Reply via email to