chickadee » pdf-truetype

pdf-truetype

Description

pdf-truetype provides functionality to embed TrueType fonts in documents created with the pdf egg, and draws text in them.

The standard fonts from pdf's build-font are not stored in the file: the viewer supplies them, so text can look different from one viewer to the next. This egg embeds a TrueType font file in the document instead, so the text always looks the same. Every metric the PDF needs (the widths of the characters, ascent, descent, cap height, italic angle, bounding box) is read from the font file itself, so it always matches the embedded font.

Text is encoded in WinAnsiEncoding, which covers the Latin-1 characters and common typographic symbols such as the euro sign, dashes and curly quotes. Embedded fonts are also what pdfa needs for PDF/A archival documents.

Author

Ivan Raikov

Repository

This egg is hosted on the CHICKEN Subversion repository:

https://anonymous@code.call-cc.org/svn/chicken-eggs/release/6/pdf-truetype

If you want to check out the source code repository of this egg and you are not familiar with Subversion, see this page.

Requirements

pdf, srfi-1, srfi-13, matchable

Documentation

Supported fonts

A font file can be embedded if:

The whole font file is embedded; fonts are not subset. Each embedded font covers the WinAnsi codes 32 to 255.

Embedding fonts

build-embedded-font
build-embedded-font DOC TTF-PATH #!key BASE-NAME AFM-PATH FLAGS FONT-BBOX ITALIC-ANGLE ASCENT DESCENT CAP-HEIGHT STEM-Vprocedure

Embeds the TrueType font in the file TTF-PATH in DOC and returns an embedded-font. Use it with pdf's set-font through embedded-font-name, just as a build-font font is used through font-name.

BASE-NAME sets the font's name in the PDF; it defaults to the font file's PostScript name. Characters not allowed in PDF names (spaces, delimiters such as parentheses, and #) are removed, and a name left empty is an error.

FLAGS, FONT-BBOX (a vector of four numbers), ITALIC-ANGLE, ASCENT, DESCENT, CAP-HEIGHT and STEM-V replace the values otherwise read from the font file, in the 1000-units-per-em scale PDF uses. They are rarely needed. The stem width (/StemV) is not recorded in TrueType files, so by default it is estimated from the font's weight.

AFM-PATH, if given, names an AFM metrics file whose widths are registered with pdf's pdf-font module, for its get-char-width and get-string-width. It does not change what is written into the PDF. embedded-font-string-width measures text from the font file directly.

Raises an error if the file cannot be read as a supported TrueType font.

embedded-font?
embedded-font? Xprocedure

Tests whether X is an embedded font.

embedded-font-name
embedded-font-name FONTprocedure

Returns the resource name of FONT, for set-font, e.g. "/LiberationSans101".

embedded-font-string-width
embedded-font-string-width FONT STRING SIZEprocedure

Returns the width of STRING set in FONT at SIZE, in the same units as SIZE (normally points). The widths are exactly those written in the PDF, so this is suitable for centring, right-aligning and line breaking. Raises an error for a character that embedded-font-has-glyph? rejects.

embedded-font-has-glyph?
embedded-font-has-glyph? FONT CHARprocedure

Returns true if CHAR can be drawn in FONT: it has a WinAnsi code, and the font has a glyph for it.

embedded-font-truetype
embedded-font-truetype FONTprocedure

Returns the truetype-font metrics FONT was built from (see below).

embedded-font-fs-type
embedded-font-fs-type FONTprocedure
embedded-font-restricted? FONTprocedure

embedded-font-fs-type returns the embedding permissions recorded in FONT's file (the OS/2 fsType value). embedded-font-restricted? returns true when they forbid embedding.

Drawing text

pdf's text operators write their strings unchanged. Text in an embedded font should be drawn with the procedures below instead, which map each character to its WinAnsi code, escape the result for a PDF string, and raise an error, naming the character and its position, for any character the font cannot draw. A missing character would otherwise be drawn as a blank.

draw-encoded-text
draw-encoded-text PAGE FONT STRINGprocedure

Draws STRING at the current text position, like pdf's draw-text. FONT is the embedded font that the page's current set-font names: set-font does not record the current font, so it is passed again here. Must be called inside in-text-mode.

draw-encoded-text-on-next-line
draw-encoded-text-on-next-line PAGE FONT STRINGprocedure

Moves to the next line, then draws STRING, like pdf's draw-text-on-next-line. The distance between lines is set with set-text-leading.

encode-text
encode-text FONT STRINGprocedure

Returns STRING encoded for FONT and escaped, ready for pdf's draw-text or draw-and-adjust-string. Raises an error like draw-encoded-text.

WinAnsiEncoding

winansi->unicode
winansi->unicode CODEprocedure
unicode->winansi CHARprocedure

Convert between WinAnsi codes (integers 0 to 255) and Unicode. winansi->unicode returns the Unicode code point of CODE, and unicode->winansi the WinAnsi code of CHAR; each returns #f when there is none. Codes 32 to 126 and 160 to 255 are the same as in Unicode; codes 128 to 159 hold characters such as €, — and “; the control codes and codes 129, 141, 143, 144 and 157 are undefined.

Reading TrueType files

These procedures read the metrics build-embedded-font uses, and are exported for programs that want them directly.

read-truetype-font
read-truetype-font BYTEVECTORprocedure

Parses the TrueType font file held in BYTEVECTOR (see read-byte-file) and returns a truetype-font. Raises an error, naming the problem, for data that is not a supported TrueType font, is truncated, or lacks one of the required tables (head, hhea, hmtx, cmap, post).

truetype-font accessors
truetype-font? Xprocedure
truetype-font-units-per-em FONTprocedure
truetype-font-bbox FONTprocedure
truetype-font-ascent FONTprocedure
truetype-font-descent FONTprocedure
truetype-font-cap-height FONTprocedure
truetype-font-italic-angle FONTprocedure
truetype-font-fixed-pitch? FONTprocedure
truetype-font-italic? FONTprocedure
truetype-font-weight-class FONTprocedure
truetype-font-fs-type FONTprocedure
truetype-font-postscript-name FONTprocedure
truetype-font-unicode->glyph FONTprocedure

Return the font's metrics, in the font's own design units: units per em; bounding box, as a vector #(XMIN YMIN XMAX YMAX); ascent, descent and cap height; italic angle in degrees (negative for fonts that lean right); whether every glyph has the same width; whether the font is italic; weight class (400 regular, 700 bold); embedding permissions; and PostScript name (#f if absent). truetype-font-unicode->glyph returns a procedure mapping a Unicode code point to a glyph number, or 0 when the font has no glyph for it.

truetype-glyph-advance
truetype-glyph-advance FONT GLYPHprocedure

Returns the advance width of glyph number GLYPH, in design units.

truetype-scale
truetype-scale FONT VALUEprocedure

Converts VALUE from FONT's design units to the 1000 units per em PDF uses, rounded to an integer.

truetype-embedding-restricted?
truetype-embedding-restricted? FONTprocedure

Returns true when FONT's licence forbids embedding.

read-byte-file
read-byte-file PATHprocedure

Returns the contents of the file PATH as a bytevector. Use it for binary data such as font files and ICC profiles, which should not be read into Scheme strings.

AFM metrics files

An AFM file holds a Type 1 font's metrics as text. These procedures read the parts relevant to PDF; they are kept for AFM-PATH and for programs that work with AFM files.

read-afm-file
read-afm-file PATHprocedure

Reads the AFM file PATH and returns an afm-metrics record, with the header fields below and the width of each character code. Other parts of the file, such as kerning data, are ignored.

afm-metrics accessors
afm-metrics? Xprocedure
afm-metrics-name METRICSprocedure
afm-metrics-weight METRICSprocedure
afm-metrics-font-bbox METRICSprocedure
afm-metrics-cap-height METRICSprocedure
afm-metrics-x-height METRICSprocedure
afm-metrics-italic-angle METRICSprocedure
afm-metrics-ascent METRICSprocedure
afm-metrics-descent METRICSprocedure
afm-metrics-widths METRICSprocedure
afm-metrics-first-char METRICSprocedure
afm-metrics-last-char METRICSprocedure

Return the AFM file's FontName, Weight, FontBBox (a vector of four numbers), CapHeight, XHeight, ItalicAngle, Ascender and Descender, each #f if absent; the widths, as a list of pairs (CODE . WIDTH) in code order; and the lowest and highest codes with a width.

parse-char-metric
parse-char-metric LINEprocedure

Parses an AFM character metrics line, such as "C 32 ; WX 250 ; N space ;", into a pair (CODE . WIDTH). Codes may be decimal (C) or hexadecimal (CH <20>), and widths WX or W0X. Returns #f for composite characters (code -1) and lines without a code or width.

parse-font-bbox
parse-font-bbox STRINGprocedure

Parses the arguments of an AFM FontBBox line ("-100 -200 900 800") into a vector of four numbers, or #f if there are not four.

Examples

Centered text in an embedded font. The example in the repository examples.scm draws a full font specimen, with the font's metrics and a table of all its characters.

(import scheme (chicken base) pdf pdf-truetype)

(define font-file "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf")

;; Draws text centered on x, measured with the font's own widths.
(define (draw-centered page font size x y text)
  (in-text-mode page
    (set-font page (embedded-font-name font) size)
    (move-text page (- x (/ (embedded-font-string-width font text size) 2)) y)
    (draw-encoded-text page font text)))

(with-document-to-file (doc #t "1.4") "embedded.pdf"
  (let ((font (build-embedded-font doc font-file)))
    (with-page doc (page)
      (draw-centered page font 28 306 700 "Caf\xe9; \x2014; 5 \x20ac;")
      (draw-centered page font 12 306 670
                    (string-append "Set in "
                                   (truetype-font-postscript-name
                                    (embedded-font-truetype font)))))))

Version history

1.0
Initial release

License

 Copyright 2026 Ivan Raikov.
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
 met:
 
 Redistributions of source code must retain the above copyright
 notice, this list of conditions and the following disclaimer.
 
 Redistributions in binary form must reproduce the above copyright
 notice, this list of conditions and the following disclaimer in the
 documentation and/or other materials provided with the distribution.
 
 Neither the name of the author nor the names of its contributors may
 be used to endorse or promote products derived from this software
 without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 OF THE POSSIBILITY OF SUCH DAMAGE.

Contents »