get-transformation, etc. methods on dc<%>

This commit is contained in:
Matthew Flatt 2010-08-02 08:25:47 -06:00
parent 2631853a28
commit 06a47a3c54
7 changed files with 209 additions and 42 deletions

View File

@ -94,7 +94,24 @@
(super-new))) (super-new)))
(define black (send the-color-database find-color "black"))
(define bitmap-dc% (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%) (install-bitmap-dc-class! bitmap-dc%)

View File

@ -102,6 +102,7 @@
(define-cairo cairo_matrix_translate (_fun _cairo_matrix_t-pointer _double* _double* -> _void)) (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_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_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 ;; Stroke & Fill
(define-cairo cairo_set_source_rgb (_fun _cairo_t _double* _double* _double* -> _void)) (define-cairo cairo_set_source_rgb (_fun _cairo_t _double* _double* _double* -> _void))

View File

@ -38,6 +38,16 @@
(define -bitmap-dc% #f) (define -bitmap-dc% #f)
(define (install-bitmap-dc-class! v) (set! -bitmap-dc% v)) (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 ;; dc-backend : interface
;; ;;
;; This is the interface that the backend specific code must implement ;; This is the interface that the backend specific code must implement
@ -238,6 +248,37 @@
(reset-matrix))) (reset-matrix)))
(def/public (get-rotation) rotation) (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]) (def/public (set-initial-matrix [matrix-vector? m])
(set! matrix (make-cairo_matrix_t (vector-ref m 0) (set! matrix (make-cairo_matrix_t (vector-ref m 0)
(vector-ref m 1) (vector-ref m 1)
@ -256,6 +297,19 @@
(cairo_matrix_t-x0 m) (cairo_matrix_t-x0 m)
(cairo_matrix_t-y0 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) (define/private (do-reset-matrix cr)
(cairo_set_matrix cr matrix) (cairo_set_matrix cr matrix)
(cairo_translate cr origin-x origin-y) (cairo_translate cr origin-x origin-y)

View File

@ -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)]) [mask (or/c (is-a?/c bitmap%) false/c)])
boolean?]{ boolean?]{
Display part of a bitmap with smooth scaling. For most platforms, this The same as @method[dc<%> draw-bitmap-section]. In older version, this
method produces better results than adjusting the scale of a drawing method smoothed drawing more than @method[dc<%> draw-bitmap-section], but
context before using @method[dc<%> draw-bitmap] and @method[dc<%> smoothing is now provided by @method[dc<%> draw-bitmap-section].
draw-bitmap-section], but this method is much slower.
} }

View File

@ -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 SeeMzParam @elem{(see @secref[#:doc reference-doc "parameters"])})
(define DrawSizeNote @elem{Restrictions on the magnitude of (define DrawSizeNote "")
drawing coordinates are described with @scheme[dc<%>].})
(define LineNumbering @elem{Lines are numbered starting with @scheme[0].}) (define LineNumbering @elem{Lines are numbered starting with @scheme[0].})
(define ParagraphNumbering @elem{Paragraphs are numbered starting with @scheme[0].}) (define ParagraphNumbering @elem{Paragraphs are numbered starting with @scheme[0].})

View File

@ -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 text. It represents output devices in a generic way; e.g., a canvas
has a drawing context, as does a printer. 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) @defmethod[(cache-font-metrics-key)
exact-integer?]{ 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 @math{(0,0)} in logical coordinates. The origin offset applies after
the initial transformation matrix, but before scaling and rotation. 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, coordinates. Rotation applies after the initial transformation matrix,
origin offset, and scaling. 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 coordinates. Scaling applies after the initial transformation matrix
and origin offset, but before rotation. 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) @defmethod[(get-text-mode)
(one-of/c 'solid 'transparent)]{ (one-of/c 'solid 'transparent)]{
Reports how text is drawn; see 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] @defmethod[(glyph-exists? [c char]
[font (or/c (is-a?/c font%) false/c) #f]) [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)]) @defmethod[(set-alpha [opacity (real-in 0 1)])
void?]{ 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 See @method[dc<%> get-initial-matrix] for information on the matrix as
represented by a vector @racket[m]. represented by a vector @racket[m].
Changing a @scheme[dc<%>] object's transformations does not affect See also @method[dc<%> transform], which adds a transformation to the
@scheme[region%] objects that were previously created. See current transformation, instead of changing the transformation
@scheme[region%] for more information. composition in the middle.
@|DrawSizeNote| @|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 @math{(0,0)} in logical coordinates. The origin offset applies after
the initial transformation matrix, but before scaling and rotation. the initial transformation matrix, but before scaling and rotation.
Changing a @scheme[dc<%>] object's transformations does not affect See also @method[dc<%> translate], which adds a translation to the
@scheme[region%] objects that were previously created. See current transformation, instead of changing the transformation
@scheme[region%] for more information. composition in the middle.
@|DrawSizeNote| @|DrawSizeNote|
@ -849,25 +890,25 @@ Set the rotation of logical coordinates in radians to device
coordinates. Rotation applies after the initial transformation matrix, coordinates. Rotation applies after the initial transformation matrix,
origin offset, and scaling. origin offset, and scaling.
Changing a @scheme[dc<%>] object's transformations does not affect See also @method[dc<%> rotate], which adds a rotation to the current
@scheme[region%] objects that were previously created. See transformation, instead of changing the transformation composition.
@scheme[region%] for more information.
@|DrawSizeNote| @|DrawSizeNote|
} }
@defmethod[(set-scale [x-scale (and/c real? (not/c negative?))] @defmethod[(set-scale [x-scale real?]
[y-scale (and/c real? (not/c negative?))]) [y-scale real?])
void?]{ void?]{
Sets a scaling factor that maps logical coordinates to device Sets a scaling factor that maps logical coordinates to device
coordinates. Scaling applies after the initial transformation matrix 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 See also @method[dc<%> scale], which adds a scale to the current
@scheme[region%] objects that were previously created. See transformation, instead of changing the transformation composition in
@scheme[region%] for more information. the middle.
@|DrawSizeNote| @|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?]) @defmethod[(start-doc [message string?])
boolean?]{ 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%)] @defmethod[(try-color [try (is-a?/c color%)]
[result (is-a?/c color%)]) [result (is-a?/c color%)])
void?]{ void?]{

View File

@ -29,23 +29,40 @@ Changes to the drawing toolbox:
* A `dc<%>' supports additional drawing transformations: a rotation * A `dc<%>' supports additional drawing transformations: a rotation
(via `set-rotation') and a general transformation matrix (via (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)', 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 where a point (x1, y1) is transformed to a point (x2, y2) with x2 =
x2 = xx*x1 + yx*y1 + x0 and y2 = xy*x1 + yy*y1 + y0. 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 The old translation and scaling transformations apply after the
initial matrix. The new rotation transformation applies after the initial matrix. The new rotation transformation applies after the
other transformations. This layering is a little redundant, since other transformations. This layering is redundant, since all
all transformations could be expressed in a single matrix, but it transformations can be expressed in a single matrix, but it is
is backward compatibile. 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 * A `region%' can be created as independent of any `dc<%>', in which
cases it uses the drawing context's current transformation at the cases it uses the drawing context's current transformation at the
time that it is installed as a clipping region. 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: Changes to the GUI toolbox: