File Coverage

blib/lib/Tk/Canvas/GradientColor.pm
Criterion Covered Total %
statement 15 15 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 20 20 100.0


line stmt bran cond sub pod time code
1             package Tk::Canvas::GradientColor;
2              
3 1     1   24034 use warnings;
  1         3  
  1         37  
4 1     1   8 use strict;
  1         1  
  1         35  
5 1     1   6 use Carp;
  1         6  
  1         96  
6              
7             #=============================================================================
8             # $Author : Djibril Ousmanou $
9             # $Copyright : 2014 $
10             # $Update : 30/04/2014 $
11             # $AIM : Create gradient background color on a button in Canvas widget $
12             #=============================================================================
13              
14 1     1   5 use vars qw($VERSION);
  1         2  
  1         57  
15             $VERSION = '1.06';
16              
17 1     1   6 use base qw/Tk::Derived Tk::Canvas/;
  1         1  
  1         832  
18             use POSIX qw( ceil );
19              
20             Construct Tk::Widget 'GradientColor';
21              
22             my $COLOR_TAG = 'bg_gradient_color_canvas';
23             my $MIN_START = 0;
24             my $MIDDLE_START = 50;
25             my $MAX_START = 100;
26             my $NBR_COLOR = 100;
27             my $PERCENT = 100;
28              
29             sub Populate {
30             my ( $cw, $ref_parameters ) = @_;
31              
32             $cw->SUPER::Populate($ref_parameters);
33             $cw->Advertise( 'canvas' => $cw );
34             $cw->Advertise( 'Canvas' => $cw );
35              
36             # remove highlightthickness if necessary
37             if ( !exists $ref_parameters->{-highlightthickness} ) {
38             $cw->configure( -highlightthickness => 0 );
39             }
40              
41             $cw->Delegates( DEFAULT => $cw );
42              
43             $cw->{GradientColorCanvas}{activation} = 1;
44             foreach my $key (qw{ Down End Home Left Next Prior Right Up }) {
45             $cw->Tk::bind( 'Tk::Canvas::GradientColor', "", undef );
46             $cw->Tk::bind( 'Tk::Canvas::GradientColor', "", undef );
47             }
48             $cw->Tk::bind( '' => \&set_gradientcolor );
49              
50             return;
51             }
52              
53             sub get_gradientcolor {
54             my $cw = shift;
55             return $cw->{GradientColorCanvas}{gradient};
56             }
57              
58             sub disabled_gradientcolor {
59             my $cw = shift;
60             $cw->{GradientColorCanvas}{activation} = '0';
61             if ( $cw->find( 'withtag', $COLOR_TAG ) ) { $cw->delete($COLOR_TAG); }
62             return 1;
63             }
64              
65             sub enabled_gradientcolor {
66             my $cw = shift;
67             $cw->{GradientColorCanvas}{activation} = 1;
68             $cw->set_gradientcolor;
69             return 1;
70             }
71              
72             sub set_gradientcolor {
73             my ( $cw, %gradient ) = @_;
74              
75             if ( $cw->{GradientColorCanvas}{activation} == 0 ) { return; }
76              
77             my $ref_gradient = $cw->_treat_parameters_bg( \%gradient );
78             my $start_color = $ref_gradient->{-start_color};
79             my $end_color = $ref_gradient->{-end_color};
80             my $number_color = $ref_gradient->{-number_color} + 1;
81             my $start = $ref_gradient->{-start};
82             my $end = $ref_gradient->{-end};
83             my $type = $ref_gradient->{-type};
84              
85             my ( $red1, $green1, $blue1 ) = $cw->hex_to_rgb($start_color);
86             my ( $red2, $green2, $blue2 ) = $cw->hex_to_rgb($end_color);
87              
88             my $ref_colors = $cw->_gradient_colors( $start_color, $end_color, $number_color );
89              
90             if ( $cw->find( 'withtag', $COLOR_TAG ) ) { $cw->delete($COLOR_TAG); }
91             my @alltags = $cw->find('all');
92              
93             if ( $ref_gradient->{-type} eq 'linear_horizontal' ) {
94             $cw->_linear_horizontal( $ref_colors, $start, $end, $number_color );
95             }
96             elsif ( $ref_gradient->{-type} eq 'linear_vertical' ) {
97             $cw->_linear_vertical( $ref_colors, $start, $end, $number_color );
98             }
99             elsif ( $ref_gradient->{-type} eq 'radial' ) {
100             $cw->_radial( $ref_colors, $number_color );
101             }
102             elsif ( $ref_gradient->{-type} eq 'losange' ) {
103             $cw->_losange( $ref_colors, $number_color );
104             }
105             elsif ( $ref_gradient->{-type} eq 'corner_right' ) {
106             $cw->_corner_to_right( $ref_colors, $number_color );
107             }
108             elsif ( $ref_gradient->{-type} eq 'corner_left' ) {
109             $cw->_corner_to_left( $ref_colors, $number_color );
110             }
111             elsif ( $ref_gradient->{-type} eq 'mirror_horizontal' ) {
112             $cw->_mirror_horizontal( $ref_colors, $start, $end, $number_color );
113             }
114             elsif ( $ref_gradient->{-type} eq 'mirror_vertical' ) {
115             $cw->_mirror_vertical( $ref_colors, $start, $end, $number_color );
116             }
117             else {
118             $cw->_linear_horizontal( $ref_colors, $start, $end, $number_color );
119             }
120              
121             foreach (@alltags) {
122             $cw->raise( $_, $COLOR_TAG );
123             }
124              
125             return 1;
126             }
127              
128             sub rgb_to_hex {
129             my ( $cw, $red, $green, $blue ) = @_;
130             my $hexcolor = sprintf '#%02X%02X%02X', $red, $green, $blue;
131             return uc $hexcolor;
132             }
133              
134             sub hex_to_rgb {
135             my ( $cw, $hexcolor ) = @_;
136              
137             $hexcolor = uc $hexcolor;
138             $hexcolor =~ s{^#([0-9A-F])([0-9A-F])([0-9A-F])$}{#$1$1$2$2$3$3};
139              
140             my ( $red, $green, $blue ) = ();
141             if ( $hexcolor =~ m{^#(?:[0-9A-F]{2}){3}$} ) {
142             $red = hex( substr $hexcolor, 1, 2 );
143             $green = hex( substr $hexcolor, 3, 2 );
144             $blue = hex( substr $hexcolor, 5, 2 );
145             }
146             elsif ( $hexcolor =~ m{^#} ) {
147             $cw->_error_bg( "Invalid color : We need color name or #RRGGBB or #RGB \n", 1 );
148             }
149              
150             # Color name (Tk work in 16 bits)
151             else {
152             ( $red, $green, $blue ) = map { int( ( $_ / 257 ) + 0.5 ) } $cw->rgb($hexcolor);
153             }
154              
155             return ( $red, $green, $blue );
156             }
157              
158             sub _test_start_end_values {
159             my ( $cw, $start, $end ) = @_;
160             if ( $start < $MIN_START or $end > $MAX_START or $start > $end ) {
161             $cw->_error_bg( "Bad start ($start) and end ($end) options\n"
162             . "end value must be > start value and $MIN_START <= start and end value <= $MAX_START\n" );
163             return;
164             }
165             return 1;
166             }
167              
168             sub _gradient_colors {
169             my ( $cw, $color1, $color2, $number_color ) = @_;
170              
171             my ( $red1, $green1, $blue1 ) = $cw->hex_to_rgb($color1);
172             my ( $red2, $green2, $blue2 ) = $cw->hex_to_rgb($color2);
173             my @allcolors;
174             for my $number ( 0 .. $number_color - 1 ) {
175             my $red = $red1 + ( $number / $number_color ) * ( $red2 - $red1 );
176             my $green = $green1 + ( $number / $number_color ) * ( $green2 - $green1 );
177             my $blue = $blue1 + ( $number / $number_color ) * ( $blue2 - $blue1 );
178             push @allcolors, $cw->rgb_to_hex( $red, $green, $blue );
179             }
180             push @allcolors, $cw->rgb_to_hex( $red2, $green2, $blue2 );
181              
182             return \@allcolors;
183             }
184              
185             sub _treat_parameters_bg {
186             my ( $cw, $ref_gradient ) = @_;
187              
188             if ( defined $ref_gradient and ref($ref_gradient) ne 'HASH' ) {
189             $cw->_error_bg( "'Can't set -gradient to `$ref_gradient', " . "$ref_gradient' is not an hash reference\n", 1 );
190             }
191             my $start_color = $ref_gradient->{-start_color};
192             my $end_color = $ref_gradient->{-end_color};
193             my $number_color = $ref_gradient->{-number_color};
194             my $start = $ref_gradient->{-start};
195             my $end = $ref_gradient->{-end};
196             my $type = $ref_gradient->{-type};
197              
198             $start_color = defined $start_color ? $start_color : $cw->{GradientColorCanvas}{gradient}{-start_color};
199             $end_color = defined $end_color ? $end_color : $cw->{GradientColorCanvas}{gradient}{-end_color};
200             $number_color =
201             defined $number_color
202             ? $number_color
203             : $cw->{GradientColorCanvas}{gradient}{-number_color};
204             $start = defined $start ? $start : $cw->{GradientColorCanvas}{gradient}{-start};
205             $end = defined $end ? $end : $cw->{GradientColorCanvas}{gradient}{-end};
206             $type = defined $type ? $type : $cw->{GradientColorCanvas}{gradient}{-type};
207              
208             if ( ( defined $type ) and ( $type eq 'mirror_horizontal' or $type eq 'mirror_vertical' ) ) {
209             if ( not defined $start ) { $start = $MIDDLE_START; }
210             if ( not defined $end ) { $end = $MAX_START; }
211             }
212              
213             $cw->{GradientColorCanvas}{gradient}{-start_color} = defined $start_color ? $start_color : '#8BC2F5';
214             $cw->{GradientColorCanvas}{gradient}{-end_color} = defined $end_color ? $end_color : 'white';
215             $cw->{GradientColorCanvas}{gradient}{-number_color} = defined $number_color ? $number_color : $NBR_COLOR;
216             $cw->{GradientColorCanvas}{gradient}{-start} = defined $start ? $start : $MIN_START;
217             $cw->{GradientColorCanvas}{gradient}{-end} = defined $end ? $end : $MAX_START;
218             $cw->{GradientColorCanvas}{gradient}{-type} = defined $type ? $type : 'linear_horizontal';
219              
220             return $cw->{GradientColorCanvas}{gradient};
221             }
222              
223             sub _error_bg {
224             my ( $cw, $error_message, $croak ) = @_;
225              
226             if ( defined $croak and $croak == 1 ) {
227             croak "[BE CARREFUL] : $error_message\n";
228             }
229             else {
230             carp "[WARNING] : $error_message\n";
231             }
232              
233             return;
234             }
235              
236             sub _linear_horizontal {
237             my ( $cw, $ref_colors, $start, $end, $number_color ) = @_;
238              
239             if ( !$cw->_test_start_end_values( $start, $end ) ) { return; }
240              
241             $start = $start / $PERCENT;
242             $end = $end / $PERCENT;
243              
244             my $width = $cw->width;
245             my $height = $cw->height;
246              
247             # Largeur du canvas à dégrader
248             my $width_can_grad = ( $width * $end ) - ( $width * $start );
249              
250             my $width_rec = POSIX::ceil( $width_can_grad / ( $number_color + 1 ) );
251             my $x1 = $start * $width;
252             my $y1 = 0;
253             my $x2 = $x1 + $width_rec;
254             my $y2 = $height;
255              
256             # start > 0
257             if ( $start > 0 ) {
258             $cw->createRectangle(
259             0, 0, $x1, $y2,
260             -outline => $ref_colors->[0],
261             -fill => $ref_colors->[0],
262             -width => 2,
263             -tags => $COLOR_TAG,
264             );
265             }
266              
267             # gradient color
268             foreach my $color ( @{$ref_colors} ) {
269             $cw->createRectangle(
270             $x1, $y1, $x2, $y2,
271             -outline => $color,
272             -fill => $color,
273             -width => 0,
274             -tags => $COLOR_TAG,
275             );
276             $x1 = $x2;
277             $x2 += $width_rec;
278             }
279              
280             # end < 1
281             if ( $end < 1 ) {
282             $x1 = $end * $width;
283             $cw->createRectangle(
284             $x1, $y1, $width, $y2,
285             -outline => $ref_colors->[ scalar( @{$ref_colors} - 1 ) ],
286             -fill => $ref_colors->[ scalar( @{$ref_colors} - 1 ) ],
287             -width => 0,
288             -tags => $COLOR_TAG,
289             );
290             }
291              
292             return 1;
293             }
294              
295             sub _linear_vertical {
296             my ( $cw, $ref_colors, $start, $end, $number_color ) = @_;
297              
298             if ( !$cw->_test_start_end_values( $start, $end ) ) { return; }
299              
300             $start = $start / $PERCENT;
301             $end = $end / $PERCENT;
302              
303             my $width = $cw->width;
304             my $height = $cw->height;
305              
306             my $height_can_grad = ( $height * $end ) - ( $height * $start );
307             my $height_rec = POSIX::ceil( $height_can_grad / ( $number_color + 1 ) );
308             my $x1 = 0;
309             my $y1 = $start * $height;
310             my $x2 = $width;
311             my $y2 = $y1 + $height_rec;
312              
313             # start > 0
314             if ( $start > 0 ) {
315             $cw->createRectangle(
316             $x1, 0, $x2, $y2,
317             -outline => $ref_colors->[0],
318             -fill => $ref_colors->[0],
319             -width => 0,
320             -tags => $COLOR_TAG,
321             );
322             }
323              
324             # gradient color
325             foreach my $color ( @{$ref_colors} ) {
326             $cw->createRectangle(
327             $x1, $y1, $x2, $y2,
328             -outline => $color,
329             -fill => $color,
330             -width => 0,
331             -tags => $COLOR_TAG,
332             );
333             $y1 = $y2;
334             $y2 += $height_rec;
335             }
336              
337             # end < 1
338             if ( $end < 1 ) {
339             $cw->createRectangle(
340             $x1, $y1, $x2, $height,
341             -outline => $ref_colors->[ scalar( @{$ref_colors} - 1 ) ],
342             -fill => $ref_colors->[ scalar( @{$ref_colors} - 1 ) ],
343             -width => 0,
344             -tags => $COLOR_TAG,
345             );
346             }
347              
348             return 1;
349             }
350              
351             sub _mirror_vertical {
352             my ( $cw, $ref_colors, $start, $end, $number_color ) = @_;
353              
354             if ( !$cw->_test_start_end_values( $start, $end ) ) { return; }
355              
356             $start = $start / $PERCENT;
357             $end = $end / $PERCENT;
358              
359             my $width = $cw->width;
360             my $height = $cw->height;
361              
362             my $height_can_grad = ( $height * $end ) - ( $height * $start );
363             my $height_rec = POSIX::ceil( $height_can_grad / ( $number_color + 1 ) );
364             my $x1 = 0;
365             my $y1 = $start * $height;
366             my $x2 = $width;
367             my $y2 = $y1 + $height_rec;
368              
369             # gradient color
370             foreach my $color ( @{$ref_colors} ) {
371             $cw->createRectangle(
372             $x1, $y1, $x2, $y2,
373             -outline => $color,
374             -fill => $color,
375             -width => 0,
376             -tags => $COLOR_TAG,
377             );
378             $y1 = $y2;
379             $y2 += $height_rec;
380             }
381              
382             # end < 1
383             if ( $end < 1 ) {
384             $cw->createRectangle(
385             $x1, $y1, $x2, $height,
386             -outline => $ref_colors->[ scalar( @{$ref_colors} - 1 ) ],
387             -fill => $ref_colors->[ scalar( @{$ref_colors} - 1 ) ],
388             -width => 0,
389             -tags => $COLOR_TAG,
390             );
391             }
392              
393             # other end (mirror)
394             my $other_end = ( 2 * $start ) - $end;
395              
396             # other_end to start
397             $x1 = 0;
398             $y1 = ( $start * $height ) - $height_rec;
399             $x2 = $width;
400             $y2 = $start * $height;
401              
402             # gradient color
403             foreach my $color ( @{$ref_colors} ) {
404             $cw->createRectangle(
405             $x1, $y1, $x2, $y2,
406             -outline => $color,
407             -fill => $color,
408             -width => 0,
409             -tags => $COLOR_TAG,
410             );
411             $y2 = $y1;
412             $y1 -= $height_rec;
413             last if ( $y2 < 0 );
414             }
415              
416             if ( $other_end > 0 ) {
417             $y1 += $height_rec;
418             $y2 += $height_rec;
419              
420             $cw->createRectangle(
421             $x1, 0, $x2, $y2,
422             -outline => $ref_colors->[ scalar( @{$ref_colors} - 1 ) ],
423             -fill => $ref_colors->[ scalar( @{$ref_colors} - 1 ) ],
424             -width => 0,
425             -tags => $COLOR_TAG,
426             );
427             }
428              
429             return 1;
430             }
431              
432             sub _mirror_horizontal {
433             my ( $cw, $ref_colors, $start, $end, $number_color ) = @_;
434              
435             if ( !$cw->_test_start_end_values( $start, $end ) ) { return; }
436              
437             $start = $start / $PERCENT;
438             $end = $end / $PERCENT;
439              
440             my $width = $cw->width;
441             my $height = $cw->height;
442              
443             my $width_can_grad = ( $width * $end ) - ( $width * $start );
444             my $width_rec = POSIX::ceil( $width_can_grad / ( $number_color + 1 ) );
445              
446             # Start to end
447             my $x1 = $start * $width;
448             my $y1 = 0;
449             my $x2 = $x1 + $width_rec;
450             my $y2 = $height;
451              
452             # gradient color
453             foreach my $color ( @{$ref_colors} ) {
454             $cw->createRectangle(
455             $x1, $y1, $x2, $y2,
456             -outline => $color,
457             -fill => $color,
458             -width => 0,
459             -tags => $COLOR_TAG,
460             );
461             $x1 = $x2;
462             $x2 += $width_rec;
463             }
464              
465             # end < 1
466             if ( $end < 1 ) {
467             $cw->createRectangle(
468             $x1, $y1, $width, $y2,
469             -outline => $ref_colors->[ scalar( @{$ref_colors} - 1 ) ],
470             -fill => $ref_colors->[ scalar( @{$ref_colors} - 1 ) ],
471             -width => 0,
472             -tags => $COLOR_TAG,
473             );
474             }
475              
476             # other end (mirror)
477             my $other_end = ( 2 * $start ) - $end;
478              
479             # other_end to start
480             $x1 = ( $start * $width ) - $width_rec;
481             $y1 = 0;
482             $x2 = $start * $width;
483             $y2 = $height;
484             foreach my $color ( @{$ref_colors} ) {
485             $cw->createRectangle(
486             $x1, $y1, $x2, $y2,
487             -outline => $color,
488             -fill => $color,
489             -width => 0,
490             -tags => $COLOR_TAG,
491             );
492             $x2 = $x1;
493             $x1 -= $width_rec;
494             last if ( $x2 < 0 );
495             }
496             if ( $other_end > 0 ) {
497             $x1 += $width_rec;
498             $x2 += $width_rec;
499             $cw->createRectangle(
500             0, $y1, $x1, $y2,
501             -outline => $ref_colors->[ scalar( @{$ref_colors} - 1 ) ],
502             -fill => $ref_colors->[ scalar( @{$ref_colors} - 1 ) ],
503             -width => 0,
504             -tags => $COLOR_TAG,
505             );
506             }
507              
508             return 1;
509             }
510              
511             sub _corner_to_right {
512             my ( $cw, $ref_colors, $number_color ) = @_;
513              
514             my $width = $cw->width;
515             my $height = $cw->height;
516              
517             my $xdiff = POSIX::ceil( ( 2 * $width ) / ( $number_color + 1 ) );
518             my $ydiff = POSIX::ceil( ( 2 * $height ) / ( $number_color + 1 ) );
519              
520             my $x1 = 0;
521             my $y1 = 0;
522             my $x2 = $x1 + $xdiff;
523             my $y2 = 0;
524             my $x3 = 0;
525             my $y3 = 0;
526             my $x4 = 0;
527             my $y4 = $y3 + $ydiff;
528              
529             # gradient color
530             foreach my $color ( @{$ref_colors} ) {
531             $cw->createPolygon(
532             $x1, $y1, $x3, $y3, $x4, $y4, $x2, $y2,
533             -outline => $color,
534             -fill => $color,
535             -width => 0,
536             -tags => $COLOR_TAG,
537             );
538              
539             $x1 = $x2;
540             $x2 = $x1 + $xdiff;
541             $x3 = $x4;
542              
543             $y1 = $y2;
544             $y3 = $y4;
545             $y4 += $ydiff;
546             }
547              
548             return 1;
549             }
550              
551             sub _corner_to_left {
552             my ( $cw, $ref_colors, $number_color ) = @_;
553              
554             my $width = $cw->width;
555             my $height = $cw->height;
556              
557             my $xdiff = POSIX::ceil( ( 2 * $width ) / ( $number_color + 1 ) );
558             my $ydiff = POSIX::ceil( ( 2 * $height ) / ( $number_color + 1 ) );
559              
560             my $x1 = $width - $xdiff;
561             my $y1 = 0;
562             my $x2 = $width;
563             my $y2 = 0;
564             my $x3 = $width;
565             my $y3 = 0;
566             my $x4 = $width;
567             my $y4 = $y3 + $ydiff;
568              
569             # gradient color
570             foreach my $color ( @{$ref_colors} ) {
571             $cw->createPolygon(
572             $x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4,
573             -outline => $color,
574             -fill => $color,
575             -width => 0,
576             -tags => $COLOR_TAG,
577             );
578              
579             $x1 -= $xdiff;
580             $x2 -= $xdiff;
581             $x3 = $width;
582             $y3 += $ydiff;
583             $x4 = $width;
584             $y4 += $ydiff;
585             }
586              
587             return 1;
588             }
589              
590             sub _radial {
591             my ( $cw, $ref_colors, $number_color ) = @_;
592              
593             my $width = $cw->width;
594             my $height = $cw->height;
595              
596             if ( $number_color < 2 ) { $number_color++; }
597             my $xdiff = POSIX::ceil( ( $width / 2 ) / ( $number_color + 1 ) );
598             my $ydiff = POSIX::ceil( ( $height / 2 ) / ( $number_color + 1 ) );
599             my $x1 = 0;
600             my $y1 = 0;
601             my $x2 = $width;
602             my $y2 = $height;
603              
604             $cw->createRectangle(
605             $x1, $y1, $x2, $y2,
606             -outline => $ref_colors->[0],
607             -fill => $ref_colors->[0],
608             -width => 0,
609             -tags => $COLOR_TAG,
610             );
611              
612             # gradient color
613             foreach my $color ( @{$ref_colors} ) {
614             next if ( $x1 >= $x2 or $y1 >= $y2 );
615             $cw->createOval(
616             $x1, $y1, $x2, $y2,
617             -outline => $color,
618             -fill => $color,
619             -width => 0,
620             -tags => $COLOR_TAG,
621             );
622             $x1 += $xdiff;
623             $y1 += $ydiff;
624             $x2 -= $xdiff;
625             $y2 -= $ydiff;
626             }
627              
628             return 1;
629             }
630              
631             sub _losange {
632             my ( $cw, $ref_colors, $number_color ) = @_;
633              
634             my $width = $cw->width;
635             my $height = $cw->height;
636              
637             if ( $number_color < 2 ) { $number_color++; }
638             my $xdiff = POSIX::ceil( ( $width / 2 ) / ( $number_color + 1 ) );
639             my $ydiff = POSIX::ceil( ( $height / 2 ) / ( $number_color + 1 ) );
640             my $x1 = 0;
641             my $y1 = 0;
642             my $x2 = $width;
643             my $y2 = $height;
644              
645             $cw->createRectangle(
646             $x1, $y1, $x2, $y2,
647             -outline => $ref_colors->[0],
648             -fill => $ref_colors->[0],
649             -width => 0,
650             -tags => $COLOR_TAG,
651             );
652              
653             $x1 = $width / 2;
654             $x2 = $width;
655             my $x3 = $width / 2;
656             my $x4 = 0;
657             $y1 = 0;
658             $y2 = $height / 2;
659             my $y3 = $height;
660             my $y4 = $height / 2;
661              
662             # gradient color
663             foreach my $color ( @{$ref_colors} ) {
664             next if ( $y1 >= $y3 );
665             $cw->createPolygon(
666             $x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4,
667             -outline => $color,
668             -fill => $color,
669             -width => 0,
670             -tags => $COLOR_TAG,
671             );
672             $x2 -= $xdiff;
673             $x4 += $xdiff;
674             $y1 += $ydiff;
675             $y3 -= $ydiff;
676             }
677              
678             return 1;
679             }
680              
681             1;
682              
683             __END__