racket/draw: fix outline adjustment in `draw-rectangle' and others

This commit is contained in:
Matthew Flatt 2012-05-10 09:12:48 -06:00
parent dbd940611e
commit 1432912357
2 changed files with 52 additions and 42 deletions

View File

@ -312,6 +312,15 @@
(set! x-align-delta (/ (bitwise-and 1 (max 1 (inexact->exact (floor (* effective-scale-x w))))) 2.0)) (set! x-align-delta (/ (bitwise-and 1 (max 1 (inexact->exact (floor (* effective-scale-x w))))) 2.0))
(set! y-align-delta (/ (bitwise-and 1 (max 1 (inexact->exact (floor (* effective-scale-y w))))) 2.0)))))) (set! y-align-delta (/ (bitwise-and 1 (max 1 (inexact->exact (floor (* effective-scale-y w))))) 2.0))))))
(define/private (sub1w w)
(if (aligned? smoothing)
(max 0.0 (- w (/ effective-scale-x)))
w))
(define/private (sub1h h)
(if (aligned? smoothing)
(max 0.0 (- h (/ effective-scale-y)))
h))
(def/public (set-font [font% f]) (def/public (set-font [font% f])
(set! font f)) (set! font f))
@ -994,15 +1003,15 @@
(with-cr (with-cr
(check-ok who) (check-ok who)
cr cr
(let ([draw-one (lambda (align-x align-y brush? pen? d) (let ([draw-one (lambda (align-x align-y brush? pen? sub1w sub1h)
(let* ([orig-x x] (let* ([orig-x x]
[orig-y y] [orig-y y]
[x (align-x x)] [x (align-x x)]
[y (align-y y)] [y (align-y y)]
[width (- (align-x (+ orig-x width)) x)] [width (- (align-x (+ orig-x width)) x)]
[width (if (width . >= . d) (- width d) width)] [width (sub1w width)]
[height (- (align-y (+ orig-y height)) y)] [height (- (align-y (+ orig-y height)) y)]
[height (if (height . >= . d) (- height d) height)] [height (sub1h height)]
[radius-x (/ width 2)] [radius-x (/ width 2)]
[radius-y (/ height 2)] [radius-y (/ height 2)]
[center-x (+ x radius-x)] [center-x (+ x radius-x)]
@ -1024,9 +1033,10 @@
(cairo_restore cr) (cairo_restore cr)
(draw cr brush? pen?))))]) (draw cr brush? pen?))))])
(when (brush-draws?) (when (brush-draws?)
(draw-one (lambda (x) x) (lambda (y) y) #t #f 0.0)) (draw-one (lambda (x) x) (lambda (y) y) #t #f (lambda (x) x) (lambda (x) x)))
(when (pen-draws?) (when (pen-draws?)
(draw-one (lambda (x) (align-x x)) (lambda (y) (align-y y)) #f #t 1.0))))) (draw-one (lambda (x) (align-x x)) (lambda (y) (align-y y)) #f #t
(lambda (x) (sub1w x)) (lambda (x) (sub1h x)))))))
(def/public (draw-arc [real? x] [real? y] [nonnegative-real? width] [nonnegative-real? height] (def/public (draw-arc [real? x] [real? y] [nonnegative-real? width] [nonnegative-real? height]
[real? start-radians] [real? end-radians]) [real? start-radians] [real? end-radians])
@ -1100,8 +1110,8 @@
(cairo_new_path cr) (cairo_new_path cr)
(cairo_rectangle cr x y width height) (cairo_rectangle cr x y width height)
(draw cr #t #f) (draw cr #t #f)
(let ([w2 (- (align-x (+ x (sub1 width))) ax)] (let ([w2 (- (align-x (+ x (sub1w width))) ax)]
[h2 (- (align-y (+ y (sub1 height))) ay)]) [h2 (- (align-y (+ y (sub1h height))) ay)])
(when (and (positive? w2) (when (and (positive? w2)
(positive? h2)) (positive? h2))
(cairo_new_path cr) (cairo_new_path cr)
@ -1125,7 +1135,7 @@
(rounded-rect x y width height (lambda (x) x) (lambda (y) y)) (rounded-rect x y width height (lambda (x) x) (lambda (y) y))
(draw cr #t #f)) (draw cr #t #f))
(when (pen-draws?) (when (pen-draws?)
(rounded-rect x y (sub1 width) (sub1 height) (rounded-rect x y (sub1w width) (sub1h height)
(lambda (x) (align-x x)) (lambda (y) (align-y y))) (lambda (x) (align-x x)) (lambda (y) (align-y y)))
(draw cr #f #t))))) (draw cr #f #t)))))

View File

@ -66,14 +66,16 @@ Draws a counter-clockwise circular arc, a part of the ellipse
The current pen is used for the arc. If the current brush is not The current pen is used for the arc. If the current brush is not
transparent, it is used to fill the wedge bounded by the arc plus transparent, it is used to fill the wedge bounded by the arc plus
lines (not drawn) extending to the center of the inscribed ellipse. lines (not drawn) extending to the center of the inscribed ellipse.
If both the pen and brush are non-transparent, the wedge is filled
with the brush before the arc is drawn with the pen.
The wedge and arc meet so that no space is left between them, but the
precise overlap between the wedge and arc is platform- and
size-specific. Typically, the regions drawn by the brush and pen
overlap. In unsmoothed or aligned mode, the path for the outline is
adjusted by shrinking the bounding ellipse width and height by one
drawing unit after scaling.
If both the pen and brush are non-transparent, the wedge is filled
with the brush before the arc is drawn with the pen. The wedge and
arc meet so that no space is left between them, but the precise
overlap between the wedge and arc is platform- and size-specific.
Typically, the regions drawn by the brush and pen overlap. More
generally, the pen is centered over the outline of the arc, rounding
toward the center in unsmoothed mode.
@|DrawSizeNote| @|DrawSizeNote|
@ -179,15 +181,16 @@ See @method[dc<%> draw-bitmap] for information about @racket[dest-x],
Draws an ellipse contained in a rectangle with the given top-left Draws an ellipse contained in a rectangle with the given top-left
corner and size. The current pen is used for the outline, and the corner and size. The current pen is used for the outline, and the
current brush is used for filling the shape. current brush is used for filling the shape. If both the pen and
brush are non-transparent, the ellipse is filled with the brush
before the outline is drawn with the pen.
If both the pen and brush are non-transparent, the ellipse is filled Brush filling and pen outline meet so that no space is left between
with the brush before the outline is drawn with the pen. The filling them, but the precise overlap between the filling and outline is
and outline meet so that no space is left between them, but the platform- and size-specific. Thus, the regions drawn by the brush
precise overlap between the filling and outline is platform- and and pen may partially overlap. In unsmoothed or aligned mode, the
size-specific. Typically, the regions drawn by the brush and pen path for the outline is adjusted by shrinking the ellipse width and
overlap. More generally, the pen is centered over the outline of the height by one drawing unit after scaling.
ellipse, rounding toward the center in unsmoothed mode.
@|DrawSizeNote| @|DrawSizeNote|
@ -324,17 +327,15 @@ See also @method[dc<%> set-smoothing] for information on the
Draws a rectangle with the given top-left corner and size. The Draws a rectangle with the given top-left corner and size. The
current pen is used for the outline and the current brush for filling current pen is used for the outline and the current brush for filling
the shape. the shape. If both the pen and brush are non-transparent, the
rectangle is filled with the brush before the outline is drawn with
the pen.
If both the pen and brush are non-transparent, the rectangle is filled In unsmoothed or aligned mode, when the pen is size 0 or 1, the
with the brush before the outline is drawn with the pen. In filling precisely overlaps the entire outline. More generally, in
unsmoothed mode, when the pen is size 0 or 1, the filling precisely unsmoothed or aligned mode, the path for the outline is adjusted by
overlaps the entire outline. As a result, if a rectangle is drawn shrinking the rectangle width and height by one drawing unit after
with a size-0 or size-1 @racket['xor] @racket[pen%] and an scaling.
@racket['xor] @racket[brush%], the outline is xored twice (first by
the brush, then by the pen), leaving it unchanged. More generally,
the pen is centered over the outline of the rectangle, rounding
toward the center in unsmoothed mode.
See also @method[dc<%> set-smoothing] for information on the See also @method[dc<%> set-smoothing] for information on the
@racket['aligned] smoothing mode. @racket['aligned] smoothing mode.
@ -354,7 +355,8 @@ See also @method[dc<%> set-smoothing] for information on the
Draws a rectangle with the given top-left corner, and with the given Draws a rectangle with the given top-left corner, and with the given
size. The corners are quarter-circles using the given radius. The size. The corners are quarter-circles using the given radius. The
current pen is used for the outline and the current brush for filling current pen is used for the outline and the current brush for filling
the shape. the shape. If both the pen and brush are non-transparent, the rectangle is filled
with the brush before the outline is drawn with the pen.
If @racket[radius] is positive, the value is used as the radius of the If @racket[radius] is positive, the value is used as the radius of the
rounded corner. If @racket[radius] is negative, the absolute value is rounded corner. If @racket[radius] is negative, the absolute value is
@ -364,14 +366,12 @@ If @racket[radius] is positive, the value is used as the radius of the
If @racket[radius] is less than @racket[-0.5] or more than half of If @racket[radius] is less than @racket[-0.5] or more than half of
@racket[width] or @racket[height], @|MismatchExn|. @racket[width] or @racket[height], @|MismatchExn|.
If both the pen and brush are non-transparent, the rectangle is filled Brush filling and pen outline meet so that no space is left between
with the brush before the outline is drawn with the pen. The filling them, but the precise overlap between the filling and outline is
and outline meet so that no space is left between them, but the platform- and size-specific. Thus, the regions drawn by the brush
precise overlap between the filling and outline is platform- and and pen may partially overlap. In unsmoothed or aligned mode, the
size-specific. Thus, the regions drawn by the brush and pen may path for the outline is adjusted by shrinking the rectangle width and
partially overlap. More generally, the pen is centered over the height by one drawing unit after scaling.
outline of the rounded rectangle, rounding toward the center in
unsmoothed mode.
See also @method[dc<%> set-smoothing] for information on the See also @method[dc<%> set-smoothing] for information on the
@racket['aligned] smoothing mode. @racket['aligned] smoothing mode.