+sub wontfit ($) {
+ print DEBUG " NO @_\n";
+ return 0;
+}
+
+sub psstring ($) {
+ local ($_) = @_;
+ s/[()\\]/\\$&/g;
+ return "($_)";
+}
+
+sub metrics ($$@) {
+ my ($sz, $fn, @s) = @_;
+ die unless @s;
+ print DEBUG " metrics $fn $sz";
+ my $pchild = open GI, "-|"; defined $pchild or die $!;
+ if (!$pchild) {
+ print psstring($fn)," findfont $sz scalefont setfont\n" or die $!;
+ print "0 0 moveto ", psstring($_), " show showpage\n" or die $!
+ foreach @s;
+ close STDOUT or die $!;
+ exit 0;
+ }
+ my $gchild = open GO, "-|"; defined $gchild or die $!;
+ if (!$gchild) {
+ open STDIN, "<&GI" or die $!;
+ open STDERR, ">&STDOUT" or die $!;
+ exec qw(gs -dSAFER -dNOPAUSE -q -dBATCH -sDEVICE=bbox -)
+ or die "$us: exec gs: $!\n";
+ }
+ my @bb;
+ my $count = 0;
+ while (<GO>) {
+ my @tbb;
+ if (@tbb =
+ m/^\%\%HiResBoundingBox: ($dbl_re) ($dbl_re) ($dbl_re) ($dbl_re)$/
+ ) {
+ $count++;
+ $bb[0] = min $bb[0], $tbb[0];
+ $bb[1] = min $bb[1], $tbb[1];
+ $bb[2] = max $bb[2], $tbb[2];
+ $bb[3] = max $bb[3], $tbb[3];
+ } elsif (m/^\%\%/) {
+ } else {
+ print STDERR "$us: warning: gs: $_" or die;
+ }
+ }
+ $!=0; $?=0; close GO or die "gs $! $?";
+ $!=0; $?=0; close GI or die "gs paste $! $?";
+ die "$count ".scalar(@s) unless $count==@s;
+ print DEBUG " @bb\n";
+ return @bb;
+}
+
+sub do_layout_recursive_search ($);