[racket-dev] draw-text always pixel aligned?

From: David Vanderson (david.vanderson at gmail.com)
Date: Tue Dec 17 13:33:08 EST 2013

Update - according to the cairo developers, this is a limitation of the 
current implementation of cairo, so there's nothing to be fixed. Thanks 
again for looking into it!


As a workaround, they suggested creating a path from the text and 
filling it, which works well:

#lang racket/gui

(define (draw-text dc offset)
   (send dc set-brush "red" 'solid)
   (send dc set-pen "red" 1 'transparent)

   (let ((p (new dc-path%)))
     (send p text-outline (send dc get-font) "hello" 0 0)
     (send dc draw-path p 0 0))

   (send dc set-brush "black" 'solid)
   (send dc set-pen "black" 1 'transparent)

   (let ((p (new dc-path%)))
     (send p text-outline (send dc get-font) "hello" 0 0)
     (send dc draw-path p offset offset))

   (send dc set-text-foreground "red")
   (send dc draw-text "hello" 0 20 #t)
   (send dc set-text-foreground "black")
   (send dc draw-text "hello" offset (+ 20 offset) #t)
   )

(define (draw-screen canvas dc)
   (send dc set-smoothing 'smoothed)
   (send dc set-font
         (send the-font-list find-or-create-font
               12 'default 'normal 'normal #f 'smoothed #f 'aligned))
   (send dc set-initial-matrix (vector 1 0 0 1 0 0))
   (for ((i 10))
     (draw-text dc (/ i 10.0))
     (send dc translate 50 0)))

(define frame (new frame% (label "Test draw-text")))

(define canvas
   (new canvas%
        (parent frame)
        (min-width 500)
        (min-height 100)
        (paint-callback draw-screen)))

(send frame show #t)





On 12/16/2013 02:16 PM, David Vanderson wrote:
> Thank you - I'll look into it.
>
> On 12/16/2013 02:14 PM, Matthew Flatt wrote:
>> Yes, it's the same on Mac and Windows.
>>
>> At Mon, 16 Dec 2013 14:12:18 -0500, David Vanderson wrote:
>>> Thanks for looking into it. Can you confirm if you see similar 
>>> output on
>>> a different platform (Mac or Win)?
>>>
>>> On 12/16/2013 12:26 PM, Matthew Flatt wrote:
>>>> I'm not sure about that part. I've confirmed that the cairo_move_to()
>>>> call just before pango_cairo_show_layout_line() varies the "y" 
>>>> argument
>>>> by 0.1, and I don't see any options that would affect vertical
>>>> alignment.
>>>>
>>>> At Mon, 16 Dec 2013 10:37:39 -0500, David Vanderson wrote:
>>>>> That makes sense, but the picture with 'unaligned seems strange
>>>>> (attached). It looks like each individual character is being pixel
>>>>> aligned, and also the vertical pixel drop doesn't happen until 
>>>>> it's 0.7
>>>>> pixels down. Does this make sense?
>>>>>
>>>>> On 12/16/2013 08:15 AM, Matthew Flatt wrote:
>>>>>> Did you mean to pass 'unaligned instead of 'aligned as the last
>>>>>> argument to `find-or-create-font`? That should disable pixel 
>>>>>> alignment.
>>>>>>
>>>>>> At Mon, 16 Dec 2013 01:28:23 -0500, David Vanderson wrote:
>>>>>>> Hello,
>>>>>>>
>>>>>>> It seems that draw-text always pixel-aligns its text. In the 
>>>>>>> example
>>>>>>> below, I draw a black "hello" on top of a red one, with a pixel 
>>>>>>> offset
>>>>>>> of 0, 0.1, 0.2, . . . 0.9. At least for me, I see no change 
>>>>>>> until 0.5,
>>>>>>> where the black text jumps a whole pixel (see attached image).
>>>>>>>
>>>>>>> Am I missing something? Do others see this behavior? (I'm on Linux)
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Dave
>>>>>>>
>>>>>>>
>>>>>>> #lang racket/gui
>>>>>>>
>>>>>>> (define (draw-text dc offset)
>>>>>>>       (send dc set-text-foreground "red")
>>>>>>>       (send dc draw-text "hello" 0 0 #t)
>>>>>>>       (send dc set-text-foreground "black")
>>>>>>>       (send dc draw-text "hello" offset offset #t))
>>>>>>>
>>>>>>> (define (draw-screen canvas dc)
>>>>>>>       (send dc set-smoothing 'smoothed)
>>>>>>>       (send dc set-font
>>>>>>>             (send the-font-list find-or-create-font
>>>>>>>                   12 'default 'normal 'normal #f 'smoothed #f 
>>>>>>> 'aligned))
>>>>>>>       (send dc set-initial-matrix (vector 1 0 0 1 0 0))
>>>>>>>       (for ((i 10))
>>>>>>>         (draw-text dc (/ i 10.0))
>>>>>>>         (send dc translate 50 0)))
>>>>>>>
>>>>>>> (define frame (new frame% (label "Test draw-text")))
>>>>>>>
>>>>>>> (define canvas
>>>>>>>       (new canvas%
>>>>>>>            (parent frame)
>>>>>>>            (min-width 500)
>>>>>>>            (min-height 100)
>>>>>>>            (paint-callback draw-screen)))
>>>>>>>
>>>>>>> (send frame show #t)
>>>>>
>>> ------------------------------------------------------------------------------ 
>>>
>>>>> [image/png "draw-text2-unaligned.png"] [~/Desktop & open] [~/Temp 
>>>>> & open]
>>>>> .
>


Posted on the dev mailing list.