checkpoint new GUI toolbox docs

svn: r7109
This commit is contained in:
Matthew Flatt 2007-08-17 16:19:31 +00:00
parent a07950b2ed
commit c7c3d60b16
41 changed files with 7428 additions and 103 deletions

View File

@ -314,6 +314,16 @@
[else (error 'html-render "unrecognized style symbol: ~e" style)])] [else (error 'html-render "unrecognized style symbol: ~e" style)])]
[(string? style) [(string? style)
`((span ([class ,style]) ,@(super render-element e part ht)))] `((span ([class ,style]) ,@(super render-element e part ht)))]
[(and (pair? style)
(eq? (car style) 'show-color))
`((font ((style ,(format "background-color: ~a"
(apply string-append "#"
(map (lambda (v) (let ([s (format "0~x" v)])
(substring s (- (string-length s) 2))))
(cdr style))))))
(tt nbsp nbsp nbsp nbsp nbsp))
nbsp
,@(super render-element e part ht))]
[(target-url? style) [(target-url? style)
(if (current-no-links) (if (current-no-links)
(super render-element e part ht) (super render-element e part ht)

View File

@ -480,6 +480,20 @@
(define max-proto-width 65) (define max-proto-width 65)
(define (name-this-object type-sym)
(to-element
(string->symbol
(regexp-replace
#rx"(%|<%>|-mixin)$"
(format "_a~a-~s"
(if (member
(string-ref (symbol->string type-sym) 0)
'(#\a #\e #\i #\o #\u))
"n"
"")
type-sym)
""))))
(define (*defproc mode within-id (define (*defproc mode within-id
stx-ids prototypes arg-contractss result-contracts content-thunk) stx-ids prototypes arg-contractss result-contracts content-thunk)
(let ([spacer (hspace 1)] (let ([spacer (hspace 1)]
@ -564,17 +578,7 @@
(make-element #f (make-element #f
(list (scheme send) (list (scheme send)
(hspace 1) (hspace 1)
(to-element (string->symbol (name-this-object (syntax-e within-id))
(regexp-replace
#rx"(%|<%>|-mixin)$"
(format "a~a-~s"
(if (member
(string-ref (symbol->string (syntax-e within-id)) 0)
'(#\a #\e #\i #\o #\u))
"n"
"")
(syntax-e within-id))
"")))
(hspace 1) (hspace 1)
(if first? (if first?
(let* ([mname (car prototype)] (let* ([mname (car prototype)]
@ -1225,6 +1229,7 @@
defmethod* defmethod*
methspec methspec
methimpl methimpl
this-obj
include-class) include-class)
(define-syntax-parameter current-class #f) (define-syntax-parameter current-class #f)
@ -1417,5 +1422,14 @@
(syntax-rules () (syntax-rules ()
[(_ body ...) (make-spec (lambda () (list (italic "Specification:") body ...)))])) [(_ body ...) (make-spec (lambda () (list (italic "Specification:") body ...)))]))
(define (*this-obj cname)
(name-this-object cname))
(define-syntax (this-obj stx)
(syntax-case stx ()
[(_)
(with-syntax ([cname (syntax-parameter-value #'current-class)])
#'(*this-obj 'cname))]))
;; ---------------------------------------- ;; ----------------------------------------
) )

View File

@ -0,0 +1,78 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@definterface[add-color<%> ()]{
An @scheme[add-color<%>] object is used to additively change the RGB
values of a @scheme[color%] object. An @scheme[add-color<%>] object
only exists within a @scheme[style-delta%] object.
See also @method[style-delta% get-foreground-add] and
@method[style-delta% get-background-add].
@defmethod[(get [r (box/c (integer-in -1000 1000))]
[g (box/c (integer-in -1000 1000))]
[b (box/c (integer-in -1000 1000))])
void?]{
Gets all of the additive values.
@boxisfill[(scheme r) @elem{the additive value for the red component of the color}]
@boxisfill[(scheme g) @elem{the additive value for the green component of the color}]
@boxisfill[(scheme b) @elem{the additive value for the blue component of the color}]
}
@defmethod[(get-b)
(integer-in -1000 1000)]{
Gets the additive value for the blue component of the color.
}
@defmethod[(get-g)
(integer-in -1000 1000)]{
Gets the additive value for the green component of the color.
}
@defmethod[(get-r)
(integer-in -1000 1000)]{
Gets the additive value for the red component of the color.
}
@defmethod[(set [r (integer-in -1000 1000)]
[g (integer-in -1000 1000)]
[b (integer-in -1000 1000)])
void?]{
Sets all of the additive values.
}
@defmethod[(set-b [v (integer-in -1000 1000)])
void?]{
Sets the additive value for the blue component of the color.
}
@defmethod[(set-g [v (integer-in -1000 1000)])
void?]{
Sets the additive value for the green component of the color.
}
@defmethod[(set-r [v (integer-in -1000 1000)])
void?]{
Sets the additive value for the red component of the color.
}}

View File

@ -0,0 +1,250 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@defclass[bitmap% object% ()]{
A @scheme[bitmap%] object is a pixel-based image, either
monochrome or color.
Sometimes, a bitmap object creation fails in a low-level manner. In
that case, the @method[bitmap% ok?] method returns @scheme[#f], and
the bitmap cannot be supplied to methods that consume or operate on
bitmaps (otherwise, @|MismatchExn|).
@defconstructor*/make[(([width (integer-in 1 10000)]
[height (integer-in 1 10000)]
[monochrome? any/c #f])
([filename path-string?]
[kind (one-of/c 'unknown 'unknown/mask
'gif 'gif/mask 'jpeg 'png 'png/mask
'xbm 'xpm 'bmp 'pict)
'unknown]
[bg-color (or/c (is-a?/c color%) false/c) #f])
([bits bytes?]
[width (integer-in 1 10000)]
[height (integer-in 1 10000)]))]{
When @scheme[with] and @scheme[height] are provided: Creates a new
bitmap. If @scheme[monochrome?] is @scheme[#f], the bitmap matches
the display depth of the screen. The initial content of the bitmap is
undefined.
When @scheme[filename] is provided: Creates a bitmap from a file,
where @scheme[kind] specifies the kind of image file. See
@method[bitmap% load-file] for details.
When a @scheme[bits] byte string is provided: Creates a monochrome
bitmap from an array of bit values, where each byte in @scheme[bits]
specifies eight bits, and padding bits are added so that each bitmap
line starts on a character boundary. A @scheme[1] bit value indicates
black, and @scheme[0] indicates white. If @scheme[width] times
@scheme[height] is larger than 8 times the length of @scheme[bits],
@|MismatchExn|.
}
@defmethod[(get-argb-pixels [x real?]
[y real?]
[width (integer-in 1 10000)]
[height (integer-in 1 10000)]
[pixels (and/c byte-string? mutable?)]
[alpha? any/c @scheme[#f]])
void?]{
Produces the same result as @xmethod[bitmap-dc% get-pixel] with the
bitmap selected into the DC, but the bitmap does not have to be
selected anywhere (and this method works even if the bitmap is
selected into another DC, attached as a button label, etc.).
}
@defmethod[(get-depth)
nonnegative-exact-integer?]{
Gets the color depth of the bitmap. See also @method[bitmap%
is-color?].
}
@defmethod[(get-gl-config [config (is-a?/c gl-config%)])
void?]{
Returns a copy of this bitmap's requested OpenGL configuration. See
also @method[bitmap% set-gl-config].
}
@defmethod[(get-height)
(integer-in 1 10000)]{
Gets the height of the bitmap in pixels.
}
@defmethod[(get-loaded-mask)
(or/c (is-a?/c bitmap%) false/c)]{
Returns a mask bitmap that is stored with this bitmap.
When a GIF file is loaded with @scheme['gif/mask] or
@scheme['unknown/mask] and the file contains a transparent ``color,''
a mask bitmap is generated to identify the transparent pixels. The
mask bitmap is monochrome, with white pixels where the loaded bitmap
is transparent and black pixels everywhere else.
When a PNG file is loaded with @scheme['png/mask] or
@scheme['unknown/mask] and the file contains a mask or alpha channel,
a mask bitmap is generated to identify the mask or alpha channel. If
the file contains a mask or an alpha channel with only extreme
values, the mask bitmap is monochrome, otherwise it is grayscale
(representing the alpha channel inverted).
The mast bitmap is @italic{not} used automatically by drawing
routines. The mask bitmap can be extracted and supplied explicitly as
a mask (e.g., as the sixth argument to @method[dc<%>
draw-bitmap]). The mask bitmap is used by @method[bitmap% save-file]
when saving a bitmap as @scheme['png] if the mask has the same
dimensions as the saved bitmap. The mask bitmap is also used
automatically when the bitmap is a control label.
}
@defmethod[(get-width)
(integer-in 1 10000)]{
Gets the width of the bitmap in pixels.
}
@defmethod[(is-color?)
boolean?]{
Returns @scheme[#f] if the bitmap is monochrome, @scheme[#t] otherwise.
}
@defmethod[(load-file [name pat-string?]
[kind (one-of/c 'unknown 'unknown/mask
'gif 'gif/mask 'jpeg 'png 'png/mask
'xbm 'xpm 'bmp 'pict)
'unknown]
[bg-color (or/c (is-a?/c color%) false/c) #f])
boolean?]{
Loads a bitmap from a file. If the bitmap is in use by a
@scheme[bitmap-dc%] object or a control, the bitmap file is not
loaded. The bitmap changes its size and depth to match that of
the loaded image.
The @scheme[kind] argument specifies the file's format:
@itemize{
@item{@scheme['unknown] --- examine the file to determine its format}
@item{@scheme['unknown/mask] --- like @scheme['unknown], but see @method[bitmap% get-loaded-mask]}
@item{@scheme['gif] --- load a GIF bitmap file (X, Windows, Mac OS X)}
@item{@scheme['gif/mask] --- like @scheme['gif], but see @method[bitmap% get-loaded-mask] (X, Windows, Mac OS X)}
@item{@scheme['jpeg] --- load a JPEG bitmap file (X, Windows, Mac OS X)}
@item{@scheme['png] --- load a PNG bitmap file (X, Windows, Mac OS X)}
@item{@scheme['png/mask] --- like @scheme['png], but see @method[bitmap% get-loaded-mask] (X, Windows, Mac OS X)}
@item{@scheme['xbm] --- load an X bitmap file (X, Windows, Mac OS X); creates a monochrome bitmap}
@item{@scheme['xpm] --- load an XPM bitmap file (X, Windows, Mac OS X)}
@item{@scheme['bmp] --- load a Windows bitmap file (X, Windows, Mac OS X)}
@item{@scheme['pict] --- load a PICT bitmap file (Mac OS X)}
}
An XBM image is always loaded as a monochrome bitmap. A 1-bit
grayscale PNG without a mask or alpha channel is also loaded as a
monochrome bitmap. An image in any other format is always loaded as a
bitmap that matches the depth of the screen.
For PNG loading, if @scheme[bg-color] is not @scheme[#f], then it is
combined with the file's alpha channel or mask (if any) while loading
the image; in this case, no separate mask bitmap is generated, even
if @scheme['unknown/mask] or @scheme['png/mask] is specified for the
format. If the format is specified as @scheme['unknown] or
@scheme['png] and @scheme[bg-color] is not specified, the PNG file is
consulted for a background color to use for loading, and white is
used if no background color is indicated in the file.
@index["gamma correction"]{In} all PNG-loading modes, gamma correction
is applied when the file provides a gamma value, otherwise gamma
correction is not applied. The current display's gamma factor is
determined by the @ResourceFirst{gamma} (see @|mrprefsdiscuss|) if it
is set, or else by the @indexed-envvar{SCREEN_GAMMA} environment
variable if it is defined. If the preference and environment variable
are both undefined, a platform-specific default is used.
}
@defmethod[(ok?)
boolean?]{
Returns @scheme[#t] if the bitmap is usable (created or changed
successfully). If @scheme[#f] is returned, the bitmap cannot be
supplied to methods that consume or operate on bitmaps (otherwise,
@|MismatchExn|).
}
@defmethod[(save-file [name pat-string?]
[kind (one-of/c 'png 'jpeg 'xbm 'xpm 'bmp)]
[quality (integer-in 0 100) 75])
boolean?]{
Saves a bitmap in the named file.
The @scheme[kind] argument determined the type of file that is created,
one of:
@itemize{
@item{@scheme['png] --- save a PNG file (X, Windows, Mac OS X)}
@item{@scheme['jpeg] --- save a JPEG file (X, Windows, Mac OS X)}
@item{@scheme['xbm] --- save an X bitmap file (X, Windows, Mac OS X)}
@item{@scheme['xpm] --- save an XPM bitmap file (X, Windows, Mac OS X)}
@item{@scheme['bmp] --- save a Windows bitmap file (Windows)}
}
The @scheme[quality] argument is used only for saving as @scheme['jpeg], in
which case it specifies the trade-off between image precision (high
quality matches the content of the @scheme[bitmap%] object more
precisely) and size (low quality is smaller).
When saving as @scheme['png], if @method[bitmap% get-loaded-mask]
returns a bitmap of the same size as this one, a grayscale version is
included in the PNG file as the alpha channel.
A monochrome bitmap saved as @scheme['png] without a mask bitmap
produces a 1-bit grayscale PNG file (which , when read with
@method[bitmap% load-file], creates a monochrome @scheme[bitmap%]
object.)
}
@defmethod[(set-gl-config [config (is-a?/c gl-config%)])
void?]{
Sets the requested OpenGL configuration for this bitmap. The
configuration is used when the bitmap selected into a drawing
context, and then a GL context is created for the drawing context.
The given @scheme[gl-config%] object is copied, so that changes to
the object do not affect the bitmap's configuration.
}
@defmethod[(set-loaded-mask [mask (or/c (is-a?/c bitmap%) false/c)])
void?]{
See @method[bitmap% get-loaded-mask].
}}

View File

@ -0,0 +1,170 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@defclass[bitmap-dc% object% (dc<%>)]{
A @scheme[bitmap-dc%] object allows drawing directly into a bitmap. A
@scheme[bitmap%] object must be supplied at initialization or
installed into a bitmap DC using @method[bitmap-dc% set-bitmap]
before any other method of the DC is called, except @method[dc<%>
get-text-extent], @method[dc<%> get-char-height], or @method[dc<%>
get-char-width]. If any other @scheme[bitmap-dc%] method is called
before a bitmap is selected, the method call is ignored.
Drawing to a @scheme[bitmap-dc%] with a color bitmap is guaranteed to
produce the same result as drawing into a @scheme[canvas%] instance
(with appropriate clipping and offsets). Thus, a @scheme[bitmap-dc%]
can be used for offscreen staging of canvas content.
@defconstructor[([bitmap (or/c (is-a?/c bitmap%) false/c)])]{
Creates a new memory DC. If @scheme[bitmap] is not @scheme[#f], it is
installed into the DC so that drawing commands on the DC draw to
@scheme[bitmap]. Otherwise, no bitmap is installed into the DC and
@method[bitmap-dc% set-bitmap] must be called before any other method
of the DC is called.
}
@defmethod[(draw-bitmap-section-smooth [source (is-a?/c bitmap%)]
[dest-x real?]
[dest-y real?]
[dest-width (and/c real? (not/c negative?))]
[dest-height (and/c real? (not/c negative?))]
[src-x real?]
[src-y real?]
[src-width (and/c real? (not/c negative?))]
[src-height (and/c real? (not/c negative?))]
[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.
}
@defmethod[(get-argb-pixels [x real?]
[y real?]
[width (integer-in 1 10000)]
[height (integer-in 1 10000)]
[pixels (and/c bytes? (not/c immutable?))]
[alpha? any/c @scheme[#f]])
void?]{
Gets a rectangle of pixels in the bitmap, subject to the same rules
and performance characteristics of @method[bitmap-dc% get-pixel],
except that the block get is likely to be faster than the sequence of
individual gets. Also, the @scheme[bitmap%] class also provides the
same method directly, so it is not necessary to select a bitmap into
a DC to extracts its pixel values.
The pixel RGB values are copied into @scheme[pixels]. The first byte
represents an alpha value of the pixel at (@scheme[x], @scheme[y]),
the second byte represents a red value of the pixel at (@scheme[x],
@scheme[y]), the third byte is the blue value, etc. In this way, the
first @math{@scheme[width] * @scheme[height] *4} bytes of
@scheme[pixels] are set to reflect the current pixel values in the
DC. The pixels are in row-major order, left to right then top to
bottom.
If @scheme[alpha?] is false, then the alpha value for each pixel is
set to 255. If @scheme[alpha?] is true, then @italic{only} the alpha
value is set for each pixel, based on each pixel's value. Thus, the
same @scheme[pixels] byte string is in general filled from two bitmaps:
one (the main image) for the pixel values and one (the mask) for the
alpha values.
}
@defmethod[(get-bitmap)
(or/c (is-a?/c bitmap%) false/c)]{
Gets the bitmap currently installed in the DC, or @scheme[#f] if no
bitmap is installed. See @method[bitmap-dc% set-bitmap] for more
information.
}
@defmethod[(get-pixel [x real?]
[y real?]
[color (is-a?/c color%)])
boolean?]{
Fills @scheme[color] with the color of the current pixel at position
(@scheme[x], @scheme[y]) in the drawing context. If the color is
successfully obtained, the return value is @scheme[#t], otherwise the
result is @scheme[#f].
Under X, interleaving drawing commands with @method[bitmap-dc%
get-pixel] calls (for the same @scheme[bitmap-dc%] object) incurs a
substantial performance penalty, except for interleaved calls to
@method[bitmap-dc% set-pixel], @method[bitmap-dc% set-argb-pixels],
and @method[bitmap-dc% get-argb-pixels].
}
@defmethod[(set-argb-pixels [x real?]
[y real?]
[width (integer-in 1 10000)]
[height (integer-in 1 10000)]
[pixels bytes?]
[alpha? any/c @scheme[#f]])
void?]{
Sets a rectangle of pixels in the bitmap, subject to the same
rules and performance characteristics of
@method[bitmap-dc% set-pixel], except that the block set is likely to be faster than the
sequence of individual sets.
The pixel RGB values are taken from @scheme[pixels]. The first byte
represents an alpha value, the second byte represents a red value to
used for the pixel at (@scheme[x], @scheme[y]), the third byte is a blue
value, etc. In this way, the first
@math{@scheme[width] * @scheme[height] * 4} bytes of @scheme[pixels]
determine the new pixel values in the DC. The pixels are in row-major
order, left to right then top to bottom.
If @scheme[alpha?] is false, then the alpha value for each pixel is
ignored. If @scheme[alpha?] is true, then @italic{only} the each
pixel is set based @italic{only} on the alpha value. Thus, the same
@scheme[pixels] byte string is in general used with two bitmaps, one
(the main image) for the pixel values and one (the mask) for the
alpha values.
}
@defmethod[(set-bitmap [bitmap (or/c (is-a?/c bitmap%) false/c)])
void?]{
Installs a bitmap into the DC, so that drawing operations on the bitmap
DC draw to the bitmap. A bitmap is removed from a DC by setting the
bitmap to @scheme[#f].
A bitmap can be selected into at most one bitmap DC, and only when it
is not used by a control (as a label) or in a @scheme[pen%] or
@scheme[brush%] (as a stipple). If the argument to @method[bitmap-dc%
set-bitmap] is already in use by another DC, a control, a
@scheme[pen%], or a @scheme[brush%], @|MismatchExn|.
}
@defmethod[(set-pixel [x real?]
[y real?]
[color (is-a?/c color%)])
void?]{
Sets a pixel in the bitmap.
The current clipping region might not affect the pixel change. Under
X, interleaving drawing commands with @method[bitmap-dc% set-pixel]
calls (for the same @scheme[bitmap-dc%] object) incurs a substantial
performance penalty, except for interleaved calls to
@method[bitmap-dc% get-pixel], @method[bitmap-dc% get-argb-pixels],
and @method[bitmap-dc% set-argb-pixels].
}}

View File

@ -52,12 +52,6 @@
@elem{The bitmap label is installed only @elem{The bitmap label is installed only
if the control was originally created with a bitmap label.}) if the control was originally created with a bitmap label.})
(define (NotDCRelated)
@elem{A path is not connected to any particular @scheme[dc<%>] object, so
setting a @scheme[dc<%>] origin or scale does not affect path
operations. Instead, a @scheme[dc<%>]'s origin and scale apply at the
time that the path is drawn or used to set a region.})
(define (popupmenuinfo what other more) (define (popupmenuinfo what other more)
(make-splice (make-splice
(list* (list*
@ -250,7 +244,7 @@ information@|details|, even if the editor currently has delayed refreshing (see
@elem{snip @techlink{position}})) @elem{snip @techlink{position}}))
(define (colorName name name2 r g b) (define (colorName name name2 r g b)
name) (make-element `(show-color ,r ,g ,b) (list (to-element (bytes->string/latin-1 name)))))
(define (Resource s) (define (Resource s)
@elem{@to-element[`(quote ,(string->symbol (string-append "MrEd:" s)))] @elem{@to-element[`(quote ,(string->symbol (string-append "MrEd:" s)))]
@ -271,5 +265,10 @@ information@|details|, even if the editor currently has delayed refreshing (see
"smaller" "smaller"
@elem{the editor is @|b|-aligned in the snip})) @elem{the editor is @|b|-aligned in the snip}))
(define (boxisfill which what)
@elem{The @|which| box is filled with @|what|.})
(define (boxisfillnull which what)
@elem{The @|which| box is filled with @|what|, unless @|which| is @scheme[#f].})
) )

View File

@ -0,0 +1,213 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@defclass[brush% object% ()]{
A brush is a drawing tool with a color and a style that is used for
filling in areas, such as the interior of a rectangle or ellipse. On
a monochrome display, all non-white brushes are drawn as black.
In addition to its color and style, a brush can have a stipple bitmap.
This stipple is used only in unsmoothed mode (see @method[dc<%>
set-smoothing]) or in a PostScript drawing context. Painting with a
stipple brush is similar to calling @method[dc<%> draw-bitmap] with
the stipple bitmap in the filled region, except that the bitmap may
not be scaled in the same way (depending on the platform and device).
A brush's style is one of the following:
@itemize{
@item{@indexed-scheme['transparent] --- Draws with no effect (on the
interior of the drawn shape).}
@item{@indexed-scheme['solid] --- Draws using the brush's color. If a
monochrome stipple is installed into the brush, black pixels
from the stipple are transferred to the destination using the
brush's color, and white pixels from the stipple are not
transferred.}
@item{@indexed-scheme['opaque] --- Same as @scheme['solid], except when a
monochrome stipple is installed for unsmoothed or PostScript
drawing; in that case, white pixels from the stipple are
transferred to the destination using the destination's
background color.}
@item{@indexed-scheme['xor] --- In a smoothing mode or if a color
stipple is installed, @scheme['xor] is treated as
@scheme['solid]. Otherwise, the brush's color or colored
(monochrome) stipple is xor-ed with existing destination pixel
values. The @scheme['xor] mapping is unspecified for arbitrary
color combinations, but the mapping provides two guarantees:
@itemize{
@item{Black-and-white drawing to a color or monochrome
destination always works as expected: black xor white = black,
white xor black = black, black xor black = white, and white xor
white = white.}
@item{Performing the same drawing operation twice in a row with
@scheme['xor] is equivalent to a no-op.}
}}
@item{@indexed-scheme['hilite] --- In unsmoothed mode, existing
destination pixels are ``highlighted'' in a platform-specific
way when the brush color is black. Under Windows and X for a
color drawing context, the inverted RGB components of
destination pixel are combined with the RGB components of the
system-wide highlight color using a bitwise ``or'', and the
combination is used. (Under X, the color is specified by the
@ResourceFirst{hiliteColor} preference; see @|mrprefsdiscuss|.)
Under Mac OS X for a color drawing context, the inverted RGB
components of the system-wide highlight color are subtracted
from the RGB components of each destination pixel, and the
difference (or 0 for a negative result) is used. For any
monochrome drawing context, @scheme['hilite] is the same as
@scheme['xor]. For PostScript output, @scheme['hilite] uses a
stipple that is an array of small dots (essentially a
halftone), otherwise @scheme['hilite] is treated like
@scheme['solid] in a smoothing mode.}
@item{@indexed-scheme['panel] --- In unsmoothed mode, draws with the
same color and pattern as a top-level panel background, if the
brush's color is the same as the color returned by
@scheme[get-panel-background] and if the brush has no
stipple. To create a @scheme[canvas%] object that is drawn like
a control, use the @scheme['transparent] canvas style instead,
because certain kinds of nested panels have different
background colors (e.g., a @scheme[tab-panel%] under Mac OS
X). In a smoothing mode, @scheme['panel] is treated as
@scheme['solid].}
@item{The following modes correspond to built-in stipples drawn in
@scheme['solid] mode:
@itemize{
@item{@indexed-scheme['bdiagonal-hatch] --- diagonal lines, top-left to bottom-right}
@item{@indexed-scheme['crossdiag-hatch] --- crossed diagonal lines}
@item{@indexed-scheme['fdiagonal-hatch] --- diagonal lines, top-right to bottom-left}
@item{@indexed-scheme['cross-hatch] --- crossed horizontal and vertical lines}
@item{@indexed-scheme['horizontal-hatch] --- horizontal lines}
@item{@indexed-scheme['vertical-hatch] --- vertical lines}
}
However, when a specific stipple is installed into the brush
for when drawing with a smoothing mode into a non-PostScript
context, the above modes are ignored and @scheme['solid] is
used, instead.}
}
@index['("drawing" "outlines")]{To} draw outline shapes (such as
unfilled boxes and ellipses), use the @scheme['transparent] brush
style. See @method[brush% set-style] for more information about
styles.
To avoid creating multiple brushes with the same characteristics, use
the global @scheme[brush-list%] object
@indexed-scheme[the-brush-list], or provide a color and style to
@xmethod[dc<%> set-brush].
@defconstructor*/make[(()
([color (is-a?/c color%)]
[style (one-of/c 'transparent 'solid 'opaque
'xor 'hilite 'panel
'bdiagonal-hatch 'crossdiag-hatch
'fdiagonal-hatch 'cross-hatch
'horizontal-hatch 'vertical-hatch)])
([color-name string?]
[style (one-of/c 'transparent 'solid 'opaque
'xor 'hilite 'panel
'bdiagonal-hatch 'crossdiag-hatch
'fdiagonal-hatch 'cross-hatch
'horizontal-hatch 'vertical-hatch)]))]{
When no argument are provided, the result is a solid black brush.
Otherwise, the result is a brush with the given color and style. For
the case that the color is specified using a name, see
@scheme[color-database<%>] for information about color names; if the
name is not known, the brush's color is black.
}
@defmethod[(get-color)
(is-a?/c color%)]{
Returns the brush's color.
}
@defmethod[(get-stipple)
(or/c (is-a?/c bitmap%) false/c)]{
Gets the stipple bitmap, or @scheme[#f] if the brush has no stipple.
}
@defmethod[(get-style)
(one-of/c 'transparent 'solid 'opaque
'xor 'hilite 'panel
'bdiagonal-hatch 'crossdiag-hatch
'fdiagonal-hatch 'cross-hatch
'horizontal-hatch 'vertical-hatch)]{
Returns the brush's style. See @scheme[brush%] for information about
brush styles.
}
@defmethod*[([(set-color [color (is-a?/c color%)])
void?]
[(set-color [color-name string?])
void?]
[(set-color [red (integer-in 0 255)]
[green (integer-in 0 255)]
[blue (integer-in 0 255)])
void?])]{
Sets the brush's color. A brush cannot be modified if it was obtained
from a @scheme[brush-list%] or while it is selected into a drawing
context.
For the case that the color is specified using a string, see
@scheme[color-database<%>] for information about color names.
}
@defmethod[(set-stipple [bitmap (or/c (is-a?/c bitmap%) false/c)])
void?]{
Sets or removes the stipple bitmap, where @scheme[#f] removes the
stipple. See @scheme[brush%] for information about drawing with
stipples.
A bitmap cannot be used as a stipple if it is selected into a
@scheme[bitmap-dc%] object; if the given bitmap is selected into a
@scheme[bitmap-dc%] object, @|MismatchExn|. A brush cannot be
modified if it was obtained from a @scheme[brush-list%] or while it
is selected into a drawing context.
A pen's stipple is not used in a smoothing mode, except for a
@scheme[post-script-dc%] (which is always in a smoothing mode).
}
@defmethod[(set-style [style (one-of/c 'transparent 'solid 'opaque
'xor 'hilite 'panel
'bdiagonal-hatch 'crossdiag-hatch
'fdiagonal-hatch 'cross-hatch
'horizontal-hatch 'vertical-hatch)])
void?]{
Sets the brush's style. See
@scheme[brush%] for information about the possible styles.
A brush cannot be modified if it was obtained from a
@scheme[brush-list%] or while it is selected into a drawing
context.
}}

View File

@ -0,0 +1,40 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@defclass[brush-list% object% ()]{
A @scheme[brush-list%] object maintains a list of @scheme[brush%]
objects to avoid creating brushes repeatedly. A @scheme[brush%]
object in a brush list cannot be mutated.
A global brush list, @scheme[the-brush-list], is created
automatically.
@defconstructor/make[()]{
Creates an empty brush list.
}
@defmethod*[([(find-or-create-brush [color (is-a?/c color%)]
[style (one-of/c 'transparent 'solid 'opaque
'xor 'hilite 'panel
'bdiagonal-hatch 'crossdiag-hatch
'fdiagonal-hatch 'cross-hatch
'horizontal-hatch 'vertical-hatch)])
(is-a?/c brush%)]
[(find-or-create-brush [color-name string?]
[style (one-of/c 'transparent 'solid 'opaque
'xor 'hilite 'panel
'bdiagonal-hatch 'crossdiag-hatch
'fdiagonal-hatch 'cross-hatch
'horizontal-hatch 'vertical-hatch)])
(or/c (is-a?/c brush%) false/c)])]{
Finds a brush of the given specification, or creates one and adds it
to the list. See @scheme[brush%] for a further explanation of the
arguments, which are the same as @scheme[brush%]'s initialization
arguments.
}}

View File

@ -0,0 +1,70 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@defclass[color% object% ()]{
A color is an object representing a red-green-blue (RGB) combination
of primary colors, and is used to determine drawing colors. Each red,
green, or blue component of the color is in the range 0 to 255,
inclusive. For example, (0, 0, 0) is black, (255, 255, 255) is
white, and (255, 0, 0) is red.
See @scheme[color-database<%>] for information about obtaining a color
object using a color name.
@defconstructor*/make[(([red (integer-in 0 255)]
[green (integer-in 0 255)]
[blue (integer-in 0 255)])
([color-name string?]))]{
Creates a new color with the given RGB values, or matching the given
color name (using ``black'' if the name is not recognized). See
@scheme[color-database<%>] for more information on color names.
}
@defmethod[(blue)
(integer-in 0 255)]{
Returns the blue component of the color.
}
@defmethod[(copy-from [src (is-a?/c color%)])
(is-a?/c color%)]{
Copies the RGB values of another color object to this one, returning
this object as the result.
}
@defmethod[(green)
(integer-in 0 255)]{
Returns the green component of the color.
}
@defmethod[(ok?)
boolean?]{
Returns @scheme[#t] if the color object is valid.
}
@defmethod[(red)
(integer-in 0 255)]{
Returns the red component of the color.
}
@defmethod[(set [red (integer-in 0 255)]
[green (integer-in 0 255)]
[blue (integer-in 0 255)])
void?]{
Sets the three (red, green, and blue) component values of the color.
}}

View File

@ -0,0 +1,211 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@definterface[color-database<%> ()]{
The global @indexed-scheme[the-color-database] object is an instance of
@scheme[color-database<%>]. It maintains a database of standard RGB
colors for a predefined set of named colors (such as ``black'' and
``light grey'').
The following colors are in the database:
@schemeblock[
#, @colorName[#"Orange Red" #"OrangeRed" 255 69 0]
#, @colorName[#"OrangeRed" #"OrangeRed" 255 69 0]
#, @colorName[#"Tomato" #"Tomato" 255 99 71]
#, @colorName[#"DarkRed" #"DarkRed" 139 0 0]
#, @colorName[#"Red" #"Red" 255 0 0]
#, @colorName[#"Firebrick" #"Firebrick" 178 34 34]
#, @colorName[#"Crimson" #"Crimson" 220 20 60]
#, @colorName[#"DeepPink" #"DeepPink" 255 20 147]
#, @colorName[#"Maroon" #"Maroon" 176 48 96]
#, @colorName[#"Indian Red" #"IndianRed" 205 92 92]
#, @colorName[#"IndianRed" #"IndianRed" 205 92 92]
#, @colorName[#"Medium Violet Red" #"MediumVioletRed" 199 21 133]
#, @colorName[#"MediumVioletRed" #"MediumVioletRed" 199 21 133]
#, @colorName[#"Violet Red" #"VioletRed" 208 32 144]
#, @colorName[#"VioletRed" #"VioletRed" 208 32 144]
#, @colorName[#"LightCoral" #"LightCoral" 240 128 128]
#, @colorName[#"HotPink" #"HotPink" 255 105 180]
#, @colorName[#"PaleVioletRed" #"PaleVioletRed" 219 112 147]
#, @colorName[#"LightPink" #"LightPink" 255 182 193]
#, @colorName[#"RosyBrown" #"RosyBrown" 188 143 143]
#, @colorName[#"Pink" #"Pink" 255 192 203]
#, @colorName[#"Orchid" #"Orchid" 218 112 214]
#, @colorName[#"LavenderBlush" #"LavenderBlush" 255 240 245]
#, @colorName[#"Snow" #"Snow" 255 250 250]
#, @colorName[#"Chocolate" #"Chocolate" 210 105 30]
#, @colorName[#"SaddleBrown" #"SaddleBrown" 139 69 19]
#, @colorName[#"Brown" #"Brown" 132 60 36]
#, @colorName[#"DarkOrange" #"DarkOrange" 255 140 0]
#, @colorName[#"Coral" #"Coral" 255 127 80]
#, @colorName[#"Sienna" #"Sienna" 160 82 45]
#, @colorName[#"Orange" #"Orange" 255 165 0]
#, @colorName[#"Salmon" #"Salmon" 250 128 114]
#, @colorName[#"Peru" #"Peru" 205 133 63]
#, @colorName[#"DarkGoldenrod" #"DarkGoldenrod" 184 134 11]
#, @colorName[#"Goldenrod" #"Goldenrod" 218 165 32]
#, @colorName[#"SandyBrown" #"SandyBrown" 244 164 96]
#, @colorName[#"LightSalmon" #"LightSalmon" 255 160 122]
#, @colorName[#"DarkSalmon" #"DarkSalmon" 233 150 122]
#, @colorName[#"Gold" #"Gold" 255 215 0]
#, @colorName[#"Yellow" #"Yellow" 255 255 0]
#, @colorName[#"Olive" #"Olive" 128 128 0]
#, @colorName[#"Burlywood" #"Burlywood" 222 184 135]
#, @colorName[#"Tan" #"Tan" 210 180 140]
#, @colorName[#"NavajoWhite" #"NavajoWhite" 255 222 173]
#, @colorName[#"PeachPuff" #"PeachPuff" 255 218 185]
#, @colorName[#"Khaki" #"Khaki" 240 230 140]
#, @colorName[#"DarkKhaki" #"DarkKhaki" 189 183 107]
#, @colorName[#"Moccasin" #"Moccasin" 255 228 181]
#, @colorName[#"Wheat" #"Wheat" 245 222 179]
#, @colorName[#"Bisque" #"Bisque" 255 228 196]
#, @colorName[#"PaleGoldenrod" #"PaleGoldenrod" 238 232 170]
#, @colorName[#"BlanchedAlmond" #"BlanchedAlmond" 255 235 205]
#, @colorName[#"Medium Goldenrod" #"MediumGoldenrod" 234 234 173]
#, @colorName[#"MediumGoldenrod" #"MediumGoldenrod" 234 234 173]
#, @colorName[#"PapayaWhip" #"PapayaWhip" 255 239 213]
#, @colorName[#"MistyRose" #"MistyRose" 255 228 225]
#, @colorName[#"LemonChiffon" #"LemonChiffon" 255 250 205]
#, @colorName[#"AntiqueWhite" #"AntiqueWhite" 250 235 215]
#, @colorName[#"Cornsilk" #"Cornsilk" 255 248 220]
#, @colorName[#"LightGoldenrodYellow" #"LightGoldenrodYellow" 250 250 210]
#, @colorName[#"OldLace" #"OldLace" 253 245 230]
#, @colorName[#"Linen" #"Linen" 250 240 230]
#, @colorName[#"LightYellow" #"LightYellow" 255 255 224]
#, @colorName[#"SeaShell" #"SeaShell" 255 245 238]
#, @colorName[#"Beige" #"Beige" 245 245 220]
#, @colorName[#"FloralWhite" #"FloralWhite" 255 250 240]
#, @colorName[#"Ivory" #"Ivory" 255 255 240]
#, @colorName[#"Green" #"Green" 0 255 0]
#, @colorName[#"LawnGreen" #"LawnGreen" 124 252 0]
#, @colorName[#"Chartreuse" #"Chartreuse" 127 255 0]
#, @colorName[#"Green Yellow" #"GreenYellow" 173 255 47]
#, @colorName[#"GreenYellow" #"GreenYellow" 173 255 47]
#, @colorName[#"Yellow Green" #"YellowGreen" 154 205 50]
#, @colorName[#"YellowGreen" #"YellowGreen" 154 205 50]
#, @colorName[#"Medium Forest Green" #"MediumForestGreen" 107 142 35]
#, @colorName[#"OliveDrab" #"OliveDrab" 107 142 35]
#, @colorName[#"MediumForestGreen" #"MediumForestGreen" 107 142 35]
#, @colorName[#"Dark Olive Green" #"DarkOliveGreen" 85 107 47]
#, @colorName[#"DarkOliveGreen" #"DarkOliveGreen" 85 107 47]
#, @colorName[#"DarkSeaGreen" #"DarkSeaGreen" 143 188 139]
#, @colorName[#"Lime" #"Lime" 0 255 0]
#, @colorName[#"Dark Green" #"DarkGreen" 0 100 0]
#, @colorName[#"DarkGreen" #"DarkGreen" 0 100 0]
#, @colorName[#"Lime Green" #"LimeGreen" 50 205 50]
#, @colorName[#"LimeGreen" #"LimeGreen" 50 205 50]
#, @colorName[#"Forest Green" #"ForestGreen" 34 139 34]
#, @colorName[#"ForestGreen" #"ForestGreen" 34 139 34]
#, @colorName[#"Spring Green" #"SpringGreen" 0 255 127]
#, @colorName[#"SpringGreen" #"SpringGreen" 0 255 127]
#, @colorName[#"Medium Spring Green" #"MediumSpringGreen" 0 250 154]
#, @colorName[#"MediumSpringGreen" #"MediumSpringGreen" 0 250 154]
#, @colorName[#"Sea Green" #"SeaGreen" 46 139 87]
#, @colorName[#"SeaGreen" #"SeaGreen" 46 139 87]
#, @colorName[#"Medium Sea Green" #"MediumSeaGreen" 60 179 113]
#, @colorName[#"MediumSeaGreen" #"MediumSeaGreen" 60 179 113]
#, @colorName[#"Aquamarine" #"Aquamarine" 112 216 144]
#, @colorName[#"LightGreen" #"LightGreen" 144 238 144]
#, @colorName[#"Pale Green" #"PaleGreen" 152 251 152]
#, @colorName[#"PaleGreen" #"PaleGreen" 152 251 152]
#, @colorName[#"Medium Aquamarine" #"MediumAquamarine" 102 205 170]
#, @colorName[#"MediumAquamarine" #"MediumAquamarine" 102 205 170]
#, @colorName[#"Turquoise" #"Turquoise" 64 224 208]
#, @colorName[#"LightSeaGreen" #"LightSeaGreen" 32 178 170]
#, @colorName[#"Medium Turquoise" #"MediumTurquoise" 72 209 204]
#, @colorName[#"MediumTurquoise" #"MediumTurquoise" 72 209 204]
#, @colorName[#"Honeydew" #"Honeydew" 240 255 240]
#, @colorName[#"MintCream" #"MintCream" 245 255 250]
#, @colorName[#"RoyalBlue" #"RoyalBlue" 65 105 225]
#, @colorName[#"DodgerBlue" #"DodgerBlue" 30 144 255]
#, @colorName[#"DeepSkyBlue" #"DeepSkyBlue" 0 191 255]
#, @colorName[#"CornflowerBlue" #"CornflowerBlue" 100 149 237]
#, @colorName[#"Steel Blue" #"SteelBlue" 70 130 180]
#, @colorName[#"SteelBlue" #"SteelBlue" 70 130 180]
#, @colorName[#"LightSkyBlue" #"LightSkyBlue" 135 206 250]
#, @colorName[#"Dark Turquoise" #"DarkTurquoise" 0 206 209]
#, @colorName[#"DarkTurquoise" #"DarkTurquoise" 0 206 209]
#, @colorName[#"Cyan" #"Cyan" 0 255 255]
#, @colorName[#"Aqua" #"Aqua" 0 255 255]
#, @colorName[#"DarkCyan" #"DarkCyan" 0 139 139]
#, @colorName[#"Teal" #"Teal" 0 128 128]
#, @colorName[#"Sky Blue" #"SkyBlue" 135 206 235]
#, @colorName[#"SkyBlue" #"SkyBlue" 135 206 235]
#, @colorName[#"Cadet Blue" #"CadetBlue" 96 160 160]
#, @colorName[#"CadetBlue" #"CadetBlue" 95 158 160]
#, @colorName[#"Dark Slate Gray" #"DarkSlateGray" 47 79 79]
#, @colorName[#"DarkSlateGray" #"DarkSlateGray" 47 79 79]
#, @colorName[#"LightSlateGray" #"LightSlateGray" 119 136 153]
#, @colorName[#"SlateGray" #"SlateGray" 112 128 144]
#, @colorName[#"Light Steel Blue" #"LightSteelBlue" 176 196 222]
#, @colorName[#"LightSteelBlue" #"LightSteelBlue" 176 196 222]
#, @colorName[#"Light Blue" #"LightBlue" 173 216 230]
#, @colorName[#"LightBlue" #"LightBlue" 173 216 230]
#, @colorName[#"PowderBlue" #"PowderBlue" 176 224 230]
#, @colorName[#"PaleTurquoise" #"PaleTurquoise" 175 238 238]
#, @colorName[#"LightCyan" #"LightCyan" 224 255 255]
#, @colorName[#"AliceBlue" #"AliceBlue" 240 248 255]
#, @colorName[#"Azure" #"Azure" 240 255 255]
#, @colorName[#"Medium Blue" #"MediumBlue" 0 0 205]
#, @colorName[#"MediumBlue" #"MediumBlue" 0 0 205]
#, @colorName[#"DarkBlue" #"DarkBlue" 0 0 139]
#, @colorName[#"Midnight Blue" #"MidnightBlue" 25 25 112]
#, @colorName[#"MidnightBlue" #"MidnightBlue" 25 25 112]
#, @colorName[#"Navy" #"Navy" 36 36 140]
#, @colorName[#"Blue" #"Blue" 0 0 255]
#, @colorName[#"Indigo" #"Indigo" 75 0 130]
#, @colorName[#"Blue Violet" #"BlueViolet" 138 43 226]
#, @colorName[#"BlueViolet" #"BlueViolet" 138 43 226]
#, @colorName[#"Medium Slate Blue" #"MediumSlateBlue" 123 104 238]
#, @colorName[#"MediumSlateBlue" #"MediumSlateBlue" 123 104 238]
#, @colorName[#"Slate Blue" #"SlateBlue" 106 90 205]
#, @colorName[#"SlateBlue" #"SlateBlue" 106 90 205]
#, @colorName[#"Purple" #"Purple" 160 32 240]
#, @colorName[#"Dark Slate Blue" #"DarkSlateBlue" 72 61 139]
#, @colorName[#"DarkSlateBlue" #"DarkSlateBlue" 72 61 139]
#, @colorName[#"DarkViolet" #"DarkViolet" 148 0 211]
#, @colorName[#"Dark Orchid" #"DarkOrchid" 153 50 204]
#, @colorName[#"DarkOrchid" #"DarkOrchid" 153 50 204]
#, @colorName[#"MediumPurple" #"MediumPurple" 147 112 219]
#, @colorName[#"Cornflower Blue" #"CornflowerBlue" 68 64 108]
#, @colorName[#"Medium Orchid" #"MediumOrchid" 186 85 211]
#, @colorName[#"MediumOrchid" #"MediumOrchid" 186 85 211]
#, @colorName[#"Magenta" #"Magenta" 255 0 255]
#, @colorName[#"Fuchsia" #"Fuchsia" 255 0 255]
#, @colorName[#"DarkMagenta" #"DarkMagenta" 139 0 139]
#, @colorName[#"Violet" #"Violet" 238 130 238]
#, @colorName[#"Plum" #"Plum" 221 160 221]
#, @colorName[#"Lavender" #"Lavender" 230 230 250]
#, @colorName[#"Thistle" #"Thistle" 216 191 216]
#, @colorName[#"GhostWhite" #"GhostWhite" 248 248 255]
#, @colorName[#"White" #"White" 255 255 255]
#, @colorName[#"WhiteSmoke" #"WhiteSmoke" 245 245 245]
#, @colorName[#"Gainsboro" #"Gainsboro" 220 220 220]
#, @colorName[#"Light Gray" #"LightGray" 211 211 211]
#, @colorName[#"LightGray" #"LightGray" 211 211 211]
#, @colorName[#"Silver" #"Silver" 192 192 192]
#, @colorName[#"Gray" #"Gray" 190 190 190]
#, @colorName[#"Dark Gray" #"DarkGray" 169 169 169]
#, @colorName[#"DarkGray" #"DarkGray" 169 169 169]
#, @colorName[#"Dim Gray" #"DimGray" 105 105 105]
#, @colorName[#"DimGray" #"DimGray" 105 105 105]
#, @colorName[#"Black" #"Black" 0 0 0]
]
The names are not case-sensitive.
See also @scheme[color%].
@defmethod[(find-color [color-name string?])
(or/c (is-a?/c color%) false/c)]{
Finds a color by name (character case is ignored). If no color is
found for the name, @scheme[#f] is returned.
}}

View File

@ -0,0 +1,909 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@definterface[dc<%> ()]{
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[(clear)
void?]{
Clears the drawing region (fills it with the current background color,
as determined by @method[dc<%> get-background]).
}
@defmethod[(draw-arc [x real?]
[y real?]
[width (and/c real? (not/c negative?))]
[height (and/c real? (not/c negative?))]
[start-radians real?]
[end-radians real?])
void?]{
Draws a counter-clockwise circular arc, a part of the ellipse
inscribed in the rectangle specified by @scheme[x] (left), @scheme[y]
(top), @scheme[width], and @scheme[height]. The arc starts at the angle
specified by @scheme[start-radians] (@scheme[0] is three o'clock and
half-pi is twelve o'clock) and continues counter-clockwise to
@scheme[end-radians]. If @scheme[start-radians] and @scheme[end-radians] are
the same, a full ellipse is drawn.
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
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. More
generally, the pen is centered over the outline of the arc, rounding
toward the center in unsmoothed mode.
@|DrawSizeNote|
}
@defmethod[(draw-bitmap [source (is-a?/c bitmap%)]
[dest-x real?]
[dest-y real?]
[style (one-of/c 'solid 'opaque 'xor) 'solid]
[color (is-a?/c color%) (send the-color-database find-color "black")]
[mask (or/c (is-a?/c bitmap%) false/c) #f])
boolean?]{
Displays a bitmap. The @scheme[dest-x] and @scheme[dest-y] arguments
are in DC coordinates.
For color bitmaps, the drawing style and color arguments are
ignored. For monochrome bitmaps, @method[dc<%> draw-bitmap] uses the
style and color arguments in the same way that a brush uses its style
and color settings to draw a monochrome stipple (see @scheme[brush%]
for more information).
If a mask bitmap is supplied, it must have the same width and height
as the bitmap to display, and its @method[bitmap% ok?] must return
true, otherwise @|MismatchExn|. The bitmap to draw and the mask
bitmap can be the same object, but if the drawing context is a
@scheme[bitmap-dc%] object, both bitmaps must be distinct from the
destination bitmap, otherwise @|MismatchExn|.
If the mask bitmap is monochrome, drawing occurs in the target
@scheme[dc<%>] only where the mask bitmap contains black pixels.
If the mask bitmap is grayscale and the bitmap to draw is not
monochrome, then the blackness of each mask pixel controls the
opacity of the drawn pixel (i.e., the mask acts as an inverted alpha
channel), at least on most platforms. (Non-monochrome masks
are collapsed to monochrome under X when the RENDER extension is not
available, and under Windows 95 and NT when @file{msing32.dll} is not
available.) Other combinations involving a non-monochrome mask (i.e.,
a non-grayscale mask or a monochrome bitmap to draw) produce
platform-specific results.
The current brush, current pen, and current text settings for the DC
have no effect on how the bitmap is drawn, but the bitmap is scaled
if the DC has a scale.
For @scheme[post-script-dc%] output, the mask bitmap is currently
ignored, and the @scheme['solid] style is treated the same as
@scheme['opaque]. (However, mask bitmaps and @scheme['solid] drawing
may become supported for @scheme[post-script-dc%] in the future.)
The result is @scheme[#t] if the bitmap is successfully drawn,
@scheme[#f] otherwise (possibly because the bitmap's @method[bitmap%
ok?] method returns @scheme[#f]).
See also @method[dc<%> draw-bitmap-section].
@|DrawSizeNote|
}
@defmethod[(draw-bitmap-section [source (is-a?/c bitmap%)]
[dest-x real?]
[dest-y real?]
[src-x real?]
[src-y real?]
[src-width (and/c real? (not/c negative?))]
[src-height (and/c real? (not/c negative?))]
[style (one-of/c 'solid 'opaque 'xor) 'solid]
[color (is-a?/c color%) (send the-color-database find-color "black")]
[mask (or/c (is-a?/c bitmap%) false/c) #f])
boolean?]{
Displays part of a bitmap.
The @scheme[src-x], @scheme[src-y], @scheme[src-width], and
@scheme[src-height] arguments specify a rectangle in the source
bitmap to copy into this drawing context.
See @method[dc<%> draw-bitmap] for information about @scheme[dest-x],
@scheme[dest-y], @scheme[style], @scheme[color], and @scheme[mask].
}
@defmethod[(draw-ellipse [x real?]
[y real?]
[width (and/c real? (not/c negative?))]
[height (and/c real? (not/c negative?))])
void?]{
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
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. The filling
and outline meet so that no space is left between them, but the
precise overlap between the filling and outline 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
ellipse, rounding toward the center in unsmoothed mode.
@|DrawSizeNote|
}
@defmethod[(draw-line [x1 real?]
[y1 real?]
[x2 real?]
[y2 real?])
void?]{
Draws a line from one point to another. The current pen is used for
drawing the line.
In unsmoothed mode, the points correspond to pixels, and the line
covers both the start and end points. For a pen whose scaled width is
larger than @scheme[1], the line is drawn centered over the start and
end points.
See also @method[dc<%> set-smoothing] for information on the
@scheme['aligned] smoothing mode.
@|DrawSizeNote|
}
@defmethod[(draw-lines [points (listof (is-a?/c point%))]
[xoffset real? 0]
[yoffset real? 0])
void?]{
Draws lines using a list of @scheme[points], adding @scheme[xoffset]
and @scheme[yoffset] to each point. The current pen is used for
drawing the lines.
See also @method[dc<%> set-smoothing] for information on the
@scheme['aligned] smoothing mode.
@|DrawSizeNote|
}
@defmethod[(draw-path [path (is-a?/c dc-path%)]
[xoffset real? 0]
[yoffset real? 0]
[fill-style (one-of/c 'odd-even 'winding) 'odd-even])
void?]{
Draws the sub-paths of the given @scheme[dc-path%] object, adding
@scheme[xoffset] and @scheme[yoffset] to each point. The current pen
is used for drawing the path as a line, and the current brush is used
for filling the area bounded by the path.
If both the pen and brush are non-transparent, the path is filled with
the brush before the outline is drawn with the pen. The filling and
outline meet so that no space is left between them, but the precise
overlap between the filling and outline is platform- and
size-specific. Thus, the regions drawn by the brush and pen may
overlap. More generally, the pen is centered over the path, rounding
left and down in unsmoothed mode.
The @scheme[fill-style] argument specifies the fill rule:
@scheme['odd-even] or @scheme['winding]. In @scheme['odd-even] mode, a
point is considered enclosed within the path if it is enclosed by an
odd number of sub-path loops. In @scheme['winding] mode, a point is
considered enclosed within the path if it is enclosed by more or less
clockwise sub-path loops than counter-clockwise sub-path loops. In
unsmoothed mode, the @scheme['winding] fill rule is not supported
under Mac OS X and it is not supported when @scheme[path] contains
multiple sub-paths; the @scheme['winding] fill rules is always
supported when smoothing is enabled (see
@method[dc<%> set-smoothing]).
See also @method[dc<%> set-smoothing] for information on the
@scheme['aligned] smoothing mode.
@|DrawSizeNote|
}
@defmethod[(draw-point [x real?]
[y real?])
void?]{
Plots a single point using the current pen.
@|DrawSizeNote|
}
@defmethod[(draw-polygon [points (listof (is-a?/c point%))]
[xoffset real? 0]
[yoffset real? 0]
[fill-style (one-of/c 'odd-even 'winding) 'odd-even])
void?]{
Draw a filled polygon using a list of @scheme[points], adding
@scheme[xoffset] and @scheme[yoffset] to each point. The polygon is
automatically closed, so the first and last point can be
different. The current pen is used for drawing the outline, and the
current brush for filling the shape.
If both the pen and brush are non-transparent, the polygon is filled
with the brush before the outline is drawn with the pen. The filling
and outline meet so that no space is left between them, but the
precise overlap between the filling and outline is platform- and
shape-specific. Thus, the regions drawn by the brush and pen may
overlap. More generally, the pen is centered over the polygon lines,
rounding left and down in unsmoothed mode.
The @scheme[fill-style] argument specifies the fill rule:
@scheme['odd-even] or @scheme['winding]. In @scheme['odd-even] mode, a
point is considered enclosed within the polygon if it is enclosed by
an odd number of loops. In @scheme['winding] mode, a point is
considered enclosed within the polygon if it is enclosed by more or
less clockwise loops than counter-clockwise loops. The
@scheme['winding] fill rule is not supported under Mac OS X,
except when smoothing is enabled (see
@method[dc<%> set-smoothing]).
See also @method[dc<%> set-smoothing] for information on the
@scheme['aligned] smoothing mode.
@|DrawSizeNote|
}
@defmethod[(draw-rectangle [x real?]
[y real?]
[width (and/c real? (not/c negative?))]
[height (and/c real? (not/c negative?))])
void?]{
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
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. In
unsmoothed mode, when the pen is size 0 or 1, the filling precisely
overlaps the entire outline. As a result, if a rectangle is drawn
with a size-0 or size-1 @scheme['xor] @scheme[pen%] and an
@scheme['xor] @scheme[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
@scheme['aligned] smoothing mode.
@|DrawSizeNote|
}
@defmethod[(draw-rounded-rectangle [x real?]
[y real?]
[width (and/c real? (not/c negative?))]
[height (and/c real? (not/c negative?))]
[radius real? -0.25])
void?]{
Draws a rectangle with the given top-left corner, and with the given
size. The corners are quarter-circles using the given radius. The
current pen is used for the outline and the current brush for filling
the shape.
If @scheme[radius] is positive, the value is used as the radius of the
rounded corner. If @scheme[radius] is negative, the absolute value is
used as the @italic{proportion} of the smallest dimension of the
rectangle.
If @scheme[radius] is less than @scheme[-0.5] or more than half of
@scheme[width] or @scheme[height], @|MismatchExn|.
If both the pen and brush are non-transparent, the rectangle is filled
with the brush before the outline is drawn with the pen. The filling
and outline meet so that no space is left between them, but the
precise overlap between the filling and outline is platform- and
size-specific. Thus, the regions drawn by the brush and pen may
partially overlap. More generally, the pen is centered over the
outline of the rounded rectangle, rounding toward the center in
unsmoothed mode.
See also @method[dc<%> set-smoothing] for information on the
@scheme['aligned] smoothing mode.
@|DrawSizeNote|
}
@defmethod[(draw-spline [x1 real?]
[y1 real?]
[x2 real?]
[y2 real?]
[x3 real?]
[y3 real?])
void?]{
Draws a spline from (@scheme[x1], @scheme[y1]) to (@scheme[x3], @scheme[y3])
using (@scheme[x2], @scheme[y2]) as the control point.
See also @method[dc<%> set-smoothing] for information on the
@scheme['aligned] smoothing mode.
@|DrawSizeNote|
}
@defmethod[(draw-text [text string?]
[x real?]
[y real?]
[combine? any/c #f]
[offset nonnegative-exact-integer? 0]
[angle real? 0])
void?]{
Draws a text string at a specified point, using the current text font,
and the current text foreground and background colors. For unrotated
text, the specified point is used as the starting top-left point for
drawing characters (e.g, if ``W'' is drawn, the point is roughly the
location of the top-left pixel in the ``W''). Rotated text is rotated
around this point.
The @scheme[text] string is drawn starting from the @scheme[offset]
character, and continuing until the end of @scheme[text] or the first
null character.
If @scheme[combine?] is @scheme[#t], then @scheme[text] may be
measured with adjacent characters combined to ligature glyphs, with
Unicode combining characters as a single glyph, with kerning, with
right-to-left rendering of characters, etc. If @scheme[combine?] is
@scheme[#f], then the result is the same as if each character is
measured separately, and Unicode control characters are ignored.
The string is rotated by @scheme[angle] radians counter-clockwise. If
@scheme[angle] is not zero, then the text is always drawn in
transparent mode (see @method[dc<%> set-text-mode]).
The current brush and current pen settings for the DC have no effect
on how the text is drawn.
See @method[dc<%> get-text-extent] for information on the size of the
drawn text.
See also @method[dc<%> set-text-foreground], @method[dc<%>
set-text-background], and @method[dc<%> set-text-mode].
@|DrawSizeNote|
}
@defmethod[(end-doc)
void?]{
Ends a document, relevant only when drawing to a printer or PostScript
device (including to a PostScript file).
For printer or PostScript output, an exception is raised if
@scheme[end-doc] is called when the document is not started with
@method[dc<%> start-doc], when a page is currently started by
@method[dc<%> start-page] and not ended with @method[dc<%> end-page],
or when the document has been ended already.
}
@defmethod[(end-page)
void?]{
Ends a single page, relevant only when drawing to a printer or
PostScript device (including to a PostScript file).
For printer or PostScript output, an exception is raised if
@scheme[end-page] is called when a page is not currently started by
@method[dc<%> start-page].
}
@defmethod[(get-background)
(is-a?/c color%)]{
Gets the color used for painting the background. See also
@method[dc<%> set-background].
}
@defmethod[(get-brush)
(is-a?/c brush%)]{
Gets the current brush. See also @method[dc<%> set-brush].
}
@defmethod[(get-char-height)
(and/c real? (not/c negative?))]{
Gets the height of a character using the current font.
Unlike most methods, this method can be called for a
@scheme[bitmap-dc%] object without a bitmap installed.
}
@defmethod[(get-char-width)
(and/c real? (not/c negative?))]{
Gets the average width of a character using the current font.
Unlike most methods, this method can be called for a
@scheme[bitmap-dc%] object without a bitmap installed.
}
@defmethod[(get-clipping-region)
(or/c (is-a?/c region%) false/c)]{
Gets the current clipping region, returning @scheme[#f] if the drawing
context is not clipped (i.e., the clipping region is the entire
drawing region).
}
@defmethod[(get-font)
(is-a?/c font%)]{
Gets the current font. See also @method[dc<%> set-font].
}
@defmethod[(get-gl-context)
(or/c (is-a?/c gl-context<%>) false/c)]{
Returns a @scheme[gl-context<%>] object for this drawing context
if it supports OpenGL, @scheme[#f] otherwise.
See @scheme[gl-context<%>] for more information.
}
@defmethod[(get-origin)
(values real? real?)]{
Returns the device origin, i.e., the location in device coordinates of
@math{(0,0)} in logical coordinates.
See also @method[dc<%> set-origin].
}
@defmethod[(get-pen)
(is-a?/c pen%)]{
Gets the current pen. See also @method[dc<%> set-pen].
}
@defmethod[(get-scale)
(values real? real?)]{
Returns the scaling factor that maps logical coordinates to device
coordinates.
See also @method[dc<%> set-scale].
}
@defmethod[(get-size)
(values nonnegative-real? nonnegative-real?)]{
Gets the size of the destination drawing area. For a @scheme[dc<%>]
object obtained from a @scheme[canvas<%>], this is the (virtual
client) size of the destination window; for a @scheme[bitmap-dc%]
object, this is the size of the selected bitmap (or 0 if no bitmap is
selected); for a @scheme[post-script-dc%] or @scheme[printer-dc%]
drawing context, this gets the horizontal and vertical size of the
drawing area.
}
@defmethod[(get-smoothing)
(one-of/c 'unsmoothed 'smoothed 'aligned)]{
Returns the current smoothing mode. See @method[dc<%> set-smoothing].
}
@defmethod[(get-text-background)
(is-a?/c color%)]{
Gets the current text background color. See also @method[dc<%>
set-text-background].
}
@defmethod[(get-text-extent [string string?]
[font (or/c (is-a?/c font%) false/c) #f]
[combine? any/c #f]
[offset nonnegative-exact-integer? 0])
(values nonnegative-real?
nonnegative-real?
nonnegative-real?
nonnegative-real?)]{
Returns the size of @scheme[str] at it would be drawn in the drawing
context, starting from the @scheme[offset] character of @scheme[str],
and continuing until the end of @scheme[str] or the first null
character. The @scheme[font] argument specifies the font to use in
measuring the text; if it is @scheme[#f], the current font of the
drawing area is used. (See also @method[dc<%> set-font].)
The result is four real numbers:
@itemize{
@item{the total width of the text (depends on both the font and the
text);}
@item{the total height of the font (depends only on the font);}
@item{the distance from the baseline of the font to the bottom of the
descender (included in the height, depends only on the font); and}
@item{extra vertical space added to the font by the font designer
(included in the height, and often zero; depends only on the font).}
}
The returned width and height define a rectangle is that guaranteed to
contain the text string when it is drawn, but the fit is not
necessarily tight. Some undefined number of pixels on the left,
right, top, and bottom of the drawn string may be ``whitespace,''
depending on the whims of the font designer and the platform-specific
font-scaling mechanism.
If @scheme[combine?] is @scheme[#t], then @scheme[text] may be drawn
with adjacent characters combined to ligature glyphs, with Unicode
combining characters as a single glyph, with kerning, with
right-to-left ordering of characters, etc. If @scheme[combine?] is
@scheme[#f], then the result is the same as if each character is
drawn separately, and Unicode control characters are ignored.
Unlike most methods, this method can be called for a
@scheme[bitmap-dc%] object without a bitmap installed.
}
@defmethod[(get-text-foreground)
(is-a?/c color%)]{
Gets the current text foreground color. See also @method[dc<%>
set-text-foreground].
}
@defmethod[(get-text-mode)
(one-of/c 'solid 'transparent)]{
Reports how text is drawn; see
@method[dc<%> set-text-mode] .
}
@defmethod[(glyph-exists? [c char]
[font (or/c (is-a?/c font%) false/c) #f])
boolean?]{
Returns @scheme[#t] if the given character has a corresponding glyph
for this drawing context, @scheme[#f] otherwise.
Due to automatic font substitution when drawing or measuring text, the
result of this method does not depend on the given font, which merely
provides a hint for the glyph search. If the font is @scheme[#f], the
drawing context's current font is used. The result depends on the
type of the drawing context, but the result for @scheme[canvas%]
@scheme[dc<%>] instances and @scheme[bitmap-dc%] instances is always
the same for a given platform and a given set of installed fonts.
See also @method[font% screen-glyph-exists?] .
}
@defmethod[(ok?)
boolean?]{
Returns @scheme[#t] if the drawing context is usable.
}
@defmethod[(set-background [color (is-a?/c color%)])
void?]{
Sets the background color for drawing in this object (e.g., using
@method[dc<%> clear] or using a stippled @scheme[brush%] with the mode
@scheme['opaque]). For monochrome drawing, all non-black colors are
treated as white.
}
@defmethod*[([(set-brush [brush (is-a?/c brush%)])
void?]
[(set-brush [color (is-a?/c color%)]
[style (one-of/c 'transparent 'solid 'opaque
'xor 'hilite 'panel
'bdiagonal-hatch 'crossdiag-hatch
'fdiagonal-hatch 'cross-hatch
'horizontal-hatch 'vertical-hatch)])
void?]
[(set-brush [color-name string?]
[style (one-of/c 'transparent 'solid 'opaque
'xor 'hilite 'panel
'bdiagonal-hatch 'crossdiag-hatch
'fdiagonal-hatch 'cross-hatch
'horizontal-hatch 'vertical-hatch)])
void?])]{
Sets the current brush for drawing in this object. While a brush is
selected into a drawing context, it cannot be modified. When a color
and style are given, the arguments are as for @xmethod[brush-list%
find-or-create-brush].
}
@defmethod[(set-clipping-rect [x real?]
[y real?]
[width (and/c real? (not/c negative?))]
[height (and/c real? (not/c negative?))])
void?]{
Sets the clipping region to a rectangular region.
See also @method[dc<%> set-clipping-region] and @method[dc<%>
get-clipping-region].
@|DrawSizeNote|
}
@defmethod[(set-clipping-region [rgn (or/c (is-a?/c region%) false/c)])
void?]{
Sets the clipping region for the drawing area, turning off all
clipping within the drawing region if @scheme[#f] is provided.
The clipping region must be reset after changing a @scheme[dc<%>]
object's origin or scale (unless it is @scheme[#f]); see
@scheme[region%] for more information.
See also @method[dc<%> set-clipping-rect] and @method[dc<%>
get-clipping-region].
}
@defmethod[(set-font [font (is-a?/c font%)])
void?]{
Sets the current font for drawing text in this object.
}
@defmethod[(set-origin [x real?]
[y real?])
void?]{
Sets the device origin, i.e., the location in device coordinates of
@math{(0,0)} in logical coordinates.
Changing a @scheme[dc<%>] object's origin or scale does not affect
@scheme[region%] objects that were previously created. See
@scheme[region%] for more information.
@|DrawSizeNote|
}
@defmethod*[([(set-pen [pen (is-a?/c pen%)])
void?]
[(set-pen [color (is-a?/c color%)]
[width (real-in 0 255)]
[style (one-of/c 'transparent 'solid 'xor 'hilite
'dot 'long-dash 'short-dash 'dot-dash
'xor-dot 'xor-long-dash 'xor-short-dash
'xor-dot-dash)])
void?]
[(set-pen [color-name string?]
[width (real-in 0 255)]
[style (one-of/c 'transparent 'solid 'xor 'hilite
'dot 'long-dash 'short-dash 'dot-dash
'xor-dot 'xor-long-dash 'xor-short-dash
'xor-dot-dash)])
void?])]{
Sets the current pen for this object. When a color, width, and style
are given, the arguments are as for @xmethod[pen-list%
find-or-create-pen].
The current pen does not affect text drawing; see also @method[dc<%>
set-text-foreground].
While a pen is selected into a drawing context, it cannot be modified.
}
@defmethod[(set-scale [x-scale (and/c real? (not/c negative?))]
[y-scale (and/c real? (not/c negative?))])
void?]{
Sets a scaling factor that maps logical coordinates to device coordinates.
Changing a @scheme[dc<%>] object's origin or scale does not affect
@scheme[region%] objects that were previously created. See
@scheme[region%] for more information.
@|DrawSizeNote|
}
@defmethod[(set-smoothing [mode (one-of/c 'unsmoothed 'smoothed 'aligned)])
void?]{
Enables or disables anti-aliased smoothing of lines, curves,
rectangles, rounded rectangles, ellipses, polygons, paths, and clear
operations. (Text smoothing is not affected by this method, and is
instead controlled through the @scheme[font%] object.)
Smoothing is supported under Windows only when Microsoft's
@file{gdiplus.dll} is installed (which is always the case for Windows
XP). Smoothing is supported under Mac OS X always. Smoothing is
supported under X only when Cairo is installed when MrEd is compiled.
Smoothing is never supported for black-and-white contexts. Smoothing
is always supported (and cannot be disabled) for PostScript output.
The smoothing mode is either @scheme['unsmoothed], @scheme['smoothed],
or @scheme['aligned]. Both @scheme['aligned] and @scheme['smoothed]
are smoothing modes.
In @scheme['smoothed] mode for a canvas or bitmap drawing context,
integer drawing coordinates correspond to the boundary between
pixels, and pen-based drawing is centered over a given line or
curve. Thus, drawing with pen width @scheme[1] from @math{(0, 10)} to
@math{(10, 10)} draws a 2-pixel wide line with @math{50%} opacity.
The @scheme['aligned] smoothing mode is like @scheme['smoothed], but
it paints pixels more like @scheme['unsmoothed] mode. Since it aligns
shapes to pixel boundaries, @scheme['aligned] mode often produces
better results than @scheme['smoothed], but the results depend on the
application. The @scheme['aligned] mode is defined in terms of
@scheme['smoothed] mode, except that drawing coordinates are rounded
down (via @scheme[floor], after scaling and origin translation). For
line drawing, coordinates are then shifted right and down by the
@scheme[floor] of half a pen width. In addition, for pen drawing
through @method[dc<%> draw-rectangle], @method[dc<%> draw-ellipse],
@method[dc<%> draw-rounded-rectangle], and @method[dc<%> draw-arc],
the given width and height are each decreased by @math{1.0}.
In either smoothing mode, brush and pen stipples are ignored (except
for PostScript drawing), and @scheme['hilite] and @scheme['xor]
drawing modes are treated as @scheme['solid]. If smoothing is not
supported, then attempting to set the smoothing mode to
@scheme['smoothed] or @scheme['aligned] will have no effect, and
@method[dc<%> get-smoothing] will always return
@scheme['unsmoothed]. Similarly, @method[dc<%> get-smoothing] for a
@scheme[post-script-dc%] always returns @scheme['smoothed].
}
@defmethod[(set-text-background [color (is-a?/c color%)])
void?]{
Sets the current text background color for this object. The text
background color is painted behind text that is drawn with
@method[dc<%> draw-text], but only for the @scheme['solid] text mode
(see @method[dc<%> set-text-mode]).
For monochrome drawing, all non-white colors are treated as black.
}
@defmethod[(set-text-foreground [color (is-a?/c color%)])
void?]{
Sets the current text foreground color for this object, used for
drawing text with
@method[dc<%> draw-text].
For monochrome drawing, all non-black colors are treated as
white.
}
@defmethod[(set-text-mode [mode (one-of/c 'solid 'transparent)])
void?]{
Determines how text is drawn:
@itemize{
@item{@scheme['solid] --- Before text is drawn, the destination area
is filled with the text background color (see @method[dc<%>
set-text-background]).}
@item{@scheme['transparent] --- Text is drawn directly over any
existing image in the destination, as if overlaying text
written on transparent film.}
}
}
@defmethod[(start-doc [message string?])
boolean?]{
Starts a document, relevant only when drawing to a printer or
PostScript device (including to a PostScript file). For some
platforms, the @scheme[message] string is displayed in a dialog until
@method[dc<%> end-doc] is called.
For printer or PostScript output, an exception is raised if
@scheme[start-doc] has been called already (even if @method[dc<%>
end-doc] has been called as well). Furthermore, drawing methods raise
an exception if not called while a page is active as determined by
@method[dc<%> start-doc] and @method[dc<%> start-page].
}
@defmethod[(start-page)
void?]{
Starts a page, relevant only when drawing to a printer or PostScript
device (including to a PostScript file).
For printer or PostScript output, an exception is raised if
@scheme[start-doc] is called when a page is already started, or when
@method[dc<%> start-doc] has not been called, or when @method[dc<%>
end-doc] has been called already. In addition, in the case of
PostScript output, Encapsulated PostScript (EPS) cannot contain
multiple pages, so calling @scheme[start-page] a second time for a
@scheme[post-script-dc%] instance raises an exception; to create
PostScript output with multiple pages, supply @scheme[#f] as the
@scheme[as-eps] initialization argument for @scheme[post-script-dc%].
}
@defmethod[(try-color [try (is-a?/c color%)]
[result (is-a?/c color%)])
void?]{
Determines the actual color used for drawing requests with the given
color. The @scheme[result] color is set to the RGB values that are
actually produced for this drawing context to draw the color
@scheme[try].
}}

View File

@ -0,0 +1,261 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@defclass[dc-path% object% ()]{
A path is a set of figures defined by curves. A path can be used with
the @method[dc<%> draw-path] method of a @scheme[dc<%>] object to draw
the path's curves as lines, fill the region bounded by the path's
curves, or both. A path can also be used with the @method[region%
set-path] method of a @scheme[region%] object to generate a region
bounded by the path's curves.
A path consists of zero or more @deftech{closed sub-paths}, and
possibly one @deftech{open sub-path}. Some @scheme[dc-path%] methods
extend the open sub-path, some @scheme[dc-path%] methods close the
open sub-path, and some @scheme[dc-path%] methods add closed
sub-paths.
When a path is drawn as a line, a closed sub-path is drawn as a closed
figure, analogous to a polygon. An open sub-path is drawn with
disjoint start and end points, analogous lines drawn with
@xmethod[dc<%> draw-lines].
When a path is filled or used as a region, the open sub-path (if any)
is treated as if it were closed. The content of a path is determined
either through the @scheme['even-odd] rule or the @scheme['winding]
rule, as selected at the time when the path is filled or used to
generate a region.
A path is not connected to any particular @scheme[dc<%>] object, so
setting a @scheme[dc<%>] origin or scale does not affect path
operations. Instead, a @scheme[dc<%>]'s origin and scale apply at the
time that the path is drawn or used to set a region.
@defconstructor/make[()]{
Creates a new path that contains no sub-paths (and no @tech{open
sub-path}).
}
@defmethod[(append [path (is-a?/c dc-path%)])
void?]{
Adds the sub-paths of @scheme[path] to @this-obj[]. @tech{Closed
sub-paths} of @scheme[path] are added as @tech{closed sub-paths} to
@this-obj[]. If both paths have an @tech{open sub-path}, then this
path's sub-path is extended by the given path's @tech{open sub-path},
adding a line from this path's current ending point to the given
path's starting point. If only one of the paths has an @tech{open
sub-path}, then it becomes (or remains) this path's @tech{open
sub-path}.
}
@defmethod[(arc [x real?]
[y real?]
[width (and/c real? (not/c negative?))]
[height (and/c real? (not/c negative?))]
[start-radians real?]
[end-radians real?]
[counter-clockwise? any/c #t])
void?]{
Extends or starts the path's @tech{open sub-path} with a curve that
corresponds to a section of an ellipse. The ellipse is the one
bounded by a rectangle whose top-left corner is @math{(@scheme[x],
@scheme[y])} and whose dimensions are @scheme[width] by
@scheme[height]. The ellipse section starts a the angle
@scheme[start-radians] (@scheme[0] is three o'clock and half-pi is
twelve o'clock) and continues to the angle @scheme[end-radians]; if
@scheme[counter-clockwise?] is true, then the arc runs
counter-clockwise from @scheme[start-radians] to
@scheme[end-radians], otherwise it runs clockwise.
If the path has no @tech{open sub-path}, a new one is started with the
arc's starting point. Otherwise, the arc extends the existing
sub-path, and the existing path is connected with a line to the arc's
starting point.
}
@defmethod[(close)
void?]{
Closes the path's @tech{open sub-path}. If the path has no @tech{open
sub-path}, @|MismatchExn|.
}
@defmethod[(curve-to [x1 real?]
[y1 real?]
[x2 real?]
[y2 real?]
[x3 real?]
[y3 real?])
void?]{
Extends the path's @tech{open sub-path} with a Bezier curve to the
given point @math{(@scheme[x3],@scheme[y3])}, using the points
@math{(@scheme[x1], @scheme[y1])}$ and @math{(@scheme[x2],
@scheme[y2])}$ as control points. If the path has no @tech{open
sub-path}, @|MismatchExn|.
}
@defmethod[(ellipse [x real?]
[y real?]
[width (and/c real? (not/c negative?))]
[height (and/c real? (not/c negative?))])
void?]{
Closes the @tech{open sub-path}, if any, and adds a @tech{closed
sub-path} that represents an ellipse bounded by a rectangle whose
top-left corner is @math{(@scheme[x], @scheme[y])} and whose
dimensions are @scheme[width] by @scheme[height]. (This convenience
method is implemented in terms of @method[dc-path% close] and
@method[dc-path% arc].)
}
@defmethod[(get-bounding-box)
(values real? real? real? real?)]{
Returns a rectangle that encloses the path's points. The return
values are the left, top, width, and height of the rectangle.
For curves within the path, the bounding box enclosed the two control
points as well as the start and end points. Thus, the bounding box
does not always tightly bound the path.
}
@defmethod[(line-to [x real?]
[y real?])
void?]{
Extends the path's @tech{open sub-path} with a line to the given
point. If the path has no @tech{open sub-path}, @|MismatchExn|.
}
@defmethod[(lines [points (listof (is-a?/c point%))]
[xoffset real? 0]
[yoffset real? 0])
void?]{
Extends the path's @tech{open sub-path} with a sequences of lines to
the given points. If the path has no @tech{open sub-path},
@|MismatchExn|. (This convenience method is implemented in terms of
@method[dc-path% line-to].)
}
@defmethod[(move-to [x real?]
[y real?])
void?]{
After closing the @tech{open sub-path}, if any, starts a new
@tech{open sub-path} with the given initial point.
}
@defmethod[(open?)
boolean?]{
Returns @scheme[#t] if the path has an @tech{open sub-path},
@scheme[#f] otherwise.
}
@defmethod[(rectangle [x real?]
[y real?]
[width (and/c real? (not/c negative?))]
[height (and/c real? (not/c negative?))])
void?]{
Closes the @tech{open sub-path}, if any, and adds a closed path that
represents a rectangle whose top-left corner is @math{(@scheme[x],
@scheme[y])} and whose dimensions are @scheme[width] by
@scheme[height]. (This convenience method is implemented in terms of
@method[dc-path% close], @method[dc-path% move-to], and
@method[dc-path% line-to].)
}
@defmethod[(reset)
void?]{
Removes all sub-paths of the path.
}
@defmethod[(reverse)
void?]{
Reverses the order of all points in all sub-paths. If the path has an
@tech{open sub-path}, the starting point becomes the ending point,
and extensions to the @tech{open sub-path} build on this new ending
point. Reversing a @tech{closed sub-path} affects how it combines
with other sub-paths when determining the content of a path in
@scheme['winding] mode.
}
@defmethod[(rotate [radians real?])
void?]{
Adjusts all points within the path (including all sub-paths), rotating
them @scheme[radians] counter-clockwise around @math{(0, 0)}. Future
additions to the path are not rotated by this call.
}
@defmethod[(rounded-rectangle [x real?]
[y real?]
[width (and/c real? (not/c negative?))]
[height (and/c real? (not/c negative?))]
[radius real? -0.25])
void?]{
Closes the @tech{open sub-path}, if any, and adds a @tech{closed
sub-path} that represents a round-cornered rectangle whose top-left
corner is @math{(@scheme[x] @scheme[y])} and whose dimensions are
@scheme[width] by @scheme[height]. (This convenience method is
implemented in terms of @method[dc-path% close], @method[dc-path%
move-to], @method[dc-path% arc], and @method[dc-path% line-to].)
If @scheme[radius] is positive, the value is used as the radius of the
rounded corner. If @scheme[radius] is negative, the absolute value is
used as the @italic{proportion} of the smallest dimension of the
rectangle.
If @scheme[radius] is less than @scheme[-0.5] or more than half of
@scheme[width] or @scheme[height], @|MismatchExn|.
}
@defmethod[(scale [x real?]
[y real?])
void?]{
@index['("paths" "flipping")]{Adjusts} all points within the path
(including all sub-paths), multiplying each x-coordinate by
@scheme[x] and each y-coordinate by @scheme[y]. Scaling by a negative
number flips the path over the corresponding axis. Future additions
to the path are not scaled by this call.
}
@defmethod[(translate [x real?]
[y real?])
void?]{
Adjusts all points within the path (including all sub-paths), shifting
then @scheme[x] to the right and @scheme[y] down. Future additions
to the path are not translated by this call.
}}

View File

@ -0,0 +1,49 @@
#reader(lib "docreader.ss" "scribble")
@require["common.ss"]
@require["diagrams.ss"]
@title[#:style '(toc quiet)]{Drawing Class Reference}
@local-table-of-contents[]
@require["bitmap-class.scrbl"]
@require["bitmap-dc-class.scrbl"]
@require["brush-class.scrbl"]
@require["brush-list-class.scrbl"]
@require["color-class.scrbl"]
@require["color-database-intf.scrbl"]
@require["dc-intf.scrbl"]
@require["dc-path-class.scrbl"]
@require["font-class.scrbl"]
@require["font-list-class.scrbl"]
@require["font-name-directory-intf.scrbl"]
@require["gl-config-class.scrbl"]
@require["gl-context-intf.scrbl"]
@require["pen-class.scrbl"]
@require["pen-list-class.scrbl"]
@require["point-class.scrbl"]
@require["post-script-dc-class.scrbl"]
@require["printer-dc-class.scrbl"]
@require["ps-setup-class.scrbl"]
@require["region-class.scrbl"]
@include-class[bitmap%]
@include-class[bitmap-dc%]
@include-class[brush%]
@include-class[brush-list%]
@include-class[color%]
@include-class[color-database<%>]
@include-class[dc<%>]
@include-class[dc-path%]
@include-class[font%]
@include-class[font-list%]
@include-class[font-name-directory<%>]
@include-class[gl-config%]
@include-class[gl-context<%>]
@include-class[pen%]
@include-class[pen-list%]
@include-class[point%]
@include-class[post-script-dc%]
@include-class[printer-dc%]
@include-class[ps-setup%]
@include-class[region%]

View File

@ -0,0 +1,11 @@
#reader(lib "docreader.ss" "scribble")
@require["common.ss"]
@title{Drawing Function Reference}
@local-table-of-contents[]
@include-section["global-draw-funcs.scrbl"]
@include-section["post-script-funcs.scrbl"]
@include-section["draw-list-funcs.scrbl"]
@include-section["font-funcs.scrbl"]

View File

@ -0,0 +1,36 @@
#reader(lib "docreader.ss" "scribble")
@require["common.ss"]
@title{Drawing Object Lists}
@defthing[the-brush-list (is-a?/c brush-list%)]{
See @scheme[brush-list%].
}
@defthing[the-color-database (is-a?/c color-database<%>)]{
See @scheme[color-database<%>].
}
@defthing[the-font-list (is-a?/c font-list%)]{
See @scheme[font-list%].
}
@defthing[the-font-name-directory (is-a?/c font-name-directory<%>)]{
See @scheme[font-name-directory<%>].
}
@defthing[the-pen-list (is-a?/c pen-list%)]{
See @scheme[pen-list%].
}

View File

@ -3,7 +3,7 @@
@require["common.ss"] @require["common.ss"]
@require["diagrams.ss"] @require["diagrams.ss"]
@title[#:tag "mred:drawing-toolbox"]{Drawing Toolbox Overview} @title[#:tag "mr:drawing-overview"]{Drawing Guide}
Drawing in MrEd requires a @deftech{device context} (@deftech{DC}), Drawing in MrEd requires a @deftech{device context} (@deftech{DC}),
which is an instance of the @scheme[dc<%>] interface. For example, which is an instance of the @scheme[dc<%>] interface. For example,

View File

@ -1,9 +0,0 @@
#reader(lib "docreader.ss" "scribble")
@require["common.ss"]
@require["diagrams.ss"]
@title[#:tag "mr:drawing" #:style 'toc]{Drawing Toolbox}
@local-table-of-contents[]
@include-section["draw-overview.scrbl"]

View File

@ -0,0 +1,44 @@
#reader(lib "docreader.ss" "scribble")
@require["common.ss"]
@require["diagrams.ss"]
@title[#:style '(toc quiet)]{Editor Class Reference}
@local-table-of-contents[]
@require["add-color-intf.scrbl"]
@require["editor-intf.scrbl"]
@;{
@require["editor-admin-class.scrbl"]
@require["editor-canvas-class.scrbl"]
@require["editor-data-class.scrbl"]
@require["editor-data-class-class.scrbl"]
@require["editor-data-class-list-intf.scrbl"]
@require["editor-snip-editor-admin-intf.scrbl"]
@require["editor-snip-class.scrbl"]
@require["editor-stream-in-class.scrbl"]
@require["editor-stream-in-base-class.scrbl"]
@require["editor-stream-in-bytes-base-class.scrbl"]
@require["editor-stream-out-class.scrbl"]
@require["editor-stream-out-base-class.scrbl"]
@require["editor-stream-out-bytes-base-class.scrbl"]
@require["editor-wordbreak-map-class.scrbl"]
@require["image-snip-class.scrbl"]
@require["keymap-class.scrbl"]
@require["mult-color-intf.scrbl"]
@require["pasteboard-class.scrbl"]
@require["readable-snip-intf.scrbl"]
@require["snip-class.scrbl"]
@require["snip-admin-class.scrbl"]
@require["snip-class-class.scrbl"]
@require["snip-class-list-intf.scrbl"]
@require["string-snip-class.scrbl"]
@require["style-intf.scrbl"]
@require["style-delta-class.scrbl"]
@require["style-list-class.scrbl"]
@require["tab-snip-class.scrbl"]
@require["text-class.scrbl"]
}
@include-class[add-color<%>]
@include-class[editor<%>]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,752 @@
#reader(lib "docreader.ss" "scribble")
@require[(lib "bnf.ss" "scribble")]
@require["common.ss"]
@title[#:tag "mr:editor-overview"]{Editor Guide}
The editor toolbox provides a foundation for two common kinds of
applications:
@itemize{
@item{@italic{Programs that need a sophisticated text editor} ---
The simple text field control is inadequate for text-intensive
applications. Many programs need editors that can handle multiple
fonts and non-text items.}
@item{@italic{Programs that need a canvas with dragable objects} ---
The drawing toolbox provides a generic drawing surface for plotting
lines and boxes, but many applications need an interactive canvas,
where the user can drag and resize individual objects.}
}
Both kinds of applications need an extensible editor that can handle
text, images, programmer-defined items, and even embedded
editors. The difference between them is the layout of items. MrEd
therefore provides two kinds of editors via two classes:
@itemize{
@item{@scheme[text%] --- in a @deftech{text editor}, items are
automatically positioned in a paragraph flow.}
@item{@scheme[pasteboard%] --- in a @deftech{pasteboard editor},
items are explicitly positioned and dragable.}
}
MrEd's editor architecture addresses the full range of real-world
issues for an editor---including cut-and-paste, extensible file
formats, and layered text styles---while supporting a high level of
extensibility. Unfortunately, the system is fairly complex as a
result, and using the editor classes effectively requires a solid
understanding of the structure and terminology of the editor
toolbox. Nevertheless, enough applications fit one (or both) of the
descriptions above to justify the depth and complexity of the toolbox
and the learning investment required to use it.
A brief example illustrates how MrEd editors work. To start, an editor
needs an @scheme[editor-canvas%] to display its contents. Then, we
can create a text editor and install it into the canvas:
@schemeblock[
(define f (new frame% [label "Simple Edit"]
[width 200]
[height 200]))
(define c (new editor-canvas% [parent f]))
(define t (new text%))
(send c #,(:: editor-canvas% set-editor) t)
(send f #,(:: top-level-window<%> show) #t)
]
At this point, the editor is fully functional: the user can type text
into the editor, but no cut-and-paste operations are available. We
can support all of the standard operations on an editor via the
menu bar:
@schemeblock[
(define mb (new menu-bar% [parent f]))
(define m-edit (new menu% [label "Edit"] [parent mb]))
(define m-font (new menu% [label "Font"] [parent mb]))
(append-editor-operation-menu-items m-edit #f)
(append-editor-font-menu-items m-font)
]
Now, the standard cut and paste operations work, and the user can even
set font styles. The user can also insert an embedded editor by
selecting @onscreen{Insert Text} from the @onscreen{Edit} menu; after
selecting the menu item, a box appears in the editor with the caret
inside. Typing with the caret in the box stretches the box as text is
added, and font operations apply wherever the caret is active. Text
on the outside of the box is rearranged as the box changes
sizes. Note that the box itself can be copied and pasted.
The content of an editor is made up of @deftech{snips}. An embedded
editor is a single snip from the embedding editor's point-of-view. To
encode immediate text, a snip can be a single character, but more
often a snip is a sequence of adjacent characters on the same
line. The @method[text% find-snip] method extracts a snip
from a text editor:
@schemeblock[
(send t #,(:: text% find-snip) 0 'after)
]
The above expression returns the first snip in the editor, which may
be a string snip (for immediate text) or an editor snip (for an
embedded editor).
An editor is not permanently attached to any display. We can take the
text editor out of our canvas and put a pasteboard editor in the
canvas, instead:
@schemeblock[
(define pb (new pasteboard%))
(send c #,(:: editor-canvas% set-editor) pb)
]
With the pasteboard editor installed, the user can no longer type
characters directly into the editor (because a pasteboard does not
support directly entered text). However, the user can cut text from
elsewhere and paste it into pasteboard, or select one of the
@onscreen{Insert} menu items in the @onscreen{Edit} menu. Snips are
clearly identifiable in a pasteboard editor (unlike a text editor)
because each snip is separately dragable.
We can insert the old text editor (which we recently removed from the
canvas) as an embedded editor in the pasteboard by explicitly
creating an editor snip:
@schemeblock[
(define s (make-object editor-snip% t)) (code:comment #, @t{@scheme[t] is the old text editor})
(send pb #,(:: editor:<%> insert) s)
]
An individual snip cannot be inserted into different editors at the
same time, or inserted multiple times in the same editor:
@schemeblock[
(send pb #,(:: editor<%> insert) s) (code:comment #, @t{no effect})
]
However, we can make a deep copy of the snip and insert the copy into
the pasteboard:
@schemeblock[
(send pb #,(:: editor<%> insert) (send s #,(:: snip% copy)))
]
Applications that use the editor classes typically derive new versions
of the @scheme[text%] and @scheme[pasteboard%] classes. For
example, to implement an append-only editor (which allows insertions
only at the end and never allows deletions), derive a new class from
@scheme[text%] and override the
@method[text% can-insert?] and
@method[text% can-delete?] methods:
@schemeblock[
(define append-only-text%
(class text%
(inherit #,(:: text% last-position))
(define/override (#,(:: text% can-insert?) s l) (= s #,(:: text% last-position)))
(define/override (#,(:: text% can-delete?) s l) #f)
(super-new)))
]
@section[#:tag "mr:tb:miaoverview"]{Editor Structure and Terminology}
MrEd supports extensible and nestable editors by decomposing an editor
assembly into three functional parts:
@itemize{
@item{The @deftech{editor} itself stores the state of the text or
pasteboard and handles most events and editing operations. The
@scheme[editor<%>] interface defines the core editor functionality,
but editors are created as instances of @scheme[text%] or
@scheme[pasteboard%].}
@item{A @deftech{snip} is a segment of information within the
editor. Each snip can contain a sequence of characters, a picture,
or an interactive object (such as an embedded editor). In a text
editor, snips are constrained to fit on a single line and generally
contain data of a single type. The @scheme[snip%] class implements a
basic snip. Other snip classes include @scheme[string-snip%] for
managing text, @scheme[image-snip%] for managing pictures, and
@scheme[editor-snip%] for managing embedded editors.}
@item{A @deftech{display} presents the editor on the screen. The
display lets the user scroll around an editor or change editors. Most
displays are instances of the @scheme[editor-canvas%] class, but the
@scheme[editor-snip%] class also acts as a display for embedded
editors.}
}
These three parts are illustrated by a simple word processor. The
editor corresponds to the text document. The editor object receives
keyboard and mouse commands for editing the text. The text itself is
distributed among snips. Each character could be a separate snip, or
multiple characters on a single line could be grouped together into a
snip. The display roughly corresponds to the window in which the
text is displayed. While the editor manages the arrangement of the
text as it is displayed into a window, the display determines which
window to draw into and which part of the editor to display.
Each selectable entity in an editor is an @deftech{item}. In a
pasteboard, all selection and dragging operations work on snips, so
there is a one-to-one correspondence between snips and items. In an
editor, one snip contains one or more consecutive items, and every
item belongs to some snip. For example, in a simple text editor, each
character is an item, but multiple adjacent characters may be grouped
into a single snip. The number of items in a snip is the snip's
@deftech{count}.
Each place where the insertion point can appear in a text editor is a
@deftech{position}. A text editor with $n$ items contains $n+1$
positions: one position before each item, and one position after the
last item.
The order of snips within a pasteboard determines each snip's drawing
plane. When two snips overlap within the pasteboard, the snip that is
earlier in the order is in front of the other snip (i.e., the former
is drawn after the latter, such that the former snip may cover part
of the latter snip).
When an editor is drawn into a display, each snip and position has a
@deftech{location}. The location of a position or snip is specified
in coordinates relative to the top-left corner of the
editor. Locations in an editor are only meaningful when the editor is
displayed.
@subsection[#:tag "mr:editoradministrators"]{Administrators}
Two extra layers of administration manage the @techlink{display}-editor and
editor-snip connections. An editor never communicates directly with
a @techlink{display}; instead, it always communicates with an @deftech{editor
administrator}, an instance of the @scheme[editor-admin%] class,
which relays information to the @techlink{display}. Similarly, a snip
communicates with a @deftech{snip administrator}, an instance of the
@scheme[snip-admin%] class.
The administrative layers make the editor hierarchy flexible without
forcing every part of an editor assembly to contain the functionality
of several parts. For example, a text editor can be a single
@techlink{item} within another editor; without administrators, the
@scheme[text%] class would also have to contain all the functionality
of a @techlink{display} (for the containing editor) and a snip (for
the embedded editor). Using administrators, an editor class can serve
as both a containing and an embedded editor without directly
implementing the @techlink{display} and snip functionality.
A snip belongs to at most one editor via a single administrator. An
editor also has only one administrator at a time. However, the
administrator that connects the an editor to the standard
@techlink{display} (i.e., an editor canvas) can work with other such
administrators. In particular, the administrator of an
@scheme[editor-canvas%] (each one has its own administrator) can work
with other @scheme[editor-canvas%] administrators, allowing an editor
to be displayed in multiple @scheme[editor-canvas%] windows at the
same time.
When an editor is displayed by multiple canvases, one of the canvases'
administrators is used as the editor's primary administrator. To
handle user and update events for other canvases, the editor's
administrator is temporarily changed and then restored through the
editor's @method[editor<%> set-admin] method. The return value of the
editor's @method[editor<%> get-admin] method thus depends on the
context of the call.
@subsection[#:tag "mr:editorstyles"]{Styles}
A @deftech{style}, an instance of the @scheme[style<%>] interface,
parameterizes high-level display information that is common to all
snip classes. This includes the font, color, and alignment for
drawing the item. A single style is attached to each snip.
Styles are hierarchical: each style is defined in terms of another
style. @index*['("Basic style") (list @elem{@scheme["Basic"]
style})]{There} is a single @deftech{root style}, named
@scheme["Basic"], from which all other styles in an editor are
derived. The difference between a base style and each of its derived
style is encoded in a @deftech{style delta} (or simply
@deftech{delta}). A delta encodes changes such as
@itemize{
@item{change the font family to @italic{X};}
@item{enlarge the font by adding @italic{Y} to the point size;}
@item{toggle the boldness of the font; or}
@item{change everything to match the style description @italic{Z}.}
}
Style objects are never created separately; rather, they are always
created through a @deftech{style list}, an instance of the
@scheme[style-list%] class. A style list manages the styles,
servicing external requests to find a particular style, and it
manages the hierarchical relationship between styles. A global style
list is available, @indexed-scheme[the-style-list], but new style
lists can be created for managing separate style hierarchies. For
example, each editor will typically have its own style list.
Each new style is defined in one of two ways:
@itemize{
@item{A @deftech{derived style} is defined in terms of a base style
and a delta. Every style (except for the root style) has a base
style, even if it does not depend on the base style in any way (i.e.,
the delta describes a fixed style rather than extensions to an
existing style). (This is the usual kind of style inheritance, as
found in word processors such as Microsoft Word.)}
@item{A @deftech{join style} is defined in terms of two other styles:
a base style and a @deftech{shift style}. The meaning of a join style
is determined by reinterpreting the shift style; in the
reinterpretation, the base style is used as the {\em root\/} style
for the shift style. (This is analogous to multi-level
styles, like the paragraph and character styles in FrameMaker. In
this analogy, the paragraph style is the base style, and the
character style is the shift style. However, FrameMaker allows only
those two levels; with join styles support any number of levels.)}
}
@index*['("Standard style") (list @elem{@scheme["Standard"]
style})]{Usually}, when text is inserted into a text editor, it
inherits the style of the preceding snip. If text is inserted into an
empty editor, the text is usually assigned a style called
@scheme["Standard"]. By default, the @scheme["Standard"] style is
unmodified from the root style. The default style name can be changed
by overriding @method[editor<%> default-style-name].
The exception to the above is when @xmethod[text% change-style] is
called with the current selection @techlink{position} (when the
selection is a @techlink{position} and not a range). In that case,
the style is remembered, and if the next editor-modifying action is a
text insertion, the inserted text gets the remembered style.
See @xmethod[text% get-styles-sticky] for more information about the
style of inserted text.
@section[#:tag "mr:editorfileformat"]{File Format}
To allow editor content to be saved to a file, the editor classes
implement a special file format. (The format is used when cutting and
pasting between applications or eventspaces, too). The file format is
not documented, except that it begins
@litchar{WXME01}@nonterm{digit}@nonterm{digit} ## }. Otherwise, the
@method[editor<%> load-file] and @method[editor<%> save-file] methods
define the format internally. The file format is the same for text
and pasteboard editors. When a pasteboard saves its content to a
file, it saves the snips from front to back, and also includes extra
location information.
Editor data is read and written using @scheme[editor-stream-in%] and
@scheme[editor-stream-out%] objects. Editor information can only be
read from or written to one stream at a time. To write one or more
editors to a stream, first call the function
@scheme[write-editor-global-header] to write initialization data into
an output stream. When all editors are written to the stream, call
@scheme[write-editor-global-footer]. Similarly, reading editors from
a stream is initialized with @scheme[read-editor-global-header] and
finalized with @scheme[read-editor-global-footer]. Optionally, to
support streams that span versions of MrEd, use
@scheme[write-editor-version] and @scheme[read-editor-version] before
the header operations.
The editor file data format can be embedded within another file, and
it can be extended with new kinds of data. The editor file format can
be extended in two ways: with snip- or content-specific data, and
with editor-specific global data. These are described in the
remainder of this section.
@subsection{Encoding Snips}
@index['("snips" "saving")]{@index['("snips" "cut and paste")]{The}}
generalized notion of a snip allows new snip types to be defined and
immediately used in any editor class. Also, when two applications
support the same kinds of snips, snip data can easily be cut and
pasted between them, and the same data files will be readable by each
program. This interoperability is due to a consistent encoding
mechanism that is built into the snip system.
Graceful and extensible encoding of snips requires that
two issues are addressed:
@itemize{
@item{The encoding function for a snip can be associated with the snip
itself. To convert a snip from an encoded representation (e.g., as
bytes in a file) to a memory object, a decoding function must be
provided for each type of snip. Furthermore, a list of such decoders
must be available to the high-level decoding process. This decoding
mapping is defined by associating a @deftech{snip class} object to
every snip. A snip class is an instance of the @scheme[snip-class%]
class.}
@item{Some editors may require additional information to be stored
about a snip; this information is orthogonal to the type-specific
information stored by the snip itself. For example, a pasteboard
needs to remember a snip's @techlink{location}, while a text editor does not
need this information. If data is being cut and pasted from one
pasteboard to another, then information about relative @techlink{location}s
needs to be maintained, but this information should not inhibit
pasting into an editor. Extra data is associated with a snip through
@deftech{editor data} objects, instances of the
@scheme[editor-data%] class; decoding requires that each editor data
object has an @deftech{editor data class}, an instance of the
@scheme[editor-data-class%] class.}
}
Snip classes, snip data, and snip data classes solve problems related
to encoding and decoding snips. In an application that has no need
for saving files or cut-and-paste, these issues can be safely
ignored.
@subsubsection[#:tag "mr:editorsnipclasses"]{Snip Classes}
Each snip can be associated to a @deftech{snip class}. This ``class''
is not a class description in the programmer's language; it is an
object which provides a way to create new snips of the appropriate
type from an encoded snip specification.
Snip class objects can be added to the eventspace-specific
@deftech{snip class list}, which is returned by
@scheme[get-the-snip-class-list]. When a snip is encoded, the snip's
class name is associated with the encoding; when the snip needs to be
decoded, then the snip class list is searched by name to find the
snip's class. The snip class will then provide a decoding function
that can create a new snip from the encoding.
If a snip class's name is of the form @scheme["(lib ...)"], then the
snip class implementation can be loaded on demand. The name is parsed
using @scheme[read]; if the result has the form @scheme[(libKW string
...)], then it is supplied to @scheme[dynamic-require] along with
@scheme['snip-class]. If the result is a @scheme[snip-class%] object,
it is inserted into the current eventspace's snip class list, and
loading or saving continues using the new class.
@subsubsection[#:tag "mr:editordata"]{Editor Data}
While a snip belongs to an editor, the editor may store extra
information about a snip in some specialized way. When the snip is to
be encoded, this extra information needs to be put into an
@deftech{editor data} object so that the extra information can be
encoded as well. In a text editor, extra information can be
associated with ranges of @techlink{item}s, as well as snips.
Just as a snip must be associated with a snip class to be decoded (see
@|snipclassdiscuss|), an editor data object needs an @deftech{editor
data class} for decoding. Every editor data class object can be added
to the eventspace-specific @deftech{editor data class list}, returned
by @scheme[get-the-editor-data-class-list]. Alternatively, like snip
classes, editor data class names can use the form @scheme["(lib ...)"]
to enable on-demand loading. The corresponding module should export an
@scheme[editor-data-class%] object named
@scheme['editor-data-class].
To store and load information about a snip or region in an editor:
@itemize{
@item{derive new classes from @scheme[editor-data%] and
@scheme[editor-data-class%].}
@item{derive a new class from the @scheme[text%] or
@scheme[pasteboard%] class, and override the @method[editor<%>
get-snip-data] and @method[editor<%> set-snip-data] methods and/or the
@method[text% get-region-data] and @method[text% set-region-data]
methods.
Note: the @method[text% get-region-data] and @method[text%
set-region-data] methods are called for cut-and-paste encoding, but
not for file-saving encoding; see @|globaleditordatadiscuss| for
information on extending the file format.}
}
@subsection[#:tag "mr:globaleditordata"]{Global Data: Headers and Footers}
The editor file format provides for adding extra global data in
special header and footer sections. To save and load special header
and/or footer records:
@itemize{
@item{Pick a name for each header/footer record. This name should not
conflict with any other header/footer record name in use, and no one
else should use these names. All names beginning with ``wx'' are
reserved for internal use. By tagging extra header and footer records
with a unique name, the file can be safely loaded under a system that
does not support the records.}
@item{Derive a new class from the @scheme[text%] or
@scheme[pasteboard%] class, and override the @method[editor<%>
write-headers-to-file], @method[editor<%> write-footers-to-file],
@method[editor<%> read-header-from-file] and/or @method[editor<%>
read-footer-from-file] methods.}
}
When an editor is saved, the methods @method[editor<%>
write-headers-to-file] and @method[editor<%> write-footers-to-file]
are invoked; at this time, the derived @scheme[text%] or
@scheme[pasteboard%] object has a chance to save records. To write a
header/footer record, first invoke the @method[editor<%>
begin-write-header-footer-to-file] method, at which point the record
name is provided. Once the record is written, call @method[editor<%>
end-write-header-footer-to-file].
When an editor is loaded and a header/footer record is encountered,
the @method[editor<%> read-header-from-file] or @method[editor<%>
read-footer-from-file] method is invoked, with the record name as the
argument. If the name matches a known record type, then the data can
be loaded.
See also @method[editor<%> write-headers-to-file] and
@method[editor<%> write-headers-to-file].
@section[#:tag "mr:editoreol"]{End of Line Ambiguity}
Because an editor can force a line break even when there is no
carriage return item, a @techlink{position} alone does not always
specify a @techlink{location} for the caret. Consider the last
@techlink{position} of a line that is soft-broken (i.e., no carriage
return is present): there is no @techlink{item} between the last
@techlink{item} of the line and the first @techlink{item} of the next
line, so two @techlink{location}s (one end-of-line and one
start-of-line) map to the same @techlink{position}.
For this reason, @techlink{position}-setting and
@techlink{position}-getting methods often have an extra argument. In
the case of a @techlink{position}-setting method, the argument
specifies whether the caret should be drawn at the left or right side
of the page (in the event that the @techlink{location} is doubly
defined); @scheme[#t] means that the caret should be drawn on the
right side. Similarly, methods which calculate a @techlink{position}
from a @techlink{location} will take an extra boxed boolean; the box
is filled with @scheme[#t] if the position is ambiguous and it came
from a right-side location, or @scheme[#f] otherwise.
@section[#:tag "mr:editorflattened"]{Flattened Text}
In plain text editors, there is a simple correlation between
@techlink{position}s and characters. In an @scheme[editor<%>] object,
this is not true much of the time, but it is still sometimes useful
to just ``get the text'' of an editor.
Text can be extracted from an editor in either of two forms:
@itemize{
@item{@deftech{Simple text}, where there is one character per
@techlink{item}. @techlink{Item}s that are characters are mapped to
themselves, and all other @techlink{item}s are mapped to a
period. Line breaks are represented by carriage-return characters
(ASCII 13).}
@item{@deftech{Flattened text}, where each @techlink{item} can map to
an arbitrary string. @techlink{Item}s that are characters are still
mapped to themselves, but more complicated @techlink{item}s can be
represented with a useful string determined by the @techlink{item}'s
snip. Newlines are mapped to platform-specific character sequences
(linefeed under X, carriage return under Mac OS X, and
linefeed-carriage return under Windows). This form is called
``flattened'' because the editor's @techlink{item}s have been reduced
to a linear sequence of characters.}
}
@section[#:tag "mr:drawcaretinfo"]{Caret Ownership}
Within a frame, only one object can contain the keyboard focus. This
property must be maintained when a frame contains multiple editors in
multiple @techlink{display}s, and when a single editor contains other
editors as @techlink{item}s.
When an editor has the keyboard focus, it will usually display the
current selection or a line indicating the insertion point; the line
is called the @deftech{caret}.
When an editor contains other editors, it keeps track of caret
ownership among the contained sub-editors. When the caret is taken
away from the main editor, it will revoke caret ownership from the
appropriate sub-editor.
When an editor or snip is drawn, an argument to the drawing method
specifies whether the caret should be drawn with the data. This
argument can be any of (in increasing order):
@itemize{
@item{@indexed-scheme['no-caret] --- The caret should not be drawn at
all.}
@item{@indexed-scheme['show-inactive-caret] --- The caret should be drawn
as inactive; items may be identified as the local current selection,
but the keyboard focus is elsewhere.}
@item{@indexed-scheme['show-caret] --- The caret should be drawn to show
keyboard focus ownership.}
}
The @scheme['show-inactive-caret] display mode is useful for showing
selection ranges in text editors that do not have the focus. This
@scheme['show-inactive-caret] mode is distinct from @scheme['no-caret]
mode; when editors are embedded, only the locally-active editor shows
its selection.
@section[#:tag "mr:editorcutandpastetime"]{Cut and Paste Time Stamps}
Methods of @scheme[editor<%>] that use the clipboard --- including
@method[editor<%> copy], @method[editor<%> cut], @method[editor<%>
paste], and @method[editor<%> do-edit-operation] --- consume a time
stamp argument. This time stamp is generally extracted from the
@scheme[mouse-event%] or @scheme[key-event%] object that triggered
the clipboard action. X uses the time stamp to synchronize clipboard
operations among the clipboard clients.
All instances of @scheme[event%] include a time stamp, which can be
obtained using @method[event% get-time-stamp].
If the time stamp is 0, it defaults to the current time. Using 0 as the
time stamp almost always works fine, but it is considered bad manners
under X.
@section[#:tag "mr:editorclickback"]{Clickbacks}
@deftech{Clickbacks} in a @scheme[text%] editor facilitate the
creation of simple interactive objects, such as hypertext. A
clickback is defined by associating a callback function with a range
of @techlink{item}s in the editor. When a user clicks on the
@techlink{item}s in that range, the callback function is invoked. For
example, a hypertext clickback would associate a range to a callback
function that changes the selection range in the editor.
By default, the callback function is invoked when the user releases
the mouse button. The @method[text% set-clickback] method accepts
an optional argument that causes the callback function to be invoked
on the button press, instead. This behavior is useful, for example,
for a clickback that creates a popup menu.
Note that there is no attempt to save clickback information when a
file is saved, since a clickback will have an arbitrary procedure
associated with it.
@section[#:tag "mr:lockinfo"]{Internal Editor Locks}
Instances of @scheme[editor<%>] have three levels of internal
locking:
@itemize{
@item{write locking --- When an editor is internally locked for
writing, the abstract content of the editor cannot be changed (e.g.,
insertion attempts fail silently). However, snips in a text editor
can still be split and merged, and the text editor can be changed in
ways that affect the flow of lines. The
@method[editor<%> locked-for-write?] method reports whether an
editor is currently locked for writing.}
@item{flow locking --- When a text editor is internally locked for
reflowing, it is locked for writing, the snip content of the editor
cannot change, the @techlink{location} of a snip cannot be computed if it
is not already known (see
@xmethod[editor% locations-computed?]), and the editor cannot
be drawn to a @techlink{display}. A request for uncomputed location
information during a flow lock produces undefined results. The
@method[editor<%> locked-for-flow?] method reports whether an
editor is currently locked for flowing.}
@item{read locking --- When an editor is internally locked for
reading, no operations can be performed on the editor (e.g., a
request for the current selection position returns an undefined
value). This extreme state is used only during callbacks to its snips
for setting the snip's administrator, splitting the snip, or merging
snips. The @method[editor<%> locked-for-read?] method reports
whether an editor is currently locked for reading.}
}
The internal lock for an editor is {\em not\/} affected by calls to
@method[editor<%> lock].
Methods that report @techlink{location}-independent information about an
editor never trigger a lock. A method that reports @techlink{location}
information may trigger a flow lock or write lock if the relevant
information has not been computed since the last modification to the
editor (see @xmethod[editor% locations-computed?]). A method
that modifies the editor in any way, even setting the selection
position, can trigger a read lock, flow lock, or write lock.
@section[#:tag "mr:editorthreads"]{Editors and Threads}
An editor is not tied to any particular thread or eventspace, except
to the degree that it is displayed in a canvas (which has an
eventspace). Concurrent access of an editor is always safe, in the
sense that the editor will not become corrupted. However, because
editor access can trigger locks, and because lock-rejected operations
tend to fail silently, concurrent access can produce unexpected
results.
Nevertheless, the editor supports certain concurrent patterns
reliably. One relevant pattern is updating an editor in one thread
while the editor is displayed in a canvas that is managed by a
different (handler) thread. To ensure that canvas refreshes are not
performed while the editor is locked for flowing, and to ensure that
refreshes do not prevent editor modifications, the following are
guaranteed:
@itemize{
@item{When an editor's @method[editor<%> refresh] method is
called during an edit sequence (which is started by
@method[editor<%> begin-edit-sequence] and ended with
@method[editor<%> end-edit-sequence]), the requested refresh
region is recorded, but the refresh is not performed. Instead, the
refresh is delayed until the end of the edit sequence.}
@item{Attempting to start an edit sequence while a refresh is in
progress blocks until the refresh is complete.}
@item{The @method[editor<%> on-display-size-when-ready] method
calls @method[editor<%> on-display-size] only when the editor
is not being refreshed and only when an edit sequence is not in
progress. In the first case, the
@method[editor<%> on-display-size] call is delegated to the
refreshing thread to be called after the refresh completes. In the
second case, the @method[editor<%> on-display-size] call is
delegated to the edit-sequence thread, to be called when the edit
sequence is complete.}
}
Thus, disabling an @scheme[editor-canvas%] object (using
@method[window<%> enable]) is sufficient to ensure that a
background thread can modify an editor displayed by the canvas, as
long as all modifications are in edit sequences. The background
modifications will impair canvas refreshes minimally and temporarily,
and refreshes will not impair modifications in the background thread.
A second supported pattern is reading an editor in a background thread
while the editor may be manipulated in other threads. Since no
@techlink{location}-independent reads introduce locks, the such reads in
the background thread will not impair other threads. However, other
threads may interfere with the background thread, causing it to
receive erroneous or out-of-date content information. This one-sided
guarantee is useful if the background thread's work can be discarded
when the editor is modified.

View File

@ -0,0 +1,226 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@defclass[font% object% ()]{
A @defterm{font} is an object which determines the appearance of text,
primarily when drawing text to a device context. A font is determined
by seven properties:
@itemize{
@item{size --- The size of the text, either in points (the default)
or logical drawing units, depending on the
``size-in-pixels?''\ property (see below).}
@item{family --- A platform- and device-independent font
designation. The families are:
@itemize{
@item{@indexed-scheme['default]}
@item{@indexed-scheme['decorative]}
@item{@indexed-scheme['roman]}
@item{@indexed-scheme['script]}
@item{@indexed-scheme['swiss]}
@item{@indexed-scheme['modern] (fixed width)}
@item{@indexed-scheme['symbol] (Greek letters and more)}
@item{@indexed-scheme['system] (used to draw control labels)}
}
The @scheme['modern] designation is special under Mac OS X and X with
fontconfig/Xft; characters in the ASCII range 0-255 are converted to
Unicode characters that match Adobe symbols. For example, @litchar{a} is
converted to @litchar["\u03B1"].}
@item{face --- A string face name, such as @scheme["Courier"] (under
Windows and Mac OS X), @scheme["-*-courier"] (under
X), or @scheme[" Luxi Sans"] (under X with
fontconfig/Xft; note the leading space). The format
and meaning of a face name is platform- and
device-specific. If a font's face name is @scheme[#f],
then the font's appearance depends only on the
family. If a face is provided but no mapping is
available for the face name (for a specific platform
or device), then the face name is ignored and the
family is used. See @scheme[font-name-directory<%>]
for information about how face names are mapped for
drawing text.}
@item{style --- The slant style of the font, one of:
@itemize{
@item{@indexed-scheme['normal]}
@item{@indexed-scheme['slant] (Windows, Mac OS X: same as @scheme['italic]; X: tries @scheme['italic] if @scheme['slant] font does not exist)}
@item{@indexed-scheme['italic] (X: tries @scheme['slant] if @scheme['italic] font does not exist)}
}}
@item{weight --- The weight of the font, one of:
@itemize{
@item{@indexed-scheme['normal]}
@item{@indexed-scheme['light]}
@item{@indexed-scheme['bold]}
}}
@item{underline? --- @scheme[#t] for underlined, @scheme[#f] for plain.}
@item{smoothing --- Amount of anti-alias smoothing, one of:
@itemize{
@item{@indexed-scheme['default] (platform-specific, sometimes user-configurable)}
@item{@indexed-scheme['partly-smoothed] (Windows: TrueType when available;
Mac OS X: 4-bit, pixel-aligned smoothing;
X: fontconfig/Xft when available)}
@item{@indexed-scheme['smoothed] (Windows: ClearType when available, XP and up;
Mac OS X: Quartz smoothing;
X: fontconfig/Xft when available)}
@item{@indexed-scheme['unsmoothed]}
}
Special case: @scheme['default] corresponds to
@scheme['partly-smoothed] when used with the @scheme['modern] family
and a font size between 9 and 13 (inclusive).}
@item{size-in-pixels? --- @scheme[#t] if the size of the font
is in logical drawing units (i.e., pixels for an unscaled screen or
bitmap drawing context), @scheme[#f] if the size of the font is in
points (which can depend on screen resolution).}
}
To avoid creating multiple fonts with the same characteristics, use
the global @scheme[font-list%] object @indexed-scheme[the-font-list].
See also
@scheme[font-name-directory<%>].
@defconstructor*/make[(()
([size (integer-in 1 255)]
[family (one-of/c 'default 'decorative 'roman 'script
'swiss 'modern 'symbol 'system)]
[style (one-of/c 'normal 'italic 'slant) 'normal]
[weight (one-of/c 'normal 'bold 'light) 'normal]
[underline? any/c #f]
[smoothing (one-of/c 'default 'partly-smoothed 'smoothed 'unsmoothed) 'default]
[size-in-pixels? any/c #f])
([size (integer-in 1 255)]
[face string?]
[family (one-of/c 'default 'decorative 'roman 'script
'swiss 'modern 'symbol 'system)]
[style (one-of/c 'normal 'italic 'slant) 'normal]
[weight (one-of/c 'normal 'bold 'light) 'normal]
[underline? any/c #f]
[smoothing (one-of/c 'default 'partly-smoothed 'smoothed 'unsmoothed) 'default]
[size-in-pixels? any/c #f]))]{
When no arguments are provided, creates an instance of the default
font. If no face name is provided, the font is created without a face
name. Otherwise, see @scheme[font-name-directory<%>] for information
about the way @scheme[face] is interpreted for drawing text on
various platforms and devices; when a platform- or device-specific
interpretation of @scheme[face] is not available, the @scheme[family]
is used to draw text.
See @scheme[font%] for information about @scheme[family],
@scheme[style], and @scheme[weight]. @scheme[font-name-directory<%>].
}
@defmethod[(get-face)
(or/c string? false/c)]{
Gets the font's face name, or @scheme[#f] if none is specified.
}
@defmethod[(get-family)
(one-of/c 'default 'decorative 'roman 'script
'swiss 'modern 'symbol 'system)]{
Gets the font's family. See @scheme[font%] for information about
families.
}
@defmethod[(get-font-id)
(and/c exact? integer?)]{
Gets the font's ID, for use with a
@scheme[font-name-directory<%>]. The ID is determined by the font's
face and family specifications, only.
}
@defmethod[(get-point-size)
(integer-in 1 255)]{
Gets the font's size (roughly the height). Despite the method name,
the size may be in logical units instead of points, depending on the
result of @method[font% get-size-in-pixels].
Due to space included in a font by a font designer, a font tends to
generate text that is slightly taller than the nominal size.
}
@defmethod[(get-size-in-pixels)
boolean?]{
Returns @scheme[#t] if the size reported by @method[font%
get-point-size] is in logical drawing units, @scheme[#f] if it is in
points.
For a size in points and a screen or bitmap drawing context, the
logical height depends on the resolution of the screen.
}
@defmethod[(get-smoothing)
(one-of/c 'default 'partly-smoothed 'smoothed 'unsmoothed)]{
Gets the font's anti-alias smoothing mode. See @scheme[font%] for
information about smoothing.
}
@defmethod[(get-style)
(one-of/c 'normal 'italic 'slant)]{
Gets the font's slant style. See @scheme[font%] for information about
styles.
}
@defmethod[(get-underlined)
boolean?]{
Returns @scheme[#t] if the font is underlined or @scheme[#f]
otherwise.
}
@defmethod[(get-weight)
(one-of/c 'normal 'bold 'light)]{
Gets the font's weight. See @scheme[font%] for information about
weights.
}
@defmethod[(screen-glyph-exists? [c char]
[for-label? any/c #f])
boolean?]{
Returns @scheme[#t] if the given character has a corresponding glyph
when drawing to the screen or a bitmap, @scheme[#f] otherwise.
If the second argument is true, the result indicates whether the glyph
is available for control labels. Otherwise, it indicates whether the
glyph is available for @scheme[dc<%>] drawing.
For @scheme[dc<%>] drawing, due to automatic font substitution when
drawing or measuring text, the result of this method does not depend
on this font's attributes (size, face, etc.). The font's attributes
merely provide a hint for the glyph search.
See also @method[dc<%> glyph-exists?] .
}}

View File

@ -0,0 +1,77 @@
#reader(lib "docreader.ss" "scribble")
@require["common.ss"]
@title{Fonts}
@defproc[(get-face-list [family (one-of/c 'mono 'all) 'all])
(listof string?)]{
Returns a list of font face names available on the current system. If
@scheme['mono] is provided as the argument, then only faces that are
known to correspond to monospace fonts are included in the list.
}
@defproc[(get-family-builtin-face [family (one-of/c 'default 'decorative 'roman 'script
'swiss 'modern 'symbol 'system)])
string?]{
Returns the built-in default face mapping for a particular font
family. The built-in default can be overridden via preferences, as
described in @secref["mr:fontresources"].
See @scheme[font%] for information about @scheme[family].
}
@defthing[menu-control-font (is-a?/c font%)]{
This font is the default for @scheme[popup-menu%] objects.
Under Mac OS X, this font is slightly larger than
@scheme[normal-control-font]. Under Windows and X, it is the same
size as @scheme[normal-control-font].
}
@defthing[normal-control-font (is-a?/c font%)]{
This font is the default for most controls, except
@scheme[list-box%] and @scheme[group-box-panel%] objects.
}
@defthing[small-control-font (is-a?/c font%)]{
This font is the default for @scheme[group-box-panel%] objects, and it is
a suitable for controls in a floating window and other contexts that
need smaller controls.
Under Windows, this font is the same size as
@scheme[normal-control-font], since the Windows control font is
already relatively small. Under X and Mac OS X, this font is slightly
smaller than @scheme[normal-control-font].
}
@defthing[tiny-control-font (is-a?/c font%)]{
This font is for tiny controls, and it is smaller than
@scheme[small-control-font] on all platforms.
}
@defthing[view-control-font (is-a?/c font%)]{
This font is the default for @scheme[list-box%] objects (but not
list box labels, which use @scheme[normal-control-font]).
Under Mac OS X, this font is slightly smaller than
@scheme[normal-control-font], and slightly larger than
@scheme[small-control-font]. Under Windows and X, it is the same size
as @scheme[normal-control-font].
}

View File

@ -0,0 +1,42 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@defclass[font-list% object% ()]{
A @scheme[font-list%] object maintains a list of @scheme[font%]
objects to avoid repeatedly creating fonts.
A global font list, @scheme[the-font-list], is created automatically.
@defconstructor/make[()]{
Creates an empty font list.
}
@defmethod*[([(find-or-create-font [size (integer-in 1 255)]
[family (one-of/c 'default 'decorative 'roman 'script
'swiss 'modern 'symbol 'system)]
[style (one-of/c 'normal 'italic 'slant)]
[weight (one-of/c 'normal 'bold 'light)]
[underline? any/c #f]
[smoothing (one-of/c 'default 'partly-smoothed 'smoothed 'unsmoothed) 'default]
[size-in-pixels? any/c #f])
(is-a?/c font%)]
[(find-or-create-font [size (integer-in 1 255)]
[face string?]
[family (one-of/c 'default 'decorative 'roman 'script
'swiss 'modern 'symbol 'system)]
[style (one-of/c 'normal 'italic 'slant)]
[weight (one-of/c 'normal 'bold 'light)]
[underline any/c #f]
[smoothing (one-of/c 'default 'partly-smoothed 'smoothed 'unsmoothed) 'default]
[size-in-pixels? any/c #f])
void?])]{
Finds an existing font in the list or creates a new one (that is
automatically added to the list). The arguments are the same as for
creating a @scheme[font%] instance.
}}

View File

@ -0,0 +1,215 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@require[(lib "bnf.ss" "scribble")]
@definterface[font-name-directory<%> ()]{
There is one @scheme[font-name-directory<%>] object:
@scheme[the-font-name-directory]. It implements the mapping from font
specifications (face, family, style, and weight) to information for
rendering text on a specific device. The mapping is different for
each platform. For example, when drawing to a bitmap in Windows, the
rendering information is simply the name of a Windows font. When
drawing to a PostScript file, the rendering information is a
PostScript font name, which encapsulates the style and weight. When
drawing to a bitmap in X, the rendering information is an X font
string, which encapsulates the style and weight, parameterized over
the size (using a ``\%d'' placeholder).
Programmers rarely need to directly invoke methods of
@scheme[the-font-name-directory]. It is used automatically when
drawing text to a @scheme[dc<%>] object. Nevertheless,
@scheme[the-font-name-directory] is available so that programmers can
query or modify the mapping manually. A programmer may also need to
understand how the face-and-family mapping works.
To extract mapping information from @scheme[the-font-name-directory],
first obtain a @defterm{font ID}, which is an index based on a family
and optional face string. Font IDs are returned by
@method[font-name-directory<%> find-or-create-font-id] and
@method[font-name-directory<%> get-font-id] . A Font ID can be
combined with a weight and style to obtain a specific mapping value
via @method[font-name-directory<%> get-screen-name] or
@method[font-name-directory<%> get-post-script-name].
For a family without a face string, the corresponding font ID has a
useful built-in mapping for every platform and device. (The built-in
mapping can be overridden through the user's preferences; see
@secref["mr:fontresources"] for information.) For a family with a
face string, @scheme[the-font-name-directory] interprets the string
(in a platform-specific way) to generate a mapping for ``screen''
drawing (to a canvas's @scheme[dc<%>], a @scheme[bitmap-dc%], or a
@scheme[printer-dc%]). When drawing to a @scheme[post-script-dc%]
object, the face-specific mapping defaults to the family's mapping.
Under Windows and Mac OS X, a face name is interpreted simply as a
system font name for drawing to the screen, bitmap, or printer. The
mapping succeeds if the system provides a font with the given name,
and fails otherwise. For example, under Windows, @scheme["MS Sans
Serif"] maps to the font that is typically used for button
labels. Under X, a face name has a more complex interpretation:
@itemize{
@item{If the string begins with a space, then the remainder of the
string is interpreted as a fontconfig/Xft font name, but only
if fontconfig/Xft support is enabled at compile time (which is
the default when available), and only if the RENDER extension
is available at run time. Multiple fontconfig/Xft font names
can appear after the initial space, separated by commas; the
first available font is used to draw text, and later fonts are
substituted for missing characters in earlier fonts.}
@item{If the string begins with @litchar["+"], then the remainder of the
string is interpreted as an X font name. These names are
usually long, such as
@litchar["+-b&h-lucidatypewriter-medium-r-normal-sans-24-240-75-75-m-140-iso8859-1"].
As usual for X font names, asterisks may appear in the string
as wildcards. Furthermore, the size of the font can be
parameterized by using @litchar["%d"] in the place of a specific
point size; if an asterisk appears in place of the pixel size,
the asterisk and @litchar["%d"] are swapped when the font size is
specified in pixels (otherwise the size is always interpreted
as points). For rotated text, @litchar["%d"] will be replaced by
a transformation matrix.}
@item{A string of the form
@litchar["-"]@nonterm{provider}@litchar{-}@nonterm{font} is
equivalent to
@litchar["+-"]@nonterm{provider}@litchar{-}@nonterm{font}@litchar{-}@nonterm{weight}@litchar{-}@nonterm{style}@litchar{-normal-*-*-%d-*-*-*-*-*-*},
where @nonterm{weight} is either @litchar{medium},
@litchar{light}, or @litchar{bold} (depending on the requested
weight mapping) and @nonterm{style} is either @litchar{r},
@litchar{i}, or @litchar{i} (depending on the requested style
mapping).}
@item{A string of the form @litchar["-"]@nonterm{font} is
equivalent to @litchar{-*-}@nonterm{font}.}
@item{A string of any other format is interpreted as an X font name,
optionally parameterized with @litchar{%d}.}
}
The mapping for face names can be overridden (on all platforms)
through the user's preferences, as described in
@secref["mr:fontresources"].
@defmethod[(find-family-default-font-id [family (one-of/c 'default 'decorative 'roman 'script
'swiss 'modern 'symbol 'system)])
(and/c exact? integer?)]{
Gets the font ID representing the default font for a family. See
@scheme[font%] for information about font families.
}
@defmethod[(find-or-create-font-id [name string?]
[family (one-of/c 'default 'decorative 'roman 'script
'swiss 'modern 'symbol 'system)])
(and/c exact? integer?)]{
Gets the face name for a font ID, initializing the mapping for
the face name if necessary.
Font ID are useful only as mapping indices for
@indexed-scheme[the-font-name-directory].
}
@defmethod[(get-face-name [font-id (and/c exact? integer?)])
(or/c string? false/c)]{
Gets the face name for a font ID. If the font ID corresponds to
the default font for a particular family, @scheme[#f] is returned.
}
@defmethod[(get-family [font-id (and/c exact? integer?)])
(one-of/c 'default 'decorative 'roman 'script
'swiss 'modern 'symbol 'system)]{
Gets the family for a font ID. See
@scheme[font%] for information about font families.
}
@defmethod[(get-font-id [name string?]
[family (one-of/c 'default 'decorative 'roman 'script
'swiss 'modern 'symbol 'system)])
(and/c exact? integer?)]{
Gets the font ID for a face name paired with a default family. If the
mapping for the given pair is not already initialized, @scheme[0] is
returned. See also @method[font-name-directory<%>
find-or-create-font-id].
Font ID are useful only as mapping indices for
@indexed-scheme[the-font-name-directory].
}
@defmethod[(get-post-script-name [font-id (and/c exact? integer?)]
[weight (one-of/c 'normal 'bold 'light)]
[style (one-of/c 'normal 'italic 'slant)])
(or/c string? false/c)]{
Gets a PostScript font name for a font ID, weight, and style
combination. The PostScript font name is used both for the font name
in PostScript output (sans character set) and as the @|AFM| file
name; see also @secref["mr:postscriptfonts"].
See @scheme[font%] for information about @scheme[weight] and
@scheme[style].
}
@defmethod[(get-screen-name [font-id (and/c exact? integer?)]
[weight (one-of/c 'normal 'bold 'light)]
[style (one-of/c 'normal 'italic 'slant)])
(or/c string? false/c)]{
Gets a platform-dependent screen font name (used for drawing to a
canvas's @scheme[dc<%>], a @scheme[bitmap-dc%], or a
@scheme[printer-dc%]) for a font ID, weight, and style combination.
See @scheme[font%] for information about @scheme[weight] and
@scheme[style].
}
@defmethod[(set-post-script-name [font-id (and/c exact? integer?)]
[weight (one-of/c 'normal 'bold 'light)]
[style (one-of/c 'normal 'italic 'slant)]
[name string?])
void?]{
Sets a PostScript font name for a font ID, weight, and style
combination. See also @method[font-name-directory<%>
get-post-script-name].
See @scheme[font%] for information about @scheme[weight] and @scheme[style].
}
@defmethod[(set-screen-name [font-id (and/c exact? integer?)]
[weight (one-of/c 'normal 'bold 'light)]
[style (one-of/c 'normal 'italic 'slant)]
[name string?])
void?]{
Sets a platform-dependent screen font name (used for drawing to a
canvas's @scheme[dc<%>], a @scheme[bitmap-dc%], or a
@scheme[printer-dc%]) for a font ID, weight, and style combination.
Under X, if the screen name contains @litchar{%d}, it is replaced by
the size of the font (point size times 10) to obtain the full screen
font name.
See @scheme[font%] for information about @scheme[weight] and
@scheme[style].
}}

View File

@ -0,0 +1,113 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@defclass[gl-config% object% ()]{
A @scheme[gl-config%] object encapsulates configuration information
for an OpenGL drawing context. Use a @scheme[gl-config%] object as an
initialization argument for @scheme[canvas%], or provide it to
@xmethod[bitmap% set-gl-config].
@defconstructor[()]{
Creates a GL configuration that indicates double buffering, a depth
buffer of size one, no stencil buffer, no accumulation buffer, no
multisampling, and not stereo.
}
@defmethod[(get-accum-size)
(integer-in 0 256)]{
Reports the accumulation-buffer size (for each of red, green, blue,
and alpha) that the configuration requests, where zero means no
accumulation buffer is requested.
}
@defmethod[(get-depth-size)
(integer-in 0 256)]{
Reports the depth-buffer size that the configuration requests, where
zero means no depth buffer is requested.
}
@defmethod[(get-double-buffered)
boolean?]{
Reports whether the configuration requests double buffering or not.
}
@defmethod[(get-multisample-size)
(integer-in 0 256)]{
Reports the multisampling size that the configuration requests, where
zero means no multisampling is requested.
}
@defmethod[(get-stencil-size)
(integer-in 0 256)]{
Reports the stencil-buffer size that the configuration requests, where
zero means no stencil buffer is requested.
}
@defmethod[(get-stereo)
boolean?]{
Reports whether the configuration requests stereo or not.
}
@defmethod[(set-accum-size [on? (integer-in 0 256)])
void?]{
Adjusts the configuration to request a particular accumulation-buffer
size for every channel (red, green, blue, and alpha), where zero
means no accumulation buffer is requested.
}
@defmethod[(set-depth-size [on? (integer-in 0 256)])
void?]{
Adjusts the configuration to request a particular depth-buffer size,
where zero means no depth buffer is requested.
}
@defmethod[(set-double-buffered [on? any/c])
void?]{
Adjusts the configuration to request double buffering or not.
}
@defmethod[(set-multisample-size [on? (integer-in 0 256)])
void?]{
Adjusts the configuration to request a particular multisample size,
where zero means no multisampling is requested. If a multisampling
context is not available, this request will be ignored.
}
@defmethod[(set-stencil-size [on? (integer-in 0 256)])
void?]{
Adjusts the configuration to request a particular stencil-buffer size,
where zero means no stencil buffer is requested.
}
@defmethod[(set-stereo [on? any/c])
void?]{
Adjusts the configuration to request stereo or not.
}}

View File

@ -0,0 +1,98 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@definterface[gl-context<%> ()]{
A @scheme[gl-context<%>] object represents a context for drawing with
@as-index{OpenGL} to a specific @scheme[dc<%>] instance. To obtain a
@scheme[gl-context<%>] object, call @method[dc<%> get-gl-context] of
the target drawing context.
Only canvas @scheme[dc<%>] and @scheme[bitmap-dc%] objects support
OpenGL (always under Windows and Mac OS X, sometimes under X), and in
the case of a @scheme[bitmap-dc%], the context is usable only when
the target bitmap is non-monochrome. When the target bitmap for a
@scheme[bitmap-dc%] context is changed via @method[bitmap-dc%
set-bitmap], the associated OpenGL context is reset, but the
@scheme[gl-context<%>] keeps its identity. Canvas contexts are double
buffered, and bitmap contexts are single buffered.
MrEd provides no OpenGL routines. Instead, they must be obtained from
a separate library, such as @scheme[(lib "sgl.ss" "sgl")]. MrEd
merely manages the current OpenGL context, connecting it to windows
and bitmaps.
Only one OpenGL context can be active at a time across all threads and
eventspaces. Except under Mac OS X, OpenGL contexts are not protected
against interference among threads; that is, if a thread selects one
of its OpenGL contexts, then other threads can write into the context
via OpenGL commands. However, if all threads issue OpenGL commands
only within a thunk passed to @method[gl-context<%> call-as-current],
then drawing from the separate threads will not interfere, because
@method[gl-context<%> call-as-current] uses a lock to serialize
context selection across all threads in MrEd.
@defmethod[(call-as-current [thunk (-> any)]
[alternate evt? never-evt]
[enable-breaks? any/c #f])
any/c]{
Calls a thunk with this OpenGL context as the current context for
OpenGL commands.
The method blocks to obtain a lock that protects the global OpenGL
context, and it releases the lock when the thunk returns or
escapes. The lock is re-entrant, so a nested use of the method in the
same thread with the same OpenGL context does not obtain or release
the lock.
The lock prevents interference among OpenGL-using threads. If a
thread is terminated while holding the context lock, the lock is
released. Continuation jumps into the thunk do not grab the lock or
set the OpenGL context. See @scheme[gl-context<%>] for more
information on interference.
The method accepts an alternate @tech{synchronizable event} for use
while blocking for the context lock; see also @scheme[sync].
The result of the method call is the result of the thunk if it is
called, or the result of the alternate event if it is chosen instead
of the context lock.
If @method[gl-context<%> ok?] returns @scheme[#f] at the time that
this method is called, then @|MismatchExn|.
If @scheme[enable-breaks?] is true, then the method uses
@scheme[sync/enable-break] while blocking for the context-setting
lock instead of @scheme[sync].
}
@defmethod[(ok?)
boolean?]{
Returns @scheme[#t] if this context is available OpenGL drawing,
@scheme[#f] otherwise.
A context is unavailable if OpenGL support is disabled at compile time
or run time, if the context is associated with a
@scheme[bitmap-dc%] with no selected bitmap or with a monochrome
selected bitmap, if the context is for a canvas that no longer
exists, or if there was a low-level error when preparing the context.
}
@defmethod[(swap-buffers)
void?]{
Swaps the front (visible) and back (OpenGL-drawing) buffer for a
context associated with a canvas, and has no effect on a bitmap
context.
This method implicitly uses @method[gl-context<%> call-as-current] to
obtain the context lock. Since the lock is re-entrant, however, the
@method[gl-context<%> swap-buffers] method can be safely used within
a @method[gl-context<%> call-as-current] thunk.
}}

View File

@ -0,0 +1,100 @@
#reader(lib "docreader.ss" "scribble")
@require["common.ss"]
@title{Global Graphics}
@defproc[(flush-display)
void?]{
Under X and Mac OS X, flushes pending display messages such that the
user's display reflects the actual state of the windows. Under
Windows, the procedure has no effect.
}
@defproc[(get-display-depth)
nonnegative-exact-integer?]{
Returns the depth of the main display (a value of 1 denotes a monochrome display).
}
@defproc[(get-display-left-top-inset [avoid-bars? bool @scheme[#f]])
(values nonnegative-exact-integer? nonnegative-exact-integer?)]{
When the optional argument is @scheme[#f] (the default), this function
returns the offset of the main screen's origin from the
top-left of the physical screen. Under X and Windows, the result is
always @scheme[0] and @scheme[0]; under Mac OS X, the result is
@scheme[0] and the height of the menu bar.
When the optional argument is true, this function returns the amount
space at the left and top of the main screen that is occupied by the
task bar (Windows) or menu bar and dock (Mac OS X). Under X, the
result is always @scheme[0] and @scheme[0].
}
@defproc[(get-display-size [full-screen? bool @scheme[#f]])
(values nonnegative-exact-integer? nonnegative-exact-integer?)]{
@index["screen resolution"]{Gets} the physical size of the display in
pixels. Under Windows, this size does not include the task bar by
default. Under Mac OS X, this size does not include the menu bar or
dock area by default.
Under Windows and Mac OS X, if the optional argument is true, then
the task bar, menu bar, and dock area are included in the result.
Returns the screen's width and height.
}
@defproc[(is-color-display?)
boolean?]{
Returns @scheme[#t] if the main display has color, @scheme[#f]
otherwise.
}
@defproc[(register-collecting-blit [canvas (is-a?/c canvas%)]
[x real?]
[y real?]
[w (and/c real? (not/c negative?))]
[h (and/c real? (not/c negative?))]
[on (is-a?/c bitmap%)]
[off (is-a?/c bitmap%)]
[on-x real? 0]
[on-y real? 0]
[off-x real? 0]
[off-y real? 0])
void?]{
Registers a blit to occur when garbage collection starts or ends.
When garbage collection starts, @scheme[(send (send canvas #,(::
canvas<%> get-dc)) #,(:: dc<%> draw-bitmap-section) on on-x on-y x y w
h)] is called. When garbage collection ends, @scheme[(send (send
canvas #,(:: canvas<%> get-dc)) #,(:: dc<%> draw-bitmap-section) off
off-x off-y x y w h)] is called. If @scheme[canvas]'s device context
has a scale, the scale may or may not be temporarily disabled during
the bitmap drawing.
The @scheme[canvas] is registered weakly, so it will be automatically
unregistered if the canvas becomes invisible and inaccessible.
Multiple registrations can be installed for the same canvas.
See also @scheme[unregister-collecting-blit].
}
@defproc[(unregister-collecting-blit [canvas (is-a?/c canvas%)])
void?]{
Unregisters a blit request installed with See also
@scheme[register-collecting-blit].
Unregisters all blits for @scheme[canvas].
}

View File

@ -1,7 +1,7 @@
#reader(lib "docreader.ss" "scribble") #reader(lib "docreader.ss" "scribble")
@require["common.ss"] @require["common.ss"]
@title{PLT Scheme GUI Reference} @title{PLT Scheme GUI Toolbox}
This manual describes MrEd. This manual describes MrEd.
@ -12,67 +12,8 @@ This manual describes MrEd.
@;------------------------------------------------------------------------ @;------------------------------------------------------------------------
@section{GUI Toolbox Organization} @include-section["guide.scrbl"]
@include-section["reference.scrbl"]
For documentation purposes, the MrEd toolbox is organized into three
parts:
@itemize{
@item{The @deftech{windowing} toolbox, for implementing form-filling
GUI programs (such as a database query window) using buttons, menus,
text fields, and events. The windowing toolbox is documented in
@secref["mr:windowing"].}
@item{The @deftech{drawing} toolbox, for drawing pictures or
implementing dynamic GUI programs (such as a video game) using
drawing canvases, pens, and brushes. The drawing toolbox is
documented in @secref["mr:drawing"].}
@item{The @deftech{editor} toolbox, for developing traditional text
editors, editors that mix text and graphics, or free-form layout
editors (such as a word processor, HTML editor, or icon-based file
browser). The editor toolbox is documented in @secref["mr:editor"].}
}
These three parts roughly represent layers of increasing
sophistication. Simple GUI programs access only the windowing toolbox
directly, more complex programs use both the windowing and drawing
toolboxes, and large-scale applications rely on all three
toolboxes. This three-layer view of the toolbox breaks down under
close scrutiny, because the windowing, drawing, and editor toolboxes
are actually interdependent and intertwined. Nevertheless, the
layered separation is a good approximation.
All three parts are immediately available when MrEd is started, as
well as the base class system from MzLib. The @indexed-file{mred.ss}
library module of the @file{mred} collection provides all of the
class, interface, and procedure names defined in this manual. When
MrEd starts up, it imports the @file{mred.ss} module and MzLib's
@indexed-file{class.ss} module into the initial namespace (so no
knowledge about modules is required to understand this manual).
The module @indexed-scheme[#%mred-kernel] is built into the MrEd
executable, and intended for use only by @file{mred.ss}. Attempting
to require @file{mred.ss} in a plain MzScheme executable will result
in a run-time error, because @scheme[#%mred-kernel] will not be
available.
To create a namespace in which the @file{mred.ss} module will be used,
call the @scheme[make-namespace-with-mred] procedure. That
procedure attaches the @file{mred.ss} instance of the current
namespace to the created namespace. Otherwise, different namespaces
create different instances of the @file{mred.ss} module, which in
turn generate distinct classes.
@;------------------------------------------------------------------------
@include-section["windowing.scrbl"]
@;------------------------------------------------------------------------
@include-section["drawing.scrbl"]
@;------------------------------------------------------------------------ @;------------------------------------------------------------------------

View File

@ -0,0 +1,58 @@
#reader(lib "docreader.ss" "scribble")
@require["common.ss"]
@title[#:style 'toc]{Guide}
For documentation purposes, the MrEd toolbox is organized into three
parts:
@itemize{
@item{The @deftech{windowing} toolbox, for implementing form-filling
GUI programs (such as a database query window) using buttons, menus,
text fields, and events. The windowing toolbox is described in
@secref["mr:windowing-overview"].}
@item{The @deftech{drawing} toolbox, for drawing pictures or
implementing dynamic GUI programs (such as a video game) using
drawing canvases, pens, and brushes. The drawing toolbox is
described in @secref["mr:drawing-overview"].}
@item{The @deftech{editor} toolbox, for developing traditional text
editors, editors that mix text and graphics, or free-form layout
editors (such as a word processor, HTML editor, or icon-based file
browser). The editor toolbox is described in
@secref["mr:editor-overview"].}
}
These three parts roughly represent layers of increasing
sophistication. Simple GUI programs access only the windowing toolbox
directly, more complex programs use both the windowing and drawing
toolboxes, and large-scale applications rely on all three
toolboxes. This three-layer view of the toolbox breaks down under
close scrutiny, because the windowing, drawing, and editor toolboxes
are actually interdependent and intertwined. Nevertheless, the
layered separation is a good approximation.
All three parts are immediately available when MrEd is started, as
well as the base class system from MzLib. The @indexed-file{mred.ss}
library module of the @file{mred} collection provides all of the
class, interface, and procedure names defined in this manual. When
MrEd starts up, it imports the @file{mred.ss} module and MzLib's
@indexed-file{class.ss} module into the initial namespace (so no
knowledge about modules is required to understand this manual).
@local-table-of-contents[]
@;------------------------------------------------------------------------
@include-section["win-overview.scrbl"]
@;------------------------------------------------------------------------
@include-section["draw-overview.scrbl"]
@;------------------------------------------------------------------------
@include-section["editor-overview.scrbl"]

View File

@ -0,0 +1,243 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@defclass[pen% object% ()]{
A pen is a drawing tool with a color, width, and style. A pen draws
lines and outlines, such as the outline of a rectangle. On a
monochrome display, all non-white pens are drawn as black.
In addition to its color, width, and style, a pen can have a stipple
bitmap that is a 8 x 8 monochrome bitmap. This stipple is used only
in unsmoothed mode (see @method[dc<%> set-smoothing]) or in a
PostScript drawing context. Painting with a stipple pen is similar to
calling @method[dc<%> draw-bitmap] with the stipple bitmap in region
painted by the pen.
A pen's style is one of the following:
@itemize{
@item{@indexed-scheme['transparent] --- Draws with no effect (on the
outline of the drawn shape).}
@item{@indexed-scheme['solid] --- Draws using the pen's color. If a
(monochrome) stipple is installed into the pen, black pixels
from the stipple are transferred to the destination using the
brush's color, and white pixels from the stipple are not
transferred.}
@item{@indexed-scheme['xor] --- In unsmoothed mode, the pen's color
or colored stipple is xor-ed with existing destination pixel
values. The @scheme['xor] mapping is unspecified for arbitrary
color combinations, but the mapping provides two guarantees:
@itemize{
@item{Black-and-white drawing to a color or monochrome
destination always works as expected: black xor white = black,
white xor black = black, black xor black = white, and white xor
white = white.}
@item{Performing the same drawing operation twice in a row with
@scheme['xor] is equivalent to a no-op.}
}
In a smoothing mode, @scheme['xor] is equivalent to @scheme['solid].}
@item{@indexed-scheme['hilite] --- In unsmoothed mode, existing
destination pixels are ``highlighted'' in a platform-specific
way when the pen color is black. Under Windows for a color
drawing context, the inverted RGB components of destination
pixel are combined with the RGB components of the system-wide
highlight color using a bitwise ``or'', and the combination is
used. Under Mac OS X for a color drawing context, the
inverted RGB components of the system-wide highlight color are
subtracted from the RGB components of each destination pixel,
and the difference (or 0 for a negative result) is used. Under
X or for any monochrome drawing context, @scheme['hilite] is the
same as @scheme['xor]. In a smoothing mode, @scheme['hilite] is
treated like @scheme['solid].}
@item{The following special pen modes use the pen's color, and they only
apply when a stipple is not used:
@itemize{
@item{@indexed-scheme['dot]}
@item{@indexed-scheme['long-dash]}
@item{@indexed-scheme['short-dash]}
@item{@indexed-scheme['dot-dash]}
@item{@indexed-scheme['xor-dot]}
@item{@indexed-scheme['xor-long-dash]}
@item{@indexed-scheme['xor-short-dash]}
@item{@indexed-scheme['xor-dot-dash]}
}}
}
To avoid creating multiple pens with the same characteristics, use the
global @scheme[pen-list%] object @indexed-scheme[the-pen-list], or
provide a color, width, and style to @xmethod[dc<%> set-pen].
A pen of size @scheme[0] uses the minimum line size for the
destination drawing context. In (unscaled) canvases and bitmaps in
unsmoothed mode, a zero-width pen behaves the nearly same as a pen of
size @scheme[1]. In a smoothing mode (including all
@scheme[post-script-dc%] drawing), a pen of size @scheme[0] draws a
line thinner than a pen of size @scheme[1]. If the pen's width is not
an integer, then the width is truncated to an integer (even before
scaling) in unsmoothed mode.
@defconstructor*/make[(()
([color (is-a?/c color%)]
[width (real-in 0 255)]
[style (one-of/c 'transparent 'solid 'xor 'hilite
'dot 'long-dash 'short-dash 'dot-dash
'xor-dot 'xor-long-dash 'xor-short-dash
'xor-dot-dash)])
([color-name string?]
[width (real-in 0 255)]
[style (one-of/c 'transparent 'solid 'xor 'dot 'hilite
'long-dash 'short-dash 'dot-dash
'xor-dot 'xor-long-dash 'xor-short-dash
'xor-dot-dash)]))]{
When no argument are provided, the result is a solid black pen of
width @scheme[0]. Otherwise, the result is a pen with the given
color, width, and style. For the case that the color is specified
using a name, see @scheme[color-database<%>] for information about
color names; if the name is not known, the pen's color is black.
}
@defmethod[(get-cap)
(one-of/c 'round 'projecting 'butt)]{
Returns the pen cap style (Windows unsmoothed, X unsmoothed, all
smoothing). The default is @scheme['round].
}
@defmethod[(get-color)
(is-a?/c color%)]{
Returns the pen's color object.
}
@defmethod[(get-join)
(one-of/c 'round 'bevel 'miter)]{
Returns the pen join style (Windows unsmoothed, X unsmoothed, all
smoothing). The default is @scheme['round].
}
@defmethod[(get-stipple)
(or/c (is-a?/c bitmap%) false/c)]{
Gets the current stipple bitmap, or returns @scheme[#f] if no stipple
bitmap is installed.
}
@defmethod[(get-style)
(one-of/c 'transparent 'solid 'xor 'hilite
'dot 'long-dash 'short-dash 'dot-dash
'xor-dot 'xor-long-dash 'xor-short-dash
'xor-dot-dash)]{
Returns the pen style. See @scheme[pen%] for information about
possible styles.
}
@defmethod[(get-width)
(real-in 0 255)]{
Returns the pen width.
}
@defmethod[(set-cap [cap-style (one-of/c 'round 'projecting 'butt)])
void?]{
Sets the pen cap style (Windows unsmoothed, X unsmoothed, all
smoothing). See @method[pen% get-cap] for information about cap
styles.
A pen cannot be modified if it was obtained from a @scheme[pen-list%]
or while it is selected into a drawing context.
}
@defmethod*[([(set-color [color (is-a?/c color%)])
void?]
[(set-color [color-name string?])
void?]
[(set-color [red (integer-in 0 255)]
[green (integer-in 0 255)]
[blue (integer-in 0 255)])
void?])]{
Sets the pen color.
A pen cannot be modified if it was obtained from a
@scheme[pen-list%] or while it is selected into a drawing context.
}
@defmethod[(set-join [join-style (one-of/c 'round 'bevel 'miter)])
void?]{
Sets the pen join style (Windows unsmoothed, X unsmoothed, all
smoothing). See @method[pen% get-join] for information about join
styles.
A pen cannot be modified if it was obtained from a
@scheme[pen-list%] or while it is selected into a drawing context.
}
@defmethod[(set-stipple [stipple (or/c (is-a?/c bitmap%) false/c)])
void?]{
Sets the pen stipple bitmap, which must be an 8 x 8 monochrome bitmap
or @scheme[#f], which turns off the stipple bitmap.
A bitmap cannot be used as a stipple if it is selected into a
@scheme[bitmap-dc%] object; if the given bitmap is selected into a
@scheme[bitmap-dc%] object, @|MismatchExn|. A pen cannot be modified
if it was obtained from a @scheme[pen-list%] or while it is selected
into a drawing context.
A pen's stipple is not used in a smoothing mode, except for a
@scheme[post-script-dc%] (which is always in smoothed mode).
}
@defmethod[(set-style [style (one-of/c 'transparent 'solid 'xor 'hilite
'dot 'long-dash 'short-dash 'dot-dash
'xor-dot 'xor-long-dash 'xor-short-dash
'xor-dot-dash)])
void?]{
Sets the pen style. See @scheme[pen%] for information about the
possible styles.
A pen cannot be modified if it was obtained from a
@scheme[pen-list%] or while it is selected into a drawing context.
}
@defmethod[(set-width [width (real-in 0 255)])
void?]{
Sets the pen width.
A pen cannot be modified if it was obtained from a
@scheme[pen-list%] or while it is selected into a drawing context.
}}

View File

@ -0,0 +1,45 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@defclass[pen-list% object% ()]{
A @scheme[pen-list%] object maintains a list of @scheme[pen%]
objects to avoid repeatedly creating pen objects. A @scheme[pen%]
object in a pen list cannot be mutated.
A global pen list @indexed-scheme[the-pen-list] is created automatically.
@defconstructor/make[()]{
Creates an empty pen list.
}
@defmethod*[([(find-or-create-pen [color (is-a?/c color%)]
[width (real-in 0 255)]
[style (one-of/c 'transparent 'solid 'xor 'hilite
'dot 'long-dash 'short-dash 'dot-dash
'xor-dot 'xor-long-dash 'xor-short-dash
'xor-dot-dash)])
(is-a?/c pen%)]
[(find-or-create-pen [color-name string?]
[width (real-in 0 255)]
[style (one-of/c 'transparent 'solid 'xor 'hilite
'dot 'long-dash 'short-dash 'dot-dash
'xor-dot 'xor-long-dash 'xor-short-dash
'xor-dot-dash)])
(or/c (is-a?/c pen%) false/c)])]{
Finds a pen of the given specification, or creates one and adds it to
the list. The arguments are the same as for creating a @scheme[pen%]
instance. When @scheme[color-name] is provided, however, the return
value is @scheme[#f] when no color matching @scheme[color-name] can be
found in @scheme[the-color-database].
}}

View File

@ -0,0 +1,41 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@defclass[point% object% ()]{
A @scheme[point%] is used for certain drawing commands. It
encapsulates two real numbers.
@defconstructor*/make[(()
([x real?]
[y real?]))]{
Creates a point. If @scheme[x] and @scheme[y] are not supplied, they
are set to @scheme[0].
}
@defmethod[(get-x)
real?]{
Gets the point x-value.
}
@defmethod[(get-y)
real?]{
Gets the point y-value.
}
@defmethod[(set-x [x real?])
void?]{
Sets the point x-value.
}
@defmethod[(set-y [y real?])
void?]{
Sets the point y-value.
}}

View File

@ -0,0 +1,58 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@defclass[post-script-dc% object% (dc<%>)]{
A @scheme[post-script-dc%] object is a PostScript device context, that
can write PostScript files on any platform. See also
@scheme[ps-setup%].
@|PrintNote|
See also @scheme[printer-dc%].
@defconstructor[([interactive any/c #t]
[parent (or/c (is-a?/c frame%) (is-a?/c dialog%) false/c) #f]
[use-paper-bbox any/c #f]
[as-eps any/c #t])]{
If @scheme[interactive] is true, the user is given a dialog for
setting printing parameters (see @scheme[get-ps-setup-from-user]);
the resulting configuration is installed as the current
configuration). If the user chooses to print to a file (the only
possibility under Windows and Mac OS X), another dialog is given to
select the filename. If the user hits cancel in either of these
dialogs, then @method[dc<%> ok?] returns @scheme[#f].
If @scheme[parent] is not @scheme[#f], it is used as the parent window of
the configuration dialog.
If @scheme[interactive] is @scheme[#f], then the settings returned by
@scheme[current-ps-setup] are used. A file dialog is still presented
to the user if the @method[ps-setup% get-file] method returns
@scheme[#f], and the user may hit cancel in that case so that
@method[dc<%> ok?] returns @scheme[#f].
If @scheme[use-paper-bbox] is @scheme[#f], then the PostScript
bounding box for the output is determined by drawing commands issued
to the object; such a bounding box encloses all parts of the drawing
@italic{ignoring} clipping regions (so the bounding box may be
approximate). If @scheme[use-paper-bbox] is not @scheme[#f], then the
bounding box is determined by the current paper size (as specified by
@scheme[current-ps-setup]), and the bounding box does not include the
margin (also specified by @scheme[current-ps-setup]).
@index["Encapsulated PostScript (EPS)"]{If} @scheme[as-eps] is
@scheme[#f], then the generated PostScript does not include an
Encapsulated PostScript (EPS) header, and instead includes a generic
PostScript header. Otherwise, the generated PostScript includes a
header that identifiers it as EPS.
See also @scheme[ps-setup%] and @scheme[current-ps-setup]. The
settings for a particular @scheme[post-script-dc%] object are fixed to
the values in the current configuration when the object is created
(after the user has interactively adjusted them when
@scheme[interactive] is true).
}}

View File

@ -0,0 +1,25 @@
#reader(lib "docreader.ss" "scribble")
@require["common.ss"]
@title{PostScript}
@defparam[current-ps-afm-file-paths paths (listof path?)]{
A parameter determines the list of paths that is used to find AFM
files. See @secref["mr:postscriptfonts"] for more information.
}
@defparam[current-ps-cmap-file-paths paths (listof path?)]{
A parameter that determines the list of paths that is used to find
CMap files. See @secref["mr:postscriptfonts"] for more information.
}
@defparam[current-ps-setup pss (is-a?/c ps-setup%)]{
A parameter that determines the current PostScript configuration
settings. See @scheme[post-script-dc%] and @scheme[printer-dc%].
}

View File

@ -0,0 +1,33 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@defclass[printer-dc% object% (dc<%>)]{
A @scheme[printer-dc%] object is a Windows or Mac OS X printer
device context. The class cannot be instantiated under X (an
@scheme[exn:misc:unsupported] exception is raised).
Under Mac OS X, a newly created @scheme[printer-dc%] object obtains
orientation (portrait versus landspace) and scaling information from
the current @scheme[ps-setup%] object, as determined by the
@scheme[current-ps-setup] parameter. This information can be
configured by the user through a dialog shown by
@scheme[get-page-setup-from-user].
@|PrintNote|
See also @scheme[post-script-dc%].
When a @scheme[printer-dc%] object is created, the user gets
platform-specific modal dialogs for configuring the output.
If the user cancels the dialog, the @method[dc<%> ok?] method
of the object returns @scheme[#f].
@defconstructor[([parent (or/c (is-a?/c frame%) (is-a?/c dialog%) false/c) #f])]{
If @scheme[parent] is not @scheme[#f], it is used as the parent window
of the configuration dialog.
}}

View File

@ -0,0 +1,273 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@defclass[ps-setup% object% ()]{
A @scheme[ps-setup%] object contains configuration information for
producing PostScript files using a @scheme[post-script-dc%] object.
To a lesser extent, it contains information for printing with a
@scheme[printer-dc%] object.
When a @scheme[post-script-dc%] object is created, its configuration
is determined by the @scheme[current-ps-setup] parameter's
@scheme[ps-setup%] value. After a @scheme[post-script-dc%] object is
created, it is unaffected by changes to the @scheme[current-ps-setup]
parameter or mutations to the @scheme[ps-setup%] object.
@defconstructor[()]{
Creates a new @scheme[ps-setup%] object with the (platform-specific)
default configuration.
}
@defmethod[(copy-from [source (is-a?/c ps-setup%)])
void?]{
Copies the settings @scheme[copy-from] to @this-obj[].
}
@defmethod[(get-command)
string?]{
Gets the printer command used to print a file in X. The default is
@scheme["lpr"]. This value is not used by other platforms.
}
@defmethod[(get-editor-margin [h-margin (box/c nonnegative-real?)]
[v-margin (box/c nonnegative-real?)])
void?]{
Returns the current settings for horizontal and vertical margins when
printing an @scheme[editor<%>]. See also @method[ps-setup%
set-editor-margin].
}
@defmethod[(get-file)
(or/c path-string? false/c)]{
Gets the PostScript output filename. A @scheme[#f] value (the default)
indicates that the user should be prompted for a filename when a
@scheme[post-script-dc%] object is created.
}
@defmethod[(get-level-2)
boolean?]{
Reports whether Level 2 commands are output in PostScript files.
Currently, Level 2 commands are only needed to include color bitmap
images in PostScript output (drawn with @method[dc<%> draw-bitmap]),
or bitmap pen and brush stipples. When Level 2 commands are disabled,
bitmaps are converted to grayscale images and stipples are not
supported.
}
@defmethod[(get-margin [h-margin (box/c nonnegative-real?)]
[v-margin (box/c nonnegative-real?)])
void?]{
Returns the current settings for horizontal and vertical PostScript
margins. See also @method[ps-setup% set-margin].
}
@defmethod[(get-mode)
(one-of/c 'preview 'file 'printer)]{
Gets the printing mode that determines where output is sent:
@scheme['preview], @scheme['file], or @scheme['printer]. The default
for X is @scheme['preview]. The value in Windows and Mac OS X is
always @scheme['file].
}
@defmethod[(get-orientation)
(one-of/c 'portrait 'landscape)]{
Gets the orientation: @scheme['portrait] or @scheme['landscape]. The
default is @scheme['portrait]. Unlike most other settings, this one
affects native printing (via @scheme[printer-dc%]) as well as
PostScript output.
Landscaped orientation affects the size of the drawing area as
reported by @method[dc<%> get-size]: the horizontal and vertical
sizes determined by the selected paper type are transposed and then
scaled.
}
@defmethod[(get-paper-name)
string?]{
Returns the name of the current paper type: @scheme["A4 210 x 297
mm"], @scheme["A3 297 x 420 mm"], @scheme["Letter 8 1/2 x 11 in"], or
@scheme["Legal 8 1/2 x 14 in"]. The default is @scheme["Letter 8 1/2
x 11 in"].
The paper name determines the size of the drawing area as reported by
@method[dc<%> get-size] (along with landscape transformations from
@method[ps-setup% get-orientation] and/or the scaling factors of
@method[ps-setup% get-scaling]). It also determines the bounding box
of PostScript output when a @scheme[post-script-dc%] context is
created with a true value for the @scheme[use-paper-bbox?]
initialization argument.
}
@defmethod[(get-preview-command)
string?]{
Gets the command used to view a PostScript file for X. The default is
@scheme["gv"]. This value is not used by other platforms.
}
@defmethod[(get-scaling [x (box/c nonnegative-real?)]
[y (box/c nonnegative-real?)])
void?]{
Gets the scaling factor for PostScript output. @boxisfill[(scheme x)
@elem{the horizontal scaling factor}] @boxisfill[(scheme y) @elem{the
vertical scaling factor}] The default is @scheme[0.8] by
@scheme[0.8].
This scale is in addition to a scale that can be set by @method[dc<%>
set-scale] in a @scheme[post-script-dc%] context. The size reported
by @method[dc<%> get-size] is the size of the selected paper type
(transposed for landscaped mode) divided by this scale.
}
@defmethod[(get-translation [x (box/c nonnegative-real?)]
[y (box/c nonnegative-real?)])
void?]{
Gets the translation (from the bottom left corner) for PostScript
output. @boxisfill[@scheme[x] @elem{the horizontal offset}]
@boxisfill[@scheme[y] @elem{the vertical offset}] The default is
@scheme[0.0] and @scheme[0.0].
The translation is not scaled by the numbers returned from
@method[ps-setup% get-scaling] and the translation does not affect
the size of the drawing area.
}
@defmethod[(set-command [command string?])
void?]{
Sets the printer command used to print a file under X. See
@method[ps-setup% get-command].
}
@defmethod[(set-editor-margin [h nonnegative-exact-integer?]
[v nonnegative-exact-integer?])
void?]{
Sets the horizontal and vertical margins used when printing an editor
with the @method[editor<%> print] method. These margins are always
used for printing, whether the drawing destination is a
@scheme[post-script-dc%] or @scheme[printer-dc%]. The margins are in
the units of the destination @scheme[printer-dc%] or
@scheme[post-script-dc%]. In the case of @scheme[post-script-dc%]
printing, the editor margin is in addition to the PostScript margin
that is determined by @method[ps-setup% set-margin].
}
@defmethod[(set-file [filename (or/c path-string? false/c)])
void?]{
Sets the PostScript output filename. See
@method[ps-setup% get-file].
}
@defmethod[(set-level-2 [on? any/c])
void?]{
Sets whether Level 2 commands are output in PostScript files. See
@method[ps-setup% get-level-2].
}
@defmethod[(set-margin [h (and/c real? (not/c negative?))]
[v (and/c real? (not/c negative?))])
void?]{
Sets the horizontal and vertical PostScript margins. When drawing to a
@scheme[post-script-dc%], the page size reported by @method[dc<%>
get-size] subtracts these margins from the normal page area (before
taking into account scaling affects). In addition, drawing into the
@scheme[post-script-dc%] produces PostScript output that is offset by
the margins.
When using the output of a @scheme[post-script-dc%] as
Encapsulated PostScript, the margin values are effectively
irrelevant. Changing the margins moves the PostScript image in
absolute coordinates, but it also moves the bounding box.
The margins are in unscaled @scheme[post-script-dc%] units, which
are points. The default margins are 16 points.
}
@defmethod[(set-mode [mode (one-of/c 'preview 'file 'printer)])
void?]{
Sets the printing mode controlling where output is sent. See
@method[ps-setup% get-mode].
Under Windows and Mac OS X, if @scheme['preview] or @scheme['printer]
is provided, @|MismatchExn|.
}
@defmethod[(set-orientation [orientation (one-of/c 'portrait 'landscape)])
void?]{
Sets the orientation. See @method[ps-setup% get-orientation].
}
@defmethod[(set-paper-name [type string?])
void?]{
Sets the name of the current paper type. See @method[ps-setup%
get-paper-name].
}
@defmethod[(set-preview-command [command string?])
void?]{
Sets the command used to view a PostScript file under X. See
@method[ps-setup% get-preview-command].
}
@defmethod[(set-scaling [x (and/c real? (not/c negative?))]
[y (and/c real? (not/c negative?))])
void?]{
Sets the scaling factor for PostScript output. See
@method[ps-setup% get-scaling].
}
@defmethod[(set-translation [x real?]
[y real?])
void?]{
Sets the translation (from the bottom left corner) for PostScript
output. See @method[ps-setup% get-translation].
}}

View File

@ -1,11 +1,12 @@
#reader(lib "docreader.ss" "scribble") #reader(lib "docreader.ss" "scribble")
@require["common.ss"] @require["common.ss"]
@require["diagrams.ss"]
@title[#:tag "mr:windowing" #:style 'toc]{Windowing Toolbox} @title[#:style 'toc]{Reference}
@local-table-of-contents[] @local-table-of-contents[]
@include-section["win-overview.scrbl"]
@include-section["win-classes.scrbl"] @include-section["win-classes.scrbl"]
@include-section["win-funcs.scrbl"] @include-section["win-funcs.scrbl"]
@include-section["draw-classes.scrbl"]
@include-section["draw-funcs.scrbl"]
@include-section["editor-classes.scrbl"]

View File

@ -0,0 +1,268 @@
#reader(lib "defreader.ss" "scribble")
@require["common.ss"]
@defclass[region% object% ()]{
A @scheme[region%] object specifies a portion of a drawing area
(possibly discontinuous). It is normally used for clipping drawing
operations.
Each @scheme[region%] object is associated to a particular
@scheme[dc<%>] object, specified when the region is created. A region
can only be used with its associated @scheme[dc<%>] object. The origin
and scale of a drawing context determine the bounding box and drawing
location of a region at the time that a region is created (or set); a
region is independent of the current scale and origin when the region
is used. For an auto-scrolled canvas, the canvas's current scrolling
applies when the region is used (and it does not affect the region's
bounding box).
See also @xmethod[dc<%> set-clipping-region] and @xmethod[dc<%>
get-clipping-region].
@defconstructor[([dc (is-a?/c dc<%>)])]{
Creates an empty region.
}
@defmethod[(get-bounding-box)
(values real? real? real? real?)]{
Returns a rectangle that encloses the region. The return values are
the left, top, width, and height of the rectangle. The bounding box
is precisely correct for unsmoothed drawing, but it is only
approximate for smoothed drawing.
}
@defmethod[(get-dc)
(is-a?/c dc<%>)]{
Returns the region's drawing context.
}
@defmethod[(in-region? [x real?]
[y real?])
boolean?]{
Returns @scheme[#t] if the given point is approximately within the
region, @scheme[#f] otherwise. The given point is scaled and
translated according to the region's @scheme[dc<%>]'s current scale
and translation.
The approximate in-region test represents the true result for
unsmoothed drawing, but it not necessarily for smoothed drawing.
}
@defmethod[(intersect [rgn (is-a?/c region%)])
void?]{
Sets the region to the intersection of itself with the given region.
The DC of @scheme[rgn] and @this-obj[] must be the same.
The result is always reliable for unsmoothed and smoothed drawing. For
smoothed drawing, an intersect corresponds to clipping with this
region's path, and then clipping with the given region's path.
Further combining sends to this region correspond to combination with
the original path before initial clip, and further combination with
this region as an argument correspond to a combination with the given
path after the initial clip. Thus, an intersecting region is a poor
input for @method[region% union], @method[region% subtract], or
@method[region% xor], but it intersects properly in further calls to
@method[region% intersect].
}
@defmethod[(is-empty?)
boolean?]{
Returns @scheme[#t] if the region is approximately empty, @scheme[#f]
otherwise. An approximately empty region is truly empty for
unsmoothed drawing, but it may contain points for smoothed drawing.
}
@defmethod[(set-arc [x real?]
[y real?]
[width (and/c real? (not/c negative?))]
[height (and/c real? (not/c negative?))]
[start-radians real?]
[end-radians real?])
void?]{
Sets the region to the interior of the specified wedge.
See also @xmethod[dc<%> draw-ellipse], since the region content is
determined the same way as brush-based filling in a @scheme[dc<%>].
The result is reliable for both unsmoothed and smoothed drawing. For
smoothed drawing, the region corresponds to a clockwise path with a
@scheme['winding] fill. The region is also @defterm{atomic} for the
purposes of region combination.
}
@defmethod[(set-ellipse [x real?]
[y real?]
[width (and/c real? (not/c negative?))]
[height (and/c real? (not/c negative?))])
void?]{
Sets the region to the interior of the specified ellipse.
See also @xmethod[dc<%> draw-ellipse], since the region content is
determined the same way as brush-based filling in a @scheme[dc<%>].
The result is reliable for both unsmoothed and smoothed drawing. For
smoothed drawing, the region corresponds to a clockwise path with a
@scheme['winding] fill. The region is also @defterm{atomic} for the
purposes of region combination.
@|DrawSizeNote|
}
@defmethod[(set-path [path (is-a?/c dc-path%)]
[xoffset real? 0]
[yoffset real? 0]
[fill-style (one-of/c 'odd-even 'winding) 'odd-even])
void?]{
Sets the region to the content of the given path.
See also @xmethod[dc<%> draw-path], since the region content is
determined the same way as brush-based filling in a @scheme[dc<%>].
The result is reliable for both unsmoothed and smoothed drawing. For
smoothed drawing, the fill style affects how well the region reliably
combines with other regions (via @method[region% union],
@method[region% xor], and @method[region% subtract]). The region is
also @defterm{atomic} for the purposes of region combination.
}
@defmethod[(set-polygon [points (listof (is-a?/c point%))]
[xoffset real? 0]
[yoffset real? 0]
[fill-style (one-of/c 'odd-even 'winding) 'odd-even])
void?]{
Sets the region to the interior of the specified polygon.
See also @xmethod[dc<%> draw-polygon], since the region content is
determined the same way as brush-based filling in a @scheme[dc<%>].
The result is reliable for both unsmoothed and smoothed drawing. For
smoothed drawing, the fill style affects how well the region reliably
combines with other regions (via @method[region% union],
@method[region% xor], and @method[region% subtract]). The region is
also @defterm{atomic} for the purposes of region combination.
}
@defmethod[(set-rectangle [x real?]
[y real?]
[width (and/c real? (not/c negative?))]
[height (and/c real? (not/c negative?))])
void?]{
Sets the region to the interior of the specified rectangle.
See also @xmethod[dc<%> draw-rectangle], since the region content is
determined the same way as brush-based filling in a @scheme[dc<%>].
The result is reliable for both unsmoothed and smoothed drawing. For
smoothed drawing, the region corresponds to a clockwise path with a
@scheme['winding] fill. The region is also @defterm{atomic} for the
purposes of region combination.
@|DrawSizeNote|
}
@defmethod[(set-rounded-rectangle [x real?]
[y real?]
[width (and/c real? (not/c negative?))]
[height (and/c real? (not/c negative?))]
[radius real? -0.25])
void?]{
Sets the region to the interior of the specified rounded rectangle.
See also @xmethod[dc<%> draw-rounded-rectangle], since the region
content is determined the same way as brush-based filling in a
@scheme[dc<%>].
The result is reliable for both unsmoothed and smoothed drawing. For
smoothed drawing, the region corresponds to a clockwise path with a
@scheme['winding] fill. The region is also @defterm{atomic} for the
purposes of region combination.
@|DrawSizeNote|
}
@defmethod[(subtract [rgn (is-a?/c region%)])
void?]{
Sets the region to the subtraction of itself minus the given region.
In other words, a point is removed from the region if it is included
in the given region. (The given region may contain points that are
not in the current region; such points are ignored.)
This region's DC and given region's DC must be the same.
The result is always reliable for unsmoothed drawing. For smoothed
drawing, the result is consistent across platforms and devices, but
it is never a true subtraction. A subtraction corresponds to
combining the sub-paths of this region with the reversed sub-paths of
the given region, then intersecting the result with this region. This
fails as a true subtraction, because the boundary of loops (with
either @scheme['odd-even] or @scheme['winding] filling) is ambiguous.
}
@defmethod[(union [rgn (is-a?/c region%)])
void?]{
Sets the region to the union of itself with the given region.
This region's DC and given region's DC must be the same.
The result is always reliable for unsmoothed drawing. For smoothed
drawing, a union corresponds to combining the sub-paths of each
region into one path, using an @scheme['odd-even] fill if either of
the region uses an @scheme['odd-even] fill (otherwise using a
@scheme['winding] fill). Consequently, while the result is consistent
across platforms and devices, it is a true union only for certain
input regions. For example, it is a true union for non-overlapping
atomic and union regions. It is also a true union for atomic and
union regions (potentially overlapping) that are all clockwise and
use @scheme['winding] fill.
}
@defmethod[(xor [rgn (is-a?/c region%)])
void?]{
Sets the region to the xoring of itself with the given region (i.e.,
contains points that are enclosed by exactly one of the two regions).
This region's DC and given region's DC must be the same.
The result is always reliable for unsmoothed drawing. For smoothed
drawing, the result is consistent across platforms and devices, but
it is not necessarily a true xoring. An xoring corresponds to
combining the sub-paths of this region with the reversed sub-paths of
the given region. The result uses an @scheme['odd-even] fill if either
of the region uses an @scheme['odd-even] fill (otherwise using a
@scheme['winding] fill). Consequently, the result is a reliable xoring
only for certain input regions. For example, it is reliable for
atomic and xoring regions that all use @scheme['even-odd] fill.
}}

View File

@ -1,7 +1,7 @@
#reader(lib "docreader.ss" "scribble") #reader(lib "docreader.ss" "scribble")
@require["common.ss"] @require["common.ss"]
@title[#:style 'toc]{Windowing Function Reference} @title{Windowing Function Reference}
@local-table-of-contents[] @local-table-of-contents[]

View File

@ -3,9 +3,7 @@
@require["common.ss"] @require["common.ss"]
@require["diagrams.ss"] @require["diagrams.ss"]
@title[#:tag "mr:windowing-overview" #:style 'toc]{Windowing Toolbox Overview} @title[#:tag "mr:windowing-overview"]{Windowing Guide}
@local-table-of-contents[]
@section{Basic GUI Building Blocks} @section{Basic GUI Building Blocks}

View File

@ -21,9 +21,9 @@
(current-directory)) (current-directory))
(let ([rel2 (fold-files (lambda (name kind accum) (let ([rel2 (fold-files (lambda (name kind accum)
(test kind values (if (file-exists? name) (test kind name (if (file-exists? name)
'file 'file
'dir)) 'dir))
(cons name accum)) (cons name accum))
null)] null)]
[sort (lambda (l) [sort (lambda (l)
@ -41,9 +41,10 @@
(test kind values (cond (test kind values (cond
[(link-exists? name) 'link] [(link-exists? name) 'link]
[(file-exists? name) 'file] [(file-exists? name) 'file]
[else 'dir])) [(dir-exists? name) 'dir]
[else '???]))
(when (member name '("filelib-link.ss" "loop-link")) (when (member name '("filelib-link.ss" "loop-link"))
(test kind values 'link)) (test kind name 'link))
(add1 accum)) (add1 accum))
0 0
#f #f
@ -58,7 +59,7 @@
[(file-exists? name) 'file] [(file-exists? name) 'file]
[else 'dir])) [else 'dir]))
(when (member name '("filelib-link.ss")) (when (member name '("filelib-link.ss"))
(test kind values 'file)) (test kind name 'file))
(add1 accum)) (add1 accum))
0 0
#f #f