ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/perl/background
(Generate patch)

Comparing rxvt-unicode/src/perl/background (file contents):
Revision 1.5 by root, Tue Jun 5 13:42:59 2012 UTC vs.
Revision 1.30 by root, Thu Jun 7 13:22:06 2012 UTC

1#! perl 1#! perl
2 2
3our $EXPR = 'move load "/root/pix/das_fette_schwein.jpg", repeat_wrap, X, Y'; 3#:META:X_RESOURCE:%.expr:string:background expression
4$EXPR = 'rotate load "/root/pix/das_fette_schwein.jpg", W, H, 50, 50, counter 1/60, repeat_mirror'; 4#:META:X_RESOURCE:%.enable:boolean:some boolean
5#:META:X_RESOURCE:%.extra.:value:extra config
6
7our $EXPR;
8#$EXPR = 'move W * 0.1, -H * 0.1, resize W * 0.5, H * 0.5, repeat_none load "opensource.png"';
9$EXPR = 'move -TX, -TY, load "argb.png"';
10#$EXPR = '
11# rotate W, H, 50, 50, counter 1/59.95, repeat_mirror,
12# clip X, Y, W, H, repeat_mirror,
13# load "/root/pix/das_fette_schwein.jpg"
14#';
15#$EXPR = 'solid "red"';
5#$EXPR = 'blur root, 10, 10' 16#$EXPR = 'blur root, 10, 10'
6#$EXPR = 'blur move (root, -x, -y), 5, 5' 17#$EXPR = 'blur move (root, -x, -y), 5, 5'
7#resize load "/root/pix/das_fette_schwein.jpg", w, h 18#resize load "/root/pix/das_fette_schwein.jpg", w, h
8 19
9use Safe; 20use Safe;
10 21
11our ($bgdsl_self, $old, $new); 22our ($bgdsl_self, $old, $new);
12our ($l, $t, $w, $h); 23our ($x, $y, $w, $h);
24
25# enforce at least this interval between updates
26our $MIN_INTERVAL = 1/100;
13 27
14{ 28{
15 package urxvt::bgdsl; # background language 29 package urxvt::bgdsl; # background language
16 30
17 *repeat_black = \&urxvt::RepeatNone; #TODO wtf 31=head2 PROVIDERS/GENERATORS
18 *repeat_wrap = \&urxvt::RepeatNormal; 32
19 *repeat_pad = \&urxvt::RepeatPad; 33=over 4
20 *repeat_mirror = \&urxvt::RepeatReflect; 34
35=item load $path
36
37Loads the image at the given C<$path>. The image is set to plane tiling
38mode.
39
40
41
42=cut
21 43
22 sub load($) { 44 sub load($) {
23 my ($path) = @_; 45 my ($path) = @_;
24 46
25 $new->{load}{$path} = $old->{load}{$path} || $bgdsl_self->new_img_from_file ($path); 47 $new->{load}{$path} = $old->{load}{$path} || $bgdsl_self->new_img_from_file ($path);
26 } 48 }
27 49
28 sub root() { 50 sub root() {
51 $new->{rootpmap_sensitive} = 1;
29 die "root op not supported, exg, we need you"; 52 die "root op not supported, exg, we need you";
30 } 53 }
31 54
55 sub solid($;$$) {
56 my $img = $bgdsl_self->new_img (urxvt::PictStandardARGB32, $_[1] || 1, $_[2] || 1);
57 $img->fill ($_[0]);
58 $img
59 }
60
61=back
62
63=head2 VARIABLES
64
65=over 4
66
67=cut
68
69 sub TX() { $new->{position_sensitive} = 1; $x }
70 sub TY() { $new->{position_sensitive} = 1; $y }
71 sub TW() { $new->{size_sensitive} = 1; $w }
72 sub TH() { $new->{size_sensitive} = 1; $h }
73
74 sub now() { urxvt::NOW }
75
76 sub again($) {
77 $new->{again} = $_[0];
78 }
79
80 sub counter($) {
81 $new->{again} = $_[0];
82 $bgdsl_self->{counter} + 0
83 }
84
85=back
86
87=head2 TILING MODES
88
89The following operators modify the tiling mode of an image, that is, the
90way that pixels outside the image area are painted when the image is used.
91
92=over 4
93
94=item tile $img
95
96Tiles the whole plane with the image and returns this new image - or in
97other words, it returns a copy of the image in plane tiling mode.
98
99=item mirror $img
100
101Similar to tile, but reflects the image each time it uses a new copy, so
102that top edges always touch top edges, right edges always touch right
103edges and so on (with normal tiling, left edges always touch right edges
104and top always touch bottom edges).
105
106=item pad $img
107
108Takes an image and modifies it so that all pixels outside the image area
109become transparent. This mode is most useful when you want to place an
110image over another image or the background colour while leaving all
111background pixels outside the image unchanged.
112
113=item extend $img
114
115Extends the image over the whole plane, using the closest pixel in the
116area outside the image. This mode is mostly useful when you more complex
117filtering operations and want the pixels outside the image to have the
118same values as the pixels near the edge.
119
120=cut
121
122 sub pad($) {
123 my $img = $_[0]->clone;
124 $img->repeat_mode (urxvt::RepeatNone);
125 $img
126 }
127
128 sub tile($) {
129 my $img = $_[0]->clone;
130 $img->repeat_mode (urxvt::RepeatNormal);
131 $img
132 }
133
134 sub mirror($) {
135 my $img = $_[0]->clone;
136 $img->repeat_mode (urxvt::RepeatReflect);
137 $img
138 }
139
140 sub extend($) {
141 my $img = $_[0]->clone;
142 $img->repeat_mode (urxvt::RepeatPad);
143 $img
144 }
145
146=back
147
148=head2 PIXEL OPERATORS
149
150The following operators modify the image pixels in various ways.
151
152=over 4
153
154=item clone $img
155
156Returns an exact copy of the image.
157
158=cut
159
32# sub clone($) { 160 sub clone($) {
33# $_[0]->clone 161 $_[0]->clone
34# } 162 }
35 163
36 sub subrect($$$$$;$) { 164=item clip $img
37 $_[0]->sub_rect ($_[1], $_[2], $_[3], $_[4], $_[5]) 165
166=item clip $width, $height, $img
167
168=item clip $x, $y, $width, $height, $img
169
170Clips an image to the given rectangle. If the rectangle is outside the
171image area (e.g. when C<$x> or C<$y> are negative) or the rectangle is
172larger than the image, then the tiling mode defines how the extra pixels
173will be filled.
174
175If C<$x> an C<$y> are missing, then C<0> is assumed for both.
176
177If C<$width> and C<$height> are missing, then the window size will be
178assumed.
179
180Example: load an image, blur it, and clip it to the window size to save
181memory.
182
183 clip blur 10, load "mybg.png"
184
185=cut
186
187 sub clip($;$$;$$) {
188 my $img = pop;
189 my $h = pop || TH;
190 my $w = pop || TW;
191 $img->sub_rect ($_[0], $_[1], $w, $h)
192 }
193
194=item scale $img
195
196=item scale $size_percent, $img
197
198=item scale $width_percent, $height_percent, $img
199
200Scales the image by the given percentages in horizontal
201(C<$width_percent>) and vertical (C<$height_percent>) direction.
202
203If only one percentage is give, it is used for both directions.
204
205If no percentages are given, scales the image to the window size without
206keeping aspect.
207
208=item resize $width, $height, $img
209
210Resizes the image to exactly C<$width> times C<$height> pixels.
211
212=cut
213
214#TODO: maximise, maximise_fill?
215
216 sub scale($$$) {
217 my $img = pop;
218
219 @_ == 2 ? $img->scale ($_[0] * $img->w * 0.01, $_[1] * $img->h * 0.01)
220 : @_ ? $img->scale ($_[0] * $img->w * 0.01, $_[0] * $img->h * 0.01)
221 : $img->scale (TW, TH)
38 } 222 }
39 223
40 sub resize($$$) { 224 sub resize($$$) {
41 $_[0]->scale ($_[1], $_[2]) 225 my $img = pop;
226 $img->scale ($_[0], $_[1])
42 } 227 }
43 228
44 sub move($$$;$) { 229 sub move($$;$) {
45 # TODO: must be simpler 230 my $img = pop->clone;
46 $_[0]->transform ($_[0]->w, $_[0]->h, 231 $img->move ($_[0], $_[1]);
47 1, 0, $_[1], 232 $img
48 0, 1, $_[2], 233 }
49 0, 0, 1, 234
235 sub rotate($$$$$$) {
236 my $img = pop;
237 $img->rotate (
50 $_[3], 238 $_[0],
239 $_[1],
240 $_[2] * $img->w * .01,
241 $_[3] * $img->h * .01,
242 $_[4] * (3.14159265 / 180),
51 ) 243 )
52 } 244 }
53 245
54 sub rotate($$$$$$;$) {
55 $_[0]->rotate (
56 $_[1],
57 $_[2],
58 $_[3] * $_[0]->w * .01,
59 $_[4] * $_[0]->h * .01,
60 $_[5] * (3.14159265 / 180),
61 $_[6],
62 )
63 }
64
65 sub blur($$$) { 246 sub blur($$;$) {
66 my ($img, $rh, $rv) = @_; 247 my $img = pop;
67 248 $img->blur ($_[0], @_ >= 2 ? $_[1] : $_[0])
68 $img = $img->clone;
69 $img->blur ($rh, $rv);
70 $img
71 } 249 }
72 250
73 sub contrast($$;$$;$) { 251 sub contrast($$;$$;$) {
252 my $img = pop;
74 my ($img, $r, $g, $b, $a) = @_; 253 my ($r, $g, $b, $a) = @_;
75 254
76 ($g, $b) = ($r, $r) if @_ < 4; 255 ($g, $b) = ($r, $r) if @_ < 4;
77 $a = 1 if @_ < 5; 256 $a = 1 if @_ < 5;
78 257
79 $img = $img->clone; 258 $img = $img->clone;
80 $img->contrast ($r, $g, $b, $a); 259 $img->contrast ($r, $g, $b, $a);
81 $img 260 $img
82 } 261 }
83 262
84 sub brightness($$;$$;$) { 263 sub brightness($$;$$;$) {
264 my $img = pop;
85 my ($img, $r, $g, $b, $a) = @_; 265 my ($r, $g, $b, $a) = @_;
86 266
87 ($g, $b) = ($r, $r) if @_ < 4; 267 ($g, $b) = ($r, $r) if @_ < 4;
88 $a = 1 if @_ < 5; 268 $a = 1 if @_ < 5;
89 269
90 $img = $img->clone; 270 $img = $img->clone;
91 $img->brightness ($r, $g, $b, $a); 271 $img->brightness ($r, $g, $b, $a);
92 $img 272 $img
93 } 273 }
94 274
95 sub X() { $new->{position_sensitive} = 1; $l } 275=back
96 sub Y() { $new->{position_sensitive} = 1; $t }
97 sub W() { $new->{size_sensitive} = 1; $w }
98 sub H() { $new->{size_sensitive} = 1; $h }
99 276
100 sub now() { urxvt::NOW } 277=cut
101 278
102 sub again($) {
103 $new->{again} = $_[0];
104 }
105
106 sub counter($) {
107 $new->{again} = $_[0];
108 $bgdsl_self->{counter}++ + 0
109 }
110} 279}
111 280
112sub parse_expr { 281sub parse_expr {
113 my $expr = eval "sub {\npackage urxvt::bgdsl;\n#line 0 'background expression'\n$_[0]\n}"; 282 my $expr = eval "sub {\npackage urxvt::bgdsl;\n#line 0 'background expression'\n$_[0]\n}";
114 die if $@; 283 die if $@;
125 294
126# evaluate the current bg expression 295# evaluate the current bg expression
127sub recalculate { 296sub recalculate {
128 my ($self) = @_; 297 my ($self) = @_;
129 298
299 # rate limit evaluation
300
301 if ($self->{next_refresh} > urxvt::NOW) {
302 $self->{next_refresh_timer} = urxvt::timer->new->after ($self->{next_refresh} - urxvt::NOW)->cb (sub {
303 $self->recalculate;
304 });
305 return;
306 }
307
308 $self->{next_refresh} = urxvt::NOW + $MIN_INTERVAL;
309
310 # set environment to evaluate user expression
311
130 local $bgdsl_self = $self; 312 local $bgdsl_self = $self;
131 313
132 local $old = $self->{state}; 314 local $old = $self->{state};
133 local $new = my $state = $self->{state} = {}; 315 local $new = my $state = $self->{state} = {};
134 316
317 my $border = 0; #d#
318
135 ($l, $t, $w, $h) = 319 ($x, $y, $w, $h) =
136 $self->get_geometry; 320 $self->background_geometry ($border);
321
322 # evaluate user expression
137 323
138 my $img = eval { $self->{expr}->() }; 324 my $img = eval { $self->{expr}->() };
139 warn $@ if $@;#d# 325 warn $@ if $@;#d#
326 die if !UNIVERSAL::isa $img, "urxvt::img";
140 327
141 %$old = (); 328 # if the expression is sensitive to external events, prepare reevaluation then
142 329
143 my $repeat; 330 my $repeat;
144 331
145 if (my $again = $state->{again}) { 332 if (my $again = $state->{again}) {
146 $repeat = 1; 333 $repeat = 1;
147 $state->{again} = urxvt::timer->new->after ($again)->cb (sub { $self->recalculate }); 334 $state->{timer} = $again == $old->{again}
335 ? $old->{timer}
336 : urxvt::timer->new->after ($again)->interval ($again)->cb (sub {
337 ++$self->{counter};
338 $self->recalculate
339 });
148 } 340 }
149 341
150 if (delete $state->{position_sensitive}) { 342 if (delete $state->{position_sensitive}) {
151 $repeat = 1; 343 $repeat = 1;
152 $self->enable (position_change => sub { $_[0]->recalculate }); 344 $self->enable (position_change => sub { $_[0]->recalculate });
159 $self->enable (size_change => sub { $_[0]->recalculate }); 351 $self->enable (size_change => sub { $_[0]->recalculate });
160 } else { 352 } else {
161 $self->disable ("size_change"); 353 $self->disable ("size_change");
162 } 354 }
163 355
356 if (delete $state->{rootpmap_sensitive}) {
357 $repeat = 1;
358 $self->enable (rootpmap_change => sub { $_[0]->recalculate });
359 } else {
360 $self->disable ("rootpmap_change");
361 }
362
363 # clear stuff we no longer need
364
365 %$old = ();
366
164 unless ($repeat) { 367 unless ($repeat) {
165 delete $self->{state}; 368 delete $self->{state};
166 delete $self->{expr}; 369 delete $self->{expr};
167 } 370 }
168 371
372 # prepare and set background pixmap
373
169 $img = $img->sub_rect (0, 0, $w, $h) 374 $img = $img->sub_rect (0, 0, $w, $h)
170 if $img->w != $w || $img->h != $h; 375 if $img->w != $w || $img->h != $h;
171 376
172 $self->set_background ($img); 377 $self->set_background ($img, $border);
173 $self->scr_recolour (0); 378 $self->scr_recolour (0);
174 $self->want_refresh; 379 $self->want_refresh;
175} 380}
176 381
177sub on_start { 382sub on_start {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines