main
Matthew Butterick 6 years ago
parent 9b59520164
commit c9dfb71d09

@ -25,12 +25,12 @@
(field [@pages null] (field [@pages null]
[@refs null] [@refs null]
[@ref-gen (generator () (let loop ([refid 1]) [@ref-gen (generator () (let loop ([refid 1])
(yield refid) (yield refid)
(loop (add1 refid))))] (loop (add1 refid))))]
[@root (ref (mhasheq 'Type "Catalog" [@root (ref 'Type "Catalog"
'Pages (ref (mhasheq 'Type "Pages" 'Pages (ref 'Type "Pages"
'Count 0 'Count 0
'Kids empty))))] ; top object 'Kids empty))] ; top object
[(@x x) 0] [(@x x) 0]
[(@y y) 0] [(@y y) 0]
[@info (mhasheq 'Producer "PITFALL" [@info (mhasheq 'Producer "PITFALL"
@ -52,14 +52,18 @@
(current-compress-streams? (hash-ref @options 'compress #t)) (current-compress-streams? (hash-ref @options 'compress #t))
(current-auto-first-page (hash-ref @options 'autoFirstPage #t)) (current-auto-first-page (hash-ref @options 'autoFirstPage #t))
(current-doc-offset 0) (current-doc-offset 0)
(when (current-auto-first-page) (add-page))
(define/public (page) (first @pages)) (define/public (page) (first @pages))
;; for use by page.rkt rather than invading our fields (define/public (ref . args)
(define/public (page-parent) (send @root get-key 'Pages))
(define/public (ref [payload (mhasheq)])
(define refid (@ref-gen)) (define refid (@ref-gen))
(define payload (match args
[(list (? hash? h)) h]
[_ (define h (make-hasheq))
(for ([pr (in-hash-pairs (apply hasheq args))])
(hash-set! h (car pr) (cdr pr)))
h]))
(define new-ref (make-object PDFReference this refid payload)) (define new-ref (make-object PDFReference this refid payload))
(set! @refs (cons new-ref @refs)) (set! @refs (cons new-ref @refs))
new-ref) new-ref)
@ -69,13 +73,14 @@
(write-bytes bstr) (write-bytes bstr)
(current-doc-offset (file-position (current-output-port)))) (current-doc-offset (file-position (current-output-port))))
(define/public (addPage [options-arg @options]) (define/public (add-page [options-arg @options])
;; end the current page if needed ;; end the current page if needed
(unless (hash-ref @options 'bufferPages #f) (unless (hash-ref @options 'bufferPages #f)
(flush-pages)) (flush-pages))
;; create a page object ;; create a page object
(set! @pages (cons (make-object PDFPage this options-arg) @pages)) (define page-parent (send @root get-key 'Pages))
(set! @pages (cons (make-object PDFPage this page-parent options-arg) @pages))
;; in Kids, store page dictionaries in correct order ;; in Kids, store page dictionaries in correct order
;; this determines order in document ;; this determines order in document
@ -100,13 +105,11 @@
(send (page) write data) (send (page) write data)
this) this)
(define/public (end) ; called from source file to finish doc (define/public (end)
(write (format "%PDF-~a" (current-pdf-version))) (write (format "%PDF-~a\n%ÿÿÿÿ" (current-pdf-version)))
(write (string-append "%" (list->string (map integer->char (make-list 4 #xFF)))))
(flush-pages) (flush-pages)
(define doc-info (ref)) (define doc-info (ref))
(for ([(key val) (in-hash @info)]) (for ([(key val) (in-hash @info)])
;; upgrade string literal to String struct
(send doc-info set-key! key (if (string? val) (String val) val))) (send doc-info set-key! key (if (string? val) (String val) val)))
(send doc-info end) (send doc-info end)
@ -134,20 +137,15 @@
(write (string-append (~r offset #:min-width 10 #:pad-string "0") " 00000 n "))) (write (string-append (~r offset #:min-width 10 #:pad-string "0") " 00000 n ")))
(write "trailer") (write "trailer")
(write (convert (write (convert (mhasheq 'Size (add1 (length this-offsets))
(mhash 'Size (add1 (length this-offsets)) 'Root @root
'Root @root 'Info doc-info)))
'Info doc-info)))
(write "startxref") (write "startxref")
(write (numberizer xref-offset)) (write (numberizer xref-offset))
(write "%%EOF")) (write "%%EOF"))
; if no 'info key, nothing will be copied from (hash) (for ([(key val) (in-hash (hash-ref @options 'info (hasheq)))])
(for ([(key val) (in-hash (hash-ref @options 'info (hash)))]) (hash-set! @info key val))))
(hash-set! @info key val))
;; Add the first page
(when (current-auto-first-page) (addPage))))
(module+ test (module+ test
(define d (new PDFDocument))) (define d (new PDFDocument)))

@ -17,4 +17,4 @@
(check-equal? (· p dictionary payload MediaBox) '(0 0 612.0 792.0)) (check-equal? (· p dictionary payload MediaBox) '(0 0 612.0 792.0))
(check-true (is-a? (· p dictionary payload Contents) PDFReference)) (check-true (is-a? (· p dictionary payload Contents) PDFReference))
(check-true (is-a? (· p dictionary payload Resources) PDFReference)) (check-true (is-a? (· p dictionary payload Resources) PDFReference))
(check-true (is-a? (· p dictionary payload Parent) PDFReference)) #;(check-true (is-a? (· p dictionary payload Parent) PDFReference))

@ -11,7 +11,7 @@
(define PDFPage (define PDFPage
(class object% (class object%
(super-new) (super-new)
(init-field document [options (mhash)]) (init-field document [page-parent #false] [options (mhash)])
(field [size (hash-ref options 'size "letter")] (field [size (hash-ref options 'size "letter")]
[layout (hash-ref options 'layout "portrait")] [layout (hash-ref options 'layout "portrait")]
;; calculate page dimensions ;; calculate page dimensions
@ -36,7 +36,7 @@
[dictionary [dictionary
(send document ref (send document ref
(mhash 'Type "Page" (mhash 'Type "Page"
'Parent (send document page-parent) 'Parent page-parent
'MediaBox (list 0 0 width height) 'MediaBox (list 0 0 width height)
'Contents content 'Contents content
'Resources resources))]) 'Resources resources))])

Loading…
Cancel
Save