specially record transparent-canvas drawing for a small number of drawing ops

which enables background-sensitive smoothing of text

original commit: f700a15d854b9154bba5518a5c3e1c2367508b52
This commit is contained in:
Matthew Flatt 2010-12-17 09:10:33 -07:00
parent fd46124286
commit c04212f538
7 changed files with 91 additions and 49 deletions

View File

@ -27,7 +27,7 @@
(define canvas cnvs)
(inherit end-delay)
(super-new)
(super-new [transparent? (not (send canvas get-canvas-background))])
(define gl #f)
(define/override (get-gl-context)
@ -89,13 +89,6 @@
(let* ([surface (cairo_quartz_surface_create_for_cg_context cg (unbox w) (unbox h))]
[cr (cairo_create surface)])
(cairo_surface_destroy surface)
(let ([s (cairo_get_source cr)])
(cairo_pattern_reference s)
(cairo_set_source_surface cr (send bm get-cairo-surface) 0 0)
(cairo_new_path cr)
(cairo_rectangle cr 0 0 (unbox w) (unbox h))
(cairo_fill cr)
(cairo_set_source cr s)
(cairo_pattern_destroy s))
(backing-draw-bm bm cr (unbox w) (unbox h))
(cairo_destroy cr))))))
(tellv ctx restoreGraphicsState)))

View File

@ -4,11 +4,14 @@
racket/draw/private/bitmap-dc
racket/draw/private/bitmap
racket/draw/private/local
racket/draw/private/record-dc
racket/draw/unsafe/cairo
"../../lock.rkt"
"queue.rkt")
(provide
(protect-out backing-dc%
backing-draw-bm
;; scoped method names:
get-backing-size
@ -35,13 +38,19 @@
end-delay)
(define backing-dc%
(class (dc-mixin bitmap-dc-backend%)
(class (record-dc-mixin (dc-mixin bitmap-dc-backend%))
(init transparent?)
(inherit internal-get-bitmap
internal-set-bitmap
reset-cr)
reset-cr
set-recording-limit
get-recorded-command)
(super-new)
(set-recording-limit (if transparent? 1024 -1))
(define/override (ok?) #t)
;; Override this method to get the right size
@ -67,7 +76,8 @@
[(not retained-cr) #f]
[(positive? retained-counter)
(unless nada?
(proc (internal-get-bitmap)))
(proc (or (get-recorded-command)
(internal-get-bitmap))))
#t]
[else
(reset-backing-retained proc)
@ -155,3 +165,43 @@
(define (release-backing-bitmap bm)
(send bm release-bitmap-storage))
(define cairo-dc
(make-object (dc-mixin
(class default-dc-backend%
(inherit reset-cr)
(define cr #f)
(define w 0)
(define h 0)
(super-new)
(define/public (set-cr new-cr new-w new-h)
(set! cr new-cr)
(set! w new-w)
(set! h new-h)
(when cr
(reset-cr cr)))
(define/override (get-cr) cr)
(define/override (reset-clip cr)
(super reset-clip cr)
(cairo_rectangle cr 0 0 w h)
(cairo_clip cr))))))
(define (backing-draw-bm bm cr w h)
(if (procedure? bm)
(begin
(send cairo-dc set-cr cr w h)
(bm cairo-dc)
(send cairo-dc set-cr #f 0 0))
(let ([s (cairo_get_source cr)])
(cairo_pattern_reference s)
(cairo_set_source_surface cr (send bm get-cairo-surface) 0 0)
(cairo_new_path cr)
(cairo_rectangle cr 0 0 w h)
(cairo_fill cr)
(cairo_set_source cr s)
(cairo_pattern_destroy s))))

View File

@ -96,7 +96,7 @@
(inherit end-delay)
(define canvas cnvs)
(super-new)
(super-new [transparent? (not (send canvas get-canvas-background))])
(define gl #f)
(define/override (get-gl-context)
@ -146,12 +146,5 @@
[h (box 0)])
(send canvas get-client-size w h)
(let ([cr (gdk_cairo_create win)])
(let ([s (cairo_get_source cr)])
(cairo_pattern_reference s)
(cairo_set_source_surface cr (send bm get-cairo-surface) 0 0)
(cairo_new_path cr)
(cairo_rectangle cr 0 0 (unbox w) (unbox h))
(cairo_fill cr)
(cairo_set_source cr s)
(cairo_pattern_destroy s))
(backing-draw-bm bm cr (unbox w) (unbox h))
(cairo_destroy cr))))))

View File

@ -67,7 +67,7 @@
(inherit end-delay)
(define canvas cnvs)
(super-new)
(super-new [transparent? (not (send canvas get-canvas-background))])
(define gl #f)
(define/override (get-gl-context)
@ -116,14 +116,7 @@
(let* ([surface (cairo_win32_surface_create hdc)]
[cr (cairo_create surface)])
(cairo_surface_destroy surface)
(let ([s (cairo_get_source cr)])
(cairo_pattern_reference s)
(cairo_set_source_surface cr (send bm get-cairo-surface) 0 0)
(cairo_new_path cr)
(cairo_rectangle cr 0 0 (unbox w) (unbox h))
(cairo_fill cr)
(cairo_set_source cr s)
(cairo_pattern_destroy s))
(backing-draw-bm cr bm (unbox w) (unbox h))
(cairo_destroy cr))))))
(define (request-flush-delay canvas)

View File

@ -55,8 +55,9 @@ The @scheme[style] argument indicates one or more of the following styles:
canvas before calls to @method[canvas% on-paint]}
@item{@scheme['transparent] --- the canvas is automatically ``erased''
before an update using it's parent window's background; the result is
undefined if this flag is combined with @scheme['no-autoclear]}
before an update using it's parent window's background; see @racket[canvas<%>]
for information on the interaction of @racket['transparent] and offscreen buffering;
the result is undefined if this flag is combined with @scheme['no-autoclear]}
@item{@scheme['no-focus] --- prevents the canvas from accepting the
keyboard focus when the canvas is clicked, or when the

View File

@ -6,9 +6,6 @@
A canvas is a subwindow onto which graphics and text can be drawn. Canvases also
receive mouse and keyboard events.
To draw onto a canvas, get its device context (see
@method[canvas<%> get-dc]).
The @scheme[canvas<%>] interface is implemented by two classes:
@itemize[
@ -20,6 +17,28 @@ The @scheme[canvas<%>] interface is implemented by two classes:
]
To draw onto a canvas, get its device context (see
@method[canvas<%> get-dc]).
Drawing to a canvas's drawing context actually renders into an
offscreen buffer. The buffer is automatically flushed to the screen by
a background thread, explicitly via the @method[canvas<%> flush]
method, or explicitly via @racket[flush-display]---unless flushing
has been disabled for the canvas. The @method[canvas<%>
suspend-flush] method suspends flushing for a canvas until a matching
@method[canvas<%> resume-flush] calls; calls to @method[canvas<%>
suspend-flush] and @method[canvas<%> resume-flush] can be nested, in
which case flushing is suspended until the outermost @method[canvas<%>
suspend-flush] is balanced by a @method[canvas<%> resume-flush].
In the case of a transparent canvas (i.e., one that is created with
@racket['transparent] style), line and text smoothing can depend on
the window that serves as the canvas's background. For example,
smoothing may color pixels differently depending on whether the target
context is white or gray. Background-sensitive smoothing is supported
only if a relatively small number of drawing commands are recorded in
the canvas's offscreen buffer, however.
@defmethod*[([(accept-tab-focus)
boolean?]
@ -191,7 +210,7 @@ Does nothing.
@defmethod[(resume-flush) void?]{
See @method[canvas<%> suspend-flush].}
See @racket[canvas<%>] for information on canvas flushing.}
@ -223,19 +242,10 @@ Under Mac OS X, enables or disables space for a resize tab at the
@defmethod[(suspend-flush) void?]{
Drawing to a canvas's drawing context actually renders into an
offscreen buffer. The buffer is automatically flushed to the screen by
a background thread, explicitly via the @method[canvas<%> flush] method,
or explicitly via @racket[flush-display] --- unless flushing has been disabled for the canvas.
The @method[canvas<%> suspend-flush] method suspends flushing for a
canvas until a matching @method[canvas<%> resume-flush] calls; calls to
@method[canvas<%> suspend-flush] and @method[canvas<%> resume-flush] can
be nested, in which case flushing is suspended until the outermost
@method[canvas<%> suspend-flush] is balanced by a @method[canvas<%>
resume-flush].
See @racket[canvas<%>] for information on canvas flushing.
On some platforms, beware that suspending flushing for a canvas can
discourage refreshes for other windows in the same frame.}
Beware that suspending flushing for a canvas can discourage refreshes
for other windows in the same frame on some platforms.}
@defmethod[(warp-pointer [x (integer-in 0 10000)]

View File

@ -71,7 +71,9 @@ The @scheme[style] list can contain the following flags:
method}
@item{@scheme['transparent] --- the canvas is ``erased'' before an
update using its parent window's background}
update using its parent window's background; see @racket[canvas<%>]
for information on the interaction of @racket['transparent] and
offscreen buffering}
]