6 # read/write XPM format, simple transformations; grayscale for the moment
9 for(my$i=0;$i<256;$i++){$hex[$i]=sprintf "%02x", $i}
15 $val=~m/\#(.)(.)(.)/ if(length($val)==4);
16 $val=~m/\#(..)(..)(..)/ if(length($val)==7);
17 $val=~m/\#(..)..(..)..(..)/ if(length($val)==13);
21 if(length($val)==4){$r*=16;$g*=16;$b*=16};
24 my($r,$g,$b)=$main::toplevel
->rgb($val);
25 ($r/256,$g/256,$b/256);
31 die "Couldn't open $file for reading: $!" unless open(XPM
,"$file");
41 $transp="#ffffff"if(!defined($transp));
42 my@lines=split "\n", $data;
49 m/^\"(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/;
53 my$width=$xpm{"width"}=$1;
54 my$height=$xpm{"height"}=$2;
59 my$type='g'; # graymap until upgraded
61 for(my$i=0;$i<$colors;$i++){
62 $_=shift @lines;;m/^\"(.)\s+(\S)\s+([^\"\s]+)/;
63 $type='c' if($2 eq 'c');
64 $entries.=sprintf "\\%03o", ord $1;
67 $val=$transp if(ucfirst($val) eq 'None');
68 ($red,$green,$blue)=MGM
::Xpm
::rgb
($val);
70 $val=$red*.3+$green*.5+$blue*.2;
72 $gentries.=sprintf "\\%03o", $val;
77 for(my$y=0;$y<$height;$y++){
79 $line=substr $line, 1, $width;
81 # sometimes Perl makes me positively weep for joy:
82 eval "\$line=~tr[$entries][$gentries];";
90 bless($ref,"MGM::Xpm");
93 print STDERR
"This code can only handle Pixmaps with single ".
94 "byte color indicies\n";
98 print STDERR
"Input file is not in XPM format ".
99 "(must begin with /* XPM */)\n";
109 $copy{"width"}=$xpm->{"width"};
110 my$height=$copy{"height"}=$xpm->{"height"};
113 $copy{"gray"}=$xpm->{"gray"};
116 bless $ret, "MGM::Xpm";
120 my($xpm,$black,$white,$quant,$transp)=@_;
121 # easier than reading, but harder to do efficiently
123 $transp=-1 if(!defined($transp));
125 my$width=$xpm->{"width"};
126 my$height=$xpm->{"height"};
135 my($br,$bg,$bb)=&rgb
($black);
136 my($wr,$wg,$wb)=&rgb
($white);
142 for(my$i=0;$i<$height;$i++){
143 my@g=unpack 'C*', substr $xpm->{"gray"}, $i*$width, $width;
146 for(my$j=0;$j<$width;$j++){
147 $buffer.=chr(int($g[$j]*($quant/255))+65);
151 $out="/* XPM */\nstatic char * mgm_xpm[] = {\n".
152 "\"$width $height ".($quant+1)." 1";
154 foreach $key (0..$quant){
156 $out.="\",\n\"$c $type ";
161 my$r=($key/$quant)*$wr+$br;
162 my$g=($key/$quant)*$wg+$bg;
163 my$b=($key/$quant)*$wb+$bb;
165 my$val=$hex[$r].$hex[$g].$hex[$b];
171 $out.=$buffer."\"};\n";
176 my($width,$height,$val)=@_;
179 $height=int($height);
181 my($red,$green,$blue)=MGM
::Xpm
::rgb
($val);
182 my$gray=chr($red*.3+$green*.5+$blue*.2);
185 $xpm{"width"}=$width;
186 $xpm{"height"}=$height;
187 $xpm{"gray"}= ($gray) x
($width*$height);
190 bless $ret, "MGM::Xpm";
204 my($to,$tox,$toy,$from,$x,$y,$w,$h)=@_;
206 my$twidth=$to->{"width"};
207 my$fwidth=$from->{"width"};
209 $w=$twidth-$tox if($w+$tox>$twidth);
210 $w=$fwidth-$x if($w+$x>$fwidth);
212 for(my$i=0;$i<$h;$i++){
213 substr($to->{"gray"}, $tox+($i+$toy)*$twidth, $w) =
214 substr $from->{"gray"}, $x+($i+$y)*$fwidth, $w;
227 for(my$i=$w-1;$i>=0;$i--){
228 for(my$j=0;$j<$h;$j++){
229 $gray.=substr $xpm->{"gray"}, $j*$w+$i, 1;
232 $xpm->{"gray"}=$gray;
240 my$del=(1.0*$w)/($nw?
$nw:1);
245 for(my$nx=0;$nx<$nw;$nx++){
250 my$val=$oldval*(1-$prev);
251 for(my$i=$iprev+1;$i<$ix;$i++){$val+=$v->[$i]};
253 $val+=$oldval*$x if($x>.0001);
255 $v->[$nx]=$val/$del+.5;
267 my$oldval=$v->[$w-1];
268 for(my$nx=$nw-1;$nx>=0;$nx--){
275 my$val=$oldval*($prev-$iprev);
276 $val+=($oldval=$v->[$ix])*(1-$x+$ix);
277 $v->[$nx]=$val/$del+.5;
285 my($w,$h,$nh,$vv)=@_;
291 for(my$ny=0;$ny<$nh;$ny++){
296 my$idel=(1-$prev+$iprev)/$del;
297 my@v=unpack 'C*', substr $$vv, $iprev*$w, $w;
298 for(my$x=0;$x<$w;$x++){$nv[$x]=$v[$x]*$idel+.5;}
302 @v=unpack 'C*', substr $$vv, $iprev*$w, $w;
303 for(my$x=0;$x<$w;$x++){$nv[$x]+=$v[$x]/$del;}
309 @v=unpack 'C*', substr $$vv, $iy*$w, $w;
310 for(my$x=0;$x<$w;$x++){$nv[$x]+=$v[$x]*$idel;}
315 substr($$vv, $ny*$w, $w)=pack 'C*', @nv[0..$w-1];
320 my($w,$h,$nh,$vv)=@_;
326 for(my$ny=$nh-1;$ny>=0;$ny--){
331 substr($$vv, $ny*$w, $w)=
332 substr($$vv, $iprev*$w, $w);
335 my$idel=($prev-$iprev)/$del;
336 @v=unpack 'C*', substr $$vv, $iprev*$w, $w;
337 for(my$x=0;$x<$w;$x++){$nv[$x]=$v[$x]*$idel;}
339 $idel=(1-$y+$iy)/$del;
340 @v=unpack 'C*', substr $$vv, $iy*$w, $w;
341 for(my$x=0;$x<$w;$x++){$nv[$x]+=$v[$x]*$idel+.5;}
342 substr($$vv, $ny*$w, $w)=pack 'C*', @nv[0..$w-1];
357 for(my$y=0;$y<$h;$y++){
358 my@temp=unpack 'C*', substr ($xpm->{"gray"}, $y*$w, $w);
359 &reduceonex
($w,$nw,\
@temp);
360 substr ($xpm->{"gray"}, $y*$nw, $nw) = pack 'C*', @temp[0..$nw-1];
367 &reduceoney
($w,$h,$nh,\
$xpm->{"gray"});
373 substr($xpm->{"gray"}, $h*$w)= 'Xpm Xpm ' x
($h*($nw-$w)/8);
374 for(my$y=$h-1;$y>=0;$y--){
375 my@temp=unpack 'C*', substr ($xpm->{"gray"}, $y*$w, $w);
376 &enlargeonex
($w,$nw,\
@temp);
377 substr ($xpm->{"gray"}, $y*$nw, $nw) = pack 'C*', @temp[0..$nw-1];
384 substr($xpm->{"gray"}, $h*$w)= 'Xpm Xpm ' x
($w*($nh-$h)/8);
385 &enlargeoney
($w,$h,$nh,\
$xpm->{"gray"});
395 my$w=$xpm->{"width"};
396 ord (substr ($xpm->{"gray"}, $y*$w+$x, 1));
408 $font{"bitmap"}=$xpm;
409 $font{"height"}=$xpm->height-1;
410 while($pos<$xpm->width){
411 $font{"$count"}=$pos;
414 while(++$pos<$xpm->width){
415 last if (!$xpm->getpixel($pos,0));
417 $font{($count)."w"}=$pos-$font{"$count"};
421 bless $ref, "MGM::Font";
425 my($font,$text,$height)=@_;
428 while($pop=ord chop($text)){
429 $acc+=$font->{($pop)."w"};
432 if(!defined($height)){
433 ($acc,$font->{"height"});
435 (int($height/$font->{"height"}*$acc),$height);
442 my($font,$text,$height,$widthlimit,$stretch,$rot90,$cache)=@_;
447 if(!defined($textcache{$text})){
450 ($bigw,$bigh)=$font->textsize($text);
452 # make a pixmap frame
453 $bigtext=MGM
::Xpm
::new
($bigw+2,$bigh+2,'#ffffff');
454 $textcache{$text}=$bigtext if(defined($cache));
456 # paste in characters
458 while(my$pop=ord chop($text)){
459 my$w=$font->{($pop)."w"};
461 $bigtext->merge($pos,1,$font->{"bitmap"},$font->{$pop},1,
466 $bigtext=$textcache{$text};
467 $bigw=$bigtext->width;
468 $bigh=$bigtext->height;
473 $width=int($height/$bigh*$bigw*$stretch+.9);
474 $width=$widthlimit if (defined($widthlimit) && $width>$widthlimit);
475 my$ret=$bigtext->copy;
477 $ret->scale($width,$height);
479 $ret->rot90 if ($rot90);
483 #$xpm=MGM::Xpm::read("/home/xiphmont/SnotfishCVS/mgm/lib/helvetica.xpm","#ffffff");
484 #$xpm->scale(200,31);
486 #$m=MGM::Xpm::new(100,100,'#6542ee');
487 #$m->merge(2,2,$xpm,4,4,50,50);
488 #print $m->write('#161262','#ffffff','#ffffff');