next: put unit tests in page-test

main
Matthew Butterick 7 years ago
parent f83c68043e
commit e629fd832f

@ -3,8 +3,7 @@
(require sugar/debug)
(provide PDFDocument)
(require "reference.rkt" "struct.rkt" "object.rkt")
;(require "page.rkt")
(require "reference.rkt" "struct.rkt" "object.rkt" "page.rkt")
(define PDFDocument
(class object% ; actually is an instance of readable.Stream, which is an input port
@ -59,6 +58,8 @@
(for ([(key val) (in-hash (hash-ref options 'info))])
(hash-set! info key val)))
(report info)
;; Write the header
;; PDF version
(_write (format "%PDF-~a" version))
@ -68,8 +69,8 @@
(_write (string-append "%" (string c c c c))))
;; Add the first page
#;(unless (not (hash-ref options 'autoFirstPage #t))
(addPage)) ; todo
(unless (not (hash-ref options 'autoFirstPage #t))
(addPage))
;; todo
;;mixin = (methods) =>
@ -88,15 +89,15 @@
(field [x 0])
(field [y 0])
(field [_ctm null])
(define/public (addPage [options options])
(define/public (addPage [my-options options])
;; end the current page if needed
(unless (hash-ref options 'bufferPages #f)
(flushPages))
;; create a page object
(define page 42) ; todo new PDFPage(this, options)
(define page (make-object PDFPage this my-options))
(push! _pageBuffer page)
#|
;; add the page to the object store
(define pages (make-hasheq)) ; todo @_root.data.Pages.data
(hash-update! pages 'Kids (λ (val) (cons 42 val)) null) ; todo @page.dictionary
@ -113,7 +114,9 @@
;; @emit('pageAdded') ;; todo
this)
this
|#
)
(define/public (flushPages)
;; this local variable exists so we're future-proof against
@ -197,6 +200,7 @@
;; end the stream
;; in node you (push null) which signals to the stream
;; to copy to its output port
;; here we'll do it manually
(copy-port (open-input-bytes
(apply bytes-append (reverse byte-strings)))
op)
@ -208,4 +212,4 @@
(module+ test
(require rackunit)
(send doc pipe (open-output-file "testrkt0.pdf" #:exists 'replace))
(check-equal? (send doc end) 'done))
(check-equal? (send doc end) 'done))

@ -0,0 +1,13 @@
#lang br
(require rackunit "document.rkt" "page.rkt")
(define p (make-object PDFPage (make-object PDFDocument)))
(get-field size p)
(get-field layout p)
(get-field margins p)
(get-field height p)
(get-field width p)
(get-field resources p)
(get-field data (get-field resources p))
(send p fonts)
(get-field data (get-field dictionary p))

@ -0,0 +1,125 @@
#lang racket/base
(require racket/class)
(provide PDFPage)
(define PDFPage
(class object%
(super-new)
(init-field document
[options (make-hasheq)])
(field [size (hash-ref options 'size "letter")])
(field [layout (hash-ref options 'layout "portrait")])
;; process margins
(field [margins
(let ([margin-value (hash-ref options 'margin #f)])
(if (number? margin-value)
(hasheq 'top margin-value
'left margin-value
'bottom margin-value
'right margin-value)
;; default to 1 inch margins
(hash-ref options 'margins DEFAULT_MARGINS)))])
;; calculate page dimensions
(define dimensions (if (list? size)
size
(hash-ref SIZES (string-upcase size))))
(field [width (list-ref dimensions (if (equal? layout "portrait") 0 1))])
(field [height (list-ref dimensions (if (equal? layout "portrait") 1 0))])
(field [content (send document ref)])
;; Initialize the Font, XObject, and ExtGState dictionaries
(field [resources (send document ref (make-hash (list (cons 'ProcSet '("PDF" "Text" "ImageB" "ImageC" "ImageI")))))])
;; Lazily create these dictionaries
(define/public (fonts)
(hash-ref! (get-field data resources) 'Font (make-hash)))
(define/public (xobjects)
(hash-ref! (get-field data resources) 'XObject (make-hash)))
(define/public (ext_gstates)
(hash-ref! (get-field data resources) 'ExtGState (make-hash)))
(define/public (patterns)
(hash-ref! (get-field data resources) 'Pattern (make-hash)))
(define/public (annotations)
(hash-ref! (get-field data resources) 'Annots null))
;; The page dictionary
(field [dictionary
(send document ref
(make-hash (list
(cons 'Type "Page")
(cons 'Parent (hash-ref (get-field data (get-field _root document)) 'Pages))
(cons 'MediaBox (list 0 0 width height))
(cons 'Contents content)
(cons 'Resources resources))))])
))
(define DEFAULT_MARGINS
(hasheq 'top 72
'left 72
'bottom 72
'right 72))
(define 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)))

@ -1,3 +0,0 @@
%PDF-1.3
%ÿÿÿÿ
foobar
Loading…
Cancel
Save