Commit | Line | Data |
---|---|---|
f1ac5027 | 1 | package Imager::Fill; |
efdc2568 | 2 | use strict; |
f1ac5027 TC |
3 | # this needs to be kept in sync with the array of hatches in fills.c |
4 | my @hatch_types = | |
5 | qw/check1x1 check2x2 check4x4 vline1 vline2 vline4 | |
6 | hline1 hline2 hline4 slash1 slosh1 slash2 slosh2 | |
7 | grid1 grid2 grid4 dots1 dots4 dots16 stipple weave cross1 cross2 | |
8 | vlozenge hlozenge scalesdown scalesup scalesleft scalesright stipple2 | |
cc6483e0 | 9 | tile_L stipple3/; |
f1ac5027 TC |
10 | my %hatch_types; |
11 | @hatch_types{@hatch_types} = 0..$#hatch_types; | |
12 | ||
efdc2568 TC |
13 | my @combine_types = |
14 | qw/none normal multiply dissolve add subtract diff lighten darken | |
15 | hue saturation value color/; | |
16 | my %combine_types; | |
17 | @combine_types{@combine_types} = 0 .. $#combine_types; | |
18 | $combine_types{mult} = $combine_types{multiply}; | |
19 | $combine_types{sub} = $combine_types{subtract}; | |
20 | $combine_types{sat} = $combine_types{saturation}; | |
21 | ||
22 | # this function tries to DWIM for color parameters | |
23 | # color objects are used as is | |
24 | # simple scalars are simply treated as single parameters to Imager::Color->new | |
25 | # hashrefs are treated as named argument lists to Imager::Color->new | |
26 | # arrayrefs are treated as list arguments to Imager::Color->new iff any | |
27 | # parameter is > 1 | |
28 | # other arrayrefs are treated as list arguments to Imager::Color::Float | |
29 | ||
30 | sub _color { | |
31 | my $arg = shift; | |
32 | my $result; | |
33 | ||
34 | if (ref $arg) { | |
35 | if (UNIVERSAL::isa($arg, "Imager::Color") | |
36 | || UNIVERSAL::isa($arg, "Imager::Color::Float")) { | |
37 | $result = $arg; | |
38 | } | |
39 | else { | |
40 | if ($arg =~ /^HASH\(/) { | |
41 | $result = Imager::Color->new(%$arg); | |
42 | } | |
43 | elsif ($arg =~ /^ARRAY\(/) { | |
44 | if (grep $_ > 1, @$arg) { | |
45 | $result = Imager::Color->new(@$arg); | |
46 | } | |
47 | else { | |
48 | $result = Imager::Color::Float->new(@$arg); | |
49 | } | |
50 | } | |
51 | else { | |
52 | $Imager::ERRSTR = "Not a color"; | |
53 | } | |
54 | } | |
55 | } | |
56 | else { | |
57 | # assume Imager::Color::new knows how to handle it | |
58 | $result = Imager::Color->new($arg); | |
59 | } | |
60 | ||
61 | return $result; | |
62 | } | |
63 | ||
f1ac5027 TC |
64 | sub new { |
65 | my ($class, %hsh) = @_; | |
66 | ||
67 | my $self = bless { }, $class; | |
68 | $hsh{combine} ||= 0; | |
efdc2568 TC |
69 | if (exists $combine_types{$hsh{combine}}) { |
70 | $hsh{combine} = $combine_types{$hsh{combine}}; | |
71 | } | |
f1ac5027 | 72 | if ($hsh{solid}) { |
efdc2568 TC |
73 | my $solid = _color($hsh{solid}); |
74 | if (UNIVERSAL::isa($solid, 'Imager::Color')) { | |
75 | $self->{fill} = | |
76 | Imager::i_new_fill_solid($solid, $hsh{combine}); | |
f1ac5027 | 77 | } |
efdc2568 TC |
78 | elsif (UNIVERSAL::isa($solid, 'Imager::Color::Float')) { |
79 | $self->{fill} = | |
80 | Imager::i_new_fill_solidf($solid, $hsh{combine}); | |
f1ac5027 TC |
81 | } |
82 | else { | |
83 | $Imager::ERRSTR = "solid isn't a color"; | |
84 | return undef; | |
85 | } | |
86 | } | |
87 | elsif (defined $hsh{hatch}) { | |
88 | $hsh{dx} ||= 0; | |
89 | $hsh{dy} ||= 0; | |
90 | $hsh{fg} ||= Imager::Color->new(0, 0, 0); | |
91 | if (ref $hsh{hatch}) { | |
92 | $hsh{cust_hatch} = pack("C8", @{$hsh{hatch}}); | |
93 | $hsh{hatch} = 0; | |
94 | } | |
95 | elsif ($hsh{hatch} =~ /\D/) { | |
96 | unless (exists($hatch_types{$hsh{hatch}})) { | |
97 | $Imager::ERRSTR = "Unknown hatch type $hsh{hatch}"; | |
98 | return undef; | |
99 | } | |
100 | $hsh{hatch} = $hatch_types{$hsh{hatch}}; | |
101 | } | |
efdc2568 TC |
102 | my $fg = _color($hsh{fg}); |
103 | if (UNIVERSAL::isa($fg, 'Imager::Color')) { | |
104 | my $bg = _color($hsh{bg} || Imager::Color->new(255, 255, 255)); | |
f1ac5027 | 105 | $self->{fill} = |
efdc2568 | 106 | Imager::i_new_fill_hatch($fg, $bg, $hsh{combine}, |
f1ac5027 TC |
107 | $hsh{hatch}, $hsh{cust_hatch}, |
108 | $hsh{dx}, $hsh{dy}); | |
109 | } | |
efdc2568 TC |
110 | elsif (UNIVERSAL::isa($fg, 'Imager::Color::Float')) { |
111 | my $bg = _color($hsh{bg} || Imager::Color::Float->new(1, 1, 1)); | |
f1ac5027 | 112 | $self->{fill} = |
efdc2568 | 113 | Imager::i_new_fill_hatchf($fg, $bg, $hsh{combine}, |
f1ac5027 TC |
114 | $hsh{hatch}, $hsh{cust_hatch}, |
115 | $hsh{dx}, $hsh{dy}); | |
116 | } | |
117 | else { | |
118 | $Imager::ERRSTR = "fg isn't a color"; | |
119 | return undef; | |
120 | } | |
121 | } | |
122 | elsif (defined $hsh{fountain}) { | |
123 | # make sure we track the filter's defaults | |
124 | my $fount = $Imager::filters{fountain}; | |
125 | my $def = $fount->{defaults}; | |
126 | my $names = $fount->{names}; | |
127 | ||
128 | $hsh{ftype} = $hsh{fountain}; | |
129 | # process names of values | |
130 | for my $name (keys %$names) { | |
131 | if (defined $hsh{$name} && exists $names->{$name}{$hsh{$name}}) { | |
132 | $hsh{$name} = $names->{$name}{$hsh{$name}}; | |
133 | } | |
134 | } | |
135 | # process defaults | |
136 | %hsh = (%$def, %hsh); | |
137 | my @parms = @{$fount->{callseq}}; | |
138 | shift @parms; | |
139 | for my $name (@parms) { | |
140 | unless (defined $hsh{$name}) { | |
141 | $Imager::ERRSTR = | |
142 | "required parameter '$name' not set for fountain fill"; | |
143 | return undef; | |
144 | } | |
145 | } | |
146 | ||
147 | $self->{fill} = | |
148 | Imager::i_new_fill_fount($hsh{xa}, $hsh{ya}, $hsh{xb}, $hsh{yb}, | |
149 | $hsh{ftype}, $hsh{repeat}, $hsh{combine}, $hsh{super_sample}, | |
150 | $hsh{ssample_param}, $hsh{segments}); | |
151 | } | |
152 | else { | |
153 | $Imager::ERRSTR = "No fill type specified"; | |
154 | warn "No fill type!"; | |
155 | return undef; | |
156 | } | |
157 | ||
158 | $self; | |
159 | } | |
160 | ||
161 | sub hatches { | |
162 | return @hatch_types; | |
163 | } | |
164 | ||
efdc2568 TC |
165 | sub combines { |
166 | return @combine_types; | |
167 | } | |
168 | ||
f1ac5027 TC |
169 | 1; |
170 | ||
171 | =head1 NAME | |
172 | ||
173 | Imager::Fill - general fill types | |
174 | ||
175 | =head1 SYNOPSIS | |
176 | ||
177 | my $fill1 = Imager::Fill->new(solid=>$color, combine=>$combine); | |
178 | my $fill2 = Imager::Fill->new(hatch=>'vline2', fg=>$color1, bg=>$color2, | |
179 | dx=>$dx, dy=>$dy); | |
180 | ||
181 | =head1 DESCRIPTION | |
182 | ||
183 | Creates fill objects for use by some drawing functions, currently just | |
184 | the Imager box() method. | |
185 | ||
186 | The currently available fills are: | |
187 | ||
188 | =over | |
189 | ||
190 | =item * | |
191 | ||
192 | solid | |
193 | ||
194 | =item * | |
195 | ||
196 | hatch | |
197 | ||
198 | =item | |
199 | ||
200 | fountain (similar to gradients in paint software) | |
201 | ||
202 | =back | |
203 | ||
204 | =head1 Common options | |
205 | ||
206 | =over | |
207 | ||
208 | =item combine | |
209 | ||
efdc2568 TC |
210 | The way in which the fill data is combined with the underlying image, |
211 | possible values include: | |
212 | ||
213 | =over | |
214 | ||
215 | =item none | |
216 | ||
217 | The fill pixel replaces the target pixel. | |
218 | ||
219 | =item normal | |
220 | ||
221 | The fill pixels alpha value is used to combine it with the target pixel. | |
222 | ||
223 | =item multiply | |
224 | ||
225 | =item mult | |
226 | ||
227 | Each channel of fill and target is multiplied, and the result is | |
228 | combined using the alpha channel of the fill pixel. | |
229 | ||
230 | =item dissolve | |
231 | ||
232 | If the alpha of the fill pixel is greater than a random number, the | |
233 | fill pixel is alpha combined with the target pixel. | |
f1ac5027 | 234 | |
efdc2568 TC |
235 | =item add |
236 | ||
237 | The channels of the fill and target are added together, clamped to the range of the samples and alpha combined with the target. | |
238 | ||
239 | =item subtract | |
240 | ||
241 | The channels of the fill are subtracted from the target, clamped to be | |
242 | >= 0, and alpha combined with the target. | |
243 | ||
244 | =item diff | |
245 | ||
246 | The channels of the fill are subtracted from the target and the | |
247 | absolute value taken this is alpha combined with the target. | |
248 | ||
249 | =item lighten | |
250 | ||
251 | The higher value is taken from each channel of the fill and target pixels, which is then alpha combined with the target. | |
252 | ||
253 | =item darken | |
254 | ||
255 | The higher value is taken from each channel of the fill and target pixels, which is then alpha combined with the target. | |
256 | ||
257 | =item hue | |
258 | ||
259 | The combination of the saturation and value of the target is combined | |
260 | with the hue of the fill pixel, and is then alpha combined with the | |
261 | target. | |
262 | ||
263 | =item sat | |
264 | ||
265 | The combination of the hue and value of the target is combined | |
266 | with the saturation of the fill pixel, and is then alpha combined with the | |
267 | target. | |
268 | ||
269 | =item value | |
270 | ||
271 | The combination of the hue and value of the target is combined | |
272 | with the value of the fill pixel, and is then alpha combined with the | |
273 | target. | |
274 | ||
275 | =item color | |
276 | ||
277 | The combination of the value of the target is combined with the hue | |
278 | and saturation of the fill pixel, and is then alpha combined with the | |
279 | target. | |
280 | ||
281 | =back | |
f1ac5027 TC |
282 | |
283 | =back | |
284 | ||
285 | In general colors can be specified as Imager::Color or | |
286 | Imager::Color::Float objects. The fill object will typically store | |
287 | both types and convert from one to the other. If a fill takes 2 color | |
288 | objects they should have the same type. | |
289 | ||
290 | =head2 Solid fills | |
291 | ||
292 | my $fill = Imager::Fill->new(solid=>$color, $combine =>$combine) | |
293 | ||
294 | Creates a solid fill, the only required parameter is C<solid> which | |
295 | should be the color to fill with. | |
296 | ||
297 | =head2 Hatched fills | |
298 | ||
299 | my $fill = Imager::Fill->new(hatch=>$type, fg=>$fgcolor, bg=>$bgcolor, | |
300 | dx=>$dx, $dy=>$dy); | |
301 | ||
302 | Creates a hatched fill. You can specify the following keywords: | |
303 | ||
304 | =over | |
305 | ||
306 | =item hatch | |
307 | ||
308 | The type of hatch to perform, this can either be the numeric index of | |
309 | the hatch (not recommended), the symbolic name of the hatch, or an | |
310 | array of 8 integers which specify the pattern of the hatch. | |
311 | ||
312 | Hatches are represented as cells 8x8 arrays of bits, which limits their | |
313 | complexity. | |
314 | ||
315 | Current hatch names are: | |
316 | ||
317 | =over | |
318 | ||
319 | =item check1x1, check2x2, check4x4 | |
320 | ||
321 | checkerboards at varios sizes | |
322 | ||
323 | =item vline1, vline2, vline4 | |
324 | ||
325 | 1, 2, or 4 vertical lines per cell | |
326 | ||
327 | =item hline1, hline2, hline4 | |
328 | ||
329 | 1, 2, or 4 horizontal lines per cell | |
330 | ||
331 | =item slash1, slash2 | |
332 | ||
333 | 1 or 2 / lines per cell. | |
334 | ||
335 | =item slosh1, slosh2 | |
336 | ||
337 | 1 or 2 \ lines per cell | |
338 | ||
339 | =item grid1, grid2, grid4 | |
340 | ||
341 | 1, 2, or 4 vertical and horizontal lines per cell | |
342 | ||
343 | =item dots1, dots4, dots16 | |
344 | ||
345 | 1, 4 or 16 dots per cell | |
346 | ||
347 | =item stipple, stipple2 | |
348 | ||
349 | see the samples | |
350 | ||
351 | =item weave | |
352 | ||
353 | I hope this one is obvious. | |
354 | ||
355 | =item cross1, cross2 | |
356 | ||
357 | 2 densities of crosshatch | |
358 | ||
359 | =item vlozenge, hlozenge | |
360 | ||
361 | something like lozenge tiles | |
362 | ||
363 | =item scalesdown, scalesup, scalesleft, scalesright | |
364 | ||
365 | Vaguely like fish scales in each direction. | |
366 | ||
367 | =item tile_L | |
368 | ||
369 | L-shaped tiles | |
370 | ||
371 | =back | |
372 | ||
373 | =item fg | |
374 | ||
375 | =item bg | |
376 | ||
377 | The fg color is rendered where bits are set in the hatch, and the bg | |
378 | where they are clear. If you use a transparent fg or bg, and set | |
379 | combine, you can overlay the hatch onto an existing image. | |
380 | ||
381 | fg defaults to black, bg to white. | |
382 | ||
383 | =item dx | |
384 | ||
385 | =item dy | |
386 | ||
387 | An offset into the hatch cell. Both default to zero. | |
388 | ||
389 | =back | |
390 | ||
391 | You can call Imager::Fill->hatches for a list of hatch names. | |
392 | ||
393 | =head2 Fountain fills | |
394 | ||
395 | my $fill = Imager::Fill->new(fountain=>$ftype, | |
396 | xa=>$xa, ya=>$ya, xb=>$xb, yb=>$yb, | |
397 | segment=>$segments, repeat=>$repeat, combine=>$combine, | |
398 | super_sample=>$super_sample, ssample_param=>$ssample_param); | |
399 | ||
400 | This fills the given region with a fountain fill. This is exactly the | |
401 | same fill as the C<fountain> filter, but is restricted to the shape | |
402 | you are drawing, and the fountain parameter supplies the fill type, | |
403 | and is required. | |
404 | ||
efdc2568 TC |
405 | =head1 OTHER METHODS |
406 | ||
407 | =over | |
408 | ||
409 | =item Imager::Fill->hatches | |
410 | ||
411 | A list of all defined hatch names. | |
412 | ||
413 | =item Imager::Fill->combines | |
414 | ||
415 | A list of all combine types. | |
416 | ||
417 | =back | |
418 | ||
f1ac5027 TC |
419 | =head1 FUTURE PLANS |
420 | ||
421 | I'm planning on adding the following types of fills: | |
422 | ||
423 | =over | |
424 | ||
425 | =item image | |
426 | ||
427 | tiled image fill | |
428 | ||
429 | =item checkerboard | |
430 | ||
431 | combines 2 other fills in a checkerboard | |
432 | ||
433 | =item combine | |
434 | ||
435 | combines 2 other fills using the levels of an image | |
436 | ||
437 | =item regmach | |
438 | ||
439 | uses the transform2() register machine to create fills | |
440 | ||
441 | =back | |
442 | ||
443 | =head1 AUTHOR | |
444 | ||
445 | Tony Cook <tony@develop-help.com> | |
446 | ||
447 | =head1 SEE ALSO | |
448 | ||
449 | Imager(3) | |
450 | ||
451 | =cut |