From 114c64765d4b9076101b111c1afa41ceac4ea39c Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Fri, 8 Apr 2011 11:39:41 -0600 Subject: [PATCH] racket/draw: fix baseline on font substitution in "combine" mode --- collects/racket/draw/private/dc.rkt | 51 +++++++++++++++++------------ 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/collects/racket/draw/private/dc.rkt b/collects/racket/draw/private/dc.rkt index 5f9c71defe..af7a2ae3e6 100644 --- a/collects/racket/draw/private/dc.rkt +++ b/collects/racket/draw/private/dc.rkt @@ -1244,7 +1244,7 @@ ;; This is combine mode. It has to be a little complicated, after all, ;; because we may need to implement font substitution ourselves, which ;; breaks the string into multiple layouts. - (let loop ([s s] [w 0.0] [h 0.0] [d 0.0] [a 0.0]) + (let loop ([s s] [draw? draw?] [measured? #f] [w 0.0] [h 0.0] [d 0.0] [a 0.0]) (cond [(not s) (when rotate? (cairo_restore cr)) @@ -1280,28 +1280,37 @@ ;; find a face that works for the long character: (install-alternate-face (string-ref s 0) layout font desc attrs context)) (substring s (max 1 ok-count))))]) - (let ([logical (make-PangoRectangle 0 0 0 0)]) - (pango_layout_get_extents layout #f logical) - (when draw? - (let ([bl (/ (pango_layout_get_baseline layout) (exact->inexact PANGO_SCALE))]) - (pango_layout_get_extents layout #f logical) - (cairo_move_to cr (text-align-x/delta (+ x w) 0) (text-align-y/delta (+ y bl) 0)) - ;; Draw the text: - (pango_cairo_show_layout_line cr (pango_layout_get_line_readonly layout 0)))) - (cond - [(and draw? (not next-s)) - (g_object_unref layout) - (when rotate? (cairo_restore cr))] - [else - (let ([nw (if blank? - 0.0 - (integral (/ (PangoRectangle-width logical) (exact->inexact PANGO_SCALE))))] - [nh (/ (PangoRectangle-height logical) (exact->inexact PANGO_SCALE))] + (cond + [(and draw? next-s (not measured?)) + ;; It's going to take multiple layouts, so first gather measurements. + (let-values ([(w2 h d a) (loop s #f #f w h d a)]) + ;; draw again, supplying `h', `d', and `a' for the whole line + (loop s #t #t w h d a))] + [else + (let ([logical (make-PangoRectangle 0 0 0 0)]) + (pango_layout_get_extents layout #f logical) + (let ([nh (/ (PangoRectangle-height logical) (exact->inexact PANGO_SCALE))] [nd (/ (- (PangoRectangle-height logical) (pango_layout_get_baseline layout)) - (exact->inexact PANGO_SCALE))] - [na 0.0]) - (loop next-s (+ w nw) (max h nh) (max d nd) (max a na)))]))))])) + (exact->inexact PANGO_SCALE))]) + (when draw? + (let ([bl (if measured? (- h d) (- nh nd))]) + (pango_layout_get_extents layout #f logical) + (cairo_move_to cr + (text-align-x/delta (+ x w) 0) + (text-align-y/delta (+ y bl) 0)) + ;; Draw the text: + (pango_cairo_show_layout_line cr (pango_layout_get_line_readonly layout 0)))) + (cond + [(and draw? (not next-s)) + (g_object_unref layout) + (when rotate? (cairo_restore cr))] + [else + (let ([nw (if blank? + 0.0 + (integral (/ (PangoRectangle-width logical) (exact->inexact PANGO_SCALE))))] + [na 0.0]) + (loop next-s measured? draw? (+ w nw) (max h nh) (max d nd) (max a na)))])))])))])) ;; This is character-by-character mode. It uses a cached per-character+font layout ;; object. (let ([cache (if (or combine?