You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
typesetting/pitfall/pitfall/page.rkt

143 lines
4.5 KiB
Racket

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

#lang racket/base
(require "racket.rkt")
(provide PDFPage)
(define PDFPage
(class object%
(super-new)
(init-field document [options (mhash)])
(field [size (hash-ref options 'size "letter")]
[layout (hash-ref options 'layout "portrait")]
;; calculate page dimensions
[dimensions (if (list? size)
size
(hash-ref page-sizes (string-upcase size)))]
[width (list-ref dimensions (if (equal? layout "portrait") 0 1))]
[height (list-ref dimensions (if (equal? layout "portrait") 1 0))]
[content (· document ref)]
;; Initialize the Font, XObject, and ExtGState dictionaries
[resources (send document ref (mhash 'ProcSet '("PDF" "Text" "ImageB" "ImageC" "ImageI")))]
[margins
(let ([margin-value (hash-ref options 'margin #f)])
(if (number? margin-value)
(mhasheq 'top margin-value
'left margin-value
'bottom margin-value
'right margin-value)
;; default to 1 inch margins
(hash-ref options 'margins default-margins)))]
;; The page dictionary
[dictionary
(send document ref
(mhash 'Type "Page"
'Parent (· document _root payload Pages)
'MediaBox (list 0 0 width height)
'Contents content
'Resources resources))])
(as-methods
fonts
xobjects
ext_gstates
patterns
annotations
maxY
write
end)))
;; Lazily create these dictionaries
(define/contract (fonts this)
(->m hash?)
(hash-ref! (· this resources payload) 'Font (make-hash)))
(define/contract (xobjects this)
(->m hash?)
(hash-ref! (· this resources payload) 'XObject (make-hash)))
(define/contract (ext_gstates this)
(->m hash?)
(hash-ref! (· this resources payload) 'ExtGState (make-hash)))
(define/contract (patterns this)
(->m hash?)
(hash-ref! (· this resources payload) 'Pattern (make-hash)))
(define/contract (annotations this [annot #f])
(() (any/c) . ->*m . void?)
(if (not annot)
(hash-ref! (· this dictionary payload) 'Annots null)
(hash-update! (· this dictionary payload) 'Annots (λ (val) (cons annot val)) null)))
(define/contract (maxY this)
(->m number?)
(- (· this height) (· this margins bottom)))
(define/contract (write this chunk)
(any/c . ->m . void?)
(send (· this content) write chunk)) ; resume here
(define/contract (end this)
(->m void?)
(send (· this dictionary) end)
(send (· this resources) end)
(send (· this content) end))
(define default-margins (hasheq 'top 72
'left 72
'bottom 72
'right 72))
(define page-sizes
(hash "4A0" '(4767.87 6740.79)
"2A0" '(3370.39 4767.87)
"A0" '(2383.94 3370.39)
"A1" '(1683.78 2383.94)
"A2" '(1190.55 1683.78)
"A3" '(841.89 1190.55)
"A4" '(595.28 841.89)
"A5" '(419.53 595.28)
"A6" '(297.64 419.53)
"A7" '(209.76 297.64)
"A8" '(147.40 209.76)
"A9" '(104.88 147.40)
"A10" '(73.70 104.88)
"B0" '(2834.65 4008.19)
"B1" '(2004.09 2834.65)
"B2" '(1417.32 2004.09)
"B3" '(1000.63 1417.32)
"B4" '(708.66 1000.63)
"B5" '(498.90 708.66)
"B6" '(354.33 498.90)
"B7" '(249.45 354.33)
"B8" '(175.75 249.45)
"B9" '(124.72 175.75)
"B10" '(87.87 124.72)
"C0" '(2599.37 3676.54)
"C1" '(1836.85 2599.37)
"C2" '(1298.27 1836.85)
"C3" '(918.43 1298.27)
"C4" '(649.13 918.43)
"C5" '(459.21 649.13)
"C6" '(323.15 459.21)
"C7" '(229.61 323.15)
"C8" '(161.57 229.61)
"C9" '(113.39 161.57)
"C10" '(79.37 113.39)
"RA0" '(2437.80 3458.27)
"RA1" '(1729.13 2437.80)
"RA2" '(1218.90 1729.13)
"RA3" '(864.57 1218.90)
"RA4" '(609.45 864.57)
"SRA0" '(2551.18 3628.35)
"SRA1" '(1814.17 2551.18)
"SRA2" '(1275.59 1814.17)
"SRA3" '(907.09 1275.59)
"SRA4" '(637.80 907.09)
"EXECUTIVE" '(521.86 756.00)
"FOLIO" '(612.00 936.00)
"LEGAL" '(612.00 1008.00)
"LETTER" '(612.00 792.00)
"TABLOID" '(792.00 1224.00)))