track character-tracking in add-text

in certain cases we need to jump out of a PDF text-drawing command (`TJ`) to reset the xy position (say, if the next glyph has a special offset). We need to account for any tracking that the TJ might impose
main
Matthew Butterick 2 years ago
parent fcfebb70bf
commit 4220033f37

@ -56,7 +56,7 @@ https://github.com/mbutterick/pdfkit/blob/master/lib/mixins/text.coffee
(define (do-underline doc x y width) (do-horiz-line doc x y width 'underline)) (define (do-underline doc x y width) (do-horiz-line doc x y width 'underline))
(define (add-text doc x y str features) (define (add-text doc x y str features character-tracking)
(match-define (list encoded-char-strs positions) (encode (pdf-current-font doc) str features)) (match-define (list encoded-char-strs positions) (encode (pdf-current-font doc) str features))
(define scale (/ (pdf-current-font-size doc) 1000.0)) (define scale (/ (pdf-current-font-size doc) 1000.0))
@ -78,29 +78,35 @@ https://github.com/mbutterick/pdfkit/blob/master/lib/mixins/text.coffee
(when (positive? (length commands)) (when (positive? (length commands))
(add-content doc (format "[~a] TJ" (string-join (reverse commands) " "))) (add-content doc (format "[~a] TJ" (string-join (reverse commands) " ")))
(set! commands empty))) (set! commands empty)))
(for/fold ([previous-had-offset #f] [x x]) (for/fold ([previous-had-offset #f] [x x])
([(posn idx) (in-indexed positions)]) ([(posn idx) (in-indexed positions)])
(define has-offset (define has-offset
(cond ;; if our TJ command had tracking, we want to move to a position
;; If we have an x or y offset, we have to break out of the current TJ command ;; that is adjusted for the tracking that would've happened
;; so we can move the text position. ;; if we were still within the TJ.
[(or (not (zero? (glyph-position-x-offset posn))) (not (zero? (glyph-position-y-offset posn)))) (let ([tracking-adjustment (* idx character-tracking)])
(flush idx) (cond
(add-content doc ; Move the text position and flush just the current character ;; If we have an x or y offset, we have to break out of the current TJ command
(format "1 0 0 1 ~a ~a Tm" ;; so we can move the text position.
(numberizer (+ x (* (glyph-position-x-offset posn) scale))) [(or (not (zero? (glyph-position-x-offset posn)))
(numberizer (+ y (* (glyph-position-y-offset posn) scale))))) (not (zero? (glyph-position-y-offset posn))))
(flush (add1 idx)) ; Move the text position and flush just the current character
#true] (flush idx)
[else (add-content doc
;; If the last character had an offset, reset the text position (format "1 0 0 1 ~a ~a Tm"
(when previous-had-offset (numberizer (+ x (* (glyph-position-x-offset posn) scale) tracking-adjustment))
(add-content doc (format "1 0 0 1 ~a ~a Tm" (numberizer x) (numberizer y)))) (numberizer (+ y (* (glyph-position-y-offset posn) scale)))))
;; Group segments that don't have any advance adjustments (flush (add1 idx))
(unless (zero? (- (glyph-position-x-advance posn) (glyph-position-advance-width posn))) #true]
(add-segment (add1 idx))) [else
#false])) ;; If the last character had an offset, reset the text position
(when previous-had-offset
(add-content doc (format "1 0 0 1 ~a ~a Tm" (numberizer (+ x tracking-adjustment)) (numberizer y))))
;; Group segments that don't have any advance adjustments
(unless (zero? (- (glyph-position-x-advance posn) (glyph-position-advance-width posn)))
(add-segment (add1 idx)))
#false])))
(values has-offset (+ x (* (glyph-position-x-advance posn) scale)))) (values has-offset (+ x (* (glyph-position-x-advance posn) scale))))
(flush (vector-length positions))) (flush (vector-length positions)))
@ -172,7 +178,7 @@ https://github.com/mbutterick/pdfkit/blob/master/lib/mixins/text.coffee
(add-content doc (format "~a Tc" character-tracking))) (add-content doc (format "~a Tc" character-tracking)))
;; Add the actual text ;; Add the actual text
(add-text doc x next-y str features) (add-text doc x next-y str features character-tracking)
;; end the text object ;; end the text object
(add-content doc "ET") (add-content doc "ET")

Loading…
Cancel
Save