1#lang scribble/manual
2
3@(require (for-label pict pict/shadow racket/base racket/contract racket/class racket/draw)
4          scribble/eval)
5
6@(define the-eval (make-base-eval))
7@(the-eval '(require pict pict/shadow))
8
9@title{Shadows}
10
11@defmodule[pict/shadow]
12
13These pict transformations add shadows or blurring in various shapes and
14forms.
15
16@defproc[(blur [p pict?]
17               [h-radius (and/c real? (not/c negative?))]
18               [v-radius (and/c real? (not/c negative?)) h-radius])
19         pict?]{
20
21Blurs @racket[p] using an iterated box blur that approximates a
22gaussian blur. The @racket[h-radius] and @racket[v-radius] arguments
23control the strength of the horizontal and vertical components of the
24blur, respectively. They are given in terms of pict units, which may
25not directly correspond to screen pixels.
26
27The @racket[blur] function takes work proportional to
28@racketblock[(* (pict-width p) (pict-height p))]
29but it may be sped up by a factor of up to @racket[(processor-count)]
30due to the use of @racket[future]s.
31
32@examples[#:eval the-eval
33(blur (text "blur" null 40) 5)
34(blur (text "more blur" null 40) 10)
35(blur (text "much blur" null 40) 20)
36(blur (text "horiz. blur" null 40) 10 0)
37]
38The resulting pict has the same bounding box as @racket[p], so when
39picts are automatically @racket[clip]ped (as in Scribble documents),
40the pict should be @racket[inset] by the blur radius.
41@examples[#:eval the-eval
42(inset (blur (text "more blur" null 40) 10) 10)
43]
44
45@history[#:added "1.4"]{}
46}
47
48@defproc[(shadow [p pict?]
49                 [radius (and/c real? (not/c negative?))]
50                 [dx real? 0]
51                 [dy real? dx]
52                 [#:color color (or/c #f string? (is-a?/c color%)) #f]
53                 [#:shadow-color shadow-color (or/c #f string? (is-a?/c color%)) #f])
54         pict?]{
55
56Creates a shadow effect by superimposing @racket[p] over a
57blurred version of @racket[p]. The shadow is offset from @racket[p] by
58(@racket[dx], @racket[dy]) units.
59
60If @racket[color] is not @racket[#f], the foreground part is
61@racket[(colorize p color)]; otherwise it is just @racket[p]. If
62@racket[shadow-color] is not @racket[#f], the shadow part is produced
63by blurring @racket[(colorize p shadow-color)]; otherwise it is
64produced by blurring @racket[p].
65
66The resulting pict has the same bounding box as @racket[p].
67
68@examples[#:eval the-eval
69(inset (shadow (text "shadow" null 50) 10) 10)
70(inset (shadow (text "shadow" null 50) 10 5) 10)
71(inset (shadow (text "shadow" null 50)
72               5 0 2 #:color "white" #:shadow-color "red")
73       10)
74]
75
76@history[#:added "1.4"]{}
77}
78
79@defproc[(shadow-frame [pict pict?] ...
80                       [#:sep separation real? 5]
81                       [#:margin margin real? 20]
82                       [#:background-color bg-color (or/c string? (is-a?/c color%)) "white"]
83                       [#:frame-color frame-color (or/c string? (is-a?/c color%)) "gray"]
84                       [#:frame-line-width frame-line-width (or/c real? #f 'no-frame) 0]
85                       [#:shadow-side-length shadow-side-length real? 4]
86                       [#:shadow-top-y-offset shadow-top-y-offset real? 10]
87                       [#:shadow-bottom-y-offset shadow-bottom-y-offset real? 4]
88                       [#:shadow-descent shadow-descent (and/c real? (not/c negative?)) 40]
89                       [#:shadow-alpha-factor shadow-alpha-factor real? 3/4]
90                       [#:blur blur-radius (and/c real? (not/c negative?)) 20])
91         pict?]{
92
93Surrounds the @racket[pict]s with a rectangular frame that casts a
94symmetric ``curled paper'' shadow.
95
96The @racket[pict]s are vertically appended with @racket[separation]
97space between them. They are placed on a rectangular background of
98solid @racket[bg-color] with @racket[margin] space on all sides. A
99frame of @racket[frame-color] and @racket[frame-line-width] is added
100around the rectangle, unless @racket[frame-line-width] is
101@racket['no-frame]. The rectangle casts a shadow that extends
102@racket[shadow-side-length] to the left and right, starts
103@racket[shadow-top-y-offset] below the top of the rectangle and
104extends to @racket[shadow-bottom-y-offset] below the bottom of the
105rectangle in the center and an additional @racket[shadow-descent]
106below that on the sides. The shadow is painted using a linear
107gradient; @racket[shadow-alpha-factor] determines its density at the
108center. Finally, the shadow is blurred by @racket[blur-radius]; all
109previous measurements are pre-blur measurements.
110
111@examples[#:eval the-eval
112(shadow-frame (text "text in a nifty frame" null 60))
113]
114
115@history[#:added "1.4"]{}
116}
117
118@(close-eval the-eval)
119