File Coverage

blib/lib/Image/Base/Prima/Drawable.pm
Criterion Covered Total %
statement 15 87 17.2
branch 0 40 0.0
condition 0 12 0.0
subroutine 5 15 33.3
pod 7 8 87.5
total 27 162 16.6


line stmt bran cond sub pod time code
1             # Copyright 2010, 2011 Kevin Ryde
2              
3             # This file is part of Image-Base-Prima.
4             #
5             # Image-Base-Prima is free software; you can redistribute it and/or modify
6             # it under the terms of the GNU General Public License as published by the
7             # Free Software Foundation; either version 3, or (at your option) any later
8             # version.
9             #
10             # Image-Base-Prima is distributed in the hope that it will be useful, but
11             # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12             # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13             # for more details.
14             #
15             # You should have received a copy of the GNU General Public License along
16             # with Image-Base-Prima. If not, see .
17              
18              
19             # Prima::Drawable -- drawing operations
20             #
21             # fillpoly()
22             # polyline()
23              
24             package Image::Base::Prima::Drawable;
25 1     1   579 use 5.005;
  1         3  
  1         38  
26 1     1   4 use strict;
  1         1  
  1         24  
27 1     1   5 use Carp;
  1         4  
  1         86  
28 1     1   6 use vars '$VERSION', '@ISA';
  1         1  
  1         64  
29              
30 1     1   914 use Image::Base;
  1         2026  
  1         1273  
31             @ISA = ('Image::Base');
32              
33             $VERSION = 8;
34              
35             # uncomment this to run the ### lines
36             #use Devel::Comments '###';
37              
38             sub new {
39 0     0 1   my $class = shift;
40 0           my $self = bless { _set_colour => '' }, $class;
41 0           $self->set (@_);
42 0           return $self;
43             }
44              
45             my %get_methods = (-width => 'width',
46             -height => 'height',
47             # these two not documented yet
48             -depth => 'get_bpp',
49             -bpp => 'get_bpp',
50             );
51             sub _get {
52 0     0     my ($self, $key) = @_;
53             ### Prima-Drawable _get(): $key
54 0 0         if (my $method = $get_methods{$key}) {
55 0           return $self->{'-drawable'}->$method;
56             }
57 0           return $self->SUPER::_get($key);
58             }
59              
60             sub set {
61 0     0 1   my ($self, %params) = @_;
62 0           my $width = delete $params{'-width'};
63 0           my $height = delete $params{'-height'};
64              
65 0           %$self = (%$self, %params);
66              
67 0           my $drawable = $self->{'-drawable'};
68 0 0         if (defined $width) {
    0          
69 0 0         if (defined $height) {
70 0           $drawable->size ($width, $height);
71             } else {
72 0           $drawable->width ($width);
73             }
74             } elsif (defined $height) {
75 0           $drawable->height ($height);
76             }
77             }
78              
79             sub xy {
80 0     0 1   my ($self, $x, $y, $colour) = @_;
81 0           my $drawable = $self->{'-drawable'};
82 0           $y = $drawable->height - 1 - $y;
83 0 0         if (@_ == 4) {
84             #### xy store: $x,$y
85 0           $drawable->pixel ($x,$y, $self->colour_to_pixel($colour));
86             } else {
87             #### fetch: $x,$y
88 0           return sprintf '#%06X', $drawable->pixel($x,$y);
89             }
90             }
91              
92             sub line {
93 0     0 1   my ($self, $x1,$y1, $x2,$y2, $colour) = @_ ;
94             ### Image-Base-Prima-Drawable line(): "$x1,$y1, $x2,$y2"
95 0           my $y_top = $self->{'-drawable'}->height - 1;
96 0           _set_colour($self,$colour)->line ($x1, $y_top-$y1,
97             $x2, $y_top-$y2);
98             }
99              
100             sub rectangle {
101 0     0 1   my ($self, $x1, $y1, $x2, $y2, $colour, $fill) = @_;
102              
103             # In Prima 1.28 under X, if lineWidth==0 then a one-pixel unfilled
104             # rectangle x1==x2 and y1==y2 draws nothing. This will be just the usual
105             # server-dependent behaviour on a zero-width line. Use bar() for this
106             # case so as to be sure of getting pixels drawn whether lineWidth==0 or
107             # lineWidth==1.
108             #
109 0 0 0       my $method = ($fill || ($x1==$x2 && $y1==$y2)
110             ? 'bar'
111             : 'rectangle');
112 0           my $y_top = $self->{'-drawable'}->height - 1;
113             ### Image-Base-Prima-Drawable rectangle(): $method
114 0           _set_colour($self,$colour)->$method ($x1, $y_top - $y1,
115             $x2, $y_top - $y2);
116             }
117             sub ellipse {
118 0     0 1   my ($self, $x1, $y1, $x2, $y2, $colour, $fill) = @_;
119              
120             # In Prima 1.28 under X, if lineWidth==0 then a one-pixel ellipse x1==x2
121             # and y1==y2 draws nothing, the same as for an unfilled rectangle above.
122             # Also trouble with diameter==1 when filled draws one pixel short at the
123             # right. Do any width<=2 or height<=2 as a rectangle.
124             #
125 0           my $drawable = _set_colour($self,$colour);
126 0           my $y_top = $drawable->height - 1;
127 0           my $dx = $x2-$x1+1; # diameters
128 0           my $dy = $y2-$y1+1;
129 0 0 0       if ($dx <= 2 || $dy <= 2) {
130 0           $drawable->bar ($x1, $y_top - $y1,
131             $x2, $y_top - $y2);
132             } else {
133             # For an even diameter the X,Y centre is rounded down to the next lower
134             # integer. (To be documented in a Prima post 1.28, perhaps.) For the Y
135             # coordinate that rounding down can be applied after flipping $y_top-$y1
136             # puts Y=0 at the bottom per Prima coordinates.
137             #
138 0 0         my $method = ($fill ? 'fill_ellipse' : 'ellipse');
139              
140             ### Prima ellipse()
141             ### $dx
142             ### $dy
143             ### x centre: $x1 + int(($dx-1)/2)
144             ### y centre: ($y_top - $y1) - int($dy/2)
145             ### $method
146              
147 0           $drawable->$method ($x1 + int(($dx-1)/2),
148             ($y_top - $y1) - int($dy/2),
149             $dx, $dy);
150             }
151             }
152              
153             sub diamond {
154 0     0 1   my ($self, $x1, $y1, $x2, $y2, $colour, $fill) = @_;
155             ### Drawable diamond(): $x1, $y1, $x2, $y2, $colour
156              
157 0           my $drawable = $self->{'-drawable'};
158 0           $y1 = $drawable->height - 1 - $y1;
159 0           $y2 = $drawable->height - 1 - $y2;
160              
161 0 0 0       if ($x1==$x2 && $y1==$y2) {
162             # 1x1 polygon draws nothing, do it as a point instead
163 0           $drawable->pixel ($x1,$y1, $self->colour_to_pixel($colour));
164              
165             } else {
166 0           _set_colour($self,$colour);
167              
168 0           my $xh = ($x2 - $x1);
169 0           my $yh = ($y1 - $y2); # y1 bigger
170 0           my $xeven = ($xh & 1);
171 0           my $yeven = ($yh & 1);
172 0           $xh = int($xh / 2);
173 0           $yh = int($yh / 2);
174             ### assert: $x1+$xh+$xeven == $x2-$xh
175             ### assert: $y2+$yh+$yeven == $y1-$yh
176              
177 0 0         my $poly = [$x1+$xh, $y1, # top centre
    0          
    0          
    0          
178              
179             # left
180             $x1, $y1-$yh,
181             ($yeven ? ($x1, $y2+$yh) : ()),
182              
183             # bottom
184             $x1+$xh, $y2,
185             ($xeven ? ($x2-$xh, $y2) : ()),
186              
187             # right
188             ($yeven ? ($x2, $y2+$yh) : ()),
189             $x2, $y1-$yh,
190              
191             ($xeven ? ($x2-$xh, $y1) : ()),
192             $x1+$xh, $y1]; # back to start in X11 PolyLine style
193 0 0         if ($fill) {
194 0 0         $drawable->fillpoly ($poly) or croak $@;
195             }
196 0 0         $drawable->polyline ($poly) or croak $@;
197             }
198             }
199              
200             sub _set_colour {
201 0     0     my ($self, $colour) = @_;
202 0           my $drawable = $self->{'-drawable'};
203 0 0         if ($colour ne $self->{'_set_colour'}) {
204             ### Image-Base-Prima-Drawable _set_colour() change to: $colour
205 0           $self->{'_set_colour'} = $colour;
206 0           $drawable->color ($self->colour_to_pixel ($colour));
207             }
208 0           return $drawable;
209             }
210              
211             # not documented yet
212             sub colour_to_pixel {
213 0     0 0   my ($self, $colour) = @_;
214             ### colour_to_pixel(): $colour
215              
216             # Crib: [:xdigit:] new in 5.6, so only 0-9A-F, and in any case as of perl
217             # 5.12.4 [:xdigit:] matches some wide chars but hex() doesn't accept them
218 0 0         if ($colour =~ /^#([0-9A-F]{6})$/i) {
219 0           return hex(substr($colour,1));
220             }
221 0 0         if ($colour =~ /^#([0-9A-F]{2})[0-9A-F]{2}([0-9A-F]{2})[0-9A-F]{2}([0-9A-F]{2})[0-9A-F]{2}$/i) {
222 0           return hex($1.$2.$3);
223             }
224              
225 0           (my $c = $colour) =~ s/^cl:://;
226 0 0 0       if (my $coderef = (cl->can($c) || cl->can(ucfirst($c)))) {
227             ### coderef: &$coderef()
228 0           return &$coderef();
229             }
230              
231             ### $c
232 0           croak "Unrecognised colour: $colour";
233             }
234              
235             # is prima_allocate_color() meant to be public? It's not normally reached
236             # unless in a paint anyway ...
237             #
238             # sub add_colours {
239             # ...
240             # }
241              
242             1;
243             __END__