Initial commit 10/2210/1 1.0_branch accepted/trunk/20121010.225551 submit/trunk/20121010.230435
authorGraydon, Tracy <tracy.graydon@intel.com>
Wed, 10 Oct 2012 23:03:03 +0000 (16:03 -0700)
committerGraydon, Tracy <tracy.graydon@intel.com>
Wed, 10 Oct 2012 23:03:03 +0000 (16:03 -0700)
38 files changed:
bin/compare-repo-font-audit [new file with mode: 0755]
bin/filter-fontlint [new file with mode: 0755]
bin/filter-langcover [new file with mode: 0755]
bin/filter-unicover [new file with mode: 0755]
bin/fix-font-naming [new file with mode: 0755]
bin/repo-font-audit [new file with mode: 0755]
bin/ttfcoverage [new file with mode: 0755]
changelog.txt [new file with mode: 0644]
fontconfig-templates/basic-font-template.conf [new file with mode: 0644]
fontconfig-templates/basic-font-template.txt [new file with mode: 0644]
fontconfig-templates/fontconfig-generics.txt [new file with mode: 0644]
fontconfig-templates/fontconfig-priorities.txt [new file with mode: 0644]
fontconfig-templates/index.txt [new file with mode: 0644]
fontconfig-templates/l10n-font-template.conf [new file with mode: 0644]
fontconfig-templates/l10n-font-template.txt [new file with mode: 0644]
fontconfig-templates/merging-font-template.conf [new file with mode: 0644]
fontconfig-templates/merging-font-template.txt [new file with mode: 0644]
fontconfig-templates/remapping-font-template.conf [new file with mode: 0644]
fontconfig-templates/remapping-font-template.txt [new file with mode: 0644]
fontconfig-templates/rescaling-font-template.conf [new file with mode: 0644]
fontconfig-templates/rescaling-font-template.txt [new file with mode: 0644]
fontconfig-templates/substitution-font-template.conf [new file with mode: 0644]
fontconfig-templates/substitution-font-template.txt [new file with mode: 0644]
license.txt [new file with mode: 0644]
packaging/fontpackages.changes [new file with mode: 0644]
packaging/fontpackages.spec [new file with mode: 0644]
private/core-fonts-report [new file with mode: 0755]
private/font-links-report [new file with mode: 0755]
private/fonts-report [new file with mode: 0755]
private/process-fc-query [new file with mode: 0755]
private/repo-font-audit.mk [new file with mode: 0644]
private/test-info [new file with mode: 0755]
readme.txt [new file with mode: 0644]
rpm/macros.fonts [new file with mode: 0644]
spec-templates/spectemplate-fonts-multi.spec [new file with mode: 0644]
spec-templates/spectemplate-fonts-partial-multi.spec [new file with mode: 0644]
spec-templates/spectemplate-fonts-partial-simple.spec [new file with mode: 0644]
spec-templates/spectemplate-fonts-simple.spec [new file with mode: 0644]

diff --git a/bin/compare-repo-font-audit b/bin/compare-repo-font-audit
new file mode 100755 (executable)
index 0000000..9d5df66
--- /dev/null
@@ -0,0 +1,324 @@
+#!/bin/sh
+# Compares the output of two repo-font-audit runs and print test score changes
+
+DATADIR="$(dirname $0)/../private"
+
+usage() {
+cat >&2 << EOF_USAGE
+Usage: $0 <resultset1> <resultset2>
+<resultsetx>: “Extracted data” archive produced by repo-font-audit
+
+Example:
+$0 repo-font-audit-fedora-12-20091121T110127Z.tar.xz repo-font-audit-rawhide-20091121T110127Z.tar.xz
+EOF_USAGE
+exit 1
+}
+
+
+find_package_changes() {
+awk -F '|' '
+  FNR==1 {
+    filenames = filenames FILENAME "|"
+  }
+  (FNR>1) && ($15!="") {
+    rpm[$3] = rpm[$3] FILENAME "|" $1 "|" $2 "|" $7 "|" $10 "|" $11 "|" $12 "|" $15 "#"
+  }
+  END {
+    sub("\\|$","",filenames)
+    split(filenames,filenamest,"|")
+
+    print "B. Font package changes:"
+    nr = asorti(rpm,rpms)
+    for ( r = 1 ; r <= nr ; r++ ) {
+      sub("#$","",rpm[rpms[r]])
+      na = split(rpm[rpms[r]],rpma,"#")
+      delete rpmv
+      for ( a = 1 ; a <= na ; a++ ) {
+        if (rpmv[rpma[a]]) {
+          delete rpma[a]
+        }
+        else {
+          rpmv[rpma[a]] = 1
+        }
+      }
+      for (i in minus) {
+        delete minus[i]
+      }
+      for (i in plus) {
+        delete plus[i]
+      }
+      for (i in changed) {
+        delete changed[i]
+      }
+      infom = ""
+      infop = ""
+      na = asort(rpma)
+      for ( a = 1 ; a <= na ; a++ ) {
+        ni = split(rpma[a],rpmi,"|")
+        if ( rpmi[1] == filenamest[1] ) {
+          infom = rpmi[2] "|" rpmi[3] "|" rpmi[4]
+          minus[rpmi[5]] = rpmi[6] "|" rpmi[7] "|" rpmi[8]
+        }
+        if ( rpmi[1] == filenamest[2] ) {
+          infop = rpmi[2] "|" rpmi[3] "|" rpmi[4]
+          plus[rpmi[5]] = rpmi[6] "|" rpmi[7] "|" rpmi[8]
+        }
+      }
+      for ( file in minus ) {
+        if ( plus[file] == minus[file] ) {
+            delete plus[file]
+            delete minus[file]
+        }
+        else {
+          changed[file] = 1
+          if ( plus[file] == "" ) {
+            delete plus[file]
+          }
+        }
+      }
+      for ( file in plus ) {
+        changed[file] = 1
+      }
+      change = 0
+      if ( length(minus) > 0 ) {
+        change = 1
+      }
+      if ( length(plus) > 0 ) {
+        change = change + 2
+      }
+     if ( change > 0 ) {
+        split(infom, infomt, "|")
+        split(infop, infopt, "|")
+        if ( infomt[3] == "M" ) {
+          infomt[3] = ", M"
+        }
+        if ( infopt[3] == "M" ) {
+          infopt[3] = ", M"
+        }
+        if ( change == 1 ) {
+          print "— " rpms[r] ".rpm (" infomt[2] ".src.rpm , " infomt[1] infomt[3] ")"
+          rpmcount = rpmcount - 1
+        }
+        if ( change == 2 ) {
+          print "+ " rpms[r] ".rpm (" infopt[2] ".src.rpm, " infopt[1] infopt[3] ")"
+          rpmcount = rpmcount + 1
+        }
+        if ( change == 3 ) {
+          print "= " rpms[r] ".rpm (" infomt[2] ".src.rpm, " infomt[1] infomt[3] ")"
+          print "    ⇒ " infopt[2] ".src.rpm, " infopt[1] infopt[3]
+        }
+        nc = asorti(changed)
+        for (i in out) {
+          delete out[i]
+        }
+        for ( c = 1 ; c <= nc ; c++ ) {
+          if ( minus[changed[c]] ) {
+            split(minus[changed[c]], infoc, "|")
+            sig = infoc[1] ", " infoc[2]
+            out[sig] = out [sig] infoc[3] "|−|" changed[c] "#" 
+            formatcount[infoc[3]] = formatcount[infoc[3]] - 1
+            maintcount[infomt[1]] = maintcount[infomt[1]] - 1
+          }
+          if ( plus[changed[c]] ) {
+            split(plus[changed[c]], infoc, "|")
+            sig = infoc[1] ", " infoc[2]
+            out[sig] = out [sig] infoc[3] "|+|" changed[c] "#"
+            formatcount[infoc[3]] = formatcount[infoc[3]] + 1
+            maintcount[infopt[1]] = maintcount[infopt[1]] + 1
+          }
+        }
+        no = asorti(out, outs)
+        for ( o = 1 ; o <= no ; o++ ) {
+          font = outs[o]
+          sub("#$", "", out[font])
+          nf = split(out[font],fs, "#")
+          asort(fs)
+          for ( f = 1 ; f <= nf ; f++ ) {
+            split(fs[f], oi, "|")
+            print "    " oi[2] " " font ", " oi[1] "\t" oi[3]
+          }
+        }
+      }
+    }
+    nf = asorti (formatcount, fcs)
+    for ( f = 1 ; f <= nf ; f++ ) {
+      if ( formatcount[fcs[f]] > 0 ) {
+        total = total "+" formatcount[fcs[f]] " " fcs[f] ", "
+      }
+      if ( formatcount[fcs[f]] < 0 ) {
+        total = total formatcount[fcs[f]] " " fcs[f] ", "
+      }
+    }
+    sub(", $", ".", total)
+    if ( total == "" ) {
+      total = "—"
+    }
+    print ""
+    print "C. Font count changes: " total
+    print ""
+    print "D. Packager activity: "
+    for ( m in maintcount ) {
+      score = maintcount[m]
+      if ( score < 0 ) { score = - score }
+      score = score / 10000
+      rmaintcount[score] = rmaintcount[score] m "|"
+    }
+    nc = asorti(rmaintcount, rmcs)
+    for ( c = nc ; c >= 1 ; c-- ) {
+      sub("\\|$", "", rmaintcount[rmcs[c]])
+      split(rmaintcount[rmcs[c]], maint, "|")
+      nm = asort(maint)
+      for ( m = 1 ; m <= nm ; m++ ) {
+        print maint[m]
+      }
+    }
+  }' "$1" "$2"
+}
+
+compare_tests() {
+
+awk -F '|' '
+  BEGIN {
+    lh = 7
+  }
+  FNR==1 {
+    filenames = filenames FILENAME "|"
+    for (i = lh ; i <= NF ; i++) {
+      testid[ FILENAME "|" i ] = $i
+    }
+  }
+  FNR>1 {
+    for (i = lh ; i <= NF ; i++) {
+      score[ FILENAME "|" $1 "|" $2 "|" $3 "|" i ] += $i
+    }
+  }
+  END {
+    sub("\\|$","",filenames)
+    split(filenames,filenamest,"|")
+    for ( sig in score ) {
+      split(sig,sigt,"|")
+      nsig = sigt[2] "|" sigt[3] "|" sigt[4] "|" testid[ sigt[1] "|" sigt[5] ]
+      if ( sigt[1] == filenamest[1] ) {
+        total_score[nsig] = total_score[nsig] - score[sig]
+      }
+      if ( sigt[1] == filenamest[2] ) {
+        total_score[nsig] = total_score[nsig] + score[sig]
+      }
+    }
+    for ( sig in total_score ) {
+      split(sig,sigt,"|")
+      if ( total_score[sig] != 0 ) {
+        test_diff[ sigt[4] ] = 1
+        pk_diff[ sigt[1] "|" sigt[2] "|" sigt[3] ] = 1
+        total_score_diff[sig] = total_score[sig]
+      }
+    }
+    line = "Maintainer|SRPM|RPM|"
+    nt = asorti(test_diff)
+    for ( t = 1 ; t <= nt ; t++ ) {
+      line = line test_diff[t] "|"
+    }
+    sub("\\|$","",line)
+    print line
+    np = asorti(pk_diff)
+    for ( p = 1 ; p <= np ; p++ ) {
+      line = pk_diff[p] "|"
+      for ( t = 1 ; t <= nt ; t++ ) {
+        line = line total_score_diff[ pk_diff[p] "|" test_diff[t] ] "|"
+      }
+      sub("\\|$","",line)
+      print line
+    }
+  }' "$1" "$2"
+}
+
+
+pretty_print() {
+awk -F '|' '
+  BEGIN {
+    lh = 4
+  }
+  NR==1 {
+    max = NF
+    headline = "P#"
+    for ( i = lh ; i < max ; i++ ) {
+      headline = headline "|t" i+1-lh
+    }
+    print headline
+  }
+  NR>1 {
+    line = NR - 1
+    for ( i = lh ; i < max ; i++ ) {
+      if ( $i ) { line = line "|" $i }
+      else      { line = line "|‧"   }
+      total[i] = total[i] + $i
+    }
+    print line
+  }
+ END {
+  totalline = "Balance"
+  for ( i = lh ; i < max ; i++ ) {
+      totalline = totalline "|" total[i]
+    }
+  print totalline
+  }' "$1" | column -t -s '|'
+
+  echo ""
+
+awk -F '|' '
+  BEGIN {
+    lh = 4
+  }
+  NR==1 {
+    print "P#|Maintainer|RPM|SRPM"
+  }
+  NR>1 {
+    line = NR - 1
+    for ( i = 1 ; i < lh ; i++ ) {
+      if ( $i ) { line = line "|" $i }
+      else      { line = line "| "   }
+    }
+    print line
+  }' "$1" | column -t -s '|'
+
+  echo ""
+
+  awk -F '|' '
+    BEGIN { lh = 4 }
+    NR==1 {
+      for ( i = lh ; i < NF ; i++ ) {
+        print "t" i+1-lh "|" $i
+      }
+    }' "$1" \
+  | while read line ; do
+      testnumber=$(echo $line | cut -d "|" -f 1)
+      testid=$(echo $line | cut -d "|" -f 2)
+      echo -n "$testnumber. "
+      "$DATADIR/test-info" $testid title
+    done
+}
+
+[ "$#" -lt "2" ] && usage
+
+TIMESTAMP=$(date -u +%Y%m%dT%H%M%SZ)
+
+FL="consolidated-data.csv"
+TSUM="test-summary.csv"
+
+TMPDIR=$(mktemp -d --tmpdir=/tmp "$(basename $0)-$TIMESTAMP-XXXXXXXXXX")
+
+tar xf "$1" "*/$TSUM" -O > "$TMPDIR/1-$TSUM"
+tar xf "$1" "*/$FL" -O > "$TMPDIR/1-$FL"
+tar xf "$2" "*/$TSUM" -O > "$TMPDIR/2-$TSUM"
+tar xf "$2" "*/$FL" -O > "$TMPDIR/2-$FL"
+
+echo "A. Test result changes:"
+echo ""
+
+compare_tests "$TMPDIR/1-$TSUM" "$TMPDIR/2-$TSUM" > "$TMPDIR/D-$TSUM"
+[ $(cat "$TMPDIR/D-$TSUM" | wc -l) -gt 1 ] && pretty_print "$TMPDIR/D-$TSUM"
+
+echo ""
+find_package_changes "$TMPDIR/1-$FL" "$TMPDIR/2-$FL"
+
+rm -fr "$TMPDIR"
diff --git a/bin/filter-fontlint b/bin/filter-fontlint
new file mode 100755 (executable)
index 0000000..fd46616
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/sh
+# Try to filter useless fontlint messages
+
+awk -F "|" '
+    NR==4               { result = $0 }
+    NR>4 && $1 !~ /^  / { result = result "\n" $0 }
+    NR>4 && $1  ~ /^  / { gsub("^  ", "|",$1)
+                        result = result $0 }
+    END { print result }' \
+  | awk -F "|" '
+    $1 ~ /Validation/ {
+      l=2
+      while (l<=NF) {
+        print $l
+        l++
+      }
+    }
+    $1 !~ /Validation/ { print }' \
+  | awk -F "|" '
+    NR==1              { result = $0 }
+    NR>1 && $1 !~ /^ / { result = result "\n" $0 }
+    NR>1 && $1  ~ /^ / { gsub("^ ", "|",$1)
+                         result = result $0 }
+    END { if (result != "") { print result } }' \
+  | grep -v -e "^The following table(s) in the font have been ignored by FontForge" \
+            -e "^The glyph named .* is mapped to .*But its name indicates it should be mapped to .*." \
+            -e "^A glyph uses at least one, but not all, anchor classes in a subtable" \
+            -e "^This font contains both a .* table and a .* table." \
+            -e "^Missing Points at Extrema" \
+            -e "^Self Intersecting Glyph" \
+            -e "^Wrong Direction"
diff --git a/bin/filter-langcover b/bin/filter-langcover
new file mode 100755 (executable)
index 0000000..8500597
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/sh
+# Filter the output of fc-query in debug mode to keep only lang coverage
+
+grep '^[a-z]\{1,4\}\(-[a-z]\{1,4\}\)\?([1-9]) \+{ \+\([a-f0-9]\{4\} \)\+}'
diff --git a/bin/filter-unicover b/bin/filter-unicover
new file mode 100755 (executable)
index 0000000..e51c093
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+# Filter unicover output to keep only blocks with less than 10 missing glyphs
+# (as fc-query does for lang coverage
+
+sed 's=^\([^\:]*\):\( *\)\([0-9]\+\)/\([0-9]\+\)\( *\)(\([0-9.]\+\)%)$=\1|\3|\4|\6='\
+  | awk -F '|' '($3-$2 > 0) && ($3-$2 < 10) { print $1 ": " $3-$2 }'
diff --git a/bin/fix-font-naming b/bin/fix-font-naming
new file mode 100755 (executable)
index 0000000..8f4dcb2
--- /dev/null
@@ -0,0 +1,184 @@
+#!/bin/sh
+# Implements a font name cleanup heuristic similar to the one described in
+# http://blogs.msdn.com/text/attachment/2249036.ashx
+
+usage() {
+cat >&2 << EOF_USAGE
+Usage: $0 <family> <style>
+<family>: font family to test
+<style>:  font style to test
+
+Example:
+$0 "DejaVu Sans" "Condensed Bold Oblique"
+
+EOF_USAGE
+exit 1
+}
+
+fix_naming() {
+awk --re-interval -v family="$1" -v face="$2" '
+  BEGIN {
+    # regular is a slant but is special-cased in naming
+    attrs = "regular|slant|stretch|weight"
+
+    blocks["regular"] = "Regular"
+    blocks["slant"]   = "Italic|Oblique"
+    blocks["stretch"] = "UltraCondensed|ExtraCondensed|SemiCondensed|SemiExpanded|ExtraExpanded|UltraExpanded|Condensed|Expanded"
+    blocks["weight"]  = "Thin1|ExtraLight|DemiBold1|ExtraBold1|Bold|Thin2|Light|Medium|ExtraBlack|Black|DemiBold2|ExtraBold2"
+
+    aliases["Regular"]  = "Book|Normal|Regular|Roman|Upright"
+
+    aliases["Italic"]  = "ita|ital|Italic|cursive|kursiv"
+    aliases["Oblique"] = "inclined|Oblique|backslanted|backslant|slanted"
+
+    aliases["UltraCondensed"] = "extra compressed|ext compressed|ultra compressed|ultra condensed|ultra cond|UltraCondensed"
+    aliases["ExtraCondensed"] = "compressed|extra condensed|ext condensed|extra cond|ext cond|ExtraCondensed"
+    aliases["SemiCondensed"]  = "narrow|compact|semi condensed|semi cond|SemiCondensed"
+    aliases["SemiExpanded"]   = "wide|semi expanded|semi extended|SemiExpanded"
+    aliases["ExtraExpanded"]  = "extra expanded|ext expanded|extra extended|ext extended|ExtraExpanded"
+    aliases["UltraExpanded"]  = "ultra expanded|ultra extended|UltraExpanded"
+    aliases["Condensed"]    = "Condensed|cond"
+    aliases["Expanded"]     = "extended|Expanded|extended"
+
+    aliases["Thin1"]    = "extra thin|ext thin|ultra thin"
+    aliases["ExtraLight"] = "extra light|ext light|ultra light|UltraLight|ExtraLight"
+    aliases["DemiBold1"]  = "semi bold|demi bold|SemiBold|DemiBold"
+    aliases["ExtraBold1"] = "extra bold|ext bold|ultra bold|UltraBold|ExtraBold"
+    aliases["Bold"]     = "Bold"
+    aliases["Thin2"]    = "thin"
+    aliases["Light"]    = "Light"
+    aliases["Medium"]     = "Medium"
+    aliases["ExtraBlack"] = "extra black|ext black|ultra black|UltraBlack|ExtraBlack"
+    aliases["Black"]    = "Black|heavy|nord"
+    aliases["DemiBold2"]  = "demi"
+    aliases["ExtraBold2"] = "ultra"
+
+    nat = split(attrs,attributes,"|")
+    for ( at = 1 ; at <= nat ; at++ ) {
+      nb = split(blocks[attributes[at]],b_l,"|")
+      for ( b = 1 ; b <= nb ; b++ ) {
+        nal = split(tolower(aliases[b_l[b]]),al_l,"|")
+        aliases[b_l[b]] = ""
+        for ( al = 1 ; al <= nal ; al++ ) {
+          # WWS uses reverse-matching everywhere
+          nw = split(al_l[al], words," ")
+          for (w = nw ; w >= 1 ; w-- ) {
+            aliases[b_l[b]] = aliases[b_l[b]] words[w] " "
+          }
+          sub(" $", "|", aliases[b_l[b]])
+        }
+        sub("\\|$", "", aliases[b_l[b]])
+      }
+    }
+
+    nf = split(family "|" face, s, "|")
+    # This is more aggressive than demanded by WWS
+    for ( i = 1 ; i <= nf ; i++ ) {
+      fs[i] = gensub("&", " and ", "g", s[i])
+      fs[i] = gensub("\\([[:digit:]]){3}", " ", "g", fs[i])
+      fs[i] = gensub("([[:digit:]]+)", " \\1 ", "g", fs[i])
+      fs[i] = gensub("([[:lower:]])([[:upper:]])([[:lower:]])", "\\1 \\2\\3", "g", fs[i])
+      fs[i] = gensub("[ \t_\\.-]+", " ", "g", fs[i])
+      fs[i] = tolower(fs[i])
+      rfs[i] = ""
+      nw = split(fs[i], words, " ")
+      for (w = nw ; w >= 1 ; w-- ) {
+        rfs[i] = rfs[i] words[w] " "
+      }
+      sub("^"," ",rfs[i])
+    }
+
+    rffamily = rfs[1]
+    rfface = rfs[2]
+
+    # Remove the rightmost occurrence of a regular face name
+    nrfface = rfface
+    control = nrfface
+    nb = split(blocks[attributes[1]],b_l,"|")
+    b = 1
+    while ((b <= nb) && (nrfface == control)) {
+      nal = split(aliases[b_l[b]],al_l,"|")
+      al = 1
+      while ((al <= nal) && (nrfface == control)) {
+        sub(" " al_l[al] " ", " ", nrfface)
+        al++
+      }
+      b++
+    }
+    # We should canonalize Regular too but too many fonts get it wrong and
+    # it is not terribly important
+    if (nrfface != control) {
+      canonical_attribute["regular"] = toupper(substr(al_l[al-1], 1,1)) substr(al_l[al-1], 2)
+    }
+
+    # Append FaceName to FontFamily
+    sub(nrfface, " ", rffamily)
+    nrffont = gensub("  ", " ", "g", nrfface rffamily)
+
+    # Process other qualifiers
+    for ( at = 2 ; at <= nat ; at++ ) {
+      canonical_attribute[attributes[at]] = ""
+      control = nrffont
+      nb = split(blocks[attributes[at]],b_l,"|")
+      b = 1
+      while ((b <= nb) && (nrffont == control)) {
+        nal = split(aliases[b_l[b]],al_l,"|")
+        al = 1
+        while ((al <= nal) && (nrffont == control)) {
+          sub(" " al_l[al] " ", " ", nrffont)
+          al++
+        }
+        b++
+      }
+      if (nrffont != control) {
+        canonical_attribute[attributes[at]] = gensub("[[:digit:]]", "", "g", b_l[b-1])
+      }
+    }
+
+    cnface = canonical_attribute["stretch"] " " canonical_attribute["weight"] " " canonical_attribute["slant"]
+    sub("  ", " ", cnface)
+    sub(" $", "", cnface)
+    sub("^ ", "", cnface)
+    if (cnface == "") {
+      if ( canonical_attribute["regular"] != "" )
+           { cnface = canonical_attribute["regular"] }
+      else { cnface = "Regular" }
+    }
+
+    # Make sure there are no stray attributes left
+    for ( at = 1 ; at <= nat ; at++ ) {
+      nb = split(blocks[attributes[at]],b_l,"|")
+      for ( b = 1 ; b <= nb ; b++ ) {
+        nal = split(aliases[b_l[b]],al_l,"|")
+        for ( al = 1 ; al <= nal ; al++ ) {
+          sub(" " al_l[al] " ", " ", nrffont)
+        }
+      }
+    }
+
+    cnfamily = ""
+    nw = split(nrffont, words, " ")
+    for (w = nw ; w >= 1 ; w-- ) {
+      cnfamily = cnfamily toupper(substr(words[w], 1,1)) substr(words[w], 2) " "
+    }
+    sub(" $", "", cnfamily)
+
+    # Keep the original family name if it matches since some of the
+    # operations performed before, while necessary for attribute detection,
+    # can be needlessly destructive on legitimate family names
+    nfamily = gensub("([[:digit:]]+)", " \\1 ", "g", family)
+    nfamily = gensub("([[:lower:]])([[:upper:]])([[:lower:]])", "\\1 \\2\\3", "g", nfamily)
+    sub("-", " ", nfamily)
+    sub(" +", " ", nfamily)
+    sub(" $", "", nfamily)
+    sub("^ ", "", nfamily)
+
+    if ( tolower(nfamily) == tolower(cnfamily) ) { cnfamily = family }
+
+    print cnfamily "\t" cnface
+  }'
+
+}
+
+[ "$#" -lt "2" ] && usage
+fix_naming "$1" "$2"
diff --git a/bin/repo-font-audit b/bin/repo-font-audit
new file mode 100755 (executable)
index 0000000..0cff9e4
--- /dev/null
@@ -0,0 +1,1180 @@
+#!/bin/sh
+# Quick and dirty script to audit font use in a yum package repository
+#
+# It is slow, it is ugly, and it requires a good network connection
+
+# Function declarations
+
+usage() {
+cat >&2 << EOF_USAGE
+Usage: $0 <id> <location>
+<id>:       identifier of the package repository to check
+<location>: location of the package repository to check
+
+Examples:
+$0 tmp /tmp/rpm
+$0 tmp file://tmp/rpm
+$0 rawhide http://example.com/mirrors/fedora.redhat.com/fedora/linux/development/x86_64/os/
+
+EOF_USAGE
+exit 1
+}
+
+DATADIR="$(dirname $0)/../private"
+
+# Filenames with whitespace or & + makefile = !!!
+bad_pattern="[[:space:]&\:]"
+
+# Tools and humans make mistakes; try to fix some obvious ones
+fix_url() {
+sed 's=^file:\(\/*\)=/=' | sed 's=^\(ftp\|http\|https\):\(\/*\)=\1://='
+}
+
+pretty_indent() {
+  fold -s -w $(($(tput cols) - 2)) \
+  | while read line ; do echo "  $line" ; done
+}
+
+# $1 = CSV file to evaluate
+tally() {
+
+awk -F "|" '
+  {
+    filesize   += $17
+    filenumber += 1
+    rpmsz[$3 "-" $4 "." $5] = $6
+    srpms[$2] = 1
+  }
+  END {
+    for (rpm in rpmsz) {
+      rpmsize   += rpmsz[rpm]
+      rpmnumber +=1
+    }
+    for (srpm in srpms) {
+      srpmnumber +=1
+    }
+    rpmsize  = rpmsize  / (1024*1024)
+    filesize = filesize / (1024*1024)
+    print filenumber "|" rpmnumber "|" srpmnumber "|" filesize "|" rpmsize
+  }' "$1"
+}
+
+
+summary() {
+if [ $(cat "$1" | wc -l) -gt 0 ] ; then
+  tally "$1" | awk -F '|' '{ print "⇒ " $1 " file(s) (" $4 " MiB) in " $2 \
+        " package(s) (" $5 " MiB) generated from " $3 " source package(s)." }'\
+        | pretty_indent
+else
+  echo "⇒  None!" | pretty_indent
+fi
+echo ""
+}
+
+
+# $1 = summary file
+# $2 = temporary data file
+# $3 = test id
+complete_csv_summary() {
+  awk -F '|' -v t_datafile="$2" -v testlabel="$3" \
+      'FILENAME==t_datafile { fail[$1"|"$2"|"$3"|"$4"|"$5"|"$10] = 1 }
+       FILENAME!=t_datafile && FNR==1 {
+        max = NF + 1
+        header = $1
+        for (i = 2 ; i <= max ; i++) {
+           header = header "|" $i
+         }
+        print header testlabel
+       }
+       FILENAME!=t_datafile && FNR>1 {
+         line = $1 "|" $2 "|" $3 "|" $4 "|" $5 "|" $6
+         newline = $1
+         for (i = 2 ; i <= max ; i++) {
+           newline = newline "|" $i
+         }
+         print newline fail[line]
+         processed[line] = 1
+       }
+       END {
+         for ( line in fail ) {
+           if ( ! processed[line] ) {
+             newline = line
+             for (i = 7 ; i <= max ; i++) {
+               newline = newline "|"
+             }
+             print newline fail[line]
+           }
+         }
+       }' "$2" "$1" > tmp/tmp.ccs.csv
+  awk 'FNR==1' tmp/tmp.ccs.csv > "$1"
+  awk 'FNR>1'  tmp/tmp.ccs.csv | sort -f -t '|' >> "$1"
+  rm tmp/tmp.ccs.csv
+}
+
+
+substats() {
+ss_datafile="$1"
+
+awk -F '|' '{ print $NF }' "$ss_datafile" | sort | uniq \
+  | while read key ; do
+    echo -n "$key|"
+    awk -F '|' -v key="$key" '$NF==key' "$ss_datafile" > tmp/tmp.ss.csv
+    tally tmp/tmp.ss.csv
+    rm tmp/tmp.ss.csv
+  done
+}
+
+
+# $1 = CSV file to sum_up
+stats() {
+s_datafile="$1"
+
+summary "$s_datafile"
+
+if [ $(cat "$s_datafile" | wc -l) -gt 0 ] ; then
+  (echo "Format|Files|rpm|srpm|Files (MiB)|rpm (MiB)"
+  awk -F '|' '$13 != "" { print $0 "|" $15 }' "$s_datafile" > tmp/tmp.s.csv
+  substats tmp/tmp.s.csv) | column -t -s '|' | pretty_indent
+  echo ""
+
+  (echo "Arch|Files|rpm|srpm|Files (MiB)|rpm (MiB)"
+  awk -F '|' '{ print $0 "|" $5 }' "$s_datafile" > tmp/tmp.s.csv
+  substats tmp/tmp.s.csv)| column -t -s '|' | pretty_indent
+  echo ""
+
+  rm tmp/tmp.s.csv
+fi
+}
+
+
+# $1 = CSV file to sum_up
+list_rpm() {
+
+[ $(cat "$1" | wc -l) -gt 0 ] && \
+awk -F '|' '
+  {
+    rpm = $3
+    if ( $7 == "M" ) { rpm = "[" rpm "]" }
+    total[rpm] += 1
+  }
+  END {
+    n = asorti(total, sorted)
+    for ( i = 1 ; i <= n ; i++ ) {
+      line = line sorted[i] "(" total[sorted[i]] "), "
+    }
+    sub(", $","",line)
+    print line
+  }' "$1" | pretty_indent
+
+}
+
+# Pipe CSV file to sum_up
+# It is assumed to be of the form
+# rpm | pattern to match | pattern to display
+# patterns may include # as separators
+enum_rpm() {
+awk -F '|' '
+  BEGIN { print "" }
+  {
+    rpm = $1
+    key = $2
+    pat = $3
+    files[key] = files[key] pat "#" rpm "|"
+  }
+  END {
+    for (key in files) {
+      sub("\\|$", "", files[key])
+      total = split(files[key], lines,"|")
+      pb[total] = pb[total] key "|"
+    }
+    n = asorti(pb, sorted)
+    for (i = n; i >= 1; i--) {
+      total = sorted[i]
+      sub("\\|$", "", pb[total])
+      split(pb[total], keys,"|")
+      nk = asort(keys, sortedkeys)
+      for ( k = 1 ; k <= nk ; k++ ) {
+        key = sortedkeys[k]
+        print gensub("#", ", ", "g", key)
+        split(files[key], lines, "|")
+        nl = asort(lines, sortedlines)
+        for ( l = 1 ; l <= nl ; l++ ) {
+          print "  " gensub("#", "\t", "G", lines[l])
+        }
+        print ""
+      }
+    }
+  }' | pretty_indent
+}
+
+# $1 = this test id
+# $2 = csv file with the results of this test
+# $3 = csv file that consolidates the results of all tests
+test_wrapup() {
+
+complete_csv_summary "$3" "$2" "$1"
+summary "$2"
+
+}
+
+
+# $1 = csv file with test results
+test_score() {
+if [ $(cat "$1" | wc -l) -gt 1 ] ; then
+  awk -F '|' '
+    BEGIN {
+      lh=7
+      headerline = "P#"
+    }
+    FNR==1 {
+      max = NF
+    }
+    FNR>1 {
+      id = ""
+      for (i = 1 ; i < (lh-1) ; i++) {
+        if ($i != "") id = id $i "|"
+        else          id = id   " |"
+      }
+      sub("\\|$","",id)
+      fail[id] = 1
+      for (i = lh ; i <= max ; i++) {
+        score[id"|"i] = score[id"|"i] + $i
+        totalscore[i] = totalscore[i] + $i
+      }
+    }
+    END {
+      for (i = lh ; i <= max ; i++) {
+          if ( totalscore[i] ) { headerline  = headerline "|" "t" i+1-lh }
+        }
+      print headerline
+      n = asorti(fail)
+      for (l = 1; l <= n; l++) {
+        newline = l
+        for (c = lh ; c <= max ; c++) {
+          if ( totalscore[c] ) {
+            if ( score[fail[l]"|"c] )
+              { newline = newline "|" score[fail[l]"|"c] }
+            else
+              { newline = newline "|‧" }
+          }
+        }
+        print newline
+      }
+      totalline = "Total"
+      for (i = lh ; i <= max ; i++) {
+        if ( totalscore[i] ) { totalline = totalline "|"  totalscore[i] }
+      }
+      print totalline
+    }' "$1" | column -t -s '|'
+
+  echo ""
+
+  awk -F '|' '
+    BEGIN { lh=7 }
+    FNR>1 {
+      id = ""
+      for (i = 1 ; i < (lh-1) ; i++) {
+        if ($i != "") id = id $i "|"
+        else          id = id   " |"
+      }
+      sub("\\|$","",id)
+      fail[id] = 1
+    }
+    END {
+      print "P#|Maintainer|SRPM|RPM|EVR|Arch"
+      n = asorti(fail)
+      for (l = 1; l <= n; l++) {
+      print l "|" fail[l]
+      }
+    }' "$1" | column -t -s '|'
+
+  echo ""
+  echo "Test explanation:"
+  echo ""
+
+  awk -F '|' '
+    BEGIN { lh = 7 }
+    FNR==1 {
+      max = NF
+      for (i = lh ; i <= max ; i++) {
+        legend[i] = i+1-lh "|" $i }
+      }
+    FNR>1 {
+      for (i = lh ; i <= max ; i++) {
+        totalscore[i] = totalscore[i] + $i
+      }
+    }
+    END {
+      for (i = lh ; i <= max ; i++) {
+        if ( totalscore[i] ) { print legend[i] }
+      }
+    }' "$1" | while read line ; do
+      testnumber=$(echo $line | awk -F '|' '{ print "t"$1 }')
+      testid=$(echo $line | awk -F '|' '{ print $2 }')
+      echo -n "$testnumber. "
+      "$DATADIR/test-info" $testid title
+      echo ""
+      ( "$DATADIR/test-info" $testid help ) | pretty_indent
+    done
+
+else
+  echo "⇒  None!"
+fi
+
+}
+
+
+collect() {
+start_time=$(date "+%s")
+
+# This is very ugly but the safest syntax to use with any repoquery version
+FREPOURL=$(echo "$REPOURL" | sed 's=^/=file:///=')
+
+echo "Looking for packages:"
+echo "— with font metadata…"
+repoquery --repofrompath=$REPOID,$FREPOURL --repoid=$REPOID \
+          --qf "%{sourcerpm}|%{name}|%{epoch}:%{version}-%{release}|%{arch}|%{packagesize}|M" \
+          --whatprovides "font(*)" --quiet \
+          | sort | uniq \
+          | sed 's=^\([^|]\+\?\)\-\([^-|]\+\?\)\-\([^-|]\+\?\)|=\1|=g' \
+          > "$FPL"
+
+echo "— that include files with common font extensions…"
+repoquery --repofrompath=$REPOID,$FREPOURL --repoid=$REPOID \
+          --qf "%{sourcerpm}|%{name}|%{epoch}:%{version}-%{release}|%{arch}|%{packagesize}|E" \
+          -f '*.ttf' -f '*.otf' -f '*.ttc' \
+          -f '*.pfb' -f '*.pfa' \
+          -f '*.pcf.gz' -f '*.pcf' -f '*.bdf' --quiet \
+          | sort | uniq \
+          | sed 's=^\([^|]\+\?\)\-\([^-|]\+\?\)\-\([^-|]\+\?\)|=\1|=g' \
+          > "$PWFL"
+
+echo "— that use the core X11 protocol…"
+repoquery --repofrompath=$REPOID,$FREPOURL --repoid=$REPOID \
+          --qf "%{sourcerpm}|%{name}|%{epoch}:%{version}-%{release}|%{arch}|%{packagesize}|X" \
+          --whatrequires 'libX11.so*' \
+          | sort | uniq \
+          | sed 's=^\([^|]\+\?\)\-\([^-|]\+\?\)\-\([^-|]\+\?\)|=\1|=g' \
+          > "$XPL"
+
+if [ $(cat "$FPL" "$PWFL" "$XPL" | wc -l) -eq 0 ] ; then
+  echo "Nothing to do!"
+  exit
+fi
+
+cat "$FPL" "$PWFL" "$XPL" \
+  | awk -F '|' '
+      { tag[$1 "|" $2 "|" $3 "|" $4 "|" $5] = tag[$1 "|" $2 "|" $3 "|" $4 "|" $5] $6 "," }
+      END {
+        n =  asorti(tag,rpm)
+        for (l = 1; l <= n; l++) {
+          sub(",$", "", tag[rpm[l]])
+          print rpm[l] "|" tag[rpm[l]]
+        }
+      }' > "tmp/$FL.1"
+
+echo ""
+echo "Inspecting packages:"
+cd "tmp"
+rm -f "$FL.2"
+
+cat "$FL.1" | while read line ; do
+  rpm=$(echo "$line" | awk -F '|' '{ print $2 "-" $3 "." $4 }')
+  rpmline=$(echo "$line" | awk -F '|' '{ print $1 "|" $2 "|" $3 "|" $4 "|" $5 }')
+  rpmd=$(echo "$rpm" | sed "s+$bad_pattern+_+g")
+  echo "$line" | cut -d "|" -f 6 | grep -q "M" && metadata="M" || metadata=""
+  echo -n "– $rpm ◔"
+  mkdir "$rpmd"
+  cd "$rpmd"
+  rpm_loc=$(repoquery --repofrompath=$REPOID,$REPOURL --repoid=$REPOID \
+                      --location "$rpm" 2>/dev/null \
+              | fix_url)
+  if $(echo "$rpm_loc" | grep -q -e '^[\./~]') ; then
+    ln -s "$rpm_loc" .
+  else
+    curl -O --silent --show-error --retry 3 --connect-timeout 10 --retry-delay 15 --url "$rpm_loc"
+  fi
+  echo -ne "\b◑"
+  rpm2cpio *.rpm > "$rpm.cpio"
+  echo -ne "\b◕"
+  cat "$rpm.cpio" | cpio --quiet -it > "$rpm.lst"
+  nofont_score=$(cat "$rpm.lst" | sed 's=^\./=/=g' \
+    | grep -viE -e "^/usr/share/fonts" \
+                -e "^/usr/share/fontconfig/conf.avail/" \
+                -e "^/etc/fonts/conf.d/" \
+                -e "^/usr/share/doc/" \
+                -e "^/etc/X11/fontpath.d/" \
+                -e '\.((ttf)|(ttc)|(otf)|(pfa)|(pfb)|(bdf)|(pcf)|(pcf\.gz))$' \
+    | wc -l)
+  echo "$rpmline|$metadata|$nofont_score" > rpm-info.txt
+  if $(echo $line | cut -d "|" -f 6 | grep -q "E") ; then
+    cat "$rpm.lst" \
+      | grep -iE '\.((ttf)|(ttc)|(otf)|(pfa)|(pfb)|(bdf)|(pcf)|(pcf\.gz))$' \
+      | sort > "$rpm.fonts.lst"
+  fi
+  if $(echo $line | cut -d "|" -f 6 | grep -q "X") ; then
+    cat "$rpm.lst" \
+      | grep -i  -e "^./sbin/" \
+                 -e "^./usr/sbin/" \
+                 -e "^./usr/kerberos/sbin" \
+                 -e "^./bin/" \
+                 -e "^./usr/bin/" \
+                 -e "^./usr/kerberos/bin/" \
+                 -e "^./lib.*/" \
+                 -e "^./usr/lib.*/" \
+                 -e "^./opt/" \
+                 -e "^./usr/X11R6/" \
+                 -e "^./usr/games/" \
+                 -e "^./usr/local/" \
+      | grep -vi -e "^./usr/bin/dmxwininfo" \
+                 -e "^./usr/bin/Xdmx" \
+                 -e "^./usr/bin/xfontsel" \
+                 -e "^./usr/bin/xlsfonts" \
+                 -e "^./usr/bin/Xnest" \
+                 -e "^./usr/bin/xprop" \
+                 -e "^./usr/bin/xsetroot" \
+                 -e "^./usr/bin/xwininfo" \
+                 -e "^./usr/bin/x11vnc" \
+                 -e "^./usr/bin/x2vnc" \
+                 -e "^./usr/lib.*/libXcursor.so" \
+      | sort > "$rpm.bin.lst"
+  fi
+  touch "$rpm.fonts.lst" "$rpm.bin.lst"
+  cat "$rpm.fonts.lst" "$rpm.bin.lst"  | sort | uniq > "$rpm.files.lst"
+  mkdir src
+  cd src
+  cpio -idm --quiet -E "../$rpm.files.lst" < "../$rpm.cpio"
+  cd ..
+  rm "$rpm.cpio"
+  echo -ne "\b● "
+  sed 's=^\./==g' "$rpm.fonts.lst" \
+    | while read file; do
+    unset target
+    type=$(file -bzh "src/$file")
+    case $(echo "$type" | sed 's+ (\(.*\)++g' \
+                             | sed 's+ `\(.*\)++g' \
+                             | sed 's+,\(.*\)++g' \
+                             | sed 's+\( \)*$++g' ) in
+      "TrueType font data")
+        echo -n "t"
+        ;;
+      "TrueType font collection data")
+        echo -n "T"
+        ;;
+      "OpenType font data")
+        echo -n "o"
+        ;;
+      "X11 Portable Compiled Font data")
+        echo -n "b"
+        ;;
+      "X11 BDF font text")
+        echo -n "B"
+        ;;
+      # PostScript files are a mess
+      "PostScript Type 1 font text")
+        echo -n "P"
+        ;;
+      "PostScript Type 1 font program data")
+        echo -n "p"
+        ;;
+      "PostScript document text conforming DSC level 3.0")
+        type="ignored"
+        echo -n "-"
+        ;;
+      "PostScript document text"|"8086 relocatable")
+        echo -n "!" >&2
+        ;;
+      "symbolic link to"|"broken symbolic link to")
+        target=$(readlink -m "src/$file" | sed "s+^$PWD/src++g")
+        if $(echo "$target" | grep -q "^/usr/share/fonts") ; then
+          type="Link"
+          echo -n "l"
+        else
+          type="ignored"
+          echo -n "-"
+        fi
+        ;;
+      *)
+        echo -n "?"
+        ;;
+    esac
+    if [ "$type" != "ignored" -a ! -h "src/$file" ] ; then
+       mkdir -p $(dirname "tmp/$file")
+       echo "/$file|$type" > "tmp/$file.rfo.fonts.info"
+       if [ "$type" != "TrueType font data" -a \
+            "$type" != "OpenType font data" ] ; then
+         touch "tmp/$file.rfo.unicover"
+       fi
+    fi
+    if [ "$type" = "Link" ] ; then
+      echo "/$file|$target" >> font-links.txt
+    fi
+  done
+
+  sed 's=^\./==g' "$rpm.bin.lst" \
+    | while read file ; do
+    type=$(file -bzh "src/$file")
+    if $(echo "$type" | grep -q -e '^ELF ' -e ' ELF ') ; then
+      echo -n "‧"
+      mkdir -p $(dirname "tmp/$file")
+      echo "/$file|$type" > "tmp/$file.rfo.core-fonts.info"
+    fi
+  done
+
+  echo ""
+  cd ..
+done
+
+echo ""
+echo "Analysing files…"
+
+find . -type d | grep "$bad_pattern" \
+  | while read dir ; do
+      mkdir -p $(echo "$dir" | sed "s+$bad_pattern+_+g")
+    done
+
+find . -type f | grep "$bad_pattern" \
+  | while read file ; do
+      mv "$file" $(echo "$file"| sed "s+$bad_pattern+_+g")
+    done
+
+# There must be a cleaner way to do this
+parallelism=$(($(cat /proc/cpuinfo | grep processor | wc -l)+1))
+make -s -r -j $parallelism -f "$DATADIR/repo-font-audit.mk"
+
+find .  -name "*\.rfo\.fonts" \
+     -o -name "*\.rfo\.core-fonts" \
+     -o -name processed-font-links.txt \
+  | while read datafile ; do
+      cat "$datafile" >> "$FL.2"
+    done
+
+mkdir ../data
+for rpmlint in */rpmlint.txt ; do
+  mkdir "../data/$(dirname $rpmlint)"
+  mv "$rpmlint" "../data/$rpmlint"
+done
+
+for ext in fontlint unicover fc-query ; do
+  find . -name "*\.rfo\.$ext" \
+     | while read file ; do
+          dest=$(echo "$file" \
+            | sed "s+./\([^/]*\)/tmp/\(.*\).rfo.$ext+\1|\2.$ext.txt+" \
+            | sed 's+/+_+g' | sed 's+|+/+g')
+          [ -s "$file" ] && mv "$file" "../data/$dest"
+       done
+done
+
+rm -fr "*/"
+echo " ♻"
+cd ..
+}
+
+
+consolidate() {
+echo ""
+echo "Consolidating data…"
+
+echo "Maintainer|SRPM|RPM|EVR|Arch|RPM size|RPM metadata|foreign data|\
+rpmlint score|filename|family name|face name|fixed family name|\
+fixed face name|format (fontconfig)|format (libmagic)|file size|checksum|\
+partial scripts|partial blocks|fontlint|symlink target|symlink provider|\
+core fonts use" > "$FL"
+
+if  [ -s "tmp/$FL.2" -a -r "tmp/$FL.2" ] ; then
+
+  # FIXME: make this distro-agnostic
+  cut -d "|" -f 1 "tmp/$FL.2" | sort | uniq \
+    | /usr/bin/fedoradev-pkgowners 2>/dev/null \
+    | sed 's+ +|+g' \
+    | awk -F "|" -v file="tmp/$FL.2" '
+        { owner[$2]=$1 }
+        END {
+          while ((getline < file) > 0) {
+            print owner[$1] "|" $0
+          }
+        }' | sort -df -t "|" -k 1 -k 2 -k 3 > "tmp/$FL.3"
+
+  awk -F "|" '
+    ($16 != "Link") { source[$10] = $3 "-" $4
+                      out[$0] = $0 "|" }
+    ($16 == "Link") { link[$0] = $22 }
+    END {
+      for (line in link) {
+        out[line] = line "|" source[link[line]]
+      }
+      n = asort(out)
+      for (i = 1; i <= n; i++) print out[i]
+    }' "tmp/$FL.3" > "tmp/$FL.4"
+
+  cat "tmp/$FL.4" \
+    | sort -df -t "|" -k 1 -k 2 -k 3 -k 4n -k 13 -k 14 -k 10 \
+    | sed 's=$=|=g' | sed 's=|0|=||=g' | sed 's=|0|=||=g' | sed 's=|\+$==g' \
+    >> "$FL"
+
+fi
+
+echo "Maintainer|SRPM|RPM|EVR|Arch|File" > "$TSUM"
+}
+
+
+analyse() {
+
+echo ""
+echo "Conducting tests:"
+echo ""
+
+
+echo -n "— "
+"$DATADIR/test-info" outside-usr-share-fonts title }
+
+awk -F '|' '(NR > 1) && ($16 != "Link") && ($24!="X") && \
+            ($10 !~ /^\/usr\/share\/fonts\//)' "$FL" \
+  | sort -df -t "|" > tmp/tmp.csv
+
+list_rpm tmp/tmp.csv
+test_wrapup outside-usr-share-fonts tmp/tmp.csv "$TSUM"
+
+
+echo -n "— "
+"$DATADIR/test-info" without-rpm-metadata title
+
+awk -F '|' '(NR > 1) && ($16 != "Link") && ($24!="X") && \
+            ($7 != "M")' "$FL" \
+  | sort -df -t "|" > tmp/tmp.csv
+
+list_rpm tmp/tmp.csv
+test_wrapup without-rpm-metadata tmp/tmp.csv "$TSUM"
+
+
+echo -n "— "
+"$DATADIR/test-info" family-mixing title
+
+awk -F '|' '
+  (NR > 1) && ($11 != "") {
+    rpm = $3 "-" $4 "." $5
+    files[rpm] = files[rpm] $0 "#"
+    if ( ! family[rpm] ) {
+      family[rpm] = $11
+    }
+    else {
+      if (family[rpm] != $11) {
+        mixed[rpm] = 1
+      }
+    }
+  }
+  END {
+    for (rpm in mixed) {
+      sub("#$", "", files[rpm])
+      split(files[rpm], lines,"#")
+      for (l in lines) {
+        print lines[l]
+      }
+    }
+  }' "$FL" \
+  | sort -df -t "|" > tmp/tmp.csv
+
+list_rpm tmp/tmp.csv
+test_wrapup family-mixing tmp/tmp.csv "$TSUM"
+
+
+echo -n "— "
+"$DATADIR/test-info" duplicated-file title
+
+awk -F '|' '
+  (NR > 1) && ($24 != "X") && ($16 != "Link") {
+    files[$18] = files[$18] $0 "#"
+  }
+  END {
+    for (checksum in files) {
+      sub("#$", "", files[checksum])
+      count = split(files[checksum], lines,"#")
+      if (count > 1) {
+        for (l in lines) {
+          print lines[l]
+        }
+      }
+    }
+  }' "$FL" \
+  | sort -g -t "|" -k 18 > tmp/tmp.csv
+
+[ $(cat tmp/tmp.csv | wc -l) -gt 0 ] && \
+awk -F '|' '
+  {
+    rpm = $3
+    if ( $7 == "M" ) { rpm = "[" rpm "]" }
+    sub(".*/", "", $10)
+    if ( $11 != "" ) { sig = $11 }
+    if ( $12 != "") {
+      if ( sig != "" ) { sig = sig ", " }
+      sig = sig $12
+    }
+    if ( sig != "" ) { sig = "#(" sig ")" }
+    print rpm "|" $18 "|" $10 sig
+  }' tmp/tmp.csv | enum_rpm
+
+test_wrapup duplicated-file tmp/tmp.csv "$TSUM"
+
+echo -n "— "
+"$DATADIR/test-info" duplicated-face-ext title
+
+awk -F '|' '
+  (NR > 1) && ($11 != "") && ($12 != "") {
+    face = $11 "|" $12
+    rpm  = $3  "-" $4 "." $5
+    files[face] = files[face] $0 "#"
+    if ( ! loc[face] ) { loc[face] = rpm }
+    else {
+      if (loc[face] != rpm) {
+        duplicated[face] = 1
+      }
+    }
+  }
+  END {
+    for (face in duplicated) {
+      sub("#$", "", files[face])
+      split(files[face], lines,"#")
+      for (l in lines) {
+        print lines[l]
+      }
+    }
+  }' "$FL" \
+  | sort -df -t "|" -k 11 -k 12 > tmp/tmp.csv
+
+[ $(cat tmp/tmp.csv | wc -l) -gt 0 ] && \
+awk -F '|' '
+  {
+    rpm = $3
+    if ( $7 == "M" ) { rpm = "[" rpm "]" }
+    sub(".*/", "", $10)
+    print rpm "|" $11 ", " $12 "|" $10
+  }' tmp/tmp.csv | enum_rpm
+
+test_wrapup duplicated-face-ext tmp/tmp.csv "$TSUM"
+
+
+echo -n "— "
+"$DATADIR/test-info" fc-query title
+
+awk -F '|' '(NR > 1) && ($16 != "Link") && ($24!="X") && \
+            ($15 == "")' "$FL" > tmp/tmp.csv
+
+list_rpm tmp/tmp.csv
+test_wrapup fc-query tmp/tmp.csv "$TSUM"
+
+
+echo -n "— "
+"$DATADIR/test-info" libmagic title
+
+awk -F '|' '(NR > 1) && ($16 != "Link") && ($24!="X") && \
+            (tolower(" " $16 " ") !~ / font /)' "$FL" > tmp/tmp.csv
+
+list_rpm tmp/tmp.csv
+test_wrapup libmagic tmp/tmp.csv "$TSUM"
+
+
+echo -n "— "
+"$DATADIR/test-info" broken-symlink title
+
+awk -F '|' '(NR > 1) && ($16 == "Link") && ($23 == "")' "$FL" > tmp/tmp.csv
+
+[ $(cat tmp/tmp.csv | wc -l) -gt 0 ] && \
+awk -F '|' '
+  {
+    rpm = $3
+    if ( $7 == "M" ) { rpm = "[" rpm "]" }
+    sub(".*/", "", $10)
+    print rpm "|" $10 " ↛ " $22
+  }' tmp/tmp.csv | enum_rpm
+
+test_wrapup broken-symlink tmp/tmp.csv "$TSUM"
+
+echo -n "— "
+"$DATADIR/test-info" rpmlint title
+
+awk -F '|' '(NR > 1) && ($16 != "Link") && ($24 != "X") && \
+            ($9 != "")' "$FL" > tmp/tmp.csv
+
+list_rpm tmp/tmp.csv
+test_wrapup rpmlint tmp/tmp.csv "$TSUM"
+
+
+echo -n "— "
+"$DATADIR/test-info" mixed-with-non-font-data title
+
+awk -F '|' '(NR > 1) && ($16 != "Link") && ($24 != "X") && \
+            ($8 != "")' "$FL" > tmp/tmp.csv
+
+list_rpm tmp/tmp.csv
+test_wrapup mixed-with-non-font-data tmp/tmp.csv "$TSUM"
+
+
+echo -n "— "
+"$DATADIR/test-info" arch-package title
+
+awk -F '|' '(NR > 1) && ($16 != "Link") && ($24 != "X") && \
+            ($5 != "noarch")' "$FL" > tmp/tmp.csv
+
+list_rpm tmp/tmp.csv
+test_wrapup arch-package tmp/tmp.csv "$TSUM"
+
+
+echo -n "— "
+"$DATADIR/test-info" bad-rpm-naming title
+
+awk -F "|" '(NR > 1) && ($16 != "Link") && ($24!="X") && \
+            $3 !~ /^[0-9abcdefghijklmnopqrstuvwxyz\.-]*-fonts$/' "$FL" \
+            > tmp/tmp.csv
+
+list_rpm tmp/tmp.csv
+test_wrapup bad-rpm-naming tmp/tmp.csv "$TSUM"
+
+
+echo -n "— "
+"$DATADIR/test-info" bad-naming title
+
+awk -F '|' '(NR > 1) && \
+            ((tolower($11)!=tolower($13)) || (tolower($12)!=tolower($14)))' \
+    "$FL" > tmp/tmp.csv
+
+[ $(cat tmp/tmp.csv | wc -l) -gt 0 ] && \
+awk -F '|' '
+  {
+    rpm = $3
+    if ( $7 == "M" ) { rpm = "[" rpm "]" }
+    sub(".*/", "", $10)
+    print rpm "|" $11 ", " $12 " → " $13 ", " $14 "|" $10
+  }' tmp/tmp.csv | enum_rpm
+
+test_wrapup bad-naming tmp/tmp.csv "$TSUM"
+
+
+echo -n "— "
+"$DATADIR/test-info" core-fonts title
+
+awk -F '|' '(NR > 1) && ($24=="X")' "$FL" > tmp/tmp.csv
+
+list_rpm tmp/tmp.csv
+test_wrapup core-fonts tmp/tmp.csv "$TSUM"
+
+
+echo -n "— "
+"$DATADIR/test-info" font-linking title
+
+awk -F '|' '(NR > 1) && ($16=="Link")' "$FL" > tmp/tmp.csv
+
+list_rpm tmp/tmp.csv
+test_wrapup font-linking tmp/tmp.csv "$TSUM"
+
+
+echo -n "— "
+"$DATADIR/test-info" duplicated-face-int title
+
+awk -F '|' '
+  (NR > 1) && ($24!="X") && \
+    ($15 != "PCF") && ($15 != "Type 1") && \
+    ($11 != "") && ($12 != "") {
+    sig = $3 "|" $4 "|" $5 "|" $11 "|" $12
+    files[sig] = files[sig] $0 "#"
+  }
+  END {
+    for (sig in files) {
+      sub("#$", "", files[sig])
+      n = split(files[sig],lines,"#")
+      if (n > 1) {
+        for (l in lines) { print lines[l] }
+      }
+    }
+  }' "$FL" \
+  | sort -df -t "|" -k 11 -k 12 -k 3 -k 2 > tmp/tmp.csv
+
+[ $(cat tmp/tmp.csv | wc -l) -gt 0 ] && \
+awk -F '|' '
+  {
+    rpm = $3
+    if ( $7 == "M" ) { rpm = "[" rpm "]" }
+    sub(".*/", "", $10)
+    print rpm "|" $11 ", " $12 "|" $10
+  }' tmp/tmp.csv | enum_rpm
+
+test_wrapup duplicated-face-int tmp/tmp.csv "$TSUM"
+
+
+echo -n "— "
+"$DATADIR/test-info" fontlint title
+
+awk -F '|' '(NR > 1) && ($24!="X") && ($21 > 0)' "$FL" > tmp/tmp.csv
+
+list_rpm tmp/tmp.csv
+test_wrapup fontlint tmp/tmp.csv "$TSUM"
+
+
+echo -n "— "
+"$DATADIR/test-info" no-english-metadata title
+
+awk -F '|' '(NR > 1) && ($24!="X") && \
+            ($15 != "") && (($11 == "") || ($12 == ""))' "$FL" > tmp/tmp.csv
+
+[ $(cat tmp/tmp.csv | wc -l) -gt 0 ] && \
+awk -F '|' '
+  {
+    rpm = $3 "-" $4 "." $5
+    if ( $7 == "M" ) { rpm = "[" rpm "]" }
+    print $10 "|" rpm
+  }' tmp/tmp.csv \
+  | column -t -s '|' | pretty_indent
+
+test_wrapup no-english-metadata tmp/tmp.csv "$TSUM"
+
+
+echo -n "— "
+"$DATADIR/test-info" partial-scripts title
+
+awk -F '|' '(NR > 1) && ($24!="X") && ($19 > 0)' "$FL" > tmp/tmp.csv
+
+list_rpm tmp/tmp.csv
+test_wrapup partial-scripts tmp/tmp.csv "$TSUM"
+
+
+echo -n "— "
+"$DATADIR/test-info" partial-blocks title
+
+awk -F '|' '(NR > 1) && ($24!="X") && ($20 > 0)' "$FL" > tmp/tmp.csv
+
+list_rpm tmp/tmp.csv
+test_wrapup partial-blocks tmp/tmp.csv "$TSUM"
+}
+
+
+sum_up() {
+echo ""
+echo "Audit results:"
+echo ""
+
+echo "– packages that declare font metadata:"
+
+awk -F '|' '(NR > 1) && ($7 == "M") && ($24!="X")' "$FL" > tmp/tmp.csv
+stats tmp/tmp.csv
+
+echo "☛ File size is computed as extracted, while rpm is a compressed \
+format." | pretty_indent
+echo "☛ Mid-term, files in legacy PCF or Type1 formats need to be converted \
+or removed." | pretty_indent
+echo ""
+
+echo "– font files in other packages (we should not find any!)"
+
+awk -F '|' '(NR > 1) && ($7 != "M") && ($16 != "Link") && ($24!="X")' "$FL" > tmp/tmp.csv
+stats tmp/tmp.csv
+
+[ $(cat tmp/tmp.csv | wc -l) -gt 0 ] && \
+echo "☛ Bad packaging may result in arched packages or mixed content." \
+| pretty_indent && echo ""
+
+echo "– errors, warnings and suggestions:"
+echo ""
+
+test_score "$TSUM"
+
+}
+
+
+prepare_spam() {
+echo ""
+echo "Packing mail data…"
+
+mkdir spam
+
+for srpm in $(awk -F '|' 'FNR>1 { print $2 }' "$TSUM" | uniq) ; do
+   [ ! -d "tmp/$srpm" ] && mkdir "tmp/$srpm"
+  cp -p report.txt "tmp/$srpm/repo-report.txt"
+  for file in "$FL" "$TSUM" ; do
+    awk 'FNR==1' "$file" > "tmp/$srpm/$file"
+    awk -F '|' -v srpm="$srpm" 'FNR>1 && $2==srpm' "$file" >> "tmp/$srpm/$file"
+  done
+  for rpm in $(awk -F '|' 'FNR>1 { print $3 "-" $4 "." $5 }' "tmp/$srpm/$TSUM" | uniq | sed "s+$bad_pattern+_+g") ; do
+    cp -pr "data/$rpm" "tmp/$srpm"
+  done
+  cat > tmp/$srpm/message.txt << EOF
+Dear packager,
+
+At $TIMESTAMP, your “$srpm” package failed one or more of the tests
+I was performing on the “$ID” repository located at:
+$REPOURL
+
+There are three different reasons that may cause this message:
+1. your package is including one or more font files, but not packaging
+   them properly;
+2. your package is including one or more font files, and I've found
+   issues in some of them;
+3. your package is not shipping any font file, but the way it accesses
+   fonts in other packages is not satisfying.
+
+To stop receiving this message, you need to:
+1. drop the font files or fix their packaging;
+2. relay the fonts issues to the fonts upstream to get them revised;
+3. work with the code upstream to improve the way it accesses font
+   files (usually by making it use fontconfig through a higher-level
+   text library such as pango, pango-cairo, harfbuzz, or QT)
+
+You can self-check your packages at any time by:
+1. installing createrepo and fontpackages-tools:
+# yum install createrepo fontpackages-tools
+2. putting your packages and any font package they depends on in a
+   test directory
+3. indexing this directory with createrepo:
+$ createrepo path-to-test-directory
+4. running repo-font-audit:
+$ repo-font-audit test absolute-path-to-test-directory
+
+A summary of the issues I detected is appended here. For your
+convenience a more comprehensive analysis is also attached to this
+message.
+
+Errors, warnings and suggestions:
+
+$(test_score "tmp/$srpm/$TSUM")
+
+Please take the appropriate measures to fix the “$srpm” package.
+I will warn you again if it is still necessary next time I am ran.
+
+This report was generated by the repo-font-audit command from:
+http://fedoraproject.org/wiki/fontpackages
+
+Please post questions, suggestions, patches or bug reports to:
+https://admin.fedoraproject.org/mailman/listinfo/fonts
+(subscription required)
+
+Your friendly QA robot,
+
+-- 
+repo-font-audit
+EOF
+  cd tmp
+  tar cf "$srpm.tar" "$srpm"
+  cd ..
+  xz -9  "tmp/$srpm.tar"
+  mv "tmp/$srpm.tar.xz" spam
+done
+cat > spam/send-messages.sh << EOF
+#!/bin/sh
+# Send warnings to problem package owners
+# This is a bit distribution-specific, people from other distributions are
+# welcome to suggest how to make it more agnostic
+
+#EMAIL="repo-font-audit <your@mail>"
+#REPLYTO=another@mail
+
+#export EMAIL REPLYTO
+
+for srpm in \\
+$(awk -F '|' 'FNR>1 { print $2 " \\" }' "$TSUM" | uniq)
+; do
+  tar -xf \$srpm.tar.xz */message.txt -O \\
+    | mutt -s "[RFA] Your \$srpm $ID package did not pass QA" \\
+           -a \$srpm.tar.xz -- \$srpm-owner@fedoraproject.org
+  sleep 5
+done
+
+EOF
+chmod +x spam/send-messages.sh
+}
+
+pack_data() {
+echo "Packing result data…"
+
+
+mv spam "$SPAM"
+
+mkdir -p "$RES/data"
+cp "$TSUM" summary.txt report.txt "$FL" "$RES/"
+cp -pr data/* "$RES/data" 2>/dev/null
+
+mkdir "$SRES/"
+cp "$TSUM" summary.txt report.txt "$SRES/"
+
+for report in "$RES" "$SRES" "$SPAM" ; do
+  tar cf "$report.tar" "$report"
+  xz -9  "$report.tar"
+  mv "$report.tar.xz" "$ORIGDIR/"
+done
+
+echo ""
+echo "Audit complete!"
+
+awk 'NR > 1' "$FL" > "tmp/$FL"
+
+end_time=$(date "+%s")
+t=$(($end_time-$start_time))
+th=$(($t/(60*60)))
+tm=$((($t/60)-(th*60)))
+ts=$(($t-(($th*60+$tm)*60)))
+[ $th -gt 0 ] && elapsed_time="$th h"
+if [ $tm -gt 0 ] ; then
+  [ "$elapsed_time" != "" ] \
+    && elapsed_time="$elapsed_time $tm min" \
+    || elapsed_time="$tm min"
+fi
+if [ $ts -gt 0 ] ; then
+  [ "$elapsed_time" != "" ] \
+    && elapsed_time="$elapsed_time $ts s" \
+    || elapsed_time="$ts s"
+fi
+
+(
+cat << EOF
+
+Run time: $elapsed_time.
+Number of items processed:
+$(summary "tmp/$FL")
+
+1. Extracted data: $ORIGDIR/$RES.tar.xz
+2. Short summary: $ORIGDIR/$SRES.tar.xz
+3. Mail data: $ORIGDIR/$SPAM.tar.xz
+
+This report was generated by the repo-font-audit command from:
+http://fedoraproject.org/wiki/fontpackages
+
+Please post questions, suggestions, patches or bug reports to:
+https://admin.fedoraproject.org/mailman/listinfo/fonts
+(subscription required)
+EOF
+) | pretty_indent
+
+}
+
+# End of function declarations
+
+[ "$#" -lt "2" ] && usage
+
+TIMESTAMP=$(date -u +%Y%m%dT%H%M%SZ)
+ID=$1
+REPOID="$1-rfa-$TIMESTAMP"
+REPOURL=$(echo "$2" | fix_url)
+ORIGDIR="$PWD"
+
+FPL="font-packages.csv"
+PWFL="packages-with-fonts.csv"
+XPL="package-using-x11.csv"
+CSL="checksums.csv"
+FL="consolidated-data.csv"
+TSUM="test-summary.csv"
+RES="repo-font-audit-$ID-$TIMESTAMP"
+SRES="repo-font-audit-$ID-$TIMESTAMP-short"
+SPAM="repo-font-audit-$ID-$TIMESTAMP-mail"
+
+TMPDIR=$(mktemp -d --tmpdir=/tmp $RES-XXXXXXXXXX)
+cd $TMPDIR
+
+mkdir tmp
+
+collect
+consolidate
+analyse | tee report.txt
+sum_up  | tee summary.txt
+prepare_spam
+pack_data
+
+cd "$ORIGDIR"
+rm -fr "$TMPDIR"
+echo "♻"
diff --git a/bin/ttfcoverage b/bin/ttfcoverage
new file mode 100755 (executable)
index 0000000..eb107b6
--- /dev/null
@@ -0,0 +1,44 @@
+#!/usr/bin/perl
+# a coverage script
+# depends on Unicode::UCD and Font::TTF
+# by Martin Hosken
+# small tweaks by Nicolas Spalinger
+
+use Font::TTF::Font;
+use Unicode::UCD qw(charblocks charblock charscripts charscript);
+use Getopt::Std;
+
+getopts('s');
+
+my $blocks, $stats;
+
+if ($opt_s)
+{
+    $blocks = charscripts;
+}
+else
+{
+    $blocks = charblocks;
+}
+
+foreach (keys %{$blocks})
+{
+    foreach $r (@{$blocks->{$_}})
+    { $stats->{$_}[0] += ($r->[1] - $r->[0]) + 1; }
+}
+
+$f = Font::TTF::Font->open($ARGV[0]) || die "Can't open font $ARGV[0]";
+$cmap = $f->{'cmap'}->read->find_ms->{'val'};
+
+foreach $c (keys %{$cmap})
+{
+    $r = $opt_s ? charscript($c) : charblock($c);
+    $stats->{$r}[1]++;
+}
+
+foreach (sort keys %{$stats})
+{
+    next unless ($_ && $stats->{$_}[1]);
+    printf "%s: %d/%d (%.2f%%)\n", $_, $stats->{$_}[1], $stats->{$_}[0], $stats->{$_}[1] / $stats->{$_}[0] * 100.;
+}
+
diff --git a/changelog.txt b/changelog.txt
new file mode 100644 (file)
index 0000000..fa02757
--- /dev/null
@@ -0,0 +1,132 @@
+1.44
+     - spec templates: fix bad change in spectemplate-fonts-multi.spec
+1.43
+     - spec templates: remove BuildRoot directive (ignored since rpm 4.6.0)
+     - l10n-font-template.conf: get rid of binding=same (rhbz#578015)
+1.42
+     - repo-font-audit: update mailing list references
+1.41
+     - repo-font-audit: misc. small bug fixes
+     - fix-font-naming: try to match Black after ExtraBlack only
+1.40
+     - repo-font-audit: ironclad urls++
+1.39
+     - repo-font-audit: fix libmagic test for bitmap fonts
+1.38
+     - fontconfig-priorities.txt: reference corresponding fontconfig readme
+     - filter-fontlint: filter out fontlint success message when fontlint has
+       nothing bad to say bout a font file (yes it really happens)
+1.37
+     - repo-font-audit: do not complain of font naming when there are only
+       casing differences (ie mplus)
+1.36
+     - repo-font-audit: make local repo urls more reliable
+1.35
+     - repo-font-audit: misc. small bug fixes
+1.34
+     - compare-repo-font-audit: make output more comprehensive
+1.33
+     - repo-font-audit: add ancilliary script to compare the results of two
+       different runs
+     - repo-font-audit: print run time
+     - repo-font-audit: split out test info from the main script
+1.32
+     - repo-font-audit: replace the two existing WWS tests with a more
+       comprehensive one, and externalize it
+     - repo-font-audit: add core fonts use test
+     - repo-font-audit: add fedora packager name detection
+     - repo-font-audit: add a processed total to reassure users when no problem
+       is identified
+     - repo-font-audit: rework messenging (again)
+     - repo-font-audit: parallelize file tests to make it run faster
+     - repo-font-audit: rewrite several tests to make them more reliable
+1.31
+     - repo-font-audit: try to sort tests by criticity
+     - repo-font-audit: rework messages to make them clearer and (hopefully)
+       better received
+1.30
+     - repo-font-audit: misc. bugfixes
+1.29
+     - repo-font-audit: add (filtered) fontlint checks
+     - repo-font-audit: check partial block coverage according to ttfcoverage
+     - repo-font-audit: check partial script coverage according to fontconfig
+1.28
+     - repo-font-audit: add package maintainer spamming capabilities
+     - repo-font-audit: refactor test comment system
+     - repo-font-audit: make test_score() compacter
+     - repo-font-audit: fixes for bitmap fonts
+     - repo-font-audit: make test_score() smarter
+1.27
+     - do not forget to rewrite fullname in the remapping and merging
+       fontconfig templates
+     - repo-font-audit: move temporary working directory to /tmp
+     - repo-font-audit: fix family mixing check
+     - repo-font-audit: only check naming of packages that contain actual
+       font files
+1.26
+     - repo-font-audit: fix face-in-family check
+     - repo-font-audit: small fixes
+1.25
+     - repo-font-audit: move general statistics to the end, display test
+       summary
+     - repo-font-audit: compute a short test summary
+     - repo-font-audit: clean-up repoquery invocation (compute srpm name, fail
+       gracefully)
+1.24
+     - update readme
+     - make repo-font-audit also output the main csv file separately to make
+       it easy to attach it to mail reports
+     - make repo-font-audit generate tar.xz archives
+     - make some repo-font-audit tests succeed even if there are no matches
+     - make repo-font-audit work on local (file://) repositories
+     - make repo-font-audit WWS checking more accurate, improve its output
+     - make repo-font-audit less chatty when no problems are detected
+     - remove use of style in remapping reverse aliasing, since fontconfig
+       does not like it
+1.23
+     - add an index file in the fontconfig directory, since it is getting
+       crowded
+     - add a template to merge several font families into one
+     - add a template to remap fonts with broken metadata naming to corrected
+       values
+     - use canonical dtd declaration in templates, need to declare the dtd in
+       the system catalog for it to be useful (ie tweak the fontconfig
+       package)
+     - Remove debug output to stderr: it works and is convenient but rpmlint
+       files it as an error, confusing packagers.
+1.22 - Add a quick & dirty script to audit font packaging in a repository
+     - Fix %_font_pkg macro not to eat the following end of line in the spec
+1.21 - Split naming computation in a separate %_font_pkg_name macro and
+       change its logic to handle more corner naming cases. Some fallout in
+       existing packages with weird naming choices is to be expected.
+     - Add debug output to give packagers feedback on the computed names and
+       help detect collisions
+1.20 - Change %define to %global in templates
+1.19 - Add partial templates for fonts subpackages of other packages, update
+       for rpm 4.6 changes in fedora-devel
+1.18 - Auto-own the fonts directory, multiple ownership is ok after all
+1.17 - Tweak spec templates documentation, add fontconfig documentation
+1.16 - Fix recently introduced typo in the simple spec template
+1.15 - Replace shell hacks in the main macro by clean lua code
+1.14 - New subpackage naming rules
+1.13 - Small fixes
+1.12 - Make some spec indenting closer to what rpmdevtools uses; make
+       %{_sysconfdir}/fonts a macro to avoid a cycle with the fontconfig
+       package
+1.11 - Fix hosting info in readme
+1.10 - Renamed to “fontpackages”
+1.9  - Fix fontconfig documentation discrepancy noticed by Ankur Sinha, add doc
+       on fontconfig priorities
+1.8  - Simplify multi spec template: general case, 1 common license, 1 common
+       prio
+1.7  - Split fontconfig template documentation is separate files, to simplify
+       diff-ing against templates.
+1.6  - Simplify spec templates
+1.5  - Use ".conf" extension for fontconfig templates
+1.4  - Fontpackages-filesystem must be required by the common package in the
+       multi spec template
+1.3  - Remove trailing / from directory macro definitions. It's not what people
+       expect.
+1.2  - Add directory ownership in simple spec template
+1.1  - Add fontconfig templates
+1.0  - Initial release
diff --git a/fontconfig-templates/basic-font-template.conf b/fontconfig-templates/basic-font-template.conf
new file mode 100644 (file)
index 0000000..d9fd3f9
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+<fontconfig>
+  <alias>
+    <family>[genericname]</family>
+    <prefer>
+      <family>[fontname]</family>
+    </prefer>
+  </alias>
+  <alias>
+    <family>[fontname]</family>
+    <default>
+      <family>[genericname]</family>
+    </default>
+  </alias>
+</fontconfig>
diff --git a/fontconfig-templates/basic-font-template.txt b/fontconfig-templates/basic-font-template.txt
new file mode 100644 (file)
index 0000000..97850ac
--- /dev/null
@@ -0,0 +1,34 @@
+▶ Documentation for basic-font-template.conf
+
+This basic fontconfig template is sufficient for the needs of most fonts. It
+includes two rules:
+— the first one tells fontconfig it can use the font named [fontname] when an
+application asks for the generic family [genericname].
+— the second one tells fontconfig it can complete the font named [fontname]
+with glyphs taken from fonts registered under [genericname].
+
+If you have more advanced needs, take a look at the other templates.
+
+Please replace [fontname] and [genericname] with the appropriate values in the
+following blocks of instructions.
+
+A [fontname] example would be:
+DejaVu Sans
+It's the name under which the font appears in GUI font drop-downs.
+
+Fontconfig generics ([genericname]) currently include:
+— sans-serif
+— serif
+— monospace
+— fantasy
+– cursive
+
+Processing the resulting file through xmllint with the "format" flag is usually
+a good idea.
+$ xmllint --format -o [XX]-[fontname].conf [yourfile]
+The output file will be named:
+[XX]-[fontname].conf
+where [XX] should be a two-digit number corresponding to the font priority in
+fontconfig.
+
+© 2008-2009 Nicolas Mailhot <nim at fedoraproject dot org>
diff --git a/fontconfig-templates/fontconfig-generics.txt b/fontconfig-templates/fontconfig-generics.txt
new file mode 100644 (file)
index 0000000..f5242fe
--- /dev/null
@@ -0,0 +1,23 @@
+Fontconfig generic font families
+
+The CSS classification system currently used by fontconfig is the following:
+
+   1. a font that can not be used to write long “professional” texts is a 
+      “fantasy” font.
+   2. otherwise:
+         1. if it's monospaced, it's a “monospace” font,
+         2. if it's variable-width and:
+               1. it simulates hand-written text, it's a “cursive” font,
+               2. it uses serifs¹, it's a “serif” font,
+               3. it does not use serifs, it's a “sans-serif” font, 
+         3. otherwise, are you really sure it's not a “fantasy” font? 
+
+Some font authors also make their fonts self-categorize, thus checking the 
+font metadata in fontforge may provide another hint². However, sometimes this 
+metadata is missing or plain false, so do not rely on it 100%. 
+
+
+¹ http://en.wikipedia.org/wiki/Serif
+² <CTRL> + <SHIFT> + <F> then check the OS/2 tab.
+
+© 2009 Nicolas Mailhot <nim at fedoraproject dot org>
diff --git a/fontconfig-templates/fontconfig-priorities.txt b/fontconfig-templates/fontconfig-priorities.txt
new file mode 100644 (file)
index 0000000..dbc75ba
--- /dev/null
@@ -0,0 +1,28 @@
+Fontconfig configuration file ordering
+
+Fontconfig parses files in /etc/fonts/conf.d/ by filename order. The following
+conventions are used to attibute the appropriate prefix to new files:
+
+┌────────┬────────────────────────────────────────────────────────────────────┐
+│ Prefix │ Description                                                        │
+├────────┼────────────────────────────────────────────────────────────────────┤
+│ 50          │ User override                                                      │
+│ 51          │ Local system overrides                                             │
+│ 55-59  │ High priority LGC (Latin Greek Cyrillic) fonts                     │
+│        │ (distribution general-purpose default fonts)                       │
+│ 60     │ Main LGC font list                                                 │
+│ 61-64  │ Low priority LGC fonts                                             │
+│ 65-69  │ Fonts with less common encodings, ending with fonts that provide   │
+│        │ coverage of exotic unicode blocks at the expense of drawing        │
+│        │ quality                                                            │
+└────────┴────────────────────────────────────────────────────────────────────┘
+
+Fontconfig uses an inverted priority scheme where files with lower-number
+prefixes take precedence over files with higher-number prefixes.
+
+It is almost always safe to use high numbers in the prefix range your font
+belongs to, if you do not want to perturb distribution defaults.
+
+See also /etc/fonts/conf.d/README
+
+© 2007-2009 Nicolas Mailhot <nim at fedoraproject dot org>
diff --git a/fontconfig-templates/index.txt b/fontconfig-templates/index.txt
new file mode 100644 (file)
index 0000000..27c4c38
--- /dev/null
@@ -0,0 +1,34 @@
+Contents
+
+1. Generic fontconfig documentation
+
+— fontconfig-priorities.txt
+  Conventions used to name and order fontconfig files
+— fontconfig-generics.txt
+  “Fake” synthetic font families used by fontconfig, and how to choose the
+  correct one to register your font in
+
+2. Fontconfig templates
+
+Each use-case is illustrated by an XML template and the companion explanation
+text file:
+— basic-font-template.txt and basic-font-template.conf
+  A no-frills template sufficient for most fonts
+— substitution-font-template.txt and substitution-font-template.conf
+  When you know your font is a good replacement for another font, and want the
+  system to use your font when an application asks for this other font, and it
+  is not available
+— l10n-font-template.txt and l10n-font-template.conf
+  When you need to increase the priority of your font, but only when writing
+  text for a particular locale
+— rescaling-font-template.txt and rescaling-font-template.conf
+  When the font author made a scaling error, and the font appears too small or
+  too big compared to other fonts at the same settings
+— remapping-font-template.txt and remapping-font-template.conf
+  When the font name or style declared by a font file does not respect
+  conventions, and confuses applications or annoys users
+— merging-font-template.txt and merging-font-template.conf
+  When you need to make several font families appear as a single one,
+  simplifying font management for users.
+
+© 2009 Nicolas Mailhot <nim at fedoraproject dot org>
diff --git a/fontconfig-templates/l10n-font-template.conf b/fontconfig-templates/l10n-font-template.conf
new file mode 100644 (file)
index 0000000..8ef45a0
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+<fontconfig>
+  <match>
+    <test name="lang">
+      <string>[loc]</string>
+    </test>
+    <test name="family">
+      <string>[genericname]</string>
+    </test>
+    <edit name="family" mode="prepend">
+      <string>[fontname]</string>
+    </edit>
+  </match>
+  <alias>
+    <family>[fontname]</family>
+    <default>
+      <family>[genericname]</family>
+    </default>
+  </alias>
+</fontconfig>
diff --git a/fontconfig-templates/l10n-font-template.txt b/fontconfig-templates/l10n-font-template.txt
new file mode 100644 (file)
index 0000000..8c968a4
--- /dev/null
@@ -0,0 +1,47 @@
+▶ Documentation for l10n-font-template.conf
+
+This advanced template replaces the first rule of the basic template with a
+locale-specific one. It includes two rules:
+— the first one tells fontconfig it can use the font named [fontname] when an
+application asks for the generic family [genericname], but only for the [loc]
+locale code.
+— the second one tells fontconfig it can complete the font named [fontname]
+with glyphs taken from fonts registered under [genericname].
+
+The typical use-case are CJK fonts, since the so-called “Han unification”
+Unicode.org decision made different locales share the same code-points even
+though the associated glyphs are supposed to be drawn differently for each of
+them.
+
+If you have different needs, take a look at the other templates.
+
+Please replace [fontname], [genericname], and [loc] with the appropriate values
+in the following blocks of instructions.
+
+A [fontname] example would be:
+DejaVu Sans
+It's the name under which the font appears in GUI font drop-downs.
+
+Fontconfig generics ([genericname]) currently include:
+— sans-serif
+— serif
+— monospace
+— fantasy
+– cursive
+
+A [loc] example would be:
+zh-cn
+
+You may want to add more lines for [loc] to allow matching ll as well as ll-cc,
+however this is unsafe as a “foo” [loc] will match both foo and bar-foo. It is
+better to list all ll-cc locales explicitely.
+
+Processing the resulting file through xmllint with the "format" flag is usually
+a good idea.
+$ xmllint --format -o [XX]-[fontname].conf [yourfile]
+The output file will be named:
+[XX]-[fontname].conf
+where [XX] should be a two-digit number corresponding to the font priority in
+fontconfig.
+
+© 2008-2009 Nicolas Mailhot <nim at fedoraproject dot org>
diff --git a/fontconfig-templates/merging-font-template.conf b/fontconfig-templates/merging-font-template.conf
new file mode 100644 (file)
index 0000000..708600f
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+<fontconfig>
+  <match target="scan">
+    <test name="family">
+      <string>[fontname]</string>
+    </test>
+    <edit name="fontversion">
+      <int>2</int>
+    </edit>
+  </match>
+  <match target="scan">
+    <test name="family">
+      <string>[mergedfontname]</string>
+    </test>
+    <edit name="family">
+      <string>[fontname]</string>
+    </edit>
+    <edit name="fullname">
+      <string>[fontname] [fontstyle]</string>
+    </edit>
+    <edit name="fontversion">
+      <int>1</int>
+    </edit>
+  </match>
+  <alias binding="same">
+    <family>[mergedfontname]</family>
+    <accept>
+      <family>[fontname]</family>
+    </accept>
+  </alias>
+  <alias>
+    <family>[genericname]</family>
+    <prefer>
+      <family>[fontname]</family>
+    </prefer>
+  </alias>
+  <alias>
+    <family>[fontname]</family>
+    <default>
+      <family>[genericname]</family>
+    </default>
+  </alias>
+</fontconfig>
diff --git a/fontconfig-templates/merging-font-template.txt b/fontconfig-templates/merging-font-template.txt
new file mode 100644 (file)
index 0000000..e9d5f34
--- /dev/null
@@ -0,0 +1,63 @@
+▶ Documentation for merging-font-template.conf
+
+This advanced template makes it possible to merge several overlapping font
+families and make them appear as one (the target font family) to applications.
+It is composed of five rules:
+— the first one changes the version of the target [fontname] family to an
+  arbitrary high value (here 2).
+– the second one remaps the name of the font family we want to merge with it
+  ([mergedfontname]) to the target, and assigns it a lower number (here 1).
+  Therefore fontconfig will always try to resolve a request using [fontname]
+  files first, and only use [mergedfontname] files if [fontname] files are not
+  sufficient.
+— the third one is similar to our substitution rule, and is used to alias back
+  [mergedfontname] to [fontname]. This is necessary to avoid breaking
+  documents that reference [mergedfontname] since it is now hidden by the
+  previous rule.
+— the fourth one tells fontconfig it can use the font named [fontname] when an
+  application asks for the generic family [genericname].
+— the fifth one tells fontconfig it can complete the font named [fontname] with
+  glyphs taken from fonts registered under [genericname].
+
+It is possible to merge more than one family, you will only have to repeat the
+second and third rules as many times as necessary. Be careful however to
+strictly order the font versions to make sure fontconfig uses the right
+priorities within the target font family.
+
+The typical use-case are font families released as several font sets, one of
+which being of good quality but of limited Unicode coverage, and the others
+providing wider coverage at the expense of quality or variety of styles.
+Famous examples are “Arial” vs “Arial Unicode”, “Droid Sans” vs “Droid Sans
+Fallback” or “Droid Sans Japanese”. Another use-case are fonts in legacy
+formats: because those formats limited greatly the number of glyphs that could
+be put in a single file, it was common to split a logical font family in
+several encoding-specific files (of course in that case it would be better if
+someone just merged the files in a single OpenType font).
+
+If you have different needs, take a look at the other templates. For example
+changing the naming of a font without merging it with another is better done
+using the remapping template.
+
+Please replace [fontname], [mergedfontname], [genericname], with the
+appropriate values in the following blocks of instructions.
+
+A [fontname] example would be:
+DejaVu Sans
+It's the name under which the font appears in GUI font drop-downs.
+
+Fontconfig generics ([genericname]) currently include:
+— sans-serif
+— serif
+— monospace
+— fantasy
+– cursive
+
+Processing the resulting file through xmllint with the "format" flag is usually
+a good idea.
+$ xmllint --format -o [XX]-[fontname].conf [yourfile]
+The output file will be named:
+[XX]-[fontname].conf
+where [XX] should be a two-digit number corresponding to the font priority in
+fontconfig.
+
+© 2009 Nicolas Mailhot <nim at fedoraproject dot org>
diff --git a/fontconfig-templates/remapping-font-template.conf b/fontconfig-templates/remapping-font-template.conf
new file mode 100644 (file)
index 0000000..776c893
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+<fontconfig>
+  <match target="scan">
+    <test name="family">
+      <string>[problemfontname]</string>
+    </test>
+    <test name="style">
+      <string>[problemfontstyle]</string>
+    </test>
+    <edit name="family">
+      <string>[correctedfontname]</string>
+    </edit>
+    <edit name="style">
+      <string>[correctedfontstyle]</string>
+    </edit>
+    <edit name="fullname">
+      <string>[correctedfontname] [correctedfontstyle]</string>
+    </edit>
+  </match>
+  <alias binding="same">
+    <family>[problemfontname]</family>
+    <accept>
+      <family>[correctedfontname]</family>
+    </accept>
+  </alias>
+  <alias>
+    <family>[genericname]</family>
+    <prefer>
+      <family>[correctedfontname]</family>
+    </prefer>
+  </alias>
+  <alias>
+    <family>[correctedfontname]</family>
+    <default>
+      <family>[genericname]</family>
+    </default>
+  </alias>
+</fontconfig>
diff --git a/fontconfig-templates/remapping-font-template.txt b/fontconfig-templates/remapping-font-template.txt
new file mode 100644 (file)
index 0000000..6691451
--- /dev/null
@@ -0,0 +1,75 @@
+▶ Documentation for remapping-font-template.conf
+
+This advanced template makes it possible to remap bad font metadata to correct
+values at the fontconfig level. It is composed of four rules:
+— the first one (the actual remapping block) detects fonts that declare
+  [problemfontname],[problemfontstyle] and remaps them to
+  [correctedfontname],[correctedfontstyle]. You can remap other attributes, use
+  fc-query to see what a font file declares and fc-scan to check how you
+  corrected it.
+— the second one is similar to our substitution rule, and is used to alias
+  [problemfontname] to [correctedfontstyle]. This is necessary to avoid
+  breaking documents that reference the broken font naming hidden by the
+  previous rule. (it does not take the style into account because
+  unfortunately fontconfig can not handle it right now)
+— the third one tells fontconfig it can use the font named [correctedfontname]
+  when an application asks for the generic family [genericname].
+— the fourth one tells fontconfig it can complete the font named
+  [correctedfontname] with glyphs taken from fonts registered under
+  [genericname].
+
+If the problem font includes more than one style, you will have to repeat the
+two first blocks for each [problemfontname],[problemfontstyle] couple needing
+fixing. The two last rules are similar to what we do in all our other
+patterns.
+
+This kind of remapping is necessary because there were few conventions for font
+naming for a long time, and some font creators put random garbage in there
+(also some fonts were converted from older legacy formats while keeping
+the metadata limitations of those formats, and some authors even released fonts
+with plain typos in their metadata). Now that the two main companies behind the
+OpenType spec, Adobe and Microsoft, specified strict conventions (to help
+applications make sense of available fonts), all those font files need to be
+fixed.
+
+Such problems should always be reported upstream first.
+
+Unfortunately, upstream can take a long time to act, and meanwhile the problem
+metadata will appear in font lists and confuse applications. Since fixing font
+files downstream is unpalatable when they are not released as fontforge SFD
+files (otherwise, just patch the sfds and re-generate), using fontconfig to
+hide the breakage is very convenient.
+
+If you have different needs, take a look at the other templates.
+
+Please replace [problemfontname], [problemfontstyle], [correctedfontname],
+[correctedfontstyle], [genericname], with the
+appropriate values in the following blocks of instructions.
+
+A [correctedfontname] example would be:
+DejaVu Sans
+It's the name under which the font appears in GUI font drop-downs.
+
+[correctedfontname] and [correctedfontstyle] values should aim to conform
+strictly to the rules defined by Microsoft in its WWS fonts white-paper:
+http://blogs.msdn.com/text/attachment/2249036.ashx
+
+Adobe published an introduction to the WWS logic here:
+http://blogs.adobe.com/typblography/typotechnica2007/Font%20names.pdf
+
+Fontconfig generics ([genericname]) currently include:
+— sans-serif
+— serif
+— monospace
+— fantasy
+– cursive
+
+Processing the resulting file through xmllint with the "format" flag is usually
+a good idea.
+$ xmllint --format -o [XX]-[fontname].conf [yourfile]
+The output file will be named:
+[XX]-[fontname].conf
+where [XX] should be a two-digit number corresponding to the font priority in
+fontconfig.
+
+© 2009 Nicolas Mailhot <nim at fedoraproject dot org>
diff --git a/fontconfig-templates/rescaling-font-template.conf b/fontconfig-templates/rescaling-font-template.conf
new file mode 100644 (file)
index 0000000..822a7fe
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+<fontconfig>
+  <alias>
+    <family>[genericname]</family>
+    <prefer>
+      <family>[fontname]</family>
+    </prefer>
+  </alias>
+  <alias>
+    <family>[fontname]</family>
+    <default>
+      <family>[genericname]</family>
+    </default>
+  </alias>
+  <match target="font">
+    <test name="family" mode="eq">
+      <string>[fontname]</string>
+    </test>
+    <edit name="matrix" mode="assign">
+      <times>
+        <name>matrix</name>
+        <matrix>
+          <double>[factor]</double>
+          <double>0</double>
+          <double>0</double>
+          <double>[factor]</double>
+        </matrix>
+      </times>
+    </edit>
+  </match>
+</fontconfig>
diff --git a/fontconfig-templates/rescaling-font-template.txt b/fontconfig-templates/rescaling-font-template.txt
new file mode 100644 (file)
index 0000000..3ad835c
--- /dev/null
@@ -0,0 +1,46 @@
+▶ Documentation for rescaling-font-template.conf
+
+This advanced template adds one rescaling rule to the basic template. Thus, it
+includes three rules:
+— the first one tells fontconfig it can use the font named [fontname] when an
+application asks for the generic family [genericname].
+— the second one tells fontconfig it can complete the font named [fontname]
+with glyphs taken from fonts registered under [genericname].
+– the third one rescales [fontname] by a factor of [factor].
+
+The typical use-case is a font which original sizing does not fit well with the
+other system fonts. We want to be able to replace fonts with other similar
+fonts without the text size changing dramatically.
+
+Of course it is much better get the font fixed upstream, since users of systems
+without this rescaling rule will still draw the font using its original size.
+That will make exchange of electronic documents that use this font impractical.
+
+If you have different needs, take a look at the other templates.
+
+Please replace [fontname], [genericname] and [factor] with the appropriate
+values in the following blocks of instructions.
+
+A [fontname] example would be:
+DejaVu Sans
+It's the name under which the font appears in GUI font drop-downs.
+
+Fontconfig generics ([genericname]) currently include:
+— sans-serif
+— serif
+— monospace
+— fantasy
+– cursive
+
+A [factor] example would be:
+1.2
+
+Processing the resulting file through xmllint with the "format" flag is usually
+a good idea.
+$ xmllint --format -o [XX]-[fontname].conf [yourfile]
+The output file will be named:
+[XX]-[fontname].conf
+where [XX] should be a two-digit number corresponding to the font priority in
+fontconfig.
+
+© 2008-2009 Nicolas Mailhot <nim at fedoraproject dot org>
diff --git a/fontconfig-templates/substitution-font-template.conf b/fontconfig-templates/substitution-font-template.conf
new file mode 100644 (file)
index 0000000..b6e6c19
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+<fontconfig>
+  <alias>
+    <family>[genericname]</family>
+    <prefer>
+      <family>[fontname]</family>
+    </prefer>
+  </alias>
+  <alias>
+    <family>[fontname]</family>
+    <default>
+      <family>[genericname]</family>
+    </default>
+  </alias>
+  <alias binding="same">
+    <family>[otherfontname]</family>
+    <accept>
+      <family>[fontname]</family>
+    </accept>
+  </alias>
+</fontconfig>
diff --git a/fontconfig-templates/substitution-font-template.txt b/fontconfig-templates/substitution-font-template.txt
new file mode 100644 (file)
index 0000000..43d620f
--- /dev/null
@@ -0,0 +1,40 @@
+▶ Documentation for substitution-font-template.conf
+
+This advanced template adds one substitution rule to the basic template. Thus,
+it includes three rules:
+— the first one tells fontconfig it can use the font named [fontname] when an
+application asks for the generic family [genericname].
+— the second one tells fontconfig it can complete the font named [fontname]
+with glyphs taken from fonts registered under [genericname].
+— the third one tells fontconfig it can use [fontname] instead of
+[otherfontname] if an application asks for [otherfontname].
+
+The typical use-case is when you package [fontname], which is a derivative of
+[otherfontname], and want the system to propose [fontname] if [otherfontname]
+is not available.
+
+If you have different needs, take a look at the other templates.
+
+Please replace [fontname], [genericname], and [otherfontname] with the
+appropriate values in the following blocks of instructions.
+
+A [fontname] or [otherfontname] example would be:
+DejaVu Sans
+It's the name under which the font appears in GUI font drop-downs.
+
+Fontconfig generics ([genericname]) currently include:
+— sans-serif
+— serif
+— monospace
+— fantasy
+– cursive
+
+Processing the resulting file through xmllint with the "format" flag is usually
+a good idea.
+$ xmllint --format -o [XX]-[fontname].conf [yourfile]
+The output file will be named:
+[XX]-[fontname].conf
+where [XX] should be a two-digit number corresponding to the font priority in
+fontconfig.
+
+© 2008-2009 Nicolas Mailhot <nim at fedoraproject dot org>
diff --git a/license.txt b/license.txt
new file mode 100644 (file)
index 0000000..fc8a5de
--- /dev/null
@@ -0,0 +1,165 @@
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions. 
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version. 
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/packaging/fontpackages.changes b/packaging/fontpackages.changes
new file mode 100644 (file)
index 0000000..fc7e1cd
--- /dev/null
@@ -0,0 +1,2 @@
+* Tue Aug 14 19:32:18 UTC 2012 - tracy.graydon@intel.com
+- TIVI-129: add fontpackages to satisfy deps for bitstream-vera-fonts
diff --git a/packaging/fontpackages.spec b/packaging/fontpackages.spec
new file mode 100644 (file)
index 0000000..4b8597c
--- /dev/null
@@ -0,0 +1,325 @@
+%global spectemplatedir %{_sysconfdir}/rpmdevtools/
+%global ftcgtemplatedir %{_datadir}/fontconfig/templates/
+%global rpmmacrodir     %{_sysconfdir}/rpm/
+
+Name:    fontpackages
+Version: 1.44
+Release: 3%{?dist}
+Summary: Common directory and macro definitions used by font packages
+
+Group:     Development/System
+# Mostly means the scriptlets inserted via this package do not change the
+# license of the packages they're inserted in
+License:   LGPLv3+
+URL:       http://fedoraproject.org/wiki/fontpackages
+Source0:   http://fedorahosted.org/releases/f/o/%{name}/%{name}-%{version}.tar.xz
+
+BuildArch: noarch
+
+
+%description
+This package contains the basic directory layout, spec templates, rpm macros
+and other materials used to create font packages.
+
+
+%package filesystem
+Summary: Directories used by font packages
+License: Public Domain
+
+%description filesystem
+This package contains the basic directory layout used by font packages,
+including the correct permissions for the directories.
+
+
+%package devel
+Summary: Templates and macros used to create font packages
+
+Requires: rpmdevtools, %{name}-filesystem = %{version}-%{release}
+Requires: fontconfig
+
+%description devel
+This package contains spec templates, rpm macros and other materials used to
+create font packages.
+
+
+%package tools
+Summary: Tools used to check fonts and font packages
+
+Requires: fontconfig, fontforge
+Requires: curl, make, mutt
+Requires: fedora-packager, rpmlint, yum-utils
+
+%description tools
+This package contains tools used to check fonts and font packages
+
+
+%prep
+%setup -q
+
+
+%build
+
+for file in bin/repo-font-audit bin/compare-repo-font-audit ; do
+sed -i "s|^DATADIR\([[:space:]]*\)\?=\(.*\)$|DATADIR=%{_datadir}/%{name}|g" \
+  $file
+done
+
+%install
+rm -fr %{buildroot}
+
+# Pull macros out of macros.fonts and emulate them during install
+for dir in fontbasedir        fontconfig_masterdir \
+           fontconfig_confdir fontconfig_templatedir ; do
+  export _${dir}=$(rpm --eval $(%{__grep} -E "^%_${dir}\b" \
+    rpm/macros.fonts | %{__awk} '{ print $2 }'))
+done
+
+install -m 0755 -d %{buildroot}${_fontbasedir} \
+                   %{buildroot}${_fontconfig_masterdir} \
+                   %{buildroot}${_fontconfig_confdir} \
+                   %{buildroot}${_fontconfig_templatedir} \
+                   %{buildroot}%{spectemplatedir} \
+                   %{buildroot}%{rpmmacrodir} \
+                   %{buildroot}%{_datadir}/fontconfig/templates \
+                   %{buildroot}/%_datadir/%{name} \
+                   %{buildroot}%{_bindir}
+install -m 0644 -p spec-templates/*.spec       %{buildroot}%{spectemplatedir}
+install -m 0644 -p fontconfig-templates/*      %{buildroot}%{ftcgtemplatedir}
+install -m 0644 -p rpm/macros*                 %{buildroot}%{rpmmacrodir}
+install -m 0644 -p private/repo-font-audit.mk  %{buildroot}/%{_datadir}/%{name}
+install -m 0755 -p private/core-fonts-report \
+                   private/font-links-report \
+                   private/fonts-report \
+                   private/process-fc-query \
+                   private/test-info           %{buildroot}/%{_datadir}/%{name}
+install -m 0755 -p bin/*                       %{buildroot}%{_bindir}
+
+cat <<EOF > %{name}-%{version}.files
+%defattr(0644,root,root,0755)
+%dir ${_fontbasedir}
+%dir ${_fontconfig_masterdir}
+%dir ${_fontconfig_confdir}
+%dir ${_fontconfig_templatedir}
+EOF
+
+%clean
+rm -fr %{buildroot}
+
+
+%files filesystem -f %{name}-%{version}.files
+%defattr(0644,root,root,0755)
+%dir %{_datadir}/fontconfig
+
+%files devel
+%defattr(0644,root,root,0755)
+%doc license.txt readme.txt
+%config(noreplace) %{spectemplatedir}/*.spec
+%config(noreplace) %{rpmmacrodir}/macros*
+%dir %{ftcgtemplatedir}
+%{ftcgtemplatedir}/*conf
+%{ftcgtemplatedir}/*txt
+
+%files tools
+%defattr(0644,root,root,0755)
+%doc license.txt readme.txt
+%dir %{_datadir}/%{name}
+%{_datadir}/%{name}/repo-font-audit.mk
+%defattr(0755,root,root,0755)
+%{_datadir}/%{name}/core-fonts-report
+%{_datadir}/%{name}/font-links-report
+%{_datadir}/%{name}/fonts-report
+%{_datadir}/%{name}/process-fc-query
+%{_datadir}/%{name}/test-info
+%{_bindir}/*
+
+%changelog
+* Fri Jan 13 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.44-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
+
+* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.44-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
+
+* Sun Jun 13 2010 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.44-1
+— Cleanup release
+
+* Fri May 28 2010 Akira TAGOH <tagoh@redhat.com>
+- 1.42-2
+— Get rid of binding="same" from l10n-font-template.conf (#578015)
+
+* Sat Feb 13 2010 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.42-1
+— Update mailing list references
+
+* Tue Dec 01 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.41-1
+— Bugfix release
+
+* Sat Nov 28 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.40-1
+— Bugfix release
+
+* Mon Nov 23 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.35-1
+
+* Sun Nov 22 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.34-1
+— compare-repo-font-audit: make output more comprehensive
+
+* Sat Nov 21 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.33-1
+— repo-font-audit: add ancilliary script to compare the results of two
+  different runs
+- 1.32-1
+— repo-font-audit: add test for core fonts direct use
+— repo-font-audit: replace font naming tests by a more comprehensive one
+  (in a separate utility)
+— repo-font-audit: add fedora packager detection
+— repo-font-audit: parallelize (at the cost of more filesystem space use)
+— repo-font-audit: misc output and reliability fixes
+
+* Sun Nov 1 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.31-2
+— add yum-utils to deps
+- 1.31-1
+— Rework repo-font-audit messages based on packager feedback
+
+* Thu Oct 29 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.30-1
+— Bugfix release
+
+* Tue Oct 27 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.29-1
+— Split out tools as repo-font-audit requirements grow
+
+* Mon Oct 19 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.28-1
+— Rework repo-font-audit to also generate individual packager nagmails
+
+* Mon Sep 28 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.27-1
+— Brownpaper bag release ×2
+
+* Sun Sep 27 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.26-1
+— Brownpaper bag release
+- 1.25-1
+– Add short test summary to repo-font-audit
+
+* Sat Sep 26 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.24-1
+– improve repo-font-audit (make WWS check more accurate, support file://
+  local repositories…)
+
+* Sun Sep 13 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.23-1
+— cleanups + add merging/remapping templates
+
+* Fri Jul 24 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org>
+- 1.22-2
+— Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
+
+* Sat Jun 20 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.22-1
+– workaround rpm eating end-of-line after %%_font_pkg calls
+– add script to audit font sanity of yum repositories
+
+* Tue Jun 2 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.21-1
+— try to handle more corner naming cases in lua macro – expect some fallout
+  if your spec uses weird naming
+
+* Tue Feb 24 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org>
+- 1.20-2
+— Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
+
+* Wed Feb 18 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.20-1
+— global-ization
+
+* Mon Feb 16 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.19-3
+— remove workaround and explicit version checks
+- 1.19-2
+— workaround the fact koji is not ready yet
+- 1.19-1
+— Add a fontconfig dep to -devel so font autoprovides work (bz#485702)
+— Drop duplicated group declarations, rpm has been fixed (bz#470714)
+— Add partial templates for fonts subpackages of non-font source packages
+— Make them noarch (http://fedoraproject.org/wiki/Features/NoarchSubpackages)
+
+* Thu Feb 5 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.18-1
+✓ Panu wants autoprovides in rpm proper, drop it
+✓ Guidelines people are ok with multiple ownership of directories, make the
+  fonts macro auto-own the directory font files are put into
+
+* Sat Jan 31 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.17-1
+⁇ Tweak and complete documentation
+☤ Merge the autoprovides stuff and try to make it actually work
+
+* Tue Jan 27 2009 Richard Hughes <rhughes@redhat.com>
+- 1.16-2
+- Add fontconfig.prov and macros.fontconfig so that we can automatically
+  generate font provides for packages at build time.
+  This lets us do some cool things with PackageKit in the future.
+
+* Wed Jan 22 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.16-1
+
+* Thu Jan 15 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.15-1
+➜ lua-ize the main macro
+
+* Wed Jan 14 2009 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.14-1
+➽ Update for subpackage naming changes requested by FPC
+
+* Mon Dec 22 2008 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.13-1
+⟃ Add another directory to avoid depending on unowned stuff
+❤ use it to put the fontconfig examples in a better place
+
+* Sun Dec 21 2008 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.12-2
+⌂ Change homepage
+
+* Fri Dec 19 2008 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.12-1
+☺ Add another macro to allow building fontconfig without cycling
+
+* Wed Dec 10 2008 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.11-1
+☺ Add actual fedorahosted references
+
+* Sun Nov 23 2008 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.10-1
+☺ renamed to “fontpackages”
+
+* Fri Nov 14 2008 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.9-1
+☺ fix and complete fontconfig doc
+- 1.8-1
+☺ simplify multi spec template: codify general case
+- 1.7-1
+☺ split fontconfig template documentation is separate files
+- 1.6-1
+☺ simplify spec templates
+- 1.5-1
+☺ use ".conf" extension for fontconfig templates
+- 1.4-1
+☺ small multi spec template fix
+
+* Wed Nov 12 2008 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.3-1
+☺ remove trailing slashes in directory macros
+
+* Tue Nov 11 2008 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.2-1
+☺ add fontconfig templates
+☺ fix a few typos
+
+* Mon Nov 10 2008 Nicolas Mailhot <nim at fedoraproject dot org>
+- 1.0-1
+☺ initial release
diff --git a/private/core-fonts-report b/private/core-fonts-report
new file mode 100755 (executable)
index 0000000..2d9defd
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/sh
+# Tests if an ELF file tries to load core fonts, and reports the result
+
+if  $(nm -aDu "$3" 2> /dev/null | grep -q  '\<XLoad.*Font') ; then
+
+  [ -s "$1" -a -r "$1" ] && rpminfo=$(cat "$1") || rpminfo="||||||"
+  [ -s "$2" -a -r "$2" ] && rpmlint_score=$(cat "$2")
+
+  size=$(du -b "$3" | cut -f 1)
+  checksum=$(sha256sum "$3" | cut -d " " -f 1)
+
+  if [ -s "$4" -a -r "$4" ] ; then
+    file=$(cut -d "|" -f 1 < "$4")
+    type=$(cut -d "|" -f 2 < "$4")
+  fi
+
+  echo "$rpminfo|$rpmlint_score|$file||||||$type|$size|$checksum||||||X"
+fi
diff --git a/private/font-links-report b/private/font-links-report
new file mode 100755 (executable)
index 0000000..408b347
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+# Assembles font link info
+
+if [ -s "$3" -a -r "$3" ] ; then
+
+  [ -s "$1" -a -r "$1" ] && rpminfo=$(cat "$1") || rpminfo="||||||"
+  [ -s "$2" -a -r "$2" ] && rpmlint_score=$(cat "$2")
+
+  awk -F '|' -v prefix="$rpminfo|$rpmlint_score" '
+    {  print prefix "|" $1 "||||||Link||||||" $2  }' "$3"
+
+fi
diff --git a/private/fonts-report b/private/fonts-report
new file mode 100755 (executable)
index 0000000..155486b
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/sh
+# Consolidate font info spread over many generated files
+
+[ -s "$1" -a -r "$1" ] && rpminfo=$(cat "$1") || rpminfo="||||||"
+[ -s "$2" -a -r "$2" ] && rpmlint_score=$(cat "$2")
+
+size=$(du -b "$3" | cut -f 1)
+checksum=$(sha256sum "$3" | cut -d " " -f 1)
+
+if [ -s "$4" -a -r "$4" ] ; then
+  file=$(cut -d "|" -f 1 < "$4")
+  type=$(cut -d "|" -f 2 < "$4")
+fi
+
+fontlint=$(filter-fontlint < "$5" | wc -l)
+partial_blocks=$(filter-unicover < $6 | wc -l)
+
+if [ -s "$7" -a -r "$7" ] ; then
+  family=$(cat "$7" | cut -d "|" -f 1)
+  style=$(cat "$7" | cut -d "|" -f 2)
+  format=$(cat "$7" | cut -d "|" -f 3)
+fi
+
+partial_scripts=$(filter-langcover < "$8" | wc -l)
+
+if [ "$family" != "" -o "$style" != "" ] ; then
+  fnaming=$(fix-font-naming "$family" "$style")
+  ffamily=$(echo "$fnaming" | cut -f 1)
+  fstyle=$(echo "$fnaming" | cut -f 2)
+fi
+
+echo "$rpminfo|$rpmlint_score|$file|$family|$style|$ffamily|$fstyle|$format|\
+$type|$size|$checksum|$partial_scripts|$partial_blocks|$fontlint"
+
diff --git a/private/process-fc-query b/private/process-fc-query
new file mode 100755 (executable)
index 0000000..8779c29
--- /dev/null
@@ -0,0 +1,44 @@
+#!/bin/sh
+# Process fc query output to collect font file data
+
+# font file to examine
+font_file="$1"
+# Where to save fc-query data
+fc_file="$2"
+
+# FIXME: only extracts info about the first typeface in a TTC file for now
+parse_localized_fc_query() {
+  field="$1"
+  file="$2"
+  fieldstring=$(awk -F ':' -v field="$field" \
+                    '$1 == "\t"field { print $2 ; exit }' "$file" \
+               | sed 's="(s)="=g' | sed 's=" *"=|=g'| sed 's= *" *==g')"|"
+  default=$(echo $fieldstring | awk -F "|" '{ print $1 }')
+  if $(grep -q "^"$'\t'$field"lang:" "$file") ; then
+    langstring=$(awk -F ':' -v field="$field" \
+                '$1 == "\t"field"lang" { print $2 ; exit }' "$file" \
+                | sed 's="(s)="=g' | sed 's=" *"=|=g'| sed 's= *" *==g')"|"
+    # Try to find the English label
+    while [ "$langstring" != "" -a \
+            "$(echo $langstring | cut -d '|' -f 1)" != "en" ] ; do
+      fieldstring=$(echo "$fieldstring" | sed 's+\([^|]*\)|\(.*\)+\2+g')
+      langstring=$(echo "$langstring" | sed 's+\([^|]*\)|\(.*\)+\2+g')
+    done
+    # We could hide problems by reporting the first label regardless of its
+    # language. But this is an audit script — we do not hide problems
+    echo "$fieldstring" |  awk -F "|" '{ print $1 }'
+  else
+    echo $(echo $fieldstring | cut -d '|' -f 1)
+  fi
+}
+
+if $(FC_DEBUG=256 fc-query "$font_file" 2> /dev/null > "$fc_file") ; then
+  family=$(parse_localized_fc_query family "$fc_file")
+  style=$(parse_localized_fc_query style "$fc_file")
+  format=$(parse_localized_fc_query fontformat "$fc_file")
+else
+  touch "$fc_file"
+fi
+
+
+echo "$family|$style|$format"
diff --git a/private/repo-font-audit.mk b/private/repo-font-audit.mk
new file mode 100644 (file)
index 0000000..2a607b6
--- /dev/null
@@ -0,0 +1,79 @@
+# Directory with files to process
+SRCDIR = src
+# Work area
+TMPDIR = $(wildcard tmp)
+
+this_makefile := $(lastword $(MAKEFILE_LIST))
+datadir := $(dir $(this_makefile))
+
+SUBDIRS := $(wildcard */)
+
+ifneq ($(TMPDIR),)
+FONT_TARGET_ROOTS := $(subst .rfo.fonts.info,.rfo,$(shell find $(TMPDIR) -name "*\.rfo\.fonts\.info"))
+
+FONT_EXTS := fontlint unicover fc-query fonts
+add_font_ext = $(foreach file, $(FONT_TARGET_ROOTS),$(file).$(ext))
+FONT_TARGETS := $(foreach ext, $(FONT_EXTS), $(add_font_ext))
+
+CORE_FONT_TARGETS := $(subst .rfo.core-fonts.info,.rfo.core-fonts,$(shell find $(TMPDIR) -name "*\.rfo\.core-fonts\.info"))
+endif
+
+ifneq ($(wildcard font-links.txt),)
+LINK_TARGETS := processed-font-links.txt
+endif
+
+TARGETS := $(FONT_TARGETS) $(CORE_FONT_TARGETS) $(LINK_TARGETS)
+
+ifneq ($(TARGETS),)
+TARGETS := $(TARGETS) rpmlint.txt
+endif
+
+.PHONY: $(SUBDIRS) all rfo
+
+all : $(SUBDIRS)
+
+$(SUBDIRS) :
+       $(MAKE) -C $@ rfo -f $(this_makefile)
+
+ifneq ($(TARGETS),)
+rfo : $(TARGETS)
+else
+rfo : ; @echo "$(shell pwd): nothing to do!"
+endif
+
+$(TMPDIR)/%.rfo.fonts : rpm-info.txt \
+                        rpmlint.score \
+                        $(SRCDIR)/% \
+                        $(TMPDIR)/%.rfo.fonts.info \
+                        $(TMPDIR)/%.rfo.fontlint \
+                        $(TMPDIR)/%.rfo.unicover \
+                        $(TMPDIR)/%.rfo.fc-query.report \
+                        $(TMPDIR)/%.rfo.fc-query
+       $(datadir)/fonts-report $^ > $@
+       @echo -n "f"
+
+$(TMPDIR)/%.rfo.unicover : $(SRCDIR)/%
+       ttfcoverage $< > $@
+
+$(TMPDIR)/%.rfo.fontlint : $(SRCDIR)/%
+       LANG=C fontlint $(CURDIR)/$< > $@ 2>&1 || :
+
+$(TMPDIR)/%.rfo.fc-query $(TMPDIR)/%.rfo.fc-query.report : $(SRCDIR)/%
+       $(datadir)/process-fc-query $< $(TMPDIR)/$*.rfo.fc-query > $(TMPDIR)/$*.rfo.fc-query.report
+
+$(TMPDIR)/%.rfo.core-fonts : rpm-info.txt \
+                             rpmlint.score \
+                             $(SRCDIR)/% \
+                             $(TMPDIR)/%.rfo.core-fonts.info
+       $(datadir)/core-fonts-report $^ > $@
+       @echo -n "X"
+
+rpmlint.txt rpmlint.score :
+       rpmlint -i "*.rpm" > rpmlint.txt 2>&1 \
+          && touch rpmlint.score || echo "$$?" > rpmlint.score
+
+processed-font-links.txt : rpm-info.txt \
+                           rpmlint.score \
+                           font-links.txt
+       $(datadir)/font-links-report $^ > $@
+       @echo -n "l"
diff --git a/private/test-info b/private/test-info
new file mode 100755 (executable)
index 0000000..4ae4014
--- /dev/null
@@ -0,0 +1,556 @@
+#!/bin/sh
+# Prints textual info about the repo-font-audit tests
+# $1 test id
+# $2 "title" or "help"
+
+[ "$2" == "help" ] && echo -n "☛ "
+
+case "$1" in
+ "outside-usr-share-fonts")
+    case "$2" in
+      "title")
+        echo "Error: fonts deployed outside /usr/share/fonts"
+        ;;
+      "help")
+        cat << EOF
+Packager task
+
+The standard location for font files is under the /usr/share/fonts root
+(default fontconfig setting). Please simplify the work of font utilities
+and use it exclusively. It is always possible to symlink font files
+somewhere else on the file-system if an application requires it.
+
+If you fear exposing your font files in fontconfig will cause problems,
+please work with the fontconfig maintainers to resolve them.
+EOF
+        ;;
+    esac
+    ;;
+  "without-rpm-metadata")
+    case "$2" in
+      "title")
+        echo "Error: fonts in packages that do not declare font metadata"
+        ;;
+      "help")
+        cat << EOF
+Packager task
+
+Font-specific rpm metadata is required for automatic font installation to
+work. If you apply our font packaging templates, it will be generated at
+package creation time.
+EOF
+        ;;
+    esac
+    ;;
+  "family-mixing")
+    case "$2" in
+      "title")
+        echo "Error: packages that mix different font families"
+        ;;
+      "help")
+        cat << EOF
+Packager task
+
+Reliable font auto-installation requires shipping only one font family per
+font package.
+
+(If you've remapped some font names at the fontconfig level your package
+may appear here pending some fontconfig fixes upstream is aware of).
+EOF
+        ;;
+    esac
+    ;;
+  "duplicated-file")
+    case "$2" in
+      "title")
+        echo "Error: exact font duplication"
+        ;;
+      "help")
+        cat << EOF
+Packager task, eventual upstream task
+
+Several packages duplicate font files with the same checksum. This
+needlessly wastes resources infrastructure and user side  and makes font
+maintenance problematic.
+
+A repository should always include only one version of a font file.
+
+This test can not discriminate between packages and identity the correct
+owner of the font files. His maintainer will be blamed with others. If
+you're not him it is therefore unfriendly not to fix this error as soon as
+you can.
+
+It is always possible to reuse a font file packaged separately by adding a
+dependency on the other package providing it, and accessing the font
+through fontconfig.
+
+If an application can not use fontconfig today this is a serious bug that
+should be reported to the application upstream. Please ask it to add
+fontconfig support to their code (usually, via a higher-level library
+such as pango-cairo). However it can workarounded by the packager with
+symlinks (that will need maintenance).
+EOF
+        ;;
+    esac
+    ;;
+  "duplicated-face-ext")
+    case "$2" in
+      "title")
+        echo "Error: font faces duplicated by different packages"
+        ;;
+      "help")
+        cat << EOF
+Packager task, eventual upstream task
+
+Several packages duplicate font files with the same face name. This
+needlessly wastes resources infrastructure and user side and makes font
+maintenance problematic:
+
+1. Very often an upstream that copied some fonts will forget to keep them
+up to date, and the duplication will result in the distribution of old
+buggy data.
+
+2. Shipping the same font in different formats is also problematic:
+different font formats have different features, and are processed by
+different font libraries. It is almost impossible to create a font in
+multiple formats that will all behave the same. Users hate fonts that do
+not behave consistently everywhere.
+
+3. Most of our applications use fontconfig to access fonts, and fontconfig
+uses font names to identify files. Naming collisions make font selection
+unreliable. So even genuine forks with different features from the
+original are a problem if not renamed.
+
+A repository should always include only one version of a font face.
+
+This test can not discriminate between packages and identity the correct
+owner of the font face. His maintainer will be blamed with others. If
+you're not him it is therefore unfriendly not to fix this error as soon as
+you can.
+
+It is always possible to reuse a font file packaged separately by adding a
+dependency on the other package providing it, and accessing the font
+through fontconfig.
+
+If an application can not use fontconfig today this is a serious bug that
+should be reported to the application upstream. Please ask it to add
+fontconfig support to their code (usually, via a higher-level library
+such as pango-cairo). However it can workarounded by the packager with
+symlinks (that will need maintenance).
+
+If an application can not use a modern font format and forces the
+re-packaging in an older format of an exiting font this is an application
+bug that should be reported to the application upstream. In that case
+these is no good solution possible baring the fixing of the application.
+EOF
+        ;;
+    esac
+    ;;
+  "fc-query")
+    case "$2" in
+      "title")
+        echo "Error: fonts fc-query can not parse"
+        ;;
+      "help")
+        cat << EOF
+Upstream task
+
+fc-query could not parse some font files in the package. The files may be
+malformed and in need of fixing, or fc-query has a bug.
+
+Any font file rejected by fc-query will be useless in fontconfig and most
+applications. If it can not be fixed drop it
+
+Please relay the problem to the appropriate upstream to get it fixed.
+EOF
+        ;;
+    esac
+    ;;
+  "libmagic")
+    case "$2" in
+      "title")
+        echo "Error: fonts not identified as such by libmagic"
+        ;;
+      "help")
+        cat << EOF
+Upstream task
+
+libmagic could not identify some files with font-like extensions in the
+package. The files may be malformed and in need of fixing, or they use a
+font extension when they should not, or libmagic has a bug.
+
+Please relay the problem to the appropriate upstream to get it fixed.
+EOF
+        ;;
+    esac
+    ;;
+  "broken-symlink")
+    case "$2" in
+      "title")
+        echo "Error: broken symlinks to font files"
+        ;;
+      "help")
+        cat << EOF
+Packager and upstream task
+
+The symlinked font file has moved, been renamed, or the symlink was never
+properly set up. You need to change the symlink.
+
+Symlinking requires maintenance and is only necessary when an application
+lacks fontconfig support. If an application can not use fontconfig today
+this is a serious bug that should be reported to the application upstream.
+Please ask it to add fontconfig support to their code (usually, via a
+higher-level library such as pango-cairo).
+EOF
+        ;;
+    esac
+    ;;
+  "rpmlint")
+    case "$2" in
+      "title")
+        echo "Error: rpmlint"
+        ;;
+      "help")
+        cat << EOF
+Packager task
+
+Check rpmlint output to fix the listed packages (using the -i flag if you
+don't understand rpmlint messages).
+EOF
+        ;;
+    esac
+    ;;
+  "mixed-with-non-font-data")
+    case "$2" in
+      "title")
+        echo "Error: fonts in packages that contain non-font data"
+        ;;
+      "help")
+        cat << EOF
+Packager task
+
+Please do not mix font files with non-font data in packages. Fonts are
+usually useful outside of the package that deploys them and should be
+installable without pulling in other material.
+EOF
+        ;;
+    esac
+    ;;
+  "arch-package")
+    case "$2" in
+      "title")
+        echo "Error: fonts in arch packages"
+        ;;
+      "help")
+        cat << EOF
+Packager task
+
+Fonts are not arch-specific; please make sure they are deployed in noarch
+packages.
+EOF
+        ;;
+    esac
+    ;;
+  "bad-rpm-naming")
+    case "$2" in
+      "title")
+        echo "Warning: fonts in packages that do not respect font naming conventions"
+        ;;
+      "help")
+        cat << EOF
+Packager task
+
+Please respect font package naming conventions and provide consistent
+packages to users. Some scripts may depend on strict package naming.
+EOF
+        ;;
+    esac
+    ;;
+  "bad-naming")
+    case "$2" in
+      "title")
+        echo "Warning: bad font naming"
+        ;;
+      "help")
+        cat << EOF
+Font upstream task, with packager workarounds
+
+The font naming declared by one or more files in the package is not a
+canonical WWS¹ naming or has some other naming problem. As noted by Adobe²
+the W3C CSS font family model used in WPF/WWS is less than ideal, but it is
+a standard and applications expect it.
+
+This script attempted to apply some heuristics to fix this naming, and
+computed different values than those in the font files.
+
+That means some of those files are using non-standard, fuzzy,
+self-conflicting, confusing names. A correct naming:
+1. only includes “Width”, “Weight”, “Slant” qualifiers in its style name;
+2. does not declare more than one of each;
+3. declares them using the canonical keywords defined in the WWS paper;
+4. declares them in “Width”, “Weight”, “Slant” order;
+3. uses spaces to separate them;
+4. does not use “Width”, “Weight”, “Slant” qualifiers in its family name;
+5. does not use symbols such as & that cause problems in SGML/XML/HTML
+   contexts. 
+
+The canonical naming computed by this script was printed at test time.
+Please note that it is only correct in a formal sense: no attempt was made
+to check that the computed naming corresponds to actual font
+characteristics. It still needs human review (when the computed naming is
+way off however that usually indicates the original naming is particularly
+bad and confusing).
+
+Because the aim of this test is to help improve overall font naming it will
+not accept some user-unfriendly naming exceptions Microsoft handles in its
+WPF heuristic. Also, the naming parsing used in this test is more aggressive
+than the one Microsoft uses, so it will manage to “fix” some names WPF can
+not, at the expense of a few false positives³.
+
+The average application is not as smart as this script and will not attempt
+to “fix” font naming in any way. Therefore, even if this script computed a
+correct naming, you should not rely on applications doing the same. Please
+ask the font usptream to fix the naming directly in the font file(s).
+
+Packager workaround: patch the file (if it is available in .sfd format),
+or add a fontconfig rule to your package to hide the problem⁴.
+
+¹ http://blogs.msdn.com/text/attachment/2249036.ashx
+  http://blogs.adobe.com/typblography/typotechnica2007/Font%20names.pdf
+² http://blogs.adobe.com/typblography/atypi2006/CSS%20&%20OT%2015.pdf
+³ For example the family name may include some words that look like a
+  “Width”, “Weight”, “Slant” attribute, but that are used in a different
+  sense. This script is not a natural language parser and can not detect
+  those cases reliably
+⁴ cf the “fontpackages” remapping template; unfortunately this workaround
+  won't fix problems for non-fontconfig applications, or when
+  interoperating with other systems.
+EOF
+        ;;
+    esac
+    ;;
+  "core-fonts")
+    case "$2" in
+      "title")
+        echo "Warning: core fonts use"
+        ;;
+      "help")
+        cat << EOF
+Upstream task
+
+This package accesses fonts through the X11 Core protocol.
+
+Numerous long-standing problems with this mode of access, and a design
+that could not scale to modern font needs lead the (then XFree86) team to
+deprecate it in favour of fontconfig (née xft). Adoption was quick and by
+2003 it was clear fontconfig was the new standard¹. Nowadays fontconfig is
+widely used², including on non Linux/Unix platforms.
+
+While X11 Core access has been kept on life-support this font system is
+not actively maintained today. The font library it depends on is slowly
+shrinking, as it was created in a period of different legal and technical
+requirements², and there is no one to update the font files when a problem
+is found³. Therefore, projects are advised to migrate before the situation
+reaches a critical stage.
+
+Fontconfig has been our default font system for a long time, and accessing
+fonts by other means will cause behaviour inconsistencies and many other
+problems (since fontconfig can be used to change the behaviour of a font).
+
+If an application can not use fontconfig today this is a serious bug that
+should be reported to the application upstream. Please ask it to add
+fontconfig support to their code (usually, via a higher-level library
+such as pango-cairo).
+
+
+¹ http://xfree86.org/pipermail/forum/2003-March/000799.html
+² Screen technology changed, encoding standard (Unicode) changed, legal
+reviews became more comprehensive, etc.
+³ Leaving culling the only solution.
+EOF
+        ;;
+    esac
+    ;;
+  "font-linking")
+    case "$2" in
+      "title")
+        echo "Warning: font linking"
+        ;;
+      "help")
+        cat << EOF
+Upstream task
+
+Symlinking is a way for non-font packages to avoid duplicating font files,
+but it is also a symptom of missing or incomplete fontconfig support.
+
+Fontconfig has been our default font system for a long time, and accessing
+fonts by other means will cause behaviour inconsistencies and many other
+problems (since fontconfig can be used to change the behaviour of a font).
+
+If an application can not use fontconfig today this is a serious bug that
+should be reported to the application upstream. Please ask it to add
+fontconfig support to their code (usually, via a higher-level library
+such as pango-cairo).
+EOF
+        ;;
+    esac
+    ;;
+  "duplicated-face-int")
+    case "$2" in
+      "title")
+        echo "Warning: font faces duplicated within a package"
+        ;;
+      "help")
+        cat << EOF
+Packager or upstream task
+
+Face duplication within a package is almost certainly a bug (usually,
+mis-naming in one of the font files), except for special symbol font
+families.
+
+1. Fonts that were split because of the limitations of legacy font formats
+(PCF, Type 1…) should be converted to modern OpenType (TT, CFF or bitmap)
+containers.
+
+2. Shipping the same font in different formats is problematic: different
+font formats have different features, and are processed by different font
+libraries. It is almost impossible to create a font in multiple formats
+that will all behave the same. Users hate fonts that do not behave
+consistently everywhere.
+
+3. Most of our applications use fontconfig to access fonts, and fontconfig
+uses font names to identify files. Naming collisions make font selection
+unreliable.
+
+If an application can not use a modern font format and forces the
+re-packaging in an older format of an exiting font this is an application
+bug that should be reported to the application upstream. In that case
+these is no good solution possible baring the fixing of the application.
+EOF
+        ;;
+    esac
+    ;;
+  "fontlint")
+    case "$2" in
+      "title")
+        echo "Warning: fonts that do not pass fontlint sanity checks"
+        ;;
+      "help")
+        cat << EOF
+Font upstream task
+
+Fontforge's fontlint¹ test suite found problems in some files included in
+the package. Those problems may not be obvious and only manifest as
+strange behaviour in specific applications (making them hard to debug).
+For that reason it is recommanded to report those problems upstream and
+get them fixed, even if the font file seems to work fine most of the time.
+
+You can ask help about specific fontlint errors on:
+https://lists.sourceforge.net/lists/listinfo/fontforge-users
+
+Please relay the problem report to the font upstream.
+
+¹ http://fontforge.sourceforge.net/fontlint.html
+EOF
+        ;;
+    esac
+    ;;
+  "no-english-metadata")
+    case "$2" in
+      "title")
+        echo "Warning: fonts with localized metadata but no English variant"
+        ;;
+      "help")
+        cat << EOF
+Font upstream task
+
+Some font files in the package declare localized metadata, but do not
+include an English variant. They need to be fixed to also declare metadata
+in English, so it can be used in technical declarations such as CSS rules.
+(Sometimes font do include English metadata, but under another language
+label. There is no way for applications or for this test to guess some
+metadata is mislabeled).
+
+Please relay the problem report to the font upstream.
+EOF
+        ;;
+    esac
+    ;;
+  "partial-scripts")
+    case "$2" in
+      "title")
+        echo "Suggestion: fonts with partial script coverage"
+        ;;
+      "help")
+        cat << EOF
+Font upstream task
+
+Some font files included in the package are missing a few glyphs to be
+accepted by fontconfig as covering one or several scripts. Therefore they
+could be made useful to more people with only a little effort.
+
+Many scripts differ by only a few glyphs and it is unfortunately common
+for font authors not to notice they stopped just short of full support for
+some of them.
+
+To check a font file script coverage, run:
+  $ FC_DEBUG=256 fc-query font-file
+and look for lines like:
+  script-id¹(number) { list-of-unicode-codepoints }
+
+For example
+  “mi(2) { 1e34 1e35 }”
+means fontconfig will accept the tested file for Maori if codepoints 1e34
+and 1e35 are added.
+
+fontconfig is used by a lot of applications on many systems so ignoring
+its opinion on a font is a mistake.
+
+Please relay the incomplete coverage report to the font upstream.
+
+P.S.
+Of course fontconfig is not perfect either so it may require a glyph for a
+script when it should not. In that case, please report the problem to
+fontconfig upstream:
+https://bugs.freedesktop.org/enter_bug.cgi?product=fontconfig
+against the “orth” component.
+
+¹ http://www.loc.gov/standards/iso639-2/php/code_list.php
+² https://bugs.freedesktop.org/enter_bug.cgi?product=fontconfig
+EOF
+        ;;
+    esac
+    ;;
+  "partial-blocks")
+    case "$2" in
+      "title")
+        echo "Suggestion: fonts with partial unicode block coverage"
+        ;;
+      "help")
+        cat << EOF
+Font upstream task
+
+Some font files included in the package are missing only a few glyphs to
+fully cover an Unicode block. Therefore they could be made useful to more
+people with only a little effort.
+
+The Unicode consortium revises its tables regularly. A font may need to be
+extended to maintain full coverage of a block when a new Unicode standard
+revision is published¹.
+
+To check the unicode coverage of a font, run the ttfcoverage command. (It
+only works for modern .otf or .ttf fonts).
+
+Please relay the incomplete coverage report to the font upstream.
+
+¹ http://www.unicode.org/charts/
+EOF
+        ;;
+    esac
+    ;;
+ *)
+    echo "Unknown test."
+    ;;
+esac
+
+[ "$2" == "help" ] && echo ""
diff --git a/readme.txt b/readme.txt
new file mode 100644 (file)
index 0000000..fa6b8c5
--- /dev/null
@@ -0,0 +1,27 @@
+The fontpackages project is an effort to streamline font packaging, helping
+font packagers to produce clean, consistent and sane packages.
+
+It contains:
+— spec templates and rpm macros
+– fontconfig templates and documentation
+— sanity testing tools
+
+… and any other material we feel can help font packagers in their work. New
+templates are added whenever a new packaging pattern is identified.
+
+The fontpackages project was initiated by the Fedora Fonts Special Interest
+Group (http://fonts.fedoraproject.org/), and is the reference for Fedora font
+packaging guidelines. It is therefore a bit rpm-oriented. However great care
+was extended to keep it distribution-neutral, and contributors from
+other distributions are welcome, even if they use different packaging systems,
+and want to add non-rpm templates.
+
+It is licensed under the LGPLv3 (or later).
+
+The project home page is:
+http://fedoraproject.org/wiki/fontpackages
+
+And its content is published at:
+— http://fedorahosted.org/releases/f/o/fontpackages (release archives)
+— http://git.fedorahosted.org/git/fontpackages.git (content vcs)
+— http://cvs.fedoraproject.org/viewvc/rpms/fontpackages/ (package vcs)
diff --git a/rpm/macros.fonts b/rpm/macros.fonts
new file mode 100644 (file)
index 0000000..7ae71dc
--- /dev/null
@@ -0,0 +1,100 @@
+# RPM macros for font packages.
+#
+# © 2008-2009 Nicolas Mailhot <nim at fedoraproject dot org>
+
+## Default directories
+
+# Font installation directory root
+%_fontbasedir %{_datadir}/fonts
+
+# Actual font installation directory
+%_fontdir %{_fontbasedir}/%{?fontname:%{fontname}}%{?!fontname:%{name}}
+
+# Master fontconfig configuration directory
+# Only needed to avoid a circular directory dependency with the fontconfig
+# package — you should *not* use this
+%_fontconfig_masterdir   %{_sysconfdir}/fonts
+
+# Fontconfig directory for active configuration snippets
+%_fontconfig_confdir     %{_sysconfdir}/fonts/conf.d
+
+# Fontconfig configuration template directory
+# Templates are activated by symlinking in _fontconfig_confdir
+%_fontconfig_templatedir %{_datadir}/fontconfig/conf.avail
+
+## Magic
+
+# Utility macro that computes a canonical font (sub)package name
+#
+# Expects an (optional) subpackage name as argument
+
+%_font_pkg_name() %{lua:
+local function rpmeval(name)
+  local sname = rpm.expand(name)
+  if sname == name
+  then return ""
+  else
+    sname = string.lower("-" .. sname .. "-")
+    sname = string.gsub(sname, "[_%-]+", "-")
+    sname = string.gsub(sname, "%-font(s?)%-", "-")
+    sname = string.gsub(sname, "^%-", "")
+    sname = string.gsub(sname, "%-$", "")
+    return sname
+  end
+end
+local function meld(name1,name2)
+  local name3 = "-" .. name2 .. "-"
+  for token in string.gmatch(name1 .. "-" , "..-%-") do
+    token = string.gsub(token, "%-", "%%-")
+    name3 = string.gsub(name3, "%-" .. token, "-")
+  end
+  return string.gsub( name1 .. name3 , "%-+$", "")
+end
+local pkgname  = rpmeval("%{name}")
+local fontname = rpmeval("%{fontname}")
+local subname  = rpmeval("%1")
+print(meld(meld(pkgname,fontname),subname) .. "-fonts")
+} %{nil}
+
+
+# Macro to generate file sections and scriptlets for font (sub)packages
+#
+# Expects:
+# – an (optional) subpackage name as argument: -n <name>
+#      without -n the macro will work on the core package
+# – an (optional) fontconfig file pattern as argument: -f <pattern>
+# — a variable number of file patterns corresponding to the font files
+#   installed in _fontdir and associated to this (sub)package
+#
+# Files corresponding to the file pattern must be installed in
+# _fontconfig_templatedir and symlinked to _fontconfig_confdir
+#
+# If you want to install a configuration template disabled by default, make
+# the corresponding symlink point to /dev/null
+
+%_font_pkg(n:f:) \
+%define spn %_font_pkg_name %{-n:%{-n*}} \
+%post -n %{spn} \
+if [ -x %{_bindir}/fc-cache ]; then \
+    %{_bindir}/fc-cache %{_fontdir} || : \
+fi \
+\
+\
+%postun -n %{spn}  \
+if [ $1 -eq 0 -a -x %{_bindir}/fc-cache ] ; then \
+    %{_bindir}/fc-cache %{_fontdir} || : \
+fi\
+\
+\
+%files -n %{spn} \
+%defattr(0644,root,root,0755) \
+\
+%dir %{_fontdir} \
+%{lua: \
+for arg=1,rpm.expand("%#") do \
+  print(rpm.expand("%{_fontdir}/%" .. arg) .. "\\n") \
+end} \
+%{-f:%{_fontconfig_templatedir}/%{-f*}} \
+%{-f:%config(noreplace) %{_fontconfig_confdir}/%{-f*} \
+} %{nil}
+
diff --git a/spec-templates/spectemplate-fonts-multi.spec b/spec-templates/spectemplate-fonts-multi.spec
new file mode 100644 (file)
index 0000000..bf43333
--- /dev/null
@@ -0,0 +1,131 @@
+%global fontname <FONTNAME>
+%global fontconf <①>-%{fontname}
+
+#global archivename %{name}-%{version} ②
+
+%global common_desc \
+<FONT COLLECTION DESCRIPTION: ③>
+
+
+Name:           %{fontname}-fonts
+Version:        <④>
+Release:        1%{?dist}
+Summary:        
+
+Group:          User Interface/X
+License:        
+URL:            
+Source0:        
+Source1:        %{name}-fontconfig.conf
+
+BuildArch:      noarch
+BuildRequires:  fontpackages-devel
+
+%description
+%common_desc
+
+
+%package common
+Summary:        Common files of <NAME>
+Requires:       fontpackages-filesystem
+
+%description common
+%common_desc
+
+This package consists of files used by other %{name} packages.
+
+# Repeat for every font family ➅
+%package -n %{fontname}-<FAMILY>-fonts
+Summary:        
+Requires:       %{name}-common = %{version}-%{release}
+
+%description -n %{fontname}-<FAMILY>-fonts
+%common_desc
+
+<FAMILY DESCRIPTION>
+
+%_font_pkg -n <FAMILY> -f %{fontconf}-<FAMILY>.conf <NAME>*.ttf
+
+
+%prep
+%setup -q
+
+
+%build
+
+
+%install
+rm -fr %{buildroot}
+
+install -m 0755 -d %{buildroot}%{_fontdir}
+install -m 0644 -p *.ttf %{buildroot}%{_fontdir}
+
+install -m 0755 -d %{buildroot}%{_fontconfig_templatedir} \
+                   %{buildroot}%{_fontconfig_confdir}
+
+# Repeat for every font family
+install -m 0644 -p %{SOURCEX} \
+        %{buildroot}%{_fontconfig_templatedir}/%{fontconf}-<FAMILYX>.conf
+
+for fconf in %{fontconf}-<FAMILYX>.conf \
+             %{fontconf}-<FAMILYY>.conf \
+             %{fontconf}-<FAMILYZ>.conf ; do
+  ln -s %{_fontconfig_templatedir}/$fconf \
+        %{buildroot}%{_fontconfig_confdir}/$fconf
+done
+
+
+%clean
+rm -fr %{buildroot}
+
+
+%files common
+%defattr(0644,root,root,0755)
+%doc 
+
+
+%changelog
+
+
+# Documentation
+# (remove it from your final spec file, with the other comments)
+#
+#
+# This template can be used with complex multi-font releases
+# (several font families ⑤ in one upstream archive):
+# — if you intend to package a single font family, use
+#   spectemplate-fonts-simple.spec
+# – if upstream releases separate fonts in separate archives, do not try to
+#   stuff them in a single srpm, just package them separately.
+#
+# <FOO> placeholders must be replaced by something appropriate for your font.
+#
+#
+# ①
+# Two-digit fontconfig priority number, see:
+# /usr/share/fontconfig/templates/fontconfig-priorities.txt
+#
+# ②
+# Optional
+#
+# ③
+# This will be reused in every sub-package description.
+# Please do not forget to complete it with subpackage-specific information.
+#
+# ④
+# Do not trust font metadata versionning unless you've checked upstream does
+# update versions on file changes. When in doubt use the timestamp of the most
+# recent file as version. “1.0” versions especially are suspicious.
+#
+# ⑤
+# — A font family corresponds to one entry in GUI font lists. For example,
+#   DejaVu Sans, DejaVu Serif and DejaVu Sans Mono are three different font
+#   families.
+# — A font family is subdivided in faces or styles. DejaVu Sans Normal, DejaVu
+#   Sans Bold, DejaVu Sans Condensed Italic are three faces of the DejaVu Sans
+#   font family.
+# — A font-metadata aware tool such as gnome-font-viewer or fontforge can be
+#   used to check the font family name and the font face/style declared by a
+#   font file.
+# — For use in spec files, convert names to lowerscript and replace spaces
+#   with “-”
diff --git a/spec-templates/spectemplate-fonts-partial-multi.spec b/spec-templates/spectemplate-fonts-partial-multi.spec
new file mode 100644 (file)
index 0000000..f21b103
--- /dev/null
@@ -0,0 +1,111 @@
+%global fontconf <①>-%{name}
+
+# …
+
+%global common_font_desc \
+<FONT COLLECTION DESCRIPTION: ②>
+
+Source1:        %{name}-<FAMILY>-fontconfig.conf
+# …
+
+BuildRequires:  fontpackages-devel
+
+%description
+%common_font_desc
+
+
+%package fonts-common
+Summary:        Common files of <NAME>
+Group:          User Interface/X
+BuildArch:      noarch
+Requires:       fontpackages-filesystem
+
+%description fonts-common
+%common_font_desc
+
+This package consists of files used by other %{name} font packages.
+
+
+# Repeat for every font family ③
+%package <FAMILY>-fonts
+Summary:        
+Group:          User Interface/X
+BuildArch:      noarch
+Requires:       %{name}-fonts-common = %{version}-%{release}
+
+%description -n %{fontname}-<FAMILY>-fonts
+%common_font_desc
+
+<FAMILY DESCRIPTION>
+
+%_font_pkg -n <FAMILY> -f %{fontconf}-<FAMILY>.conf <NAME>*.ttf
+
+%doc <FONT DOCUMENTATION>
+
+# …
+
+%install
+rm -fr %{buildroot}
+
+# …
+
+install -m 0755 -d %{buildroot}%{_fontdir}
+install -m 0644 -p *.ttf %{buildroot}%{_fontdir}
+
+install -m 0755 -d %{buildroot}%{_fontconfig_templatedir} \
+                   %{buildroot}%{_fontconfig_confdir}
+
+# Repeat for every font family ③
+install -m 0644 -p %{SOURCEX} \
+        %{buildroot}%{_fontconfig_templatedir}/%{fontconf}-<FAMILYX>.conf
+
+for fconf in %{fontconf}-<FAMILYX>.conf \
+             %{fontconf}-<FAMILYY>.conf \
+             %{fontconf}-<FAMILYZ>.conf ; do
+  ln -s %{_fontconfig_templatedir}/$fconf \
+        %{buildroot}%{_fontconfig_confdir}/$fconf
+done
+
+# …
+
+%files common
+%defattr(0644,root,root,0755)
+%doc <FONT DOCUMENTATION>
+
+# …
+
+# Documentation
+# (remove it from your final spec file, with the other comments)
+#
+#
+# This is a partial template. It shows how one may create several font
+# subpackages in a non-font package. Since the non-fonts part of those
+# packages may vary a lot only spec extracts are documented there. Also:
+# — packaging fonts in separate dedicated packages is usually lower
+#   maintenance than using this kind of subpackaging trick.
+# — if your srpm contains only one font familiy ③, look at
+#   spectemplate-fonts-partial-simple.spec
+#
+# <FOO> placeholders must be replaced by something appropriate for your font.
+#
+#
+# ①
+# Two-digit fontconfig priority number, see:
+# /usr/share/fontconfig/templates/fontconfig-priorities.txt
+#
+# ②
+# This will be reused in every font package description.
+# Please do not forget to complete it with subpackage-specific information.
+#
+# ③
+# A font family corresponds to one entry in GUI font lists. For example,
+#   DejaVu Sans, DejaVu Serif and DejaVu Sans Mono are three different font
+#   families.
+# — A font family is subdivided in faces or styles. DejaVu Sans Normal, DejaVu
+#   Sans Bold, DejaVu Sans Condensed Italic are three faces of the DejaVu Sans
+#   font family.
+# — A font-metadata aware tool such as gnome-font-viewer or fontforge can be
+#   used to check the font family name and the font face/style declared by a
+#   font file.
+# — For use in spec files, convert names to lowerscript and replace spaces
+#   with “-”
diff --git a/spec-templates/spectemplate-fonts-partial-simple.spec b/spec-templates/spectemplate-fonts-partial-simple.spec
new file mode 100644 (file)
index 0000000..6081199
--- /dev/null
@@ -0,0 +1,77 @@
+%global fontconf <①>-%{name}-<FAMILY>.conf
+
+# …
+
+Source1:        %{name}-<FAMILY>-fontconfig.conf
+# …
+
+BuildRequires:  fontpackages-devel
+
+# …
+
+%package <FAMILY>-fonts
+Summary:        
+Group:          User Interface/X
+BuildArch:      noarch
+Requires:       fontpackages-filesystem
+
+%description <FAMILY>-fonts
+
+<FAMILY DESCRIPTION>
+
+%_font_pkg -n <FAMILY> -f %{fontconf} <NAME>*.ttf
+
+%doc <FONT DOCUMENTATION>
+
+# …
+
+%install
+rm -fr %{buildroot}
+
+# …
+
+install -m 0755 -d %{buildroot}%{_fontdir}
+install -m 0644 -p *.ttf %{buildroot}%{_fontdir}
+
+install -m 0755 -d %{buildroot}%{_fontconfig_templatedir} \
+                   %{buildroot}%{_fontconfig_confdir}
+
+install -m 0644 -p %{SOURCE1} \
+        %{buildroot}%{_fontconfig_templatedir}/%{fontconf}
+ln -s %{_fontconfig_templatedir}/%{fontconf} \
+      %{buildroot}%{_fontconfig_confdir}/%{fontconf}
+
+# …
+
+
+# Documentation
+# (remove it from your final spec file, with the other comments)
+#
+#
+# This is a partial template. It shows how one may create a single font
+# subpackage in a non-font package. Since the non-fonts part of those
+# packages may vary a lot only spec extracts are documented there. Also:
+# — packaging fonts in separate dedicated packages is usually lower
+#   maintenance than using this kind of subpackaging trick.
+# — if your srpm contains more than one font familiy ②, look at
+#   spectemplate-fonts-partial-multi.spec
+#
+
+#
+# ①
+# Two-digit fontconfig priority number, see:
+# /usr/share/fontconfig/templates/fontconfig-priorities.txt
+#
+#
+# ②
+# — A font family corresponds to one entry in GUI font lists. For example,
+#   DejaVu Sans, DejaVu Serif and DejaVu Sans Mono are three different font
+#   families.
+# — A font family is subdivided in faces or styles. DejaVu Sans Normal, DejaVu
+#   Sans Bold, DejaVu Sans Condensed Italic are three faces of the DejaVu Sans
+#   font family.
+# — A font-metadata aware tool such as gnome-font-viewer or fontforge can be
+#   used to check the font family name and the font face/style declared by a
+#   font file.
+# — For use in spec files, convert names to lowerscript and replace spaces
+#   with “-”
diff --git a/spec-templates/spectemplate-fonts-simple.spec b/spec-templates/spectemplate-fonts-simple.spec
new file mode 100644 (file)
index 0000000..b74a100
--- /dev/null
@@ -0,0 +1,95 @@
+%global fontname <FONTNAME>
+%global fontconf <①>-%{fontname}.conf
+
+#global archivename %{name}-%{version} ②
+
+Name:           %{fontname}-fonts
+Version:        <③>
+Release:        1%{?dist}
+Summary:        
+
+Group:          User Interface/X
+License:        
+URL:            
+Source0:        
+Source1:        %{name}-fontconfig.conf
+
+BuildArch:      noarch
+BuildRequires:  fontpackages-devel
+Requires:       fontpackages-filesystem
+
+%description
+
+
+%prep
+%setup -q
+
+
+%build
+
+
+%install
+rm -fr %{buildroot}
+
+install -m 0755 -d %{buildroot}%{_fontdir}
+install -m 0644 -p *.ttf %{buildroot}%{_fontdir}
+
+install -m 0755 -d %{buildroot}%{_fontconfig_templatedir} \
+                   %{buildroot}%{_fontconfig_confdir}
+
+install -m 0644 -p %{SOURCE1} \
+        %{buildroot}%{_fontconfig_templatedir}/%{fontconf}
+ln -s %{_fontconfig_templatedir}/%{fontconf} \
+      %{buildroot}%{_fontconfig_confdir}/%{fontconf}
+
+
+%clean
+rm -fr %{buildroot}
+
+
+%_font_pkg -f %{fontconf} *.ttf
+
+%doc
+
+
+%changelog
+
+
+# Documentation
+# (remove it from your final spec file, with the other comments)
+#
+#
+# This template can be used with simple font releases
+# (one font family ④ in one upstream archive):
+# — if you're unlucky enough upstream released several font families in a
+#   single archive, use spectemplate-fonts-multi.spec
+# – if upstream releases separate fonts in separate archives, do not try to
+#   stuff them in a single srpm, just package them separately.
+#
+# <FOO> placeholders must be replaced by something appropriate for your font.
+#
+#
+# ①
+# Two-digit fontconfig priority number, see:
+# /usr/share/fontconfig/templates/fontconfig-priorities.txt
+#
+# ②
+# Optional
+#
+# ③
+# Do not trust font metadata versionning unless you've checked upstream does
+# update versions on file changes. When in doubt use the timestamp of the most
+# recent file as version. “1.0” versions especially are suspicious.
+#
+# ④
+# — A font family corresponds to one entry in GUI font lists. For example,
+#   DejaVu Sans, DejaVu Serif and DejaVu Sans Mono are three different font
+#   families.
+# — A font family is subdivided in faces or styles. DejaVu Sans Normal, DejaVu
+#   Sans Bold, DejaVu Sans Condensed Italic are three faces of the DejaVu Sans
+#   font family.
+# — A font-metadata aware tool such as gnome-font-viewer or fontforge can be
+#   used to check the font family name and the font face/style declared by a
+#   font file.
+# — For use in spec files, convert names to lowerscript and replace spaces
+#   with “-”