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/quad/quad/typewriter.rkt

94 lines
4.4 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 debug br/quicklang
(require racket/promise racket/list sugar/list sugar/debug "quad.rkt" "atomize.rkt" "wrap.rkt" "qexpr.rkt" "generic.rkt" "position.rkt")
(require pitfall/document)
(provide (rename-out [mb #%module-begin]) (except-out (all-from-out br/quicklang) #%module-begin))
(define optional-break? (λ (q) (and (quad? q) (memv (car (elems q)) '(#\space #\- #\u00AD)))))
(struct $shim $quad () #:transparent)
(struct $char $quad () #:transparent)
(define (charify q)
($char (hash-set* (attrs q)
'size (const '(7.2 12))
'printable? (case (car (elems q))
[(#\u00AD) (λ (sig) (memq sig '(end)))]
[(#\space) (λ (sig) (not (memq sig '(start end))))]
[else #t])
'draw (λ (q doc)
(send doc fontSize 12)
(send/apply doc text (apply string (elems q)) (origin q)))) (elems q)))
(struct $line $quad () #:transparent)
(struct $page $quad () #:transparent)
(struct $doc $quad () #:transparent)
(struct $break $quad () #:transparent)
(define page-count 1)
(define (break . xs) ($break (hasheq 'printable? #f 'size '(0 0)) xs))
(define line-height 16)
(define consolidate-into-runs? #t)
(define (line-wrap xs size [debug #f])
(wrap xs size debug
#:break-val (break #\newline)
#:optional-break-proc optional-break?
#:finish-wrap-proc (λ (pcs) (list ($line (hasheq 'size (list +inf.0 line-height) 'out 'sw)
;; consolidate chars into a single run (naively)
;; by taking attributes from first (including origin)
;; this only works because there's only one run per line
;; that is, it suffices to position the first letter
(if consolidate-into-runs?
(list ($char (attrs (car pcs)) (append-map elems pcs)))
pcs))))))
(define pb ($break (hasheq 'printable? #f
'size '(0 0)
'draw (λ (q doc)
(send doc addPage)
(send doc fontSize 10)
(send doc text (string-append "page " (number->string page-count)) 10 10)
(set! page-count (add1 page-count)))) '(#\page)))
(define (page-wrap xs size [debug #f])
(wrap xs size debug
#:break-before? #t
#:break-val pb
#:optional-break-proc $break?
#:finish-wrap-proc (λ (pcs) (list ($page (hasheq) (filter-not $break? pcs))))))
(define (typeset args)
(define chars 25)
(define line-width (* 7.2 chars))
(define lines-per-page (* 4 line-height))
(position ($doc (hasheq 'origin '(36 36)) (page-wrap (line-wrap (map charify (atomize (apply quad #f args))) line-width) lines-per-page))))
(require hyphenate racket/runtime-path pollen/unstable/typography)
(define-runtime-path fira-mono "FiraMono-Regular.ttf")
(define-macro (mb . ARGS)
(with-pattern ([PS (syntax-property #'ARGS 'ps)])
#'(#%module-begin
(define q (typeset (map hyphenate (map smart-quotes (list . ARGS)))))
;q
(let ([doc (make-object PDFDocument
(hasheq 'compress #t
'autoFirstPage #f
'size '(300 400)))])
(send* doc
[pipe (open-output-file PS #:exists 'replace)]
[registerFont "Fira-Mono" (path->string fira-mono)]
[font "Fira-Mono"]
[fontSize 12])
(draw q doc)
(send doc end))
(void))))
(module reader syntax/module-reader
quad/typewriter
#:read quad-read
#:read-syntax quad-read-syntax
#:whole-body-readers? #t ;; need this to make at-reader work
(require scribble/reader)
(define (quad-read p) (syntax->datum (quad-read-syntax (object-name p) p)))
(define (quad-read-syntax path-string p)
(define quad-at-reader (make-at-reader
#:syntax? #t
#:inside? #t))
(syntax-property (quad-at-reader path-string p) 'ps (path-replace-extension path-string #".pdf"))))