[racket] Fwd: Transformations and hc-append
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