Skip to content

Something is rotten in flip-x/flip-y #84

@benknoble

Description

@benknoble

(define (flip-y p)

Introduced by me and @soegaard in 8328b90 (cf. #29, #78).

I've observed this with a program like this one from my Frosthaven project, so you'll want to raco pkg install https://github.com/benknoble/frosthaven-manager to see the problem:

#lang racket

(require frosthaven-manager/gui/rich-text-display
         frosthaven-manager/curlique
         (only-in racket/gui/easy
                  render
                  window)
         pict)

(define (weird)
  (define boot-scale 3)
  (define (scale-point scale)
    {~> (-< car cdr) (>< (* scale)) cons})
  (ht-append
   -3
   (vr-append
    (hline (* boot-scale 8/3) 5)
    (hline (* boot-scale 8/4) 5)
    (hline (* boot-scale 8/3) 5))
   (rotate
    (flip-y
     (dc (λ (dc dx dy)
           (send dc draw-lines
                 (map (scale-point boot-scale)
                      '((0 . 0)
                        (2 . 0)
                        (3 . 1)
                        (4 . 0)
                        (6 . 0)
                        (8 . 1)
                        (4 . 4)
                        (4 . 10)
                        (0 . 10)
                        (0 . 0)))
                 dx dy))
         (* boot-scale 8)
         (* boot-scale 10)))
    (/ pi 6))))

(render
 (window
  (rich-text-display (list "first line" newline
                           "second" (weird) "line" newline
                           "third line"))))

In particular, make the window small enough that you need the vertical scroll, and watch what happens to the "boot" when you do. (Adding more lines gets more interesting.) Also note that in the final version where I fix the coordinates so I don't need flip-y, I use (rotate _ (/ pi -6)) instead of (rotate _ (/ pi 6)), which dovetails with comments below about rotations/etc.

@mflatt writes:

Just from a quick look, is there a reason to set the initial transformation matrix instead of using transform? I expected to see a combination of get-transformation, transform and set-transformation, instead. (If dc<%> were started from scratch, there would just be the current transformation — and a separate scale, offset, etc., would not be accessible.)

Another issue is that flip-x and flip-y lose track of nested picts. Impleemnting it with scale and inset, instead, would avoid those problems.

[RE: issue with (scale _ 1 -1)]: That's what inset can solve. But for rhombus/pict, https://github.com/racket/rhombus-prototype/blob/master/rhombus/pict/private/static.rhm#L156, I now remember that I went with hflip and then implemented vflip as hflip plus rotation, which may do better things with baselines.

A DC's state is four transformations, applied in order: initial matrix, translation, scale, and rotation. If the current transformation is based on non-identity variants of the last three, then directly setting the initial matrix one will have a weird effect, because the last three happen after that.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions