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/fontland/fontland/table/cff/cff-operand.rkt

112 lines
4.2 KiB
Racket

5 years ago
#lang debug racket/base
5 years ago
(require racket/class xenomorph "cff-struct.rkt")
5 years ago
(provide CFFOperand)
#|
approximates
https://github.com/mbutterick/fontkit/blob/master/src/cff/CFFOperand.js
|#
(define FLOAT_EOF #xf)
(define FLOAT_LOOKUP (vector "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "." "E" "E-" "" "-"))
(define FLOAT_ENCODE_LOOKUP
5 years ago
(hash "." 10
5 years ago
"E" 11
"E-" 12
"-" 14))
5 years ago
(define CFFOperand%
(class x:base%
(super-new)
5 years ago
(define/augment (x:decode stream _ value)
5 years ago
(cond
[(<= 32 value 246) (- value 139)]
[(<= 247 value 250) (+ (* (- value 247) 256) (read-byte stream) 108)]
5 years ago
[(<= 251 value 254) (- (* (- 251 value) 256) (read-byte stream) 108)]
5 years ago
[(= value 28) (decode int16be stream)]
[(= value 29) (decode int32be stream)]
[(= value 30)
(for/fold ([strs null]
[break? #false]
5 years ago
#:result (* (string->number (apply string-append (reverse strs))) 1.0))
5 years ago
([i (in-naturals)]
#:break break?)
(define b (read-byte stream))
(define n1 (arithmetic-shift b -4))
5 years ago
5 years ago
(cond
[(= n1 FLOAT_EOF) (values strs 'break-now)]
[else
(let ([strs (cons (vector-ref FLOAT_LOOKUP n1) strs)])
(define n2 (bitwise-and b 15))
(cond
5 years ago
[(= n2 FLOAT_EOF) (values strs 'break-now)]
5 years ago
[else
(let ([strs (cons (vector-ref FLOAT_LOOKUP n2) strs)])
(values strs #false))]))]))]))
5 years ago
(define/augment (x:size value-arg _)
5 years ago
;; if the value needs to be forced to the largest size (32 bit)
;; e.g. for unknown pointers, set to 32768
5 years ago
(define value (cond
5 years ago
[(Ptr? value-arg) (if (Ptr-forceLarge value-arg) 32768 (Ptr-val value-arg))]
5 years ago
[else value-arg]))
5 years ago
(cond
[(not (integer? value)) ; floating point
(define str (number->string value))
(add1 (ceiling (/ (add1 (string-length str)) 2)))]
[(<= -107 value 107) 1]
[(<= -1131 value 1131) 2]
[(<= -32768 value 32767) 3]
[else 5]))
5 years ago
(define/augment (x:encode value-arg stream . _)
5 years ago
;; if the value needs to be forced to the largest size (32 bit)
;; e.g. for unknown pointers, save the old value and set to 32768
5 years ago
(define value (if (Ptr? value-arg) (Ptr-val value-arg) value-arg))
(define val (if value (string->number (format "~a" value)) 0))
5 years ago
(cond
5 years ago
[(and (Ptr? value-arg) (Ptr-forceLarge value-arg))
5 years ago
(encode uint8 29 stream)
(encode int32be val stream)]
[(not (integer? val)) ;; floating point
(encode uint8 30 stream)
(define str (list->vector (regexp-match* #rx"." (number->string val))))
5 years ago
(define n2
(for/last ([i (in-range 0 (vector-length str) 2)])
(define c1 (vector-ref str i))
(define n1 (hash-ref FLOAT_ENCODE_LOOKUP c1 (string->number c1)))
(define n2
(cond
[(= i (sub1 (vector-length str))) FLOAT_EOF]
[else
(define c2 (vector-ref str (add1 i)))
(hash-ref FLOAT_ENCODE_LOOKUP c2 (string->number c2))]))
(encode uint8 (bitwise-ior (arithmetic-shift n1 4) (bitwise-and n2 15)) stream)
n2))
5 years ago
(unless (= n2 FLOAT_EOF)
(encode uint8 (arithmetic-shift FLOAT_EOF 4) stream))]
[(<= -107 value 107)
(encode uint8 (+ val 139) stream)]
[(<= 108 value 1131)
(let ([val (- val 108)])
5 years ago
(encode uint8 (+ (arithmetic-shift val -8) 247) stream)
(encode uint8 (bitwise-and val #xff) stream))]
5 years ago
[(<= -1131 value -108)
5 years ago
(let ([val (- (+ val 108))])
5 years ago
(encode uint8 (+ (arithmetic-shift val -8) 251) stream)
5 years ago
(encode uint8 (bitwise-and val #xff) stream))]
[(<= -32768 value 32767)
(encode uint8 28 stream)
(encode uint16be val stream)]
[else
(encode uint8 29 stream)
(encode uint32be val stream)]))))
5 years ago
(define CFFOperand (make-object CFFOperand%))