From eef839b1ce1b31fa10a6ae75bff3a29b1c42ae45 Mon Sep 17 00:00:00 2001 From: Matthew Butterick Date: Wed, 29 Jan 2020 15:11:51 -0800 Subject: [PATCH] consolidate font-size and line-height attributes (addresses #45) --- quad/qtest/test-adjustment-sizing-tester.pdf | Bin 0 -> 9422 bytes quad/qtest/test-adjustment-sizing.rkt | 7 +++ quad/quad/scribblings/quad.scrbl | 13 +++--- quad/quadwriter/attrs.rkt | 13 +++--- quad/quadwriter/font.rkt | 43 ++++++++++++------- quad/quadwriter/render.rkt | 4 +- quad/quadwriter/tags.rkt | 6 +-- 7 files changed, 52 insertions(+), 34 deletions(-) create mode 100644 quad/qtest/test-adjustment-sizing-tester.pdf create mode 100644 quad/qtest/test-adjustment-sizing.rkt diff --git a/quad/qtest/test-adjustment-sizing-tester.pdf b/quad/qtest/test-adjustment-sizing-tester.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4d1d1c75d5bb131d7e1ef06470e68cfb65c8a3a4 GIT binary patch literal 9422 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 literal 0 HcmV?d00001 diff --git a/quad/qtest/test-adjustment-sizing.rkt b/quad/qtest/test-adjustment-sizing.rkt new file mode 100644 index 00000000..65f48022 --- /dev/null +++ b/quad/qtest/test-adjustment-sizing.rkt @@ -0,0 +1,7 @@ +#lang quadwriter + + +'(q ((column-count "2")(font-size "18")(line-height "2em")) "The lines in both columns should be vertically aligned. The column on the left is font size 18pt with line height 2em, or 36pt. The right column is font size 50%, or 9pt, with line height 4em, or 36pt." +(q ((break "column"))) +(q ((break "para"))) +(q ((font-size "50%")(line-height "4em")) "The lines in both columns should be vertically aligned. The column on the left is font size 18pt with line height 2em, or 36pt. The right column is font size 50%, or 9pt, with line height 4em, or 36pt.")) \ No newline at end of file diff --git a/quad/quad/scribblings/quad.scrbl b/quad/quad/scribblings/quad.scrbl index 891bafe5..a993117e 100644 --- a/quad/quad/scribblings/quad.scrbl +++ b/quad/quad/scribblings/quad.scrbl @@ -118,7 +118,7 @@ Next, on the REPL enter this: You will see the actual input to Quadwriter, which is called a @tech{Q-expression}: @repl-output{ -'(q () (q ((page-margin-left "120") (page-margin-top "80") (page-margin-bottom "120") (font-family "text") (line-height "17")) (q ((keep-first-lines "2") (keep-last-lines "3") (font-size-adjust "100%") (character-tracking "0") (hyphenate "true") (display "g49598")) "Brennan and Dale like fancy sauce."))) +'(q () (q ((page-margin-left "120") (page-margin-top "80") (page-margin-bottom "120") (font-family "text") (line-height "17")) (q ((keep-first-lines "2") (keep-last-lines "3") (font-size "100%") (character-tracking "0") (hyphenate "true") (display "g49598")) "Brennan and Dale like fancy sauce."))) } In the demos that follow, the input language will change slightly. But the PDF will be rendered the same way (by running the source file) and you can always look at @racket[doc] or use @racket[view-output]. @@ -625,9 +625,8 @@ Specify a quad with an image (either @racket{.png} or @racket{.jpeg}). @racket[i Sets the display type. Value is a string. Supply @racket["block"] as a value of this attribute to make the quad behave as a block-level element. } -@deftogether[(@defthing[#:kind "attribute" font-size symbol?] - @defthing[#:kind "attribute" font-size-adjust symbol?])]{ -Two ways of setting the point size for text. @racket[font-size] takes a @tech{dimension string}. @racket[font-size-adjust] takes a string representing a percentage (like @racket["120%"]) and sets the font size to the size of the parent, multiplied by the percentage. +@defthing[#:kind "attribute" font-size symbol?]{ +Sets the point size for text. Value is a @tech{dimension string}, a string representing a percentage (like @racket["120%"]), or an em size (like @racket["1.2em"]). If a percentage or em size is provided, the font size is the size of the parent multiplied by the percentage (or em). } @defthing[#:kind "attribute" font-family symbol?]{ @@ -666,9 +665,9 @@ Vertical offset of font baseline (positive values move the baseline up, negative Case transformation of string. Possibilities are @racket["uppercase"], @racket["lowercase"], or @racket["capitalize"] (= first letter of each word is uppercase, the rest is lowercase). } -@deftogether[(@defthing[#:kind "attribute" line-height symbol?] - @defthing[#:kind "attribute" line-height-adjust symbol?])]{ -Two ways of setting the distance between baselines. @racket[line-height] takes a @tech{dimension string}. @racket[line-height-adjust] takes a string representing a percentage (like @racket["120%"]) and sets the line height to the line height of the parent, multiplied by the percentage. + +@defthing[#:kind "attribute" line-height symbol?]{ +Sets the distance between baselines. Value is a @tech{dimension string}, a string representing a percentage (like @racket["120%"]), or an em size (like @racket["1.2em"]). If a percentage or em size is provided, the line height is the current font size multiplied by the percentage (or em). } TK: OT feature attributes, bullet attributes diff --git a/quad/quadwriter/attrs.rkt b/quad/quadwriter/attrs.rkt index 2d534c6f..555166e4 100644 --- a/quad/quadwriter/attrs.rkt +++ b/quad/quadwriter/attrs.rkt @@ -22,10 +22,11 @@ [#false str] ; a string other than a dimension string, so leave it [(list _ num-string unit) ((match unit - [(regexp #rx"(pt|point)(s)?$") values] - [(regexp #rx"in(ch(es)?)?$") in->pts] - [(regexp #rx"cm$") (compose1 in->pts cm->in)] - [(regexp #rx"mm$") (compose1 in->pts cm->in mm->cm)] + [(regexp #rx"(pt|point)(s)?$") values] ; points + [(regexp #rx"in(ch(es)?)?$") in->pts] ; inches + [(regexp #rx"cms?$") (compose1 in->pts cm->in)] ; cm + [(regexp #rx"mms?$") (compose1 in->pts cm->in mm->cm)] ; mm + [(regexp #rx"ems?$") (λ (num) (format "~aem" num))] ; em [_ (raise-argument-error 'parse-dimension "dimension string" str)]) (string->number num-string))])])) (define (copy-block-attrs source-hash dest-hash) @@ -66,7 +67,6 @@ Naming guidelines (define-attrs (font-family font-path font-size - font-size-adjust font-color font-features font-features-adjust @@ -79,7 +79,6 @@ Naming guidelines link href line-height - line-height-adjust hyphenate list-index no-colbr @@ -226,4 +225,4 @@ Naming guidelines :pdf-keywords)) #true)) (define (takes-path? k) - (and (memq k (list :image-file)) #true)) \ No newline at end of file + (and (memq k (list :image-file)) #true)) diff --git a/quad/quadwriter/font.rkt b/quad/quadwriter/font.rkt index c2f42036..18b53793 100644 --- a/quad/quadwriter/font.rkt +++ b/quad/quadwriter/font.rkt @@ -80,31 +80,42 @@ (define this-italic (hash-ref! attrs :font-italic #false)) (hash-set! attrs :font-path (font-attrs->path this-font-family this-bold this-italic)))) -(define (parse-percentage pstr) +(define (parse-adjustment pstr suffix) (and + pstr (string? pstr) - (string-suffix? pstr "%") - (/ (string->number (string-trim pstr "%")) 100.0))) + (string-suffix? pstr suffix) + (string->number (string-trim pstr suffix)))) -(define (adjuster-base attrs key adjustment-key default-value) - ;; font size and line height use this helper. - ;; because they both can be specified directly, - ;; or as an "adjustment" to the parent value, in which case - ;; we get the parent value and perform the adjustment. - (define this-val (hash-ref! attrs key default-value)) - (define this-val-adjust (parse-percentage (hash-ref! attrs adjustment-key "100%"))) - ;; we bake the adjustment into the val... - (hash-set! attrs key (and this-val (* this-val this-val-adjust))) - ;; and then set the adjustment back to 100% (since it's now accounted for) - (hash-set! attrs adjustment-key "100%")) +(define (parse-percentage pstr) + (match (parse-adjustment pstr "%") + [#false #false] + [res (/ res 100.0)])) (define (resolve-font-size! attrs) ;; convert font-size attributes into a simple font size - (adjuster-base attrs :font-size :font-size-adjust default-font-size)) + ;; we stashed the previous size in private key 'font-size-previous + (define prev-font-size-key 'font-size-previous) + (define val (hash-ref attrs :font-size default-font-size)) + (define adjustment (or (parse-percentage val) (parse-adjustment val "em"))) + ;; if our value represents an adjustment, we apply the adjustment to the previous value + ;; otherwise we use our value directly + (define base-size (if adjustment (hash-ref attrs prev-font-size-key default-font-size) val)) + (define base-size-adjusted (and base-size (* base-size (or adjustment 1)))) + ;; we write our new value into both font-size and font-size-previous + ;; because as we cascade down, we're likely to come across superseding values + ;; of font-size (but font-size-previous will persist) + (hash-set! attrs :font-size base-size-adjusted) + (hash-set! attrs prev-font-size-key base-size-adjusted)) (define (resolve-line-height! attrs) ;; convert line-height attributes into a simple line height - (adjuster-base attrs :line-height :line-height-adjust default-line-height)) + (hash-update! attrs :line-height + (λ (val) + (define adjustment (or (parse-percentage val) (parse-adjustment val "em"))) + (define base-height (if adjustment (hash-ref attrs :font-size) val)) + (and base-height (* base-height (or adjustment 1)))) + default-line-height)) (define (resolve-font-tracking! attrs) ;; if it's a percentage, we need to look at the font size. diff --git a/quad/quadwriter/render.rkt b/quad/quadwriter/render.rkt index 6134c988..5c1e6317 100644 --- a/quad/quadwriter/render.rkt +++ b/quad/quadwriter/render.rkt @@ -105,7 +105,9 @@ resolve-font-path! resolve-font-size! resolve-font-tracking! - resolve-line-height! + ;; we resolve line height after font size + ;; because line height might be dependent + resolve-line-height! parse-font-features!))]) (proc attrs))) diff --git a/quad/quadwriter/tags.rkt b/quad/quadwriter/tags.rkt index 51aa714c..2d118d31 100644 --- a/quad/quadwriter/tags.rkt +++ b/quad/quadwriter/tags.rkt @@ -25,7 +25,7 @@ [_ (qexpr (append (list->attrs :keep-first-lines "2" :keep-last-lines "3" - :font-size-adjust "100%" + :font-size "100%" :hyphenate "true" :display (symbol->string (gensym))) attrs) exprs)])) @@ -77,7 +77,7 @@ (define-tag-function (strong attrs exprs) (qexpr (append (list->attrs :font-bold "true" - :font-size-adjust "100%") + :font-size "100%") attrs) exprs)) (define b strong) @@ -91,7 +91,7 @@ (qexpr (append (list->attrs :font-italic "true" - :font-size-adjust "100%") attrs) exprs)) + :font-size "100%") attrs) exprs)) (define i em)