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