[racket] Fwd: Transformations and hc-append

From: Robby Findler (robby at eecs.northwestern.edu)
Date: Sun Oct 5 08:00:18 EDT 2014

Thanks for keeping track of this.

Robby

On Sun, Oct 5, 2014 at 5:38 AM, Jens Axel Søgaard <jensaxel at soegaard.net> wrote:
> Turns out the problem has disappeared when the latest git version of
> Racket is used.
> Presumable the bug was in Cairo.
>
> /Jens Axel
>
>
> 2014-02-11 23:23 GMT+01:00 Robby Findler <robby at eecs.northwestern.edu>:
>> Thanks very much for looking into this. I'm sure the docs will benefit from
>> what you figure out!
>>
>> Robby
>>
>>
>> On Tue, Feb 11, 2014 at 3:54 PM, Jens Axel Søgaard <jensaxel at soegaard.net>
>> wrote:
>>>
>>> 2014-02-11 20:07 GMT+01:00 Robby Findler <robby at eecs.northwestern.edu>:
>>> > I'm not sure I can give you more than just hints (and certainly not a
>>> > specification)
>>>
>>> I suddenly realized I should look in the Cairo docs, to see their
>>> intended usage.
>>>
>>> > but probably the difference is that pict->bitmap is drawing
>>> > the pict at (0,0) in the DC and scribble is drawing it at some random
>>> > place.
>>> > But yeah, I'm sorry, that's still just a guess.
>>>
>>> After some experiments I think the reason is that Cairo has both user
>>> space coordinates (aka logical coordinates) and pattern space. When a
>>> pattern is
>>> created it has the same coordinate system has the user space, but if
>>> a transformation is applied (to user space) the spaces become different.
>>>
>>> I haven't yet fully grokked what the implications are.
>>>
>>> It is still odd that DrRacket and Scribble render the same pict
>>> differently though.
>>> If I call (convert the-pict 'png-bytes) in DrRacket I get the correct
>>> image, and
>>> Scribble doesn't do anything more.
>>>
>>> > And the examples at that link are really fantastic!
>>>
>>> Thanks!
>>>
>>> > On Tue, Feb 11, 2014 at 1:03 PM, Jens Axel Søgaard
>>> > <jensaxel at soegaard.net>
>>> > wrote:
>>> >>
>>> >> 2014-02-11 19:39 GMT+01:00 Robby Findler <robby at eecs.northwestern.edu>:
>>> >> > Is the problem that you need to use (more) absolute coordinates in
>>> >> > the
>>> >> > coordinate arguments to linear-gradient% (either that or set the
>>> >> > origin
>>> >> > of
>>> >> > the dc, in the case that you wanted to create the brush only once)?
>>> >>
>>> >> The problem is that it is unspecified (as far as I know) whether
>>> >> brushes
>>> >> used in picts are specified using absolute or relative coordinates. For
>>> >> solid
>>> >> brushes this makes no difference. For non-solid brushes (gradients and
>>> >> textures) there is a choice to be made. I got surprised by the
>>> >> behavior and thought
>>> >> of it as a bug (I was looking for one - I have an example where a pict
>>> >> shows up perfectly in DrRacket but renders differently in Scribble).
>>> >>
>>> >> If I in shady make a new gradient each time the pict is to be drawn, I
>>> >> get
>>> >> the
>>> >> behavior I want:
>>> >>
>>> >>                            (new linear-gradient%
>>> >>                                 [x0 x] [y0 y] [x1 (+ x (* 2 r))] [y1
>>> >> y] ; horizontal gradient
>>> >>                                 [stops (list (list 0   red)   ; (0,0)
>>> >> to ( r,0) red->green
>>> >>                                              (list 1/2 green) ; (r,0)
>>> >> to (2r,0) green->blue
>>> >>                                              (list 1   blue))])
>>> >>
>>> >> Since the pict constructors such as filled-rectangle use the pen, there
>>> >> were no way to figure out what was intended.
>>> >>
>>> >> The last example here: shows that Scribble converts p and (pict->bitmap
>>> >> p)
>>> >> differently. I am still puzzled by this.
>>> >>
>>> >>
>>> >>
>>> >> http://soegaard.github.io/docs/metapict/metapict.html#%28part._example-rgb-triangle%29
>>> >>
>>> >> /Jens Axel
>>> >>
>>> >>
>>> >> > On Tue, Feb 11, 2014 at 10:49 AM, Jens Axel Søgaard
>>> >> > <jensaxel at soegaard.net>
>>> >> > wrote:
>>> >> >>
>>> >> >> The intent of hc-append is that (hc-append p1 p2) draws p1 and p2
>>> >> >> beside each other.
>>> >> >>
>>> >> >> The question is whether (hc-append p p) should draw to identical
>>> >> >> picts?
>>> >> >>
>>> >> >> When I use a non-solid brush I get the two ps are drawn differently.
>>> >> >> In (hc-append p1 p2) I was expecting a transformation (translation)
>>> >> >> on
>>> >> >> the brush.
>>> >> >>
>>> >> >> As a demonstration I offer the following program (a bit long, but
>>> >> >> hopefully clear.
>>> >> >>
>>> >> >> See a syntax-highligthed version here:
>>> >> >> http://pasterack.org/pastes/7953
>>> >> >> The DrRacket output is here: http://imgur.com/5BRiY0Z
>>> >> >>
>>> >> >> /Jens Axel
>>> >> >>
>>> >> >>
>>> >> >> #lang racket
>>> >> >> (require pict)
>>> >> >>
>>> >> >> ; debug : value pict -> pict
>>> >> >> ;  return a pict, that when drawn prints the
>>> >> >> ;  brush and drawing context transformation
>>> >> >> (define (debug who pict)
>>> >> >>   (dc (lambda (dc x y)
>>> >> >>         (define b   (send dc get-brush))
>>> >> >>         (define bt  (send b  get-transformation))
>>> >> >>         (define dct (send dc get-transformation))
>>> >> >>         (displayln (list who 'x x 'y y 'brush: bt 'dc: dct))
>>> >> >>         (draw-pict pict dc x y))
>>> >> >>       (pict-width pict) (pict-height pict)))
>>> >> >>
>>> >> >> (define r 20) ; use same box side for the entire example
>>> >> >>
>>> >> >> ; a black filled rectangle
>>> >> >> (define (rect) (filled-rectangle r r))
>>> >> >>
>>> >> >> ;;; Examine whether hc-append does any transformation.
>>> >> >> "Expected Image:          Two squares a black and a red"
>>> >> >> "Expected Transformation: Same for A and B. Some difference for C."
>>> >> >> (debug 'A
>>> >> >>        (hc-append (debug 'B (rect))
>>> >> >>                   (debug 'C (colorize (rect) "red" ))))
>>> >> >>
>>> >> >> ;;; --------------------------------------------------------------
>>> >> >> (require racket/draw)
>>> >> >>
>>> >> >> ; colors
>>> >> >> (define (color: name) (send the-color-database find-color name))
>>> >> >> (define red   (color: "red"))
>>> >> >> (define green (color: "green"))
>>> >> >> (define blue  (color: "blue"))
>>> >> >>
>>> >> >> ; square-path : real real real real -> path%
>>> >> >> ;     make square with side r and upper left corner (x,y)
>>> >> >> (define (square-path x y w h)
>>> >> >>   (define p (new dc-path%))
>>> >> >>   (send p move-to    x      y)
>>> >> >>   (send p line-to    x   (+ y h))
>>> >> >>   (send p line-to (+ x w)(+ y h))
>>> >> >>   (send p line-to (+ x w)(+ y 0))
>>> >> >>   (send p line-to (+ x 0)(+ y 0))
>>> >> >>   p)
>>> >> >>
>>> >> >> ; fill : pict -> pict
>>> >> >> ;   draw a path around pict using current pen and brush
>>> >> >> (define (fill pict)
>>> >> >>   (define w (pict-width pict))
>>> >> >>   (define h (pict-height pict))
>>> >> >>   (dc (lambda (dc x y)
>>> >> >>         (draw-pict pict dc x y)
>>> >> >>         (send dc draw-path (square-path x y w h)))
>>> >> >>       w h))
>>> >> >>
>>> >> >> ; shady : pict -> pict
>>> >> >> ;   Draws pict with a brush given by a linear, horizontal
>>> >> >> ;   gradient from (0,0) to (0,2r). The colors are red->green->blue.
>>> >> >> (define (shady pict)
>>> >> >>   (dc (lambda (dc x y)
>>> >> >>         ; get old brush
>>> >> >>         (define b (send dc get-brush))
>>> >> >>         ; make new brush, only change gradient
>>> >> >>         (define new-brush
>>> >> >>           (new brush%
>>> >> >>                [color          (send b get-color)]
>>> >> >>                [style          (send b get-style)]
>>> >> >>                [stipple        (send b get-stipple)]
>>> >> >>                [gradient       (new linear-gradient%
>>> >> >>                                 [x0 0] [y0 0] [x1 (* 2 r)] [y1 0] ;
>>> >> >> horizontal gradient
>>> >> >>                                 [stops (list (list 0   red)   ;
>>> >> >> (0,0)
>>> >> >> to ( r,0) red->green
>>> >> >>                                              (list 1/2 green) ;
>>> >> >> (r,0)
>>> >> >> to (2r,0) green->blue
>>> >> >>                                              (list 1   blue))])]
>>> >> >>                [transformation (send b get-transformation)]))
>>> >> >>         ; use new brush to draw the pict
>>> >> >>         (send dc set-brush new-brush)
>>> >> >>         (draw-pict pict dc x y)
>>> >> >>         ; restore old brush
>>> >> >>         (send dc set-brush b))
>>> >> >>       (pict-width pict) (pict-height pict)))
>>> >> >>
>>> >> >> (define-syntax (echo stx) (syntax-case stx () [(_ expr) #'(values
>>> >> >> 'expr
>>> >> >> expr)]))
>>> >> >>
>>> >> >> (newline) (newline)
>>> >> >> "Expected: A (black) rectangle"
>>> >> >> (echo (rect))
>>> >> >> "Expected: A rectangle filled with nothing (default brush is empty)"
>>> >> >> (echo (fill (rect)))
>>> >> >> "Expected: A rectangle filled with linear gradient (red to green)"
>>> >> >> (echo (shady (fill (rect))))
>>> >> >> "Expected: Two red-to-green rectangles"
>>> >> >> (echo (hc-append (shady (fill (rect))) (shady (fill (rect)))))
>>> >> >> "Expected: Two red-to-green rectangles"
>>> >> >> (echo (let () (define p (shady (fill (rect)))) (hc-append p p)))
>>> >> >>
>>> >> >>
>>> >> >>
>>> >> >> --
>>> >> >> Jens Axel Søgaard
>>> >> >>
>>> >> >> ____________________
>>> >> >>   Racket Users list:
>>> >> >>   http://lists.racket-lang.org/users
>>> >> >
>>> >> >
>>> >>
>>> >>
>>> >>
>>> >> --
>>> >> --
>>> >> Jens Axel Søgaard
>>> >
>>> >
>>>
>>>
>>>
>>> --
>>> --
>>> Jens Axel Søgaard
>>
>>
>
>
>
> --
> --
> Jens Axel Søgaard


Posted on the users mailing list.