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)))
(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%)

View File

@ -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))

View File

@ -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)

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)])
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].
}

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 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].})

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
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?]{

View File

@ -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: