about summary refs log tree commit diff
path: root/nixpkgs/pkgs/servers/x11/xquartz/font_cache
blob: b1191980d77f2100322564faa9122d24fa89e82c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
#!@shell@

export PATH=@PATH@:$PATH

export FONTCONFIG_FILE="@FONTCONFIG_FILE@"
ENCODINGSDIR="@ENCODINGSDIR@"
FC_LOCKFILE=""

# Are we caching system fonts or user fonts?
system=0

# Are we including OSX font dirs ({/,~/,/System/}Library/Fonts)
osxfonts=1

# Do we want to force a recache?
force=0

# How noisy are we?
verbose=0

# Check if the data in the given directory is newer than its cache
check_dirty() {
    local dir=$1
    local fontfiles=""
    local retval=1

    # If the dir does not exist, we just exit
    if [[ ! -d "${dir}" ]]; then
        return 1
    fi

    # Create a list of all files in the dir
    # Filter out config / cache files.  Ugly... counting down the day until
    # xfs finally goes away
    fontfiles="$(find ${dir}/ -maxdepth 1 -type f | awk '$0 !~ /fonts\..*$|^.*\.dir$/ {print}')"

    # Fonts were deleted (or never there).  Kill off the caches
    if [[ -z "${fontfiles}" ]] ; then
        local f
        for f in "${dir}"/fonts.* "${dir}"/encodings.dir; do
            if [[ -f ${f} ]] ; then
                rm -f "${f}"
            fi
        done
        return 1
    fi

    # Force a recache
    if [[ ${force} == 1 ]] ; then
        retval=0
    fi

    # If we don't have our caches, we are dirty
    if [[ ! -f "${dir}/fonts.list" || ! -f "${dir}/fonts.dir" || ! -f "${dir}/encodings.dir" ]]; then
        retval=0
    fi

    # Check that no files were added or removed....
    if [[ "${retval}" -ne 0 && "$(cat ${dir}/fonts.list)" != "${fontfiles}" ]] ; then
        retval=0
    fi

    # Check that no files were updated....
    if [[ "${retval}" -ne 0 ]] ; then
        local changed="$(find ${dir}/ -type f -cnewer ${dir}/fonts.dir | awk '$0 !~ /fonts\..*$|^.*\.dir$/ {print}')"

        if [[ -n "${changed}" ]] ; then
            retval=0
        fi
    fi

    # Recreate fonts.list since something changed
    if [[ "${retval}" == 0 ]] ; then
        echo "${fontfiles}" > "${dir}"/fonts.list
    fi

    return ${retval}
}

get_fontdirs() {
    local d
    if [[ $system == 1 ]] ; then
        if [[ $osxfonts == 1 ]] ; then
            find {/System/,/}Library/Fonts -type d
        fi
    else
        if [[ $osxfonts == 1 && -d "${HOME}/Library/Fonts" ]] ; then
            find "${HOME}/Library/Fonts" -type d
        fi

        if [[ -d "${HOME}/.fonts" ]] ; then
            find "${HOME}/.fonts" -type d
        fi
    fi
}

setup_fontdirs() {
    local x=""
    local fontdirs=""
    local changed="no"

    umask 022

    if [[ $system == 1 ]] ; then
        echo "font_cache: Scanning system font directories to generate X11 font caches"
    else
        echo "font_cache: Scanning user font directories to generate X11 font caches"
    fi

    OIFS=$IFS
    IFS='
'
    for x in $(get_fontdirs) ; do
        if [[ -d "${x}" ]] && check_dirty "${x}" ; then
            if [[ -z "${fontdirs}" ]] ; then
                fontdirs="${x}"
            else
                fontdirs="${fontdirs}${IFS}${x}"
            fi
        fi
    done

    if [[ -n "${fontdirs}" ]] ; then
        echo "font_cache: Making fonts.dir for updated directories."
        for x in ${fontdirs} ; do
            if [[ $verbose == 1 ]] ; then
                echo "font_cache:    ${x}"
            fi

            # First, generate fonts.scale for scaleable fonts that might be there
            @MKFONTSCALE@ \
                -a $ENCODINGSDIR/encodings.dir \
                -a $ENCODINGSDIR/large/encodings.dir \
                -- ${x}

            # Next, generate fonts.dir
            if [[ $verbose == 1 ]] ; then
                @MKFONTDIR@ \
                    -e $ENCODINGSDIR \
                    -e $ENCODINGSDIR/large \
                    -- ${x}
            else
                @MKFONTDIR@ \
                    -e $ENCODINGSDIR \
                    -e $ENCODINGSDIR/large \
                    -- ${x} > /dev/null
            fi
        done
    fi
    IFS=$OIFS

    # Finally, update fontconfig's cache
    echo "font_cache: Updating FC cache"
    if [[ $system == 1 ]] ; then
        @FC_CACHE@ -s \
            $([[ $force == 1 ]] && echo "-f -r") \
            $([[ $verbose == 1 ]] && echo "-v")
    else
        @FC_CACHE@ \
            $([[ $force == 1 ]] && echo "-f -r") \
            $([[ $verbose == 1 ]] && echo "-v")
    fi
    echo "font_cache: Done"
}

do_usage() {
    echo "font_cache [options]"
    echo "    -f, --force        : Force cache recreation"
    echo "    -n, --no-osxfonts  : Just cache X11 font directories"
    echo "                         (-n just pertains to XFont cache, not fontconfig)"
    echo "    -s, --system       : Cache system font dirs instead of user dirs"
    echo "    -v, --verbose      : Verbose Output"
}

cleanup() {
    [[ -r "${FC_LOCKFILE}" ]] && rm -f "${FC_LOCKFILE}"
    exit 1
}

while [[ $# -gt 0 ]] ; do
    case $1 in
        -s|--system) system=1 ;;
        -f|--force) force=1 ;;
        -v|--verbose) verbose=1 ;;
        -n|--no-osxfonts) osxfonts=0 ;;
        --help) do_usage ; exit 0 ;;
        *) do_usage ; exit 1 ;;
    esac
    shift
done

if [[ $system == 1 ]] ; then
    FC_LOCKFILE="/tmp/font_cache.$UID.lock"
elif [[ -w "${TMPDIR}" ]] ; then
    FC_LOCKFILE="${TMPDIR}/font_cache.lock"
elif [[ -w "/tmp" ]] ; then
    FC_LOCKFILE="/tmp/font_cache.$UID.lock"
else
    FC_LOCKFILE="${HOME}/.font_cache.lock"
fi

if [[ -x /usr/bin/lockfile ]] ; then
    if /usr/bin/lockfile -r 0 -l 240 -s 4 -! "${FC_LOCKFILE}" ; then
            echo "font_cache is already running." >&2
            echo "If you believe this to be erroneous, please remove ${FC_LOCKFILE}." >&2
            exit 1
    fi
else
    if [[ -r "${FC_LOCKFILE}" ]] ; then
        read OLD_PID < "${FC_LOCKFILE}"
        if kill -0 ${OLD_PID} >& /dev/null ; then
            echo "font_cache is already running with PID ${OLD_PID}." >&2
            echo "If you believe this to be erroneous, please remove ${FC_LOCKFILE}." >&2
            exit 1
        fi

        echo "Removing stale ${FC_LOCKFILE}" >&2
        rm -f "${FC_LOCKFILE}"
    fi

    echo $$ > "${FC_LOCKFILE}"

    if [[ ! -r "${FC_LOCKFILE}" ]] ; then
        echo "Unable to write to ${FC_LOCKFILE}." >&2
        exit 1
    fi

    # Now make sure we didn't collide mid-air
    read OLD_PID < "${FC_LOCKFILE}"
    if [[ $$ != ${OLD_PID} ]] ; then
        echo "font_cache is already running with PID ${OLD_PID}." >&2
        exit 1
    fi
fi

trap cleanup SIGINT SIGQUIT SIGABRT SIGTERM

setup_fontdirs

rm -f "${FC_LOCKFILE}"