our $debug=0;
our $output_layer= '*';
our $subsegcmapreq=0;
+our $subsegmovfeatpos='f';
+our $subsegcmapangscale;
our $ps_page_shift= 615;
our $ps_page_xmul= 765.354;
our @segments= ('/');
our %subsegcmap;
-our $drawers= 'arsclmnog';
-our %chdraw_emap= qw(A ARScg
- R aRscg
- S aRScg
- C arsCg
- c Arscg
+our $drawers= 'arscldmnog';
+our %chdraw_emap= qw(A ARScgd
+ R aRscgD
+ S aRScgd
+ C arsCgd
+ c Arscgd
r arcs
L LMg
l l
elsif (s/^S([0-9.]+)$//) { $scale= $1 * 1.0; }
elsif (s/^P(\d+)x(\d+)$//) { $page_x= $1; $page_y= $2; }
elsif (s/^GR//) { $subsegcmapreq=1; }
+ elsif (s/^GP(\d+|f)$//) { $subsegmovfeatpos=$1; }
elsif (s/^GL(.*)$//) {
my ($sscmfn) = $1;
- my ($sscmf);
+ my ($sscmf, $datum, $csss, $angbits);
local ($_);
$sscmf= new IO::File $sscmfn, 'r'
or die "$sscmfn: cannot open: $!\n";
$!=0; $_= <$sscmf>; die $! unless defined $_;
last if m/^E/;
next unless m/^C/;
- m,^C\s+(\w*/(?:[A-Za-z_]+\d+)?)\s+(\S.*\S)\s*$,
+ m,^C\s+(\w*/(?:[A-Za-z_]+)?)\s+(0x[0-9a-f]+)\s+(\d+)\s*$,
or die "$sscmfn:$.: syntax error in subseg cmap\n";
- $subsegcmap{$1}= $2;
+ ($csss,$datum,$angbits)= ($1,$2,$3);
+ if (!defined $subsegcmapangscale) {
+ $subsegcmapangscale= 1<<$angbits;
+ } else {
+ die "angbits varies" if $subsegcmapangscale != 1<<$angbits;
+ }
+ $datum= hex($datum);
+ if ($datum & 0x0ff) {
+ die "sorry, cannot put any movfeatpos or segment in red";
+ }
+ $subsegcmap{$csss}= sprintf("%.6f %.6f",
+ (($datum >> 8) & 0xff)/255.0,
+ (($datum >> 16) & 0xff)/255.0);
}
$sscmf->error and die "$sscmfn: error reading: $!\n";
close $sscmf;
our $psu_sleeperlw= 15;
our $psu_raillw= 1.0;
our $psu_thinlw= 1.0;
-our $psu_subseglw= 10.0;
+our %psu_subseglw;
+$psu_subseglw{'e'}= 20.0;
+$psu_subseglw{'m'}= 15.0;
our $lmu_marklw= 4;
our $lmu_marktpt= 11;
our $lmu_txtboxpadx= $lmu_marktpt * 0.335;
our $lmu_txtboxoff= $lmu_marklw / 2;
our $lmu_txtboxlw= 1;
+our $lmu_lenlabeloffctr= -$lmu_marklw * 1.0;
+our $lmu_lenlabeloff= $lmu_marklw * 0.5;
our $olu_left= 10 * $scale;
our $olu_right= 217 * $scale - $olu_left;
# Data structures:
# $ctx->{CmdLog}= undef } not in defobj
# $ctx->{CmdLog}[]= [ command args ] } in defobj
+# $ctx->{Parent}= $parent_ctx or undef
# $ctx->{LocsMade}[]{Id}= $id
# $ctx->{LocsMade}[]{Neg}= 1 or 0
# $ctx->{Loc}{$id}{X}
# $ctx->{SegName} # initial segment name (at start of object or file)
# # or nonexistent if in object in unknown segment
# # may have leading `-'
+# $ctx->{SegMapN}{$s}= $o
+# $ctx->{SegMapNM}{$s}= $o
# $ctx->{SavedSegment} # exists iff segment command used, is a $csss
# $ctx->{Layer}{Level}
# $ctx->{Layer}{Kind}
our $o='';
our $ol='';
-our $param; # for parametric_curve
+our $param; # for parametric_segment
# ev_... functions
#
die "invalid id" unless $sp =~ m/^[a-z][_0-9A-Za-z]*$/;
return $&;
}
-sub cva_subsegspec ($) {
- my ($sp)=@_;
- die "invalid subsegment spec" unless
- $sp =~ m,^(\-?)([0-9A-Za-z_]*)(?:/(?:([A-Za-z_]+)(\d+))?)?$,;
- my ($sign,$segname,$movfeat,$movconf)=($1,$2,$3,$4);
- $segname= exists $ctx->{SegName} ?
- $sign.$ctx->{SegName}.$segname
- : '';
- $segname =~ s/^\-(.*)\-/$1/;
- return $segname.'/'.
- (defined $movfeat ? sprintf "%s%d", $movfeat, $movconf : '');
-}
sub cva_idex ($) {
my ($sp)=@_;
my ($id,$r,$d,$k,$neg,$na,$obj_id,$vflip,$locs);
o_path_point("$pt->{X} $pt->{Y}");
}
-sub segment_used_len ($) {
- my ($used) = @_;
+our $segused_incurrent;
+our $segused_currentpt;
+our $segmentpart_counter=0;
+our $segused_restorecounter;
+
+sub segment_used__print ($) {
+ my ($pt) = @_;
+ if ($segused_incurrent > 0 && $segused_restorecounter==1) {
+ o("%L segmentpart ".
+ $segmentpart_counter++." ".
+ $ctx->{Layer}{Level}.$ctx->{Layer}{Kind}." ".
+ $segments[0]." ".
+ $segused_incurrent." ".
+ loc2dbg($segused_currentpt)." ".
+ loc2dbg($pt)."\n");
+ }
+ $segused_incurrent= undef;
+ $segused_currentpt= undef;
+}
+
+sub segment_used__len ($$) {
+ my ($used,$pt) = @_;
+ $segused_incurrent++;
+
return if @segments < 3;
$segments[1] -= $used;
return if $segments[1] > 0;
+
+ segment_used__print($pt);
+ segment_used_begin($pt);
+
@segments= @segments[2..$#segments];
+ o("% segments @segments\n");
}
+sub segment_state_save () {
+ return [ 0, $segused_incurrent, $segused_currentpt,
+ $segmentpart_counter, @segments ];
+}
+sub segment_state_restore ($) {
+ my ($r) = @_;
+ ($segused_restorecounter, $segused_incurrent, $segused_currentpt,
+ $segmentpart_counter, @segments) = @$r;
+ $r->[0]++;
+}
+
+sub segment_used_begin ($) {
+ $segused_incurrent= 0;
+ $segused_currentpt= $_[0];
+}
+sub segment_used_middle ($$) {
+ my ($used,$pt) = @_;
+ segment_used__len($used,$pt);
+}
+sub segment_used_end ($$) {
+ my ($used,$pt) = @_;
+ segment_used__len($used,$pt);
+ segment_used__print($pt);
+}
sub parametric_segment ($$$$$) {
my ($p0,$p1,$lenperp,$minradius,$calcfn) = @_;
- # makes $p (global) go from $p0 to $p1 ($p1>$p0)
+ # makes $param (global) go from $p0 to $p1 ($p1>$p0)
# $lenperp is the length of one unit p, ie the curve
# must have a uniform `density' in parameter space
- # $calcfn is invoked with $p set and should return a loc
+ # $calcfn is invoked with $param set and should return a loc
# (ie, ref to X =>, Y =>, A =>).
my ($pa,$pb,@ends,$side,$ppu,$e,$v,$tick,$draw,$allwidth);
return unless $ctx->{Draw} =~ m/[ARSCG]/;
print DEBUG "ps $p0 $p1 $lenperp ($ppu)\n";
$draw= current_draw();
if ($draw =~ m/G/) {
- my ($pt,$going,$red,$csegbare);
- $going=0;
- o("% segments @segments\n");
- o(" $psu_subseglw setlinewidth\n");
- $param=$p0;
- $pt= &$calcfn;
- for (;;) {
- $csegbare= $segments[0];
- $csegbare =~ s/^\-//;
- if ($subsegcmapreq) {
- if (!exists $subsegcmap{$csegbare}) {
- print "$csegbare\n" or die $!;
- $subsegcmap{$csegbare}++;
+ my ($pt,$going,$red,$csegbare,$movfeat,$movstroke);
+ my ($used_last,$me,$segsave);
+ $segsave= segment_state_save();
+ foreach $me (qw(e m)) {
+ segment_state_restore($segsave);
+ $going=0;
+ o("% segments @segments\n");
+ $param=$p0;
+ $pt= &$calcfn;
+ segment_used_begin($pt);
+ for (;;) {
+ $movstroke= " cmapreq-stroke\n";
+ $csegbare= $segments[0];
+ $csegbare =~ s/^\-//;
+ if ($subsegcmapreq) {
+ if (!exists $subsegcmap{$csegbare}) {
+ print "$csegbare\n" or die $!;
+ $subsegcmap{$csegbare}++;
+ }
+ } else {
+ $movfeat= $csegbare =~ s,(/\D+)(\d+)$,$1, ? $2 : 'f';
+ die "unknown subsegment colour for $csegbare\n"
+ unless exists $subsegcmap{$csegbare};
+ $red= $pt->{A} / (2*$pi);
+ $red *= $subsegcmapangscale;
+ $red += $subsegcmapangscale*2;
+ $red += $subsegcmapangscale/2 if $segments[0] =~ m/^\-/;
+ $red %= $subsegcmapangscale;
+ $red += $subsegcmapangscale if $me eq 'e';
+ $red= sprintf("%f", $red / 255.0);
+ $movstroke=
+ (" $red $subsegcmap{$csegbare} setrgbcolor\n".
+ " $psu_subseglw{$me} setlinewidth stroke\n");
+ if ($subsegmovfeatpos ne $movfeat ||
+ ($me eq 'e' && $csegbare =~ m,^/,)) {
+ $movstroke= "% no-stroke\n";
+ }
}
- } elsif (exists $subsegcmap{$csegbare}) {
- $red= $pt->{A} / (2*$pi);
- $red *= 64;
- $red += 128;
- $red += 32 if $segments[0] =~ m/^\-/;
- $red %= 64;
- $red /= 64.0;
- $red <<= 2;
- $red= sprintf("%f", $red);
- o(" $red $subsegcmap{$csegbare} setrgbcolor\n");
- } else {
- die "unknown subsegment colour for $csegbare\n";
+ o_path_begin();
+ parametric__o_pt($pt);
+
+ $param += $ppu;
+ last if $param>=$p1;
+ $pt= &$calcfn;
+ segment_used_middle($psu_ulen,$pt);
+ parametric__o_pt($pt);
+ o($movstroke);
}
- o_path_begin();
- parametric__o_pt($pt);
-
- $param += $ppu;
- last if $param>=$p1;
- segment_used_len($psu_ulen);
+ $used_last= $p1-($param-$ppu);
+ $param=$p1;
$pt= &$calcfn;
+ segment_used_end($used_last * $lenperp, $pt);
parametric__o_pt($pt);
- o_path_strokeonly();
+ o($movstroke);
}
- segment_used_len(($p1-($param-$ppu)) * $lenperp);
- $param=$p1;
- parametric__o_pt(&$calcfn);
- o_path_strokeonly();
}
if ($draw =~ m/C/) {
my ($pt);
parametric__o_pt(&$calcfn);
o(" stroke\n");
}
+ if ($draw =~ m/D/) {
+ my ($pt,$ad,$len,$off);
+ $param= ($p0+$p1)*0.5;
+ $pt= &$calcfn;
+ $ad= ang2deg($pt->{A});
+ $len= sprintf "%.0f", $lenperp * abs($p1-$p0);
+ $off= $draw =~ m/C/ ? $lmu_lenlabeloff : $lmu_lenlabeloffctr;
+ ol(" gsave\n".
+ " $pt->{X} $pt->{Y} translate\n".
+ " $ad rotate\n".
+ " lf setfont\n".
+ " 0 $off moveto\n".
+ " ($len) show\n".
+ " grestore\n");
+ }
return unless $draw =~ m/[ARS]/;
for ($pa= $p0; $pa<$p1; $pa=$pb) {
$pb= $pa + $ppu;
sub line ($$$) {
my ($from,$to,$len) = @_;
- parametric_segment(0.0, 1.0, abs($len) + 1e-6, undef, sub {
+ if ($len < 0) {
+ ($from,$to,$len) = ($to,$from,-$len);
+ }
+ parametric_segment(0.0, 1.0, $len + 1e-6, undef, sub {
ev_lincomb({}, $from, $to, $param);
});
}
$ctx= {
Trans => { X => 0.0, Y => 0.0, A => 0.0, R => 1.0 },
InRunObj => "",
- DrawMap => sub { $_[0]; }
+ DrawMap => sub { $_[0]; },
+ SegMapN => { },
+ SegMapNM => { }
};
- %{ $ctx->{Layer} }= %{ $ctx_save->{Layer} }
- if defined $ctx_save;
+ if (defined $ctx_save) {
+ %{ $ctx->{Layer} }= %{ $ctx_save->{Layer} };
+ $ctx->{Parent}= $ctx_save;
+ }
}
our $defobj_save;
}
}
+sub cva_subsegspec ($) {
+ my ($sp)=@_;
+ die "invalid subsegment spec" unless
+ $sp =~ m,^(\-?)([0-9A-Za-z_]*)(?:/(?:([A-Za-z_]+)(\d+))?)?$,;
+ my ($sign,$segname,$movfeat,$movconf)=($1,$2,$3,$4);
+
+ if (!exists $ctx->{SegName}) {
+ $segname= '';
+ $sign= '';
+ } else {
+ my ($map_ctx);
+
+ $ctx->{SegName} =~ m/^\-?/ or die;
+ $sign .= $&;
+ $segname= $'.$segname;
+
+ for ($map_ctx= $ctx;
+ defined $map_ctx;
+ $map_ctx= $map_ctx->{Parent}) {
+ if (defined $movfeat &&
+ exists $map_ctx->{SegMapNM}{"$segname/$movfeat"}) {
+ $movfeat= $map_ctx->{SegMapNM}{"$segname/$movfeat"};
+ }
+ if (exists $map_ctx->{SegMapN}{$segname}) {
+ $map_ctx->{SegMapN}{$segname} =~ m/^\-?/ or die;
+ $sign .= $&;
+ $segname= $';
+ }
+ }
+ $sign =~ s/\-\-//g;
+ }
+
+ return $sign.$segname.'/'.
+ (defined $movfeat ? sprintf "%s%d", $movfeat, $movconf : '');
+}
+
sub cmd_segment {
my ($csss,$length);
$ctx->{SavedSegment}= pop @segments
push @segments, $csss;
}
+sub cva_segmap_s {
+ my ($sp) = @_;
+ $sp =~ m,^\w+(?:/[a-zA-Z_]+)?$,
+ or die "invalid (sub)segment mapping S \`$sp'";
+ return $sp;
+}
+
+sub cva_segmap_n {
+ my ($sp) = @_;
+ $sp =~ m,^\-?\w+$, or die "invalid segment mapping N' \`$sp'";
+ return $sp;
+}
+
+sub cva_segmap_m {
+ my ($sp) = @_;
+ $sp =~ m,^[a-zA-Z_]+$, or die "invalid segment mapping M' \`$sp'";
+ return $sp;
+}
+
+sub cmd_segmap {
+ my ($s,$d);
+ while (@al) {
+ $s= can(\&cva_segmap_s);
+ if ($s =~ m,/,) {
+ $ctx->{SegMapNM}{$s}= can(\&cva_segmap_m);
+ } else {
+ $ctx->{SegMapN}{$s}= can(\&cva_segmap_n);
+ }
+ }
+}
+
sub layer_draw ($$) {
my ($k,$l) = @_;
my ($eo,$cc, $r);
} else {
$ctx->{InRunObj}= $ctx_save->{InRunObj}."${obj_id}::";
}
- $ctx->{SegName}= $1 if $segments[0] =~ m,([^-]+)/,;
+ if ($segments[0] =~ m,(.*[^-]+)/,) {
+ $ctx->{SegName}= $1;
+ }
$ctx->{DrawMap}= sub {
my ($i) = @_;
$i= &{ $ctx_save->{DrawMap} }($i);