Update to fonttosfnt 1.2.0.

Includes work done by chrisz@ to fix issues for recent pango versions.
tested with st and gvim and OK chrisz@
This commit is contained in:
matthieu 2020-10-23 11:17:04 +00:00
parent eec02f95fe
commit f3f39cb65b
13 changed files with 469 additions and 190 deletions

View File

@ -1,3 +1,135 @@
commit 91af80a0aa18c969cd90668eed80bcbfc1e40661
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date: Wed Oct 21 16:36:30 2020 +1000
Bump to 1.2.0
commit ca9ad454496bebbc37125959d049cf2173c07c2a
Author: Christopher Zimmermann <madroach@gmerlin.de>
Date: Sun Aug 16 21:56:15 2020 +0200
use PIXEL_SIZE to calculate lineGap
commit 0447b81053d4ccaa1e1b0087bf6076abae431cae
Author: Christopher Zimmermann <madroach@gmerlin.de>
Date: Fri Jul 31 00:07:26 2020 +0200
fix sign of sTypoDescender
commit 747c58aa17b9adc016aed0caab049417a20f0b22
Author: Christopher Zimmermann <madroach@gmerlin.de>
Date: Thu Jul 30 22:46:50 2020 +0200
calculate capHeight and xHeight as recommended
commit 64e7f386baf69fa6857047fc8ad9b4cd9a8185f1
Author: Christopher Zimmermann <madroach@gmerlin.de>
Date: Thu Jul 30 21:34:59 2020 +0200
move metrics calculation to write.c
commit 19412d9ac3fb7f00346273cfe914601c844f5872
Author: Christopher Zimmermann <madroach@gmerlin.de>
Date: Sat Jul 18 08:39:01 2020 +0200
Add warnings when wrapping multiple fonts and on PCF fonts
commit 1fa97fdc6dc900728be8523be89096b4cb117d4d
Author: Christopher Zimmermann <madroach@gmerlin.de>
Date: Sun Jul 12 15:36:18 2020 +0200
provide version 5 OS/2 table
this was an attempt to fix linespacing, which did not help, but
would still keep it around to avoid double efforts.
commit facf71184163d50adf0b8fccffcaffa18b7bd277
Author: Christopher Zimmermann <madroach@gmerlin.de>
Date: Sun Jul 12 15:12:59 2020 +0200
use design metrics in eblc instead of calculated metrics
This will probably not work for a font providing multiple strikes.
But .bdf fonts don't provide multiple strikes (or do they?!?)
I don't know about .pcf fonts, but I would recommend against running fonttosfnt
on .pcf fonts because bdf2pcf seems to loose some attributes during conversion.
commit 9fb05de7d6c57d045b4a88516f3c28cf3cf98722
Author: Christopher Zimmermann <madroach@gmerlin.de>
Date: Tue Jul 7 21:02:56 2020 +0200
use more properties according to XLFD
commit 58cbf737557f34744b950668e3354ec2f2dae766
Author: Christopher Zimmermann <madroach@gmerlin.de>
Date: Mon Jul 6 22:50:23 2020 +0200
use standard C rounding functions
commit f8fa7919397659fb0ac5dade75152343d57f20ce
Author: Christopher Zimmermann <madroach@gmerlin.de>
Date: Tue Jun 16 18:43:12 2020 +0200
correctly set OS2 fsSelection for italic and bold fonts
commit 1df352c9e862686692ac053b838d76a36d721805
Author: Christopher Zimmermann <madroach@gmerlin.de>
Date: Mon Jun 15 14:08:49 2020 +0200
truncate foundry if there is no known abbreviation.
Honestly I have no idea why the foundry needs to fit in four bytes.
But anyway truncation might indeed be better then "UNKN" ?
Anyone more knowledgeable than me out there?
commit 8532812f1eddfadc0bcfad220b283bf5990bba10
Author: Christopher Zimmermann <madroach@gmerlin.de>
Date: Sun May 31 08:02:24 2020 +0200
use zero lineGap, sTypoDescender should be negative
According to
https://simoncozens.github.io/fonts-and-layout/opentype.html#vertical-metrics-hhea-and-os2
sTypoDescender should be negative and lineGap should be zero.
commit de8068f9c4251fb6cb9407c07bf245e1937270bc
Author: Christopher Zimmermann <madroach@gmerlin.de>
Date: Sun May 31 07:58:10 2020 +0200
don't add arbitrary number to the glypth metrics
This caused pango to calculate wrong, too large font extents and in
consequence gvim used too large character cells.
commit 7096c58f3fe3b6c79508cb16daac5c5bb2f042e7
Author: Peng Wu <pwu@redhat.com>
Date: Thu Jun 11 14:09:35 2020 +0800
Guess Regular style for Medium Weight
X Logical Font Description recognize "Medium" as "Regular".
Update the faceWeight function to change style from "Medium" to "Regular".
commit 81a61c049e6de80120531f0770b22e7637c9acb9
Author: rnhmjoj <rnhmjoj@inventati.org>
Date: Fri Feb 7 17:47:52 2020 +0100
Fix uninitialised memory write
If macTime() fails write zeros instead of unitialized memory to
the date fields.
commit 51e8117654fb092ae5412d7aa184bfc6b498c954
Author: rnhmjoj <rnhmjoj@inventati.org>
Date: Fri Feb 7 17:46:54 2020 +0100
Fix incorrect error handling in macTime()
mktime() and time() return (time_t -1) to signal an error.
Checking for negative values will incorrectly assume an error
happened for any calendar date before the unix epoch.
commit 1d757ff6fa30079790fc44b141f6d0e4d5411f13 commit 1d757ff6fa30079790fc44b141f6d0e4d5411f13
Author: Peter Hutterer <peter.hutterer@who-t.net> Author: Peter Hutterer <peter.hutterer@who-t.net>
Date: Mon Jan 6 12:55:31 2020 +1000 Date: Mon Jan 6 12:55:31 2020 +1000

View File

@ -306,6 +306,7 @@ pdfdir = @pdfdir@
prefix = @prefix@ prefix = @prefix@
program_transform_name = @program_transform_name@ program_transform_name = @program_transform_name@
psdir = @psdir@ psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@ sbindir = @sbindir@
sharedstatedir = @sharedstatedir@ sharedstatedir = @sharedstatedir@
srcdir = @srcdir@ srcdir = @srcdir@

View File

@ -19,9 +19,9 @@ You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely. If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically 'autoreconf'.])]) To do so, use the procedure documented by the package, typically 'autoreconf'.])])
dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
dnl serial 11 (pkg-config-0.29.1) # serial 12 (pkg-config-0.29.2)
dnl
dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>. dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com> dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
dnl dnl
@ -62,7 +62,7 @@ dnl
dnl See the "Since" comment for each macro you use to see what version dnl See the "Since" comment for each macro you use to see what version
dnl of the macros you require. dnl of the macros you require.
m4_defun([PKG_PREREQ], m4_defun([PKG_PREREQ],
[m4_define([PKG_MACROS_VERSION], [0.29.1]) [m4_define([PKG_MACROS_VERSION], [0.29.2])
m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
[m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
])dnl PKG_PREREQ ])dnl PKG_PREREQ
@ -163,7 +163,7 @@ AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
pkg_failed=no pkg_failed=no
AC_MSG_CHECKING([for $1]) AC_MSG_CHECKING([for $2])
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
_PKG_CONFIG([$1][_LIBS], [libs], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2])

View File

@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1999-2018 Free Software Foundation, Inc. # Copyright (C) 1999-2020 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>. # Written by Tom Tromey <tromey@cygnus.com>.
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
@ -53,7 +53,7 @@ func_file_conv ()
MINGW*) MINGW*)
file_conv=mingw file_conv=mingw
;; ;;
CYGWIN*) CYGWIN* | MSYS*)
file_conv=cygwin file_conv=cygwin
;; ;;
*) *)
@ -67,7 +67,7 @@ func_file_conv ()
mingw/*) mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;; ;;
cygwin/*) cygwin/* | msys/*)
file=`cygpath -m "$file" || echo "$file"` file=`cygpath -m "$file" || echo "$file"`
;; ;;
wine/*) wine/*)

View File

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for fonttosfnt 1.1.0. # Generated by GNU Autoconf 2.69 for fonttosfnt 1.2.0.
# #
# Report bugs to <https://gitlab.freedesktop.org/xorg/app/fonttosfnt/issues>. # Report bugs to <https://gitlab.freedesktop.org/xorg/app/fonttosfnt/issues>.
# #
@ -581,8 +581,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='fonttosfnt' PACKAGE_NAME='fonttosfnt'
PACKAGE_TARNAME='fonttosfnt' PACKAGE_TARNAME='fonttosfnt'
PACKAGE_VERSION='1.1.0' PACKAGE_VERSION='1.2.0'
PACKAGE_STRING='fonttosfnt 1.1.0' PACKAGE_STRING='fonttosfnt 1.2.0'
PACKAGE_BUGREPORT='https://gitlab.freedesktop.org/xorg/app/fonttosfnt/issues' PACKAGE_BUGREPORT='https://gitlab.freedesktop.org/xorg/app/fonttosfnt/issues'
PACKAGE_URL='' PACKAGE_URL=''
@ -731,6 +731,7 @@ infodir
docdir docdir
oldincludedir oldincludedir
includedir includedir
runstatedir
localstatedir localstatedir
sharedstatedir sharedstatedir
sysconfdir sysconfdir
@ -811,6 +812,7 @@ datadir='${datarootdir}'
sysconfdir='${prefix}/etc' sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com' sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var' localstatedir='${prefix}/var'
runstatedir='${localstatedir}/run'
includedir='${prefix}/include' includedir='${prefix}/include'
oldincludedir='/usr/include' oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@ -1063,6 +1065,15 @@ do
| -silent | --silent | --silen | --sile | --sil) | -silent | --silent | --silen | --sile | --sil)
silent=yes ;; silent=yes ;;
-runstatedir | --runstatedir | --runstatedi | --runstated \
| --runstate | --runstat | --runsta | --runst | --runs \
| --run | --ru | --r)
ac_prev=runstatedir ;;
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
| --run=* | --ru=* | --r=*)
runstatedir=$ac_optarg ;;
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;; ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@ -1200,7 +1211,7 @@ fi
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \ datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
libdir localedir mandir libdir localedir mandir runstatedir
do do
eval ac_val=\$$ac_var eval ac_val=\$$ac_var
# Remove trailing slashes. # Remove trailing slashes.
@ -1313,7 +1324,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures fonttosfnt 1.1.0 to adapt to many kinds of systems. \`configure' configures fonttosfnt 1.2.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1353,6 +1364,7 @@ Fine tuning of the installation directories:
--sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var] --localstatedir=DIR modifiable single-machine data [PREFIX/var]
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib] --libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include] --includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include] --oldincludedir=DIR C header files for non-gcc [/usr/include]
@ -1383,7 +1395,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of fonttosfnt 1.1.0:";; short | recursive ) echo "Configuration of fonttosfnt 1.2.0:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@ -1492,7 +1504,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
fonttosfnt configure 1.1.0 fonttosfnt configure 1.2.0
generated by GNU Autoconf 2.69 generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc. Copyright (C) 2012 Free Software Foundation, Inc.
@ -1816,7 +1828,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by fonttosfnt $as_me 1.1.0, which was It was created by fonttosfnt $as_me 1.2.0, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@ $ $0 $@
@ -2645,7 +2657,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE='fonttosfnt' PACKAGE='fonttosfnt'
VERSION='1.1.0' VERSION='1.2.0'
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
@ -10513,8 +10525,8 @@ fi
# Checks for pkg-config packages # Checks for pkg-config packages
pkg_failed=no pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for FONTTOSFNT" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xproto freetype2 fontenc" >&5
$as_echo_n "checking for FONTTOSFNT... " >&6; } $as_echo_n "checking for xproto freetype2 fontenc... " >&6; }
if test -n "$FONTTOSFNT_CFLAGS"; then if test -n "$FONTTOSFNT_CFLAGS"; then
pkg_cv_FONTTOSFNT_CFLAGS="$FONTTOSFNT_CFLAGS" pkg_cv_FONTTOSFNT_CFLAGS="$FONTTOSFNT_CFLAGS"
@ -11144,7 +11156,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by fonttosfnt $as_me 1.1.0, which was This file was extended by fonttosfnt $as_me 1.2.0, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@ -11210,7 +11222,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\ ac_cs_version="\\
fonttosfnt config.status 1.1.0 fonttosfnt config.status 1.2.0
configured by $0, generated by GNU Autoconf 2.69, configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"

View File

@ -23,7 +23,7 @@ dnl Process this file with autoconf to create configure.
# Initialize Autoconf # Initialize Autoconf
AC_PREREQ([2.60]) AC_PREREQ([2.60])
AC_INIT(fonttosfnt,[1.1.0], [https://gitlab.freedesktop.org/xorg/app/fonttosfnt/issues],fonttosfnt) AC_INIT(fonttosfnt,[1.2.0], [https://gitlab.freedesktop.org/xorg/app/fonttosfnt/issues],fonttosfnt)
AC_CONFIG_SRCDIR([Makefile.am]) AC_CONFIG_SRCDIR([Makefile.am])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])

View File

@ -106,6 +106,12 @@ main(int argc, char **argv)
font = makeFont(); font = makeFont();
if(argc - i > 1)
fprintf(stderr,
"You are requesting to put more than one font into a single OpenType font.\n"
"This is not recommended. The global font metrics will not match every font face.\n"
"The creation of an OpenType font collection is recommended.\n");
if(i == argc) { if(i == argc) {
rc = readFile(NULL, font); rc = readFile(NULL, font);
if(rc != 0) if(rc != 0)

View File

@ -29,6 +29,7 @@ THE SOFTWARE.
#endif #endif
#include <stdarg.h> #include <stdarg.h>
#include <math.h>
#include <ft2build.h> #include <ft2build.h>
#include FT_FREETYPE_H #include FT_FREETYPE_H
@ -69,17 +70,15 @@ extern int reencode_flag;
#define UNITS_PER_EM 2048 #define UNITS_PER_EM 2048
#define EPSILON 0.000000001 #define UNDEF 0x80000000
#define FLOOR(x) ((x) < 0.0 ? -(int)(-(x)) : (x))
#define CEIL(x) FLOOR((x) + 1.0 - EPSILON)
/* Convert a fixed-point value into FUnits */ /* Convert a fixed-point value into FUnits */
#define FONT_UNITS(x) \ #define FONT_UNITS(x) \
FLOOR(((double)(x)) / TWO_SIXTEENTH * UNITS_PER_EM + 0.5) round(((double)(x)) / TWO_SIXTEENTH * UNITS_PER_EM)
#define FONT_UNITS_FLOOR(x) \ #define FONT_UNITS_FLOOR(x) \
FLOOR(((double)(x)) / TWO_SIXTEENTH * UNITS_PER_EM) floor(((double)(x)) / TWO_SIXTEENTH * UNITS_PER_EM)
#define FONT_UNITS_CEIL(x) \ #define FONT_UNITS_CEIL(x) \
CEIL(((double)(x)) / TWO_SIXTEENTH * UNITS_PER_EM) ceil(((double)(x)) / TWO_SIXTEENTH * UNITS_PER_EM)
typedef struct _FontNameEntry { typedef struct _FontNameEntry {
int nid; /* name id */ int nid; /* name id */
@ -87,6 +86,23 @@ typedef struct _FontNameEntry {
char *value; char *value;
} FontNameEntryRec, *FontNameEntryPtr; } FontNameEntryRec, *FontNameEntryPtr;
typedef struct _Metrics {
int height;
int size;
int maxX;
int minX;
int maxY;
int minY;
int xHeight;
int capHeight;
int maxAwidth;
int awidth;
int ascent;
int descent;
int underlinePosition;
int underlineThickness;
} MetricsRec, *MetricsPtr;
typedef struct _Font { typedef struct _Font {
int numNames; int numNames;
struct _FontNameEntry *names; struct _FontNameEntry *names;
@ -94,8 +110,8 @@ typedef struct _Font {
int weight; /* as in the OS/2 table */ int weight; /* as in the OS/2 table */
int width; /* as in the OS/2 table */ int width; /* as in the OS/2 table */
int italicAngle; /* degrees c-clockwise from the vertical */ int italicAngle; /* degrees c-clockwise from the vertical */
int underlinePosition; MetricsRec pxMetrics;
int underlineThickness; MetricsRec metrics;
unsigned foundry; unsigned foundry;
struct _Strike *strikes; struct _Strike *strikes;
} FontRec, *FontPtr; } FontRec, *FontPtr;
@ -152,9 +168,9 @@ CmapPtr makeCmap(FontPtr);
int findIndex(CmapPtr, int); int findIndex(CmapPtr, int);
int findCode(CmapPtr, int); int findCode(CmapPtr, int);
BitmapPtr strikeBitmapIndex(StrikePtr, CmapPtr, int); BitmapPtr strikeBitmapIndex(StrikePtr, CmapPtr, int);
void strikeMetrics(StrikePtr, int*, int*, int*, int*, int*); int strikeMaxWidth(StrikePtr);
int glyphMetrics(FontPtr, int, int*, int*, int*, int*, int*); int glyphMetrics(FontPtr, int, int*, int*, int*, int*, int*);
void fontMetrics(FontPtr, int*, int*, int*, int*, int*); void fontMetrics(FontPtr);
int maxIndex(CmapPtr); int maxIndex(CmapPtr);
int readFile(char *filename, FontPtr); int readFile(char *filename, FontPtr);
@ -174,6 +190,7 @@ int macTime(int *, unsigned *);
unsigned faceFoundry(FT_Face); unsigned faceFoundry(FT_Face);
char *faceEncoding(FT_Face); char *faceEncoding(FT_Face);
int faceFlags(FT_Face); int faceFlags(FT_Face);
int faceIntProp(FT_Face, const char *);
int faceWeight(FT_Face); int faceWeight(FT_Face);
int faceWidth(FT_Face); int faceWidth(FT_Face);
int faceItalicAngle(FT_Face); int faceItalicAngle(FT_Face);

View File

@ -222,6 +222,7 @@ pdfdir = @pdfdir@
prefix = @prefix@ prefix = @prefix@
program_transform_name = @program_transform_name@ program_transform_name = @program_transform_name@
psdir = @psdir@ psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@ sbindir = @sbindir@
sharedstatedir = @sharedstatedir@ sharedstatedir = @sharedstatedir@
srcdir = @srcdir@ srcdir = @srcdir@

View File

@ -29,6 +29,7 @@ THE SOFTWARE.
#include FT_FREETYPE_H #include FT_FREETYPE_H
#include FT_MODULE_H #include FT_MODULE_H
#include FT_BDF_H #include FT_BDF_H
#include FT_FONT_FORMATS_H
#include "X11/Xos.h" #include "X11/Xos.h"
#include "fonttosfnt.h" #include "fonttosfnt.h"
#include "X11/fonts/fontenc.h" #include "X11/fonts/fontenc.h"
@ -102,7 +103,7 @@ readFile(char *filename, FontPtr font)
BitmapPtr bitmap; BitmapPtr bitmap;
int symbol = 0; int symbol = 0;
int force_unicode = 1; int force_unicode = 1;
char *encoding_name = NULL; const char *encoding_name, *file_format;
FontMapPtr mapping = NULL; FontMapPtr mapping = NULL;
FontMapReversePtr reverse = NULL; FontMapReversePtr reverse = NULL;
@ -133,6 +134,15 @@ readFile(char *filename, FontPtr font)
return -1; return -1;
} }
file_format = FT_Get_Font_Format(face);
if(strcmp(file_format, "BDF") != 0)
fprintf(stderr,
"font file %s is of format %s.\n"
"It's recommended to convert directly from a BDF font.\n"
"Some font properties may get lost when converting via a PCF font.\n",
filename ? filename : "<stdin>",
file_format);
/* FreeType will insist on encodings which are simple subsets of unicode /* FreeType will insist on encodings which are simple subsets of unicode
* to be read as unicode regardless of what we call them. */ * to be read as unicode regardless of what we call them. */
for(j = 0; j < face->num_charmaps; ++j) { for(j = 0; j < face->num_charmaps; ++j) {
@ -258,30 +268,6 @@ readFile(char *filename, FontPtr font)
i++; i++;
#endif #endif
font->numNames = i; font->numNames = i;
font->flags = faceFlags(face) | (symbol ? FACE_SYMBOL : 0);
font->weight = faceWeight(face);
font->width = faceWidth(face);
font->foundry = faceFoundry(face);
font->italicAngle = faceItalicAngle(face);
rc = FT_Get_BDF_Property(face, "UNDERLINE_POSITION", &prop);
if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
font->underlinePosition =
(double)prop.u.integer / face->available_sizes[0].height *
TWO_SIXTEENTH;
else
font->underlinePosition =
- 1.5 / face->available_sizes[0].height * TWO_SIXTEENTH;
rc = FT_Get_BDF_Property(face, "UNDERLINE_THICKNESS", &prop);
if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
font->underlineThickness =
(double)prop.u.integer / face->available_sizes[0].height *
TWO_SIXTEENTH;
else
font->underlineThickness =
1.0 / face->available_sizes[0].height * TWO_SIXTEENTH;
} }
if(face->num_fixed_sizes == 0) { if(face->num_fixed_sizes == 0) {
@ -304,6 +290,20 @@ readFile(char *filename, FontPtr font)
return -1; return -1;
} }
font->flags = faceFlags(face) | (symbol ? FACE_SYMBOL : 0);
font->weight = faceWeight(face);
font->width = faceWidth(face);
font->foundry = faceFoundry(face);
font->italicAngle = faceItalicAngle(face);
font->pxMetrics.height = face->available_sizes[0].height;
font->pxMetrics.size = faceIntProp(face, "PIXEL_SIZE");
font->pxMetrics.xHeight = faceIntProp(face, "X_HEIGHT");
font->pxMetrics.capHeight = faceIntProp(face, "CAP_HEIGHT");
font->pxMetrics.ascent = faceIntProp(face, "FONT_ASCENT");
font->pxMetrics.descent = faceIntProp(face, "FONT_DESCENT");
font->pxMetrics.underlinePosition = faceIntProp(face, "UNDERLINE_POSITION");
font->pxMetrics.underlineThickness = faceIntProp(face, "UNDERLINE_THICKNESS");
for(int i = 0; i < face->num_fixed_sizes; i++) { for(int i = 0; i < face->num_fixed_sizes; i++) {
if(verbose_flag) if(verbose_flag)
fprintf(stderr, "size %d: %dx%d\n", fprintf(stderr, "size %d: %dx%d\n",

View File

@ -42,8 +42,32 @@ makeFont(void)
font->weight = 500; font->weight = 500;
font->width = 5; font->width = 5;
font->italicAngle = 0; font->italicAngle = 0;
font->underlinePosition = - TWO_SIXTEENTH; font->pxMetrics.height = UNDEF;
font->underlineThickness = TWO_SIXTEENTH; font->pxMetrics.maxX = UNDEF;
font->pxMetrics.minX = UNDEF;
font->pxMetrics.maxY = UNDEF;
font->pxMetrics.minY = UNDEF;
font->pxMetrics.xHeight = UNDEF;
font->pxMetrics.capHeight = UNDEF;
font->pxMetrics.maxAwidth = UNDEF;
font->pxMetrics.awidth = UNDEF;
font->pxMetrics.ascent = UNDEF;
font->pxMetrics.descent = UNDEF;
font->pxMetrics.underlinePosition = UNDEF;
font->pxMetrics.underlineThickness = UNDEF;
font->metrics.height = UNDEF;
font->metrics.maxX = UNDEF;
font->metrics.minX = UNDEF;
font->metrics.maxY = UNDEF;
font->metrics.minY = UNDEF;
font->metrics.xHeight = UNDEF;
font->metrics.capHeight = UNDEF;
font->metrics.maxAwidth = UNDEF;
font->metrics.awidth = UNDEF;
font->metrics.ascent = UNDEF;
font->metrics.descent = UNDEF;
font->metrics.underlinePosition = UNDEF;
font->metrics.underlineThickness = UNDEF;
font->foundry = makeName("UNKN"); font->foundry = makeName("UNKN");
font->strikes = NULL; font->strikes = NULL;
return font; return font;
@ -401,19 +425,12 @@ strikeBitmapIndex(StrikePtr strike, CmapPtr cmap, int index)
return STRIKE_BITMAP(strike, code); return STRIKE_BITMAP(strike, code);
} }
void int
strikeMetrics(StrikePtr strike, strikeMaxWidth(StrikePtr strike)
int *width_max_return,
int *x_min_return, int *y_min_return,
int *x_max_return, int *y_max_return)
{ {
BitmapPtr bitmap; BitmapPtr bitmap;
int i; int i;
int width_max = 0; int width_max = 0;
int x_min = 10000;
int y_min = 10000;
int x_max = -10000;
int y_max = -10000;
for(i = 0; i < FONT_CODES; i++) { for(i = 0; i < FONT_CODES; i++) {
bitmap = STRIKE_BITMAP(strike, i); bitmap = STRIKE_BITMAP(strike, i);
@ -421,21 +438,9 @@ strikeMetrics(StrikePtr strike,
continue; continue;
if(bitmap->advanceWidth > width_max) if(bitmap->advanceWidth > width_max)
width_max = bitmap->advanceWidth; width_max = bitmap->advanceWidth;
if(bitmap->horiBearingX < x_min)
x_min = bitmap->horiBearingX;
if(bitmap->horiBearingY > y_max)
y_max = bitmap->horiBearingY;
if(bitmap->horiBearingX + bitmap->width > x_max)
x_max = bitmap->horiBearingX + bitmap->width;
if(bitmap->horiBearingY - bitmap->height < y_min)
y_min = bitmap->horiBearingY - bitmap->height;
} }
if(width_max_return) *width_max_return = width_max; return width_max;
if(x_min_return) *x_min_return = x_min;
if(y_min_return) *y_min_return = y_min;
if(x_max_return) *x_max_return = x_max;
if(y_max_return) *y_max_return = y_max;
} }
int int
@ -453,7 +458,7 @@ glyphMetrics(FontPtr font, int code,
if(bitmap) { if(bitmap) {
if(width_return) if(width_return)
*width_return = *width_return =
(((float)bitmap->advanceWidth + 0.5) / strike->sizeX) * (((float)bitmap->advanceWidth) / strike->sizeX) *
TWO_SIXTEENTH; TWO_SIXTEENTH;
if(x_min_return) if(x_min_return)
*x_min_return = *x_min_return =
@ -463,17 +468,13 @@ glyphMetrics(FontPtr font, int code,
*y_min_return = *y_min_return =
(((float)bitmap->horiBearingY - bitmap->height) (((float)bitmap->horiBearingY - bitmap->height)
/ strike->sizeY) * TWO_SIXTEENTH; / strike->sizeY) * TWO_SIXTEENTH;
/* For the following two, 0.9 instead of 0.5 might make
more sense. However, using different rounding rules
for x_max and awidth causes problems for detecting
charcell fonts. */
if(x_max_return) if(x_max_return)
*x_max_return = *x_max_return =
(((float)bitmap->horiBearingX + bitmap->width + 0.5) (((float)bitmap->horiBearingX + bitmap->width)
/ strike->sizeX) * TWO_SIXTEENTH; / strike->sizeX) * TWO_SIXTEENTH;
if(y_max_return) if(y_max_return)
*y_max_return = *y_max_return =
(((float)bitmap->horiBearingY + 0.5) / strike->sizeY) * (((float)bitmap->horiBearingY) / strike->sizeY) *
TWO_SIXTEENTH; TWO_SIXTEENTH;
return 1; return 1;
} }
@ -482,33 +483,3 @@ glyphMetrics(FontPtr font, int code,
return -1; return -1;
} }
void
fontMetrics(FontPtr font,
int *max_awidth_return,
int *min_x_return, int *min_y_return,
int *max_x_return, int *max_y_return)
{
int i, rc;
int max_awidth = 0;
int min_x = 10000 * 65536, min_y = 10000 * 65536;
int max_x = -10000 * 65536, max_y = -10000 * 65536;
for(i = 0; i < FONT_CODES; i++) {
int awidth, x0, y0, x1, y1;
rc = glyphMetrics(font, i, &awidth, &x0, &y0, &x1, &y1);
if(rc < 0)
continue;
if(awidth > max_awidth)
max_awidth = awidth;
if(x0 < min_x) min_x = x0;
if(y0 < min_y) min_y = y0;
if(x1 > max_x) max_x = x1;
if(y1 > max_y) max_y = y1;
}
if(max_awidth_return) *max_awidth_return = max_awidth;
if(min_x_return) *min_x_return = min_x;
if(min_y_return) *min_y_return = min_y;
if(max_x_return) *max_x_return = max_x;
if(max_y_return) *max_y_return = max_y;
}

View File

@ -213,10 +213,10 @@ macTime(int *hi, unsigned *lo)
tm.tm_isdst = -1; tm.tm_isdst = -1;
macEpoch = mktime_gmt(&tm); macEpoch = mktime_gmt(&tm);
if(macEpoch < 0) return -1; if(macEpoch == -1) return -1;
current = time(NULL); current = time(NULL);
if(current < 0) if(current == -1)
return -1; return -1;
if(current < macEpoch) { if(current < macEpoch) {
@ -280,8 +280,11 @@ faceFoundry(FT_Face face)
return makeName("URW "); return makeName("URW ");
else if(strcasecmp(prop.u.atom, "y&y") == 0) else if(strcasecmp(prop.u.atom, "y&y") == 0)
return makeName("Y&Y "); return makeName("Y&Y ");
else else {
return makeName("UNKN"); char buf[5];
snprintf(buf, sizeof(buf), "%-4s", prop.u.atom);
return makeName(buf);
}
} }
/* For now */ /* For now */
return makeName("UNKN"); return makeName("UNKN");
@ -302,7 +305,7 @@ faceWeight(FT_Face face)
else if(strcasecmp(prop.u.atom, "light") == 0) else if(strcasecmp(prop.u.atom, "light") == 0)
return 300; return 300;
else if(strcasecmp(prop.u.atom, "medium") == 0) else if(strcasecmp(prop.u.atom, "medium") == 0)
return 500; return 400;
else if(strcasecmp(prop.u.atom, "semibold") == 0) else if(strcasecmp(prop.u.atom, "semibold") == 0)
return 600; return 600;
else if(strcasecmp(prop.u.atom, "bold") == 0) else if(strcasecmp(prop.u.atom, "bold") == 0)
@ -312,9 +315,9 @@ faceWeight(FT_Face face)
else if(strcasecmp(prop.u.atom, "black") == 0) else if(strcasecmp(prop.u.atom, "black") == 0)
return 900; return 900;
else else
return 500; return 400;
} else } else
return 500; /* for now */ return 400; /* for now */
} }
int int
@ -388,6 +391,19 @@ faceFlags(FT_Face face)
return flags; return flags;
} }
int
faceIntProp(FT_Face face, const char *name)
{
int rc;
BDF_PropertyRec prop;
rc = FT_Get_BDF_Property(face, name, &prop);
if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
return prop.u.integer;
else
return UNDEF;
}
char * char *
faceEncoding(FT_Face face) faceEncoding(FT_Face face)
{ {

View File

@ -61,7 +61,6 @@ static int writemaxp(FILE*, FontPtr);
static int writename(FILE*, FontPtr); static int writename(FILE*, FontPtr);
static int writepost(FILE*, FontPtr); static int writepost(FILE*, FontPtr);
int max_awidth, min_x, min_y, max_x, max_y;
static CmapPtr current_cmap = NULL; static CmapPtr current_cmap = NULL;
static int numglyphs, nummetrics; static int numglyphs, nummetrics;
static int write_error_occurred, read_error_occurred; static int write_error_occurred, read_error_occurred;
@ -206,6 +205,117 @@ readULONG(FILE *out)
return ntohl(val); return ntohl(val);
} }
void
fontMetrics(FontPtr font)
{
int i, rc;
double sumAwidth = 0;
unsigned count = 0;
font->metrics.maxAwidth = 0;
font->metrics.maxX = -10000 * TWO_SIXTEENTH;
font->metrics.maxY = -10000 * TWO_SIXTEENTH;
font->metrics.minX = 10000 * TWO_SIXTEENTH;
font->metrics.minY = 10000 * TWO_SIXTEENTH;
for(i = 0; i < FONT_CODES; i++) {
int awidth, x0, y0, x1, y1;
rc = glyphMetrics(font, i, &awidth, &x0, &y0, &x1, &y1);
if(rc < 0)
continue;
if(awidth > font->metrics.maxAwidth) font->metrics.maxAwidth = awidth;
if(x0 < font->metrics.minX) font->metrics.minX = x0;
if(y0 < font->metrics.minY) font->metrics.minY = y0;
if(x1 > font->metrics.maxX) font->metrics.maxX = x1;
if(y1 > font->metrics.maxY) font->metrics.maxY = y1;
if(awidth > 0) {
sumAwidth += awidth;
count++;
}
}
if (count) font->metrics.awidth = sumAwidth / count;
font->metrics.height = TWO_SIXTEENTH;
if(font->pxMetrics.size == UNDEF) {
font->pxMetrics.size = font->pxMetrics.height;
font->metrics.size = font->metrics.height;
}
font->metrics.size = font->pxMetrics.size
* TWO_SIXTEENTH / font->pxMetrics.height;
if(font->pxMetrics.ascent == UNDEF) {
font->metrics.ascent = font->metrics.maxY;
font->pxMetrics.ascent =
font->metrics.ascent
* font->pxMetrics.height / TWO_SIXTEENTH;
}
else
font->metrics.ascent =
font->pxMetrics.ascent
* TWO_SIXTEENTH / font->pxMetrics.height;
if(font->pxMetrics.descent == UNDEF) {
font->metrics.descent = font->metrics.minY;
font->pxMetrics.descent =
font->metrics.descent
* font->pxMetrics.height / TWO_SIXTEENTH;
}
else
font->metrics.descent =
font->pxMetrics.descent
* TWO_SIXTEENTH / font->pxMetrics.height;
if(font->pxMetrics.capHeight == UNDEF) {
if(glyphMetrics(font, 'X', NULL, NULL, NULL, NULL, &font->metrics.capHeight) != 1)
font->metrics.capHeight = font->metrics.ascent;
font->pxMetrics.capHeight =
font->metrics.capHeight * font->pxMetrics.height / TWO_SIXTEENTH;
}
else
font->metrics.capHeight =
font->pxMetrics.capHeight
* TWO_SIXTEENTH / font->pxMetrics.height;
if(font->pxMetrics.xHeight == UNDEF) {
if(glyphMetrics(font, 'x', NULL, NULL, NULL, NULL, &font->metrics.xHeight) != 1)
font->metrics.xHeight = font->metrics.capHeight * 2 / 3;
font->pxMetrics.xHeight =
font->metrics.xHeight * font->pxMetrics.height / TWO_SIXTEENTH;
}
else
font->metrics.xHeight =
font->pxMetrics.xHeight
* TWO_SIXTEENTH / font->pxMetrics.height;
if(font->pxMetrics.underlinePosition == UNDEF)
font->metrics.underlinePosition = - font->metrics.descent * 2;
else {
fprintf(stderr, "Setting underlinePosition. pxMetrics.underlinePosition is %d. height is %d\n",
font->pxMetrics.underlinePosition, font->pxMetrics.height);
font->metrics.underlinePosition =
font->pxMetrics.underlinePosition
* TWO_SIXTEENTH / font->pxMetrics.height;
}
if(font->pxMetrics.underlineThickness == UNDEF)
/* make sure thickness is at least one pixel. */
/* TODO: this could be refined according to
* X Logical Font Description Conventions (xlfd.txt)
* by also considering the font weight. */
font->metrics.underlineThickness =
TWO_SIXTEENTH
/ (font->pxMetrics.height < 9 ? font->pxMetrics.height : 9);
else
font->metrics.underlineThickness =
font->pxMetrics.underlineThickness
* TWO_SIXTEENTH / font->pxMetrics.height;
}
int int
writeFile(char *filename, FontPtr font) writeFile(char *filename, FontPtr font)
{ {
@ -219,8 +329,6 @@ writeFile(char *filename, FontPtr font)
int offset[15], length[15]; int offset[15], length[15];
StrikePtr strike; StrikePtr strike;
fontMetrics(font, &max_awidth, &min_x, &min_y, &max_x, &max_y);
out = fopen(filename, "wb+"); out = fopen(filename, "wb+");
if(out == NULL) if(out == NULL)
return -1; return -1;
@ -231,6 +339,8 @@ writeFile(char *filename, FontPtr font)
return -1; return -1;
} }
fontMetrics(font);
write_error_occurred = 0; write_error_occurred = 0;
read_error_occurred = 0; read_error_occurred = 0;
@ -434,8 +544,8 @@ fixupChecksum(FILE *out, int full_length, int head_position)
static int static int
writehead(FILE* out, FontPtr font) writehead(FILE* out, FontPtr font)
{ {
int time_hi; int time_hi = 0;
unsigned time_lo; unsigned time_lo = 0;
macTime(&time_hi, &time_lo); macTime(&time_hi, &time_lo);
@ -451,10 +561,12 @@ writehead(FILE* out, FontPtr font)
writeLONG(out, time_hi); /* modified */ writeLONG(out, time_hi); /* modified */
writeULONG(out, time_lo); writeULONG(out, time_lo);
writeUSHORT(out, FONT_UNITS_FLOOR(min_x)); /* bounding box for all glyphs */
writeUSHORT(out, FONT_UNITS_FLOOR(min_y)); writeUSHORT(out, FONT_UNITS_FLOOR(font->metrics.minX));
writeUSHORT(out, FONT_UNITS_CEIL(max_x)); writeUSHORT(out, FONT_UNITS_FLOOR(font->metrics.minY));
writeUSHORT(out, FONT_UNITS_CEIL(max_y)); writeUSHORT(out, FONT_UNITS_CEIL(font->metrics.maxX));
writeUSHORT(out, FONT_UNITS_CEIL(font->metrics.maxY));
writeUSHORT(out, font->flags); /* macStyle */ writeUSHORT(out, font->flags); /* macStyle */
writeUSHORT(out, 1); /* lowestRecPPEM */ writeUSHORT(out, 1); /* lowestRecPPEM */
writeSHORT(out, 0); /* fontDirectionHint */ writeSHORT(out, 0); /* fontDirectionHint */
@ -549,27 +661,6 @@ writeEBDT(FILE* out, FontPtr font)
return 0; return 0;
} }
static int
writeSbitLineMetrics(FILE *out, StrikePtr strike, int num, int den)
{
int width_max, x_min, y_min, x_max, y_max;
strikeMetrics(strike, &width_max, &x_min, &y_min, &x_max, &y_max);
writeCHAR(out, y_max); /* ascender */
writeCHAR(out, y_min); /* descender */
writeBYTE(out, width_max); /* widthMax */
writeCHAR(out, num); /* caretSlopeNumerator */
writeCHAR(out, den); /* caretSlopeDenominator */
writeCHAR(out, 0); /* caretOffset */
writeCHAR(out, 0); /* minOriginSB */
writeCHAR(out, 0); /* minAdvanceSB */
writeCHAR(out, 0); /* maxBeforeBL */
writeCHAR(out, 0); /* minAfterBL */
writeCHAR(out, 0); /* pad1 */
writeCHAR(out, 0); /* pad2 */
return 0;
}
static int static int
writeEBLC(FILE* out, FontPtr font) writeEBLC(FILE* out, FontPtr font)
{ {
@ -599,8 +690,20 @@ writeEBLC(FILE* out, FontPtr font)
writeULONG(out, 0xDEADFACE); /* indexTablesSize */ writeULONG(out, 0xDEADFACE); /* indexTablesSize */
writeULONG(out, 0xDEADFACE); /* numberOfIndexSubTables */ writeULONG(out, 0xDEADFACE); /* numberOfIndexSubTables */
writeULONG(out, 0); /* colorRef */ writeULONG(out, 0); /* colorRef */
writeSbitLineMetrics(out, strike, num, den); for (i = 0; i <= 1; i++) {
writeSbitLineMetrics(out, strike, num, den); writeCHAR(out, font->pxMetrics.ascent); /* ascender */
writeCHAR(out, -font->pxMetrics.descent); /* descender */
writeBYTE(out, strikeMaxWidth(strike)); /* widthMax */
writeCHAR(out, num); /* caretSlopeNumerator */
writeCHAR(out, den); /* caretSlopeDenominator */
writeCHAR(out, 0); /* caretOffset */
writeCHAR(out, 0); /* minOriginSB */
writeCHAR(out, 0); /* minAdvanceSB */
writeCHAR(out, 0); /* maxBeforeBL */
writeCHAR(out, 0); /* minAfterBL */
writeCHAR(out, 0); /* pad1 */
writeCHAR(out, 0); /* pad2 */
}
writeUSHORT(out, 0); /* startGlyphIndex */ writeUSHORT(out, 0); /* startGlyphIndex */
writeUSHORT(out, 0xFFFD); /* endGlyphIndex */ writeUSHORT(out, 0xFFFD); /* endGlyphIndex */
writeBYTE(out, strike->sizeX); /* ppemX */ writeBYTE(out, strike->sizeX); /* ppemX */
@ -648,9 +751,6 @@ writeEBLC(FILE* out, FontPtr font)
/* actual indexSubTables */ /* actual indexSubTables */
strike = font->strikes; strike = font->strikes;
while(strike) { while(strike) {
int vertAdvance, y_min, y_max;
strikeMetrics(strike, NULL, NULL, &y_min, NULL, &y_max);
vertAdvance = y_max - y_min;
table = strike->indexSubTables; table = strike->indexSubTables;
while(table) { while(table) {
int location; int location;
@ -718,7 +818,7 @@ writeEBLC(FILE* out, FontPtr font)
writeBYTE(out, bitmap->advanceWidth); writeBYTE(out, bitmap->advanceWidth);
writeCHAR(out, bitmap->horiBearingX); /* vertBearingX */ writeCHAR(out, bitmap->horiBearingX); /* vertBearingX */
writeCHAR(out, bitmap->horiBearingY); /* vertBearingY */ writeCHAR(out, bitmap->horiBearingY); /* vertBearingY */
writeBYTE(out, vertAdvance); /* vertAdvance */ writeBYTE(out, font->metrics.maxAwidth); /* vertAdvance */
} else { } else {
for(i = table->firstGlyphIndex; for(i = table->firstGlyphIndex;
i <= table->lastGlyphIndex; i++) { i <= table->lastGlyphIndex; i++) {
@ -849,13 +949,15 @@ writehhea(FILE* out, FontPtr font)
degreesToFraction(font->italicAngle, &num, &den); degreesToFraction(font->italicAngle, &num, &den);
writeULONG(out, 0x00010000); /* version */ writeULONG(out, 0x00010000); /* version */
writeSHORT(out, FONT_UNITS_CEIL(max_y)); /* ascender */ writeSHORT(out, FONT_UNITS_CEIL(font->metrics.ascent)); /* ascender */
writeSHORT(out, FONT_UNITS_FLOOR(min_y)); /* descender */ writeSHORT(out, -FONT_UNITS_CEIL(font->metrics.descent)); /* descender */
writeSHORT(out, FONT_UNITS(TWO_SIXTEENTH / 20)); /* lineGap */ writeSHORT(out, FONT_UNITS(font->metrics.size - font->metrics.ascent - font->metrics.descent)); /* lineGap */
writeUSHORT(out, FONT_UNITS(max_awidth)); /* advanceWidthMax */ writeUSHORT(out, FONT_UNITS(font->metrics.maxAwidth)); /* advanceWidthMax */
writeSHORT(out, FONT_UNITS_FLOOR(min_x)); /* minLeftSideBearing */ /* TODO: the next three are not calculated according to spec, are they ?
writeSHORT(out, FONT_UNITS_FLOOR(min_x)); /* minRightSideBearing */ * https://docs.microsoft.com/en-us/typography/opentype/spec/hhea */
writeSHORT(out, FONT_UNITS_CEIL(max_x)); /* xMaxExtent */ writeSHORT(out, FONT_UNITS_FLOOR(font->metrics.minX)); /* minLeftSideBearing */
writeSHORT(out, FONT_UNITS_FLOOR(font->metrics.minX)); /* minRightSideBearing */
writeSHORT(out, FONT_UNITS_CEIL(font->metrics.maxX)); /* xMaxExtent */
writeSHORT(out, den); /* caretSlopeRise */ writeSHORT(out, den); /* caretSlopeRise */
writeSHORT(out, num); /* caretSlopeRun */ writeSHORT(out, num); /* caretSlopeRun */
writeSHORT(out, 0); /* reserved */ writeSHORT(out, 0); /* reserved */
@ -974,8 +1076,8 @@ writepost(FILE* out, FontPtr font)
writeULONG(out, 0x00030000); /* FormatType */ writeULONG(out, 0x00030000); /* FormatType */
writeULONG(out, font->italicAngle); /* italicAngle */ writeULONG(out, font->italicAngle); /* italicAngle */
writeSHORT(out, FONT_UNITS(font->underlinePosition)); writeSHORT(out, FONT_UNITS(font->metrics.underlinePosition));
writeSHORT(out, FONT_UNITS(font->underlineThickness)); writeSHORT(out, FONT_UNITS(font->metrics.underlineThickness));
writeULONG(out, fixed_pitch); /* isFixedPitch */ writeULONG(out, fixed_pitch); /* isFixedPitch */
writeULONG(out, 0); /* minMemType42 */ writeULONG(out, 0); /* minMemType42 */
writeULONG(out, 0); /* maxMemType42 */ writeULONG(out, 0); /* maxMemType42 */
@ -989,8 +1091,8 @@ writeOS2(FILE* out, FontPtr font)
{ {
int i; int i;
writeUSHORT(out, 0x0001); writeUSHORT(out, 5); /* version */
writeSHORT(out, FONT_UNITS(max_awidth / 2)); /* xAvgCharWidth; */ writeSHORT(out, FONT_UNITS(font->metrics.awidth)); /* xAvgCharWidth; */
writeUSHORT(out, font->weight); /* usWeightClass; */ writeUSHORT(out, font->weight); /* usWeightClass; */
writeUSHORT(out, font->width); /* usWidthClass; */ writeUSHORT(out, font->width); /* usWidthClass; */
writeSHORT(out, 0); /* fsType; */ writeSHORT(out, 0); /* fsType; */
@ -1002,7 +1104,7 @@ writeOS2(FILE* out, FontPtr font)
writeSHORT(out, UNITS_PER_EM / 5); /* ySuperscriptYSize; */ writeSHORT(out, UNITS_PER_EM / 5); /* ySuperscriptYSize; */
writeSHORT(out, 0); /* ySuperscriptXOffset; */ writeSHORT(out, 0); /* ySuperscriptXOffset; */
writeSHORT(out, UNITS_PER_EM / 5); /* ySuperscriptYOffset; */ writeSHORT(out, UNITS_PER_EM / 5); /* ySuperscriptYOffset; */
writeSHORT(out, FONT_UNITS(font->underlineThickness)); writeSHORT(out, FONT_UNITS(font->metrics.underlineThickness));
/* yStrikeoutSize; */ /* yStrikeoutSize; */
writeSHORT(out, UNITS_PER_EM / 4); /* yStrikeoutPosition; */ writeSHORT(out, UNITS_PER_EM / 4); /* yStrikeoutPosition; */
writeSHORT(out, 0); /* sFamilyClass; */ writeSHORT(out, 0); /* sFamilyClass; */
@ -1013,17 +1115,38 @@ writeOS2(FILE* out, FontPtr font)
writeULONG(out, 0x03FF); /* ulUnicodeRange3; */ writeULONG(out, 0x03FF); /* ulUnicodeRange3; */
writeULONG(out, 0U); /* ulUnicodeRange4; */ writeULONG(out, 0U); /* ulUnicodeRange4; */
writeULONG(out, font->foundry); /* achVendID[4]; */ writeULONG(out, font->foundry); /* achVendID[4]; */
writeUSHORT(out, 0x0040); /* fsSelection; */ i = 0;
if (font->flags & FACE_ITALIC)
i |= 1 << 0;
if (font->flags & FACE_BOLD)
i |= 1 << 5;
if (!i)
i |= 1 << 6;
#ifndef NO_TYPO_METRICS
i |= 1 << 7; /* USE_TYPO_METRICS instead usWin metrics for line spacing. */
#endif
writeUSHORT(out, i); /* fsSelection; */
writeUSHORT(out, 0x20); /* usFirstCharIndex; */ writeUSHORT(out, 0x20); /* usFirstCharIndex; */
writeUSHORT(out, 0xFFFD); /* usLastCharIndex; */ writeUSHORT(out, 0xFFFD); /* usLastCharIndex; */
writeUSHORT(out, FONT_UNITS_CEIL(max_y)); /* sTypoAscender; */ writeUSHORT(out, FONT_UNITS_CEIL(font->metrics.ascent)); /* sTypoAscender; */
writeUSHORT(out, -FONT_UNITS_FLOOR(min_y)); /* sTypoDescender; */ writeSHORT(out, -FONT_UNITS_CEIL(font->metrics.descent)); /* sTypoDescender; */
writeUSHORT(out, FONT_UNITS(max_y - min_y)); writeSHORT(out, FONT_UNITS(font->metrics.size - font->metrics.ascent - font->metrics.descent)); /* sTypoLineGap */
/* sTypoLineGap; */ #ifdef NO_TYPO_METRICS
writeUSHORT(out, FONT_UNITS_CEIL(max_y)); /* usWinAscent; */ writeUSHORT(out, FONT_UNITS_CEIL(font->metrics.ascent)); /* usWinAscent; */
writeUSHORT(out, -FONT_UNITS_FLOOR(min_y)); /* usWinDescent; */ writeUSHORT(out, FONT_UNITS_CEIL(font->metrics.descent)); /* usWinDescent; */
#else
writeUSHORT(out, FONT_UNITS_CEIL(font->metrics.maxY)); /* usWinAscent; */
writeUSHORT(out, -FONT_UNITS_FLOOR(font->metrics.minY)); /* usWinDescent; */
#endif
writeULONG(out, 3); /* ulCodePageRange1; */ writeULONG(out, 3); /* ulCodePageRange1; */
writeULONG(out, 0); /* ulCodePageRange2; */ writeULONG(out, 0); /* ulCodePageRange2; */
writeSHORT(out, FONT_UNITS_CEIL(font->metrics.xHeight)); /* sxHeight; */
writeSHORT(out, FONT_UNITS_CEIL(font->metrics.capHeight)); /* sCapHeight; */
writeUSHORT(out, 0); /* usDefaultChar; */
writeUSHORT(out, 20); /* usBreakChar; */
writeUSHORT(out, 0); /* usMaxContext; */
writeUSHORT(out, 0); /* usLowerOpticalPointSize; */
writeUSHORT(out, 0xffff); /* usUpperOpticalPointSize; */
return 0; return 0;
} }
@ -1061,11 +1184,11 @@ writePCLT(FILE* out, FontPtr font)
writeULONG(out, 0x00010000); /* version */ writeULONG(out, 0x00010000); /* version */
writeULONG(out, 0); /* FontNumber */ writeULONG(out, 0); /* FontNumber */
writeUSHORT(out, FONT_UNITS(max_awidth)); /* pitch */ writeUSHORT(out, FONT_UNITS(font->metrics.maxAwidth)); /* pitch */
writeUSHORT(out, FONT_UNITS(max_y)); /* xHeight */ writeUSHORT(out, FONT_UNITS(font->metrics.xHeight)); /* xHeight */
writeUSHORT(out, style); /* style */ writeUSHORT(out, style); /* style */
writeUSHORT(out, 6 << 12); /* TypeFamily */ writeUSHORT(out, 6 << 12); /* TypeFamily */
writeUSHORT(out, FONT_UNITS(max_y)); /* CapHeight */ writeUSHORT(out, FONT_UNITS(font->metrics.xHeight)); /* CapHeight */
writeUSHORT(out, 0); /* SymbolSet */ writeUSHORT(out, 0); /* SymbolSet */
writeCHARs(out, name, 16); /* TypeFace */ writeCHARs(out, name, 16); /* TypeFace */
writeBYTEs(out, charComplement, 8); /* CharacterComplement */ writeBYTEs(out, charComplement, 8); /* CharacterComplement */