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