-
Notifications
You must be signed in to change notification settings - Fork 42
/
t1-font.lisp
86 lines (77 loc) · 3.91 KB
/
t1-font.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
;;; cl-pdf copyright 2002-2003 Marc Battyani see license.txt for the details
;;; You can reach me at [email protected] or [email protected]
;;; The homepage of cl-pdf is here: http://www.fractalconcept.com/asp/html/cl-pdf.html
(in-package #:pdf)
(defconstant +pfb-marker+ 128)
(defconstant +pfb-ascii+ 1)
(defconstant +pfb-binary+ 2)
(defconstant +pfb-done+ 3)
(defclass t1-font-metrics (font-metrics)
((binary-data :accessor binary-data :initform nil)
(length1 :accessor length1)
(length2 :accessor length2)
(length3 :accessor length3)))
(defun read-pfb-length (data start)
(let ((length (aref data start)))
(setf (ldb (byte 8 8) length) (aref data (1+ start)))
(setf (ldb (byte 8 16) length) (aref data (+ start 2)))
(setf (ldb (byte 8 24) length) (aref data (+ start 3)))
length))
(defun read-pfb-seg-size (data start marker)
(assert (and (= (aref data start) +pfb-marker+)(= (aref data (1+ start)) marker)))
(values (+ start 6) (read-pfb-length data (+ start 2))))
(defun read-pfb-file (pathname t1fm)
(let (data length start1 length1 start2 length2 start3 length3 binary-data)
(with-open-file (s pathname :direction :input :element-type '(unsigned-byte 8))
(setf length (file-length s))
(setf data (make-array length :element-type '(unsigned-byte 8)))
(read-sequence data s))
(setf (values start1 length1) (read-pfb-seg-size data 0 +pfb-ascii+))
(setf (values start2 length2) (read-pfb-seg-size data (+ start1 length1) +pfb-binary+))
(setf (values start3 length3) (read-pfb-seg-size data (+ start2 length2) +pfb-ascii+))
(assert (<= (+ start3 length3) length))
(setf binary-data (make-array (+ length1 length2 length3) :element-type '(unsigned-byte 8)))
(setf (subseq binary-data 0 length1)(subseq data start1 (+ start1 length1)))
(setf (subseq binary-data length1 (+ length1 length2))
(subseq data start2 (+ start2 length2)))
(setf (subseq binary-data (+ length1 length2)(+ length1 length2 length3))
(subseq data start3 (+ start3 length3)))
(setf (binary-data t1fm) binary-data
(length1 t1fm) length1
(length2 t1fm) length2
(length3 t1fm) length3)))
(defun load-t1-font (afm-file &optional pfb-file)
(let ((t1fm (read-afm-file afm-file 't1-font-metrics)))
(when pfb-file
(read-pfb-file pfb-file t1fm))
t1fm))
(defmethod font-descriptor ((t1fm t1-font-metrics) &key (embed *embed-fonts*) &allow-other-keys)
(flet ((conv-dim (d) (round (* 1000 d))))
(make-instance 'indirect-object :content
(make-instance 'dictionary ;:obj-number 0 :no-link t
:dict-values
`(("/Type" . "/FontDescriptor")
("/FontName" . ,(add-/ (font-name t1fm)))
;; 4=Symbolic - contains characters outside the standard Latin character set.
("/Flags" . 4)
("/FontBBox" . ,(map 'vector #'conv-dim (font-bbox t1fm)))
("/ItalicAngle" . ,(conv-dim (italic-angle t1fm)))
("/Ascent" . ,(conv-dim (ascender t1fm)))
("/Descent" . ,(conv-dim (descender t1fm)))
("/CapHeight" . ,(conv-dim (cap-height t1fm)))
("/XHeight" . ,(conv-dim (x-height t1fm)))
("/StemV" . ,10)
;; When binary-data is not available, don't embded.
,@(when (and embed (binary-data t1fm))
`(("/FontFile" . ,(make-instance 'indirect-object :content
(make-instance 'pdf-stream
:content (binary-data t1fm)
:no-compression (not *compress-fonts*)
:dict-values `(;("/Type" . "/Pages") ;remove!
("/Length1" . ,(length1 t1fm))
("/Length2" . ,(length2 t1fm))
("/Length3" . ,(length3 t1fm))
)))))))))))
;example of T1 font loading:
#+nil
(pdf:load-t1-font #P"/tmp/cmb10.afm" #P"/tmp/cmb10.pfb")