From 06a47a3c54fb04ad598372303ff36b779f994e9c Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Mon, 2 Aug 2010 08:25:47 -0600 Subject: [PATCH] get-transformation, etc. methods on dc<%> --- collects/racket/draw/bitmap-dc.rkt | 19 ++- collects/racket/draw/cairo.rkt | 1 + collects/racket/draw/dc.rkt | 54 +++++++ .../scribblings/gui/bitmap-dc-class.scrbl | 7 +- collects/scribblings/gui/blurbs.rkt | 3 +- collects/scribblings/gui/dc-intf.scrbl | 136 ++++++++++++++---- doc/release-notes/racket/Draw_and_GUI_5_5.txt | 31 +++- 7 files changed, 209 insertions(+), 42 deletions(-) diff --git a/collects/racket/draw/bitmap-dc.rkt b/collects/racket/draw/bitmap-dc.rkt index 46d245bf6b..54619c8b93 100644 --- a/collects/racket/draw/bitmap-dc.rkt +++ b/collects/racket/draw/bitmap-dc.rkt @@ -94,7 +94,24 @@ (super-new))) +(define black (send the-color-database find-color "black")) + (define bitmap-dc% - (dc-mixin dc-backend%)) + (class (dc-mixin dc-backend%) + (inherit draw-bitmap-section) + + (def/public (draw-bitmap-section-smooth [bitmap% src] + [real? dest-x] + [real? dest-y] + [real? src-x] + [real? src-y] + [real? src-w] + [real? src-h] + [(symbol-in solid opaque xor) [style 'solid]] + [(make-or-false color%) [color black]] + [(make-or-false bitmap%) [mask #f]]) + (draw-bitmap-section src dest-x dest-y src-x src-y src-w src-h style color mask)) + + (super-new))) (install-bitmap-dc-class! bitmap-dc%) diff --git a/collects/racket/draw/cairo.rkt b/collects/racket/draw/cairo.rkt index f0de760649..d8c3472714 100644 --- a/collects/racket/draw/cairo.rkt +++ b/collects/racket/draw/cairo.rkt @@ -102,6 +102,7 @@ (define-cairo cairo_matrix_translate (_fun _cairo_matrix_t-pointer _double* _double* -> _void)) (define-cairo cairo_matrix_scale (_fun _cairo_matrix_t-pointer _double* _double* -> _void)) (define-cairo cairo_matrix_rotate (_fun _cairo_matrix_t-pointer _double* -> _void)) +(define-cairo cairo_matrix_multiply (_fun _cairo_matrix_t-pointer _cairo_matrix_t-pointer _cairo_matrix_t-pointer -> _void)) ;; Stroke & Fill (define-cairo cairo_set_source_rgb (_fun _cairo_t _double* _double* _double* -> _void)) diff --git a/collects/racket/draw/dc.rkt b/collects/racket/draw/dc.rkt index 89a45b53d7..7ae4dfd566 100644 --- a/collects/racket/draw/dc.rkt +++ b/collects/racket/draw/dc.rkt @@ -38,6 +38,16 @@ (define -bitmap-dc% #f) (define (install-bitmap-dc-class! v) (set! -bitmap-dc% v)) +(define (transformation-vector? v) + (and (vector? v) + (= 6 (vector-length v)) + (matrix-vector? (vector-ref v 0)) + (real? (vector-ref v 1)) + (real? (vector-ref v 2)) + (real? (vector-ref v 3)) + (real? (vector-ref v 4)) + (real? (vector-ref v 5)))) + ;; dc-backend : interface ;; ;; This is the interface that the backend specific code must implement @@ -238,6 +248,37 @@ (reset-matrix))) (def/public (get-rotation) rotation) + (def/public (translate [real? ox] [real? oy]) + (transform (vector 1 0 0 1 ox oy))) + (def/public (scale [real? sx] [real? sy]) + (transform (vector sx 0 0 sy 0 0))) + (def/public (rotate [real? theta]) + (let ([s (sin (- theta))] + [c (cos (- theta))]) + (transform (vector c s (- s) c 0 0)))) + + (def/public (transform [matrix-vector? mi]) + (let* ([m matrix] + [mx (make-cairo_matrix_t 1 0 0 1 0 0)] + [mx2 (make-cairo_matrix_t (vector-ref mi 0) + (vector-ref mi 1) + (vector-ref mi 2) + (vector-ref mi 3) + (vector-ref mi 4) + (vector-ref mi 5))]) + (cairo_matrix_rotate mx (- rotation)) + (cairo_matrix_scale mx scale-x scale-y) + (cairo_matrix_translate mx origin-x origin-y) + (cairo_matrix_multiply mx mx m) + (cairo_matrix_multiply mx mx mx2) + (set! origin-x 0.0) + (set! origin-y 0.0) + (set! scale-x 1.0) + (set! scale-y 1.0) + (set! rotation 0.0) + (set! matrix mx) + (reset-matrix))) + (def/public (set-initial-matrix [matrix-vector? m]) (set! matrix (make-cairo_matrix_t (vector-ref m 0) (vector-ref m 1) @@ -256,6 +297,19 @@ (cairo_matrix_t-x0 m) (cairo_matrix_t-y0 m)))) + (def/public (get-transformation) + (vector-immutable (get-initial-matrix) + origin-x origin-y + scale-x scale-y + rotation)) + + (def/public (set-transformation [transformation-vector? v]) + (set-initial-matrix (vector-ref v 0)) + (set-origin (vector-ref v 1) (vector-ref v 2)) + (set-scale (vector-ref v 3) (vector-ref v 4)) + (set-rotation (vector-ref v 5))) + + (define/private (do-reset-matrix cr) (cairo_set_matrix cr matrix) (cairo_translate cr origin-x origin-y) diff --git a/collects/scribblings/gui/bitmap-dc-class.scrbl b/collects/scribblings/gui/bitmap-dc-class.scrbl index d2f907971c..58a50f3ec3 100644 --- a/collects/scribblings/gui/bitmap-dc-class.scrbl +++ b/collects/scribblings/gui/bitmap-dc-class.scrbl @@ -39,10 +39,9 @@ Creates a new memory DC. If @scheme[bitmap] is not @scheme[#f], it is [mask (or/c (is-a?/c bitmap%) false/c)]) boolean?]{ -Display part of a bitmap with smooth scaling. For most platforms, this - method produces better results than adjusting the scale of a drawing - context before using @method[dc<%> draw-bitmap] and @method[dc<%> - draw-bitmap-section], but this method is much slower. +The same as @method[dc<%> draw-bitmap-section]. In older version, this + method smoothed drawing more than @method[dc<%> draw-bitmap-section], but + smoothing is now provided by @method[dc<%> draw-bitmap-section]. } diff --git a/collects/scribblings/gui/blurbs.rkt b/collects/scribblings/gui/blurbs.rkt index ae2818d6e4..bd23f1dbbc 100644 --- a/collects/scribblings/gui/blurbs.rkt +++ b/collects/scribblings/gui/blurbs.rkt @@ -152,8 +152,7 @@ information@|details|, even if the editor currently has delayed refreshing (see (define SeeMzParam @elem{(see @secref[#:doc reference-doc "parameters"])}) - (define DrawSizeNote @elem{Restrictions on the magnitude of - drawing coordinates are described with @scheme[dc<%>].}) + (define DrawSizeNote "") (define LineNumbering @elem{Lines are numbered starting with @scheme[0].}) (define ParagraphNumbering @elem{Paragraphs are numbered starting with @scheme[0].}) diff --git a/collects/scribblings/gui/dc-intf.scrbl b/collects/scribblings/gui/dc-intf.scrbl index a7c56e2de5..7a7a5db392 100644 --- a/collects/scribblings/gui/dc-intf.scrbl +++ b/collects/scribblings/gui/dc-intf.scrbl @@ -7,12 +7,6 @@ A @scheme[dc<%>] object is a drawing context for drawing graphics and text. It represents output devices in a generic way; e.g., a canvas has a drawing context, as does a printer. -The drawing methods, such as @method[dc<%> draw-rectangle], accept -real number values as arguments, but the results are only well-defined -when the drawing coordinates are in the range @scheme[-16383] to -@scheme[16383]. This restriction applies to the coordinates both -before and after offsets and scaling factors are applied. - @defmethod[(cache-font-metrics-key) exact-integer?]{ @@ -530,7 +524,7 @@ following order: ] -See also @method[dc<%> set-initial-matrix]. +See also @method[dc<%> set-initial-matrix] and @method[dc<%> get-transformation]. } @@ -542,7 +536,7 @@ Returns the device origin, i.e., the location in device coordinates of @math{(0,0)} in logical coordinates. The origin offset applies after the initial transformation matrix, but before scaling and rotation. -See also @method[dc<%> set-origin]. +See also @method[dc<%> set-origin] and @method[dc<%> get-transformation]. } @@ -560,7 +554,7 @@ Returns the rotation of logical coordinates in radians to device coordinates. Rotation applies after the initial transformation matrix, origin offset, and scaling. -See also @method[dc<%> set-rotation]. +See also @method[dc<%> set-rotation] and @method[dc<%> get-transformation]. } @@ -571,7 +565,7 @@ Returns the scaling factor that maps logical coordinates to device coordinates. Scaling applies after the initial transformation matrix and origin offset, but before rotation. -See also @method[dc<%> set-scale]. +See also @method[dc<%> set-scale] and @method[dc<%> get-transformation]. } @@ -665,12 +659,36 @@ set-text-foreground]. } + @defmethod[(get-text-mode) (one-of/c 'solid 'transparent)]{ Reports how text is drawn; see -@method[dc<%> set-text-mode] . +@method[dc<%> set-text-mode].} + + +@defmethod[(get-transformation) + (vector/c (vector/c real? real? real? real? real? real?) + real? real? real? real? real?)]{ + +Returns the current transformation setting of the drawing context in a +form that is suitable for restoration via @method[dc<%> +set-transformation]. + +The vector content is as follows: + +@itemlist[ + + @item{the initial transformation matrix; see @method[dc<%> + get-initial-matrix];} + + @item{the X and Y origin; see @method[dc<%> get-origin];} + + @item{the X and Y scale; see @method[dc<%> get-origin];} + + @item{a rotation; see @method[dc<%> get-rotation].} + +]} -} @defmethod[(glyph-exists? [c char] [font (or/c (is-a?/c font%) false/c) #f]) @@ -698,6 +716,30 @@ Returns @scheme[#t] if the drawing context is usable. } +@defmethod[(rotate [angle real?]) void?]{ + +Adds a rotation of @racket[angle] radians to the drawing context's +current transformation. + +Afterward, the drawing context's transformation is represented in the +initial transformation matrix, and the separate origin, scale, and +rotation settings have their identity values. + +} + +@defmethod[(scale [x-scale real?] + [y-scale real?]) + void?]{ + +Adds a scaling of @racket[x-scale] in the X-direction and +@racket[y-scale] in the Y-direction to the drawing context's current +transformation. + +Afterward, the drawing context's transformation is represented in the +initial transformation matrix, and the separate origin, scale, and +rotation settings have their identity values. + +} @defmethod[(set-alpha [opacity (real-in 0 1)]) void?]{ @@ -790,9 +832,9 @@ Set a transformation matrix that converts logical coordinates to See @method[dc<%> get-initial-matrix] for information on the matrix as represented by a vector @racket[m]. -Changing a @scheme[dc<%>] object's transformations does not affect - @scheme[region%] objects that were previously created. See - @scheme[region%] for more information. +See also @method[dc<%> transform], which adds a transformation to the + current transformation, instead of changing the transformation + composition in the middle. @|DrawSizeNote| @@ -806,10 +848,9 @@ Sets the device origin, i.e., the location in device coordinates of @math{(0,0)} in logical coordinates. The origin offset applies after the initial transformation matrix, but before scaling and rotation. -Changing a @scheme[dc<%>] object's transformations does not affect - @scheme[region%] objects that were previously created. See -@scheme[region%] for more information. - +See also @method[dc<%> translate], which adds a translation to the + current transformation, instead of changing the transformation + composition in the middle. @|DrawSizeNote| @@ -849,25 +890,25 @@ Set the rotation of logical coordinates in radians to device coordinates. Rotation applies after the initial transformation matrix, origin offset, and scaling. -Changing a @scheme[dc<%>] object's transformations does not affect - @scheme[region%] objects that were previously created. See - @scheme[region%] for more information. +See also @method[dc<%> rotate], which adds a rotation to the current + transformation, instead of changing the transformation composition. @|DrawSizeNote| } -@defmethod[(set-scale [x-scale (and/c real? (not/c negative?))] - [y-scale (and/c real? (not/c negative?))]) +@defmethod[(set-scale [x-scale real?] + [y-scale real?]) void?]{ Sets a scaling factor that maps logical coordinates to device coordinates. Scaling applies after the initial transformation matrix - and origin offset, but before rotation. + and origin offset, but before rotation. Negative scaling factors have + the effect of flipping. -Changing a @scheme[dc<%>] object's transformations does not affect - @scheme[region%] objects that were previously created. See - @scheme[region%] for more information. +See also @method[dc<%> scale], which adds a scale to the current + transformation, instead of changing the transformation composition in + the middle. @|DrawSizeNote| @@ -957,6 +998,16 @@ Determines how text is drawn: } + +@defmethod[(set-transformation + [t (vector/c (vector/c real? real? real? real? real? real?) + real? real? real? real? real?)]) + void?]{ + +Sets the draw context's transformation. See @method[dc<%> +get-transformation] for information about @racket[t].} + + @defmethod[(start-doc [message string?]) boolean?]{ @@ -991,6 +1042,35 @@ For printer or PostScript output, an exception is raised if } +@defmethod[(transform [m (vector/c real? real? real? real? real? real?)]) + void?]{ + +Adds a transformation by @racket[m] to the drawing context's current +transformation. + +See @method[dc<%> get-initial-matrix] for information on the matrix as + represented by a vector @racket[m]. + +Afterward, the drawing context's transformation is represented in the +initial transformation matrix, and the separate origin, scale, and +rotation settings have their identity values. + +} + +@defmethod[(translate [dx real?] + [dy real?]) + void?]{ + +Adds a scaling of @racket[dx] in the X-direction and @racket[dy] in +the Y-direction to the drawing context's current transformation. + +Afterward, the drawing context's transformation is represented in the +initial transformation matrix, and the separate origin, scale, and +rotation settings have their identity values. + +} + + @defmethod[(try-color [try (is-a?/c color%)] [result (is-a?/c color%)]) void?]{ diff --git a/doc/release-notes/racket/Draw_and_GUI_5_5.txt b/doc/release-notes/racket/Draw_and_GUI_5_5.txt index 5d3b5c89b1..e70af0de5e 100644 --- a/doc/release-notes/racket/Draw_and_GUI_5_5.txt +++ b/doc/release-notes/racket/Draw_and_GUI_5_5.txt @@ -29,23 +29,40 @@ Changes to the drawing toolbox: * A `dc<%>' supports additional drawing transformations: a rotation (via `set-rotation') and a general transformation matrix (via - `set-initial-matrix'). + `set-initial-matrix'). Scaling factors can be negative, which + corresponds to flipping the direction of drawing. A transformation matrix has the form `(vector xx xy yx yy x0 y0)', - where a point (x1, y1) is transformed to a point (x2, y2) with - x2 = xx*x1 + yx*y1 + x0 and y2 = xy*x1 + yy*y1 + y0. + where a point (x1, y1) is transformed to a point (x2, y2) with x2 = + xx*x1 + yx*y1 + x0 and y2 = xy*x1 + yy*y1 + y0, which is the usual + convention. + + New methods `translate', `scale', `rotate', and `transform' + simplify adding a further translation, scaling, rotation, or + arbitrary matrix transformation on top of the current + transformation. The new `get-translation' and `set-translation' + methods help to capture and restore transformation settings. The old translation and scaling transformations apply after the initial matrix. The new rotation transformation applies after the - other transformations. This layering is a little redundant, since - all transformations could be expressed in a single matrix, but it - is backward compatibile. + other transformations. This layering is redundant, since all + transformations can be expressed in a single matrix, but it is + backward-compatibile. Methods like `get-translation', + `set-translation', `scale', etc. help hide the reundancy. + + The alpha value of a `dc<%>' (as set by `set-alpha') is used for + all drawing operations, including drawing a bitmap. + + The `draw-bitmap' and `draw-bitmap-section' methods now smooth + bitmaps while scaling, so the `draw-bitmap-section-smooth' method + of `bitmap-dc%' simply calls `draw-bitmap-section'. * A `region%' can be created as independent of any `dc<%>', in which cases it uses the drawing context's current transformation at the time that it is installed as a clipping region. - * The old 'xor mode for pens and brushes is no longer available. + * The old 'xor mode for pens and brushes is no longer available + (since it is not supported by Cairo). Changes to the GUI toolbox: