3 # We make one set of xpms for every (segment,[movfeat])
4 # For each (segment,[movfeat]) there is one `off' bitmap, a mask.
5 # For (segment,nil) there are also `on' and `detect' pixmaps.
6 # For (segment,movfeat) there are `on' and `detect' XPMs for each posn.
7 # (The `on' and `detect' XPMs share the actual pixel data.)
13 #---------- general ----------
18 $$r eq $v or die "$v $$r $w ?";
24 #---------- word-reading (for pbm) ----------
30 if ($txtrdbuf =~ s/^\s*(\S+)\s?//) {
31 #print STDERR "w>$1<\n";
35 die $! unless length $txtrdbuf;
36 $txtrdbuf='' if $txtrdbuf =~ m/^\s*\#/;
43 die "$wn ?" unless $wn =~ m/^(?:[1-9]\d*|0)$/;
44 die "$wn $_[0]..$_[1] ?" if $wn < $_[0] || $wn > $_[1];
49 while (@wns < $_[2]) { push @wns, wn($_[0],$_[1]); }
53 #---------- xpm data structure ----------
56 # $xpmdata{$style}{$namerhs}{X}{Min}
57 # $xpmdata{$style}{$namerhs}{X}{Max}
58 # $xpmdata{$style}{$namerhs}{Y}{Min}
59 # $xpmdata{$style}{$namerhs}{Y}{Max}
60 # $xpmdata{$style}{$namerhs}{Pixels}{$y}{$x}
61 # $xpmdata{$style}{$namerhs}{Holey}
62 # $xpminstance{$instancename}{Data}= $xpmname
64 sub xpmdata_setup ($$$) {
65 my ($style, $namerhs, $holey)=@_;
67 die if $xpmdata{$style}{$namerhs};
68 $xp= $xpmdata{$style}{$namerhs}= {
73 #---------- parse args ----------
75 our $gvarname= 'ui_plan_data';
78 die if $ARGV[0] =~ m/^\-/;
79 if ($ARGV[$#ARGV] =~ s/^\-g//) {
81 $gvarname =~ s/\W/_/g;
84 #---------- read segcmap ----------
86 our (%datum_numbits,%datum_basebit);
87 # $datum_numbits{Segname} etc.
89 our (@segnum_name,%movfeats,%movfeat_prefix,%movfeat_configbits);
90 # $segnum_name[$segnum]= $segname;
91 # $movfeats{$segname}[$i]= $xpmname
92 # $movfeat_prefix{$xpmname}
93 # $movfeat_configbits{$xpmname}
95 xpmdata_setup('background','',1);
98 $!=0; defined($_=<>) or die $!;
99 #print STDERR "p>$_<\n";
101 if (m/^B (\w+) (\d+) (\d+)$/) {
102 $datum_numbits{$1}= $2;
103 $datum_basebit{$1}= $3;
104 } elsif (m/^S ([0-9A-Z]+) (0x[0-9a-f]+)$/) {
105 seteq(\$segnum_name[hex $2], $1, "segnum $2");
106 xpmdata_setup("bitmap","m_$1",1);
107 xpmdata_setup("on","_$1",1);
108 xpmdata_setup("bitmap","e_$1",1);
109 } elsif (m/^F ([0-9A-Z]+) (0x[0-9a-f]+) ([A-Z]+) (0x[0-9a-f]+) (\d+)$/) {
110 my ($xpmname,$bitno,$namerhs);
111 seteq(\$segnum_name[hex $2], $1, "segnum $2 F $3");
112 push @{ $movfeats{$1} }, $3;
114 $movfeat_prefix{$xpmname}= hex $4;
115 $movfeat_configbits{$xpmname}= $5;
116 xpmdata_setup("on","u_$xpmname",1);
117 xpmdata_setup("bitmap","m_$xpmname",1);
118 for ($bitno=0; $bitno<$movfeat_configbits{$xpmname}; $bitno++) {
119 $namerhs= "${xpmname}_${bitno}";
120 xpmdata_setup("on","_$namerhs",1);
121 xpmdata_setup("bitmap","e_$namerhs",1);
126 sub ang2pixchars ($) {
127 die if $datum_numbits{Angle} > 6;
129 return substr('0123456789'.
130 'abcdefghijklmnopqrstuvwxyz'.
131 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
136 #---------- read input image ----------
141 # $overall{X|Y}{Min|Max}
145 print STDERR "xpm_sizes\n";
146 foreach $rr (values %xpmdata) {
147 foreach $xp (values %$rr) {
148 foreach $xy (qw(X Y)) {
149 $xp->{$xy}{Min}= $sz{$xy}-1;
154 foreach $xy (qw(X Y)) {
155 $overall{$xy}{Min}= $sz{$xy}-1;
156 $overall{$xy}{Max}= 0;
160 #---------- read input pixels ----------
167 sub xpmdata_pixel ($$$) {
168 my ($style,$namerhs,$pcharstr)=@_;
169 my ($xp,$pk,$xy,$was,$mima);
170 #printf STDERR "%s %s %s \`%s'", $pp, $style, $namerhs, $pcharstr;
171 $xp= $xpmdata{$style}{$namerhs};
172 defined $xp or die "$pp: $style $namerhs ?";
173 foreach $xy (qw(X Y)) {
174 foreach $mima ($xp->{$xy}, $overall{$xy}) {
175 $mima->{Min}= $p{$xy} if $p{$xy} < $mima->{Min};
176 $mima->{Max}= $p{$xy} if $p{$xy} > $mima->{Max};
179 $was= $xp->{Pixels}{$p{Y}}{$p{X}};
180 if (!defined $pcharstr || (defined($was) && $was gt $pcharstr)) {
181 #print STDERR " already \`$was'\n";
184 # die "$pp $style $namerhs \`$pcharstr',\`$xp->{Pixels}{$p{Y}}{$p{X}}' ?"
186 $xp->{Pixels}{$p{Y}}{$p{X}}= $pcharstr;
187 #print STDERR " set\n";
192 my ($namerhs,$movfeat,%t,$xpmname,$segname,$datum,$k,$angstr,$bitno,$me);
193 $pp= "$ARGV $p{X} $p{Y}";
194 $datum= unpack 'V', $pbytes."\0";
195 foreach $k (keys %datum_numbits) {
196 $t{$k}= ($datum >> $datum_basebit{$k}) &
197 ((1 << $datum_numbits{$k}) - 1);
199 #printf(STDERR "%s 0x%08lx 0x%x 0x%x %d\n",$pp,$datum,
200 # $t{Segnum},$t{Movfeatpos},$t{Edge});
203 xpmdata_pixel('background','',undef);
204 } elsif ($t{Segnum}) {
205 xpmdata_pixel('background','','!');
207 xpmdata_pixel('background','','=');
209 return unless $t{Segnum};
211 $segname= $segnum_name[$t{Segnum}];
212 defined $segname or die "$pp $t{Segnum} $datum";
215 $angstr= ang2pixchars($t{Angle});
217 if (!$t{Movfeatpos}) {
219 xpmdata_pixel("on","_$xpmname", $angstr)
221 xpmdata_pixel("bitmap", "e_${xpmname}", '*')
223 xpmdata_pixel("bitmap", "m_${segname}", '*');
227 foreach $movfeat (@{ $movfeats{$segname} }) {
228 $xpmname= $segname.'_'.$movfeat;
229 if (($t{Movfeatpos} & ~((1<< $movfeat_configbits{$xpmname})-1))
230 == $movfeat_prefix{$xpmname}) {
231 die "$pp $t{Movfeatpos} $found $movfeat"
236 die "$pp $t{Movfeatpos}"
237 unless defined $found;
238 $xpmname= $segname.'_'.$found;
239 xpmdata_pixel("on", "u_${xpmname}",
240 (($p{X} + $p{Y}) % 2) ? $angstr : '!')
242 xpmdata_pixel("bitmap", "m_${xpmname}", '*');
243 for ($bitno=0; $bitno < $movfeat_configbits{$xpmname}; $bitno++) {
244 $namerhs= "${xpmname}_${bitno}";
245 $yes= $p{Movpos} == $bitno;
246 xpmdata_pixel("on","_$namerhs", $yes ? $angstr : '!')
248 xpmdata_pixel("bitmap","e_$namerhs", $yes ? '*' : ' ')
254 #---------- read input pixmaps
256 sub read_pixmap_header () {
258 @szn= wns(1,32767,2);
260 $osz= "$sz{X} $sz{Y}";
261 "@szn" eq "$osz" or die "$osz @szn ?";
263 ($sz{X},$sz{Y})= @szn;
266 wn(1,65535)==255 or die;
270 die "$txtrdbuf ?" if length $txtrdbuf;
272 if (!defined $txtrdbuf) {
273 die $! unless ARGV->eof;
277 read_pixmap_header();
278 $ARGV =~ m/.*\.p([0-9a-f]+)\b/ or die "$ARGV ?";
279 $p{Movpos}= $1 eq 'f' ? '' : hex($1);
280 my ($pbytes,$x,$xsz);
282 for ($p{Y}=0; $p{Y}<$sz{Y}; $p{Y}++) {
283 printf STDERR "%s %d\r",$ARGV,$p{Y}
285 for ($x=0; $x<$xsz; $x++) {
286 $!=0; read(ARGV, $pbytes, 3) == 3 or die $!;
287 next if $pbytes eq "\xff\xff\xff";
294 #---------- colourmaps ----------
296 our (%cmap,%stylecmaps);
297 # $stylecmaps{$style}= [ $cmapname,... ]
298 # $cmap{$cmapname}{$pixchars}= $xpm_data_string_rhs
299 # $cmap{$cmapname}{''}= [ string names for including in xpm ]
300 # (after cmapdata_output_all)
301 $cmap{''}= {}; # fixed colours
304 my ($style,$cmapname) = @_;
305 die "$cmapname ?" if exists $cmap{$cmapname};
306 push @{ $stylecmaps{$style} }, $cmapname;
307 $cmap{$cmapname}= { };
310 sub xpm_cmap_entry ($$$) {
311 my ($cmapname,$pixchars,$rhs) = @_;
312 die "$cmapname ?" unless exists $cmap{$cmapname};
313 die "$cmapname $pixchars ?" if exists $cmap{$cmapname}{$pixchars};
314 $cmap{$cmapname}{$pixchars}= $rhs;
317 sub xpm_cmap_rgbpermil($@) {
318 my ($cmapname, @l) = @_;
319 my ($pixchars, @rgb);
320 die "$cmapname @l ?" if @l % 4;
322 ($pixchars, @rgb)= @l[0..3]; @l = @l[4..$#l];
323 xpm_cmap_entry($cmapname, $pixchars,
324 sprintf("c #%04x%04x%04x",
325 map { floor($_ * 65.535 + 0.5) } @rgb));
329 sub xpm_cmap_fixedbitmap($$) {
330 my ($cmapname,$on) = @_;
331 xpm_cmap_entry($cmapname,' ','s space');
332 xpm_cmap_entry($cmapname,$on,'s mark');
335 sub angle_to_colour ($) {
337 my ($s,$f,$u,$U,$d,$D,$R);
347 #print STDERR "a>$u|$U|$d|$D|$s<\n";
360 sub xpm_cmap_angular($$$@) {
361 my ($cmapname, $invert, $alpha, @basergb) = @_;
362 my ($angnum,$angval,@permil,@angrgb,$i);
363 for ($angnum=0; $angnum<(1<<$datum_numbits{Angle}); $angnum++) {
364 $angval= 6.0 * ($angnum+0.0) / (1<<$datum_numbits{Angle});
365 $angval += 3.0 if $invert;
366 $angval -= 6.0 if $angval >= 6.0;
367 @angrgb= angle_to_colour($angval);
368 for ($i=0; $i<3; $i++) {
369 #print STDERR ">$cmapname|$i|$alpha|$angrgb[$i]|$basergb[$i]<\n";
370 $permil[$i]= $alpha * $angrgb[$i] +
371 (1.0 - $alpha/1000.0) * $basergb[$i];
373 xpm_cmap_rgbpermil($cmapname, ang2pixchars($angnum), @permil);
377 sub cmaps_define () {
378 my ($style,$inv,$ondet);
379 my (@background, @projected, @off, @otherposn);
381 @background= qw(0 0 0);
382 @off= qw(500 500 500);
383 @otherposn= qw(150 150 150);
384 @projected= qw(5 5 5);
386 xpm_cmap("background","background");
387 xpm_cmap_rgbpermil("background",
392 xpm_cmap("bitmap","bitmap");
393 xpm_cmap_fixedbitmap("bitmap",'*');
395 foreach $inv (('','i')) {
396 foreach $ondet (qw(on det)) {
397 xpm_cmap("on","${inv}${ondet}");
398 xpm_cmap_rgbpermil("${inv}${ondet}",
402 xpm_cmap_angular("${inv}on", !!$inv, 450, qw(0 0 0));
403 xpm_cmap_angular("${inv}det",!!$inv, 450, qw(1000 1000 1000));
409 #---------- output ----------
411 sub cmapdata_output_all () {
412 my ($cmapname, $stuff, $cmap, $sname, $pixchars);
414 foreach $cmapname (sort keys %cmap) {
415 next unless length $cmapname;
417 $cmap= $cmap{$cmapname};
418 foreach $pixchars (sort keys %$cmap) {
419 $sname= "m_${cmapname}_". unpack "H*", $pixchars;
420 printf("static const char %s[]= \"%s %s\";\n",
421 $sname, $pixchars, $cmap->{$pixchars})
423 push @$stuff, $sname;
430 foreach $colour (sort keys %$cmap) {
431 $rhs= $cmap->{$colour};
432 $rhs =~ s/^c // or die "$colour $rhs ?";
433 printf("const char ui_plan_colour_%s[]= \"%s\";\n",
439 sub xpmdata_output_all () {
440 my ($style, $namerhs, $xp, $row, $pp, $xy, $pixel);
441 my ($y, $cmap_data, $header_data, $cmapname);
442 foreach $style (sort keys %xpmdata) {
443 foreach $namerhs (sort keys %{ $xpmdata{$style} }) {
444 $xp= $xpmdata{$style}{$namerhs};
446 foreach $xy (qw(X Y)) {
447 $xp->{$xy}{Max}= $xp->{$xy}{Min} if
448 $xp->{$xy}{Max} < $xp->{$xy}{Min};
449 $header_data .= $xp->{$xy}{Max} - $xp->{$xy}{Min} + 1;
452 for ($p{Y}=$xp->{Y}{Min}; $p{Y}<=$xp->{Y}{Max}; $p{Y}++) {
453 printf "static const char d%04d_%s_%s[]= \"",
454 $p{Y}, $style, $namerhs or die $!;
455 $row= $xp->{Pixels}{$p{Y}};
456 $pp= "$style $namerhs $p{X} $p{Y}";
457 for ($p{X}=$xp->{X}{Min}; $p{X}<=$xp->{X}{Max}; $p{X}++) {
458 $pixel= $row->{$p{X}};
459 if (!defined $pixel) {
460 die "$pp ?" if !$xp->{Holey};
463 print $pixel or die $!;
465 print "\";\n" or die $!;
467 #printf STDERR "style >$style<\n";
468 foreach $cmapname (sort @{ $stylecmaps{$style} }) {
469 $cmap_data= $cmap{$cmapname}{''};
470 printf("static const char *p_%s_%s[]= {\n".
473 $header_data, scalar(@$cmap_data))
475 map { printf " %s,\n", $_ or die $!; } @$cmap_data;
476 for ($y=$xp->{Y}{Min}; $y<=$xp->{Y}{Max}; $y++) {
477 printf " d%04d_%s_%s,\n", $y, $style, $namerhs
489 my ($style,$cmap,$namerhs) = @_;
491 $xpmd= $xpmdata{$style}{$namerhs};
492 defined $xpmd or die "$style $cmap $namerhs ?";
493 return sprintf("{ %d-%d,%d-%d, p_%s_%s }",
494 (map { $xpmd->{$_}{Min}, $overall{$_}{Min} } qw(X Y)),
500 return ("{ { ".ppdr('on',"on",$dname).", ".ppdr('on',"det",$dname)." },".
501 " { ".ppdr('on',"ion",$dname).", ".ppdr('on',"idet",$dname).
505 our (@oodnames, %ood);
506 # $ood{$oodname}{Data}= $data_so_far
507 # $ood{$oodname}{ArrayDelim}= "\n" or ",\n" but for oodas only
510 my ($oodname, $data) = @_;
511 die "$oodname {{$data}} ?" if exists $ood{$oodname};
512 $ood{$oodname}{Data}= $data;
513 push @oodnames, $oodname;
517 my ($oodname, $begin) = @_;
518 die "$oodname {{$begin}} ?" if exists $ood{$oodname};
519 $ood{$oodname}{Data}= $begin;
520 $ood{$oodname}{Data} .= "[]= {";
521 $ood{$oodname}{ArrayDelim}= "\n";
522 push @oodnames, $oodname;
526 my ($oodname, $entry) = @_;
527 die "$oodname {{$entry}} ?" unless defined $ood{$oodname}{ArrayDelim};
528 $ood{$oodname}{Data} .= $ood{$oodname}{ArrayDelim};
529 $ood{$oodname}{Data} .= " ".$entry;
530 $ood{$oodname}{ArrayDelim}= ",\n";
533 sub ood_output_all () {
535 foreach $oodname (reverse @oodnames) {
536 $ood= $ood{$oodname};
537 print $ood->{Data} or die $!;
538 if (defined $ood->{ArrayDelim}) {
539 print "\n};\n" or die $!;
544 sub plandata_output_all () {
545 my ($i, @segnames, $segname);
546 my (@movfeats, $movfeat, $dname, $xpmname, $n_posns, $code, $posn);
547 my ($n_movfeats, $style, $xpmd, $pedge, $me, $noppdr);
549 for ($i=1; $i<@segnum_name; $i++) {
550 $segname= $segnum_name[$i];
551 next unless defined $segname;
552 push @segnames, $segname;
556 "const PlanData $gvarname= {\n".
557 " $overall{X}{Max}-$overall{X}{Min},".
558 " $overall{Y}{Max}-$overall{Y}{Min},".
560 " ".scalar(@segnames).", segments\n".
564 "static const PlanSegmentData segments");
566 foreach $segname (sort @segnames) {
568 exists $movfeats{$segname} ? @{ $movfeats{$segname} } : ();
569 unshift @movfeats, '';
572 "static const PlanSegmovfeatData mf_$segname");
575 "{ \"$segname\", ".scalar(@movfeats).", mf_$segname }");
577 foreach $movfeat (sort @movfeats) {
578 if (!length $movfeat) {
583 $xpmname= "${segname}_${movfeat}";
584 $n_posns= $movfeat_configbits{$xpmname};
585 $code= "\"$movfeat\"";
587 #print STDERR ">$segname|$movfeat<\n";
588 $noppdr= "{-1,-1,0}";
590 "{ $code, ".ppdr('bitmap',"bitmap","m_$xpmname").", ".
591 ($n_posns > 1 ? ppdiondet("u_$xpmname") :
592 "{ { $noppdr, $noppdr }, { $noppdr, $noppdr } }").
593 ", $n_posns, posns_$xpmname }");
595 ooda0("posns_$xpmname",
596 "static const PlanPixmapOnData posns_$xpmname");
598 for ($posn=0; $posn < $n_posns; $posn++) {
599 if ($movfeat eq '') {
603 $dname= sprintf "%s_%s_%d", $segname, $movfeat, $posn;
606 ooda1("posns_$xpmname",
607 "{ ".ppdr('bitmap',"bitmap","e_$dname").",".
608 " ".ppdiondet("_$dname")." }");
614 print "#include \"plan-data-format.h\"\n" or die $!;
615 print "/* region: $overall{X}{Min}..$overall{X}{Max}".
616 " $overall{Y}{Min}..$overall{Y}{Max} */\n";
617 cmapdata_output_all();
618 xpmdata_output_all();
619 plandata_output_all();