#! /usr/bin/perl -w
use GDS2;
use strict;
use Getopt::Std;

my ($VERSION);
$VERSION = "2018-11-08 23:11" ; # written by emacs time-stamp

require './text2gds.pm';
our(%opts);
our(@ARGV);

sub usage() {
    print <<HELP;
  Synopsys:  $0 [-w width] [-l length] [-d digit] [-S size] -h [-n name]
  where
      -w width of ruler and dotsize (in micron, default 0.8um)
      -h print this help
      -l length         (in micron, default 100,000 um = 100 m/m)
      -r [vh]           (vertical or horizontal, default v)
      -s                 sparse option, default dense
      -L [VH]            label orientation, default V (H places 150u above from center)
      -m [offset]       mark offet, default 150um 
HELP
}

sub place_text($$$$$){
    my ($string) = shift;
    my ($x) 	= shift;
    my ($y)	= shift;
    my ($pitch) = shift;
    my ($gds2File) = shift;

    my ($char_count) = length ($string);
    for my $loc ( 0 .. $char_count - 1) {
	$gds2File -> printSref(
	    -name =>'letter_' . substr($string, $loc, 1),
	    -xy   =>[$x + $pitch * $loc, $y],
         );
    }
}
# --------------------------------------------------
# place a segment marks
sub segments ($$$$$$$$){
    my($count )   = shift;
    my($length)   = shift;
    my($segment)  = shift;  # length of mark
    my($width)    = shift;  # really width

    my($direction) = shift;  # v or h
    my($gds2File) = shift;

    my($OffsetX) = shift;
    my($OffsetY) = shift;

# repeat   0.. $ count steps
    foreach  my $i ( 0 .. $count){
	my ($shift) = $i * $length / $count;  # location to put segment, count to micron
	my ($ptr);
	if ($direction eq 'h') {
	    $ptr = [$OffsetX + $shift,              $OffsetY - $segment, 
		    $OffsetX + $shift,              $OffsetY + $segment];
	} else {
	    $ptr = [$OffsetX 	      - $segment,   $OffsetY + $shift, 
		    $OffsetX 	      + $segment,   $OffsetY + $shift];
	}
   $gds2File -> printPath(
		-layer=>0,
		-pathType=>0,
		-width=> $width,
		-xy=> $ptr,
	     );
    };
};

# set output name as 'self filename with extention .gds';
my ($gds2File);
my ($length)		=  100000; # 100 m/m
my ($unit_length)	=  2000;   #  2 m/m
my ($width)  		=  0.8;    # micron
my ($direction)		=  'v';    # v or y
my ($dense)		=  1;		# if 0, sparse lines, for horizontal drawing quick
my ($label_orientation) =  'H';
my ($label_offset)	=  150;
my ($option_string)	= join ' ', @ARGV;

getopts('l:hw:r:sL:m:', \%opts);

if ($opts{'h'})  { usage(); exit;}
if ($opts{'L'} ) { $label_orientation = $opts{'L'}; }
if ($opts{'m'} ne '' ) { $label_offset      = $opts{'m'}; }
if ($opts{'l'} ) { $length = $opts{'l'};}

if ($opts{'r'} ) { 
    if ( $opts{'r'}  eq 'v' || $opts{'r'} eq 'h' ) {
	$direction =  $opts{'r'};
    } else {
	print STDERR "-r only accepts v or h\n";  die;
    }
}
if ($opts{'s'} ) { $dense = 0;}
if ($opts{'w'} ) { $width  = $opts{'w'};}
                          # move (-10,-10) milli meter, to get (0,0) center

# origin to make half point to be (0,0);
my ($OffsetX, $OffsetY) = (0, 0);
if ( $direction eq 'v') { $OffsetY = -$length/2;}
else                    { $OffsetX = -$length/2;}


if ($#ARGV > -1 ) { print $ARGV[0], " ? .. not acceptable. Try $0 -h for help\n"; exit;}

my ($selfname) = $0;
my ($filename) = $selfname;

my ($length_in_milli) =  int($length / 1000);

if ($dense == 0 ) {
    $filename .= '-sparse' ;
}    
if ($width == 1 ) {
    $filename .= sprintf("-%s-%02dmm", $direction, $length_in_milli). '.gds';
} else {
    $filename .= sprintf("-%s-%02dmm", $direction, $length_in_milli) . sprintf("-%1.1f.gds", $width);
}

$gds2File = new GDS2(-fileName=> '>'. $filename);
$gds2File -> printInitLib(-name=>'rulerlib');

# prepare character string structure 0 .. 9
foreach my $i ( 0 .. 9 ) {
    my($string) = sprintf("%d", $i);
#               layer dotsize, structure name text
    text2gds::text(0, $width , 'letter_' . $string, $string, $gds2File );
}

text2gds::text(0, $width , 'letter_-', '-', $gds2File );
text2gds::text(0, $width , 'letter_,', ',', $gds2File );
text2gds::text(0, $width , 'letter_ ', '_', $gds2File );

# prepare Filename ID structure
text2gds::text(0, $width , 'filename' ,
	       $filename . '                   ' . $VERSION . ' perl '. $0. ' ' . $option_string,
	       $gds2File );

# --------------------------------------------------
    $gds2File -> printBgnstr(-name => $selfname);

# x and y axis straight lines
# print $length,"\n";
my (%table);  # count (in 2 m/m) -> length list 
if ($dense) {
   (%table) =  (  2, 15,   # 1.00 m/m
		  4, 12,   # 0.50 m/m
		 20,  9,   # 0.10 m/m
		 40,  6,   # 0.05 m/m
                200,  3);  # 0.01 m/m
} else {
   (%table) =  (  2, 15,   # 1.00 m/m
		  4, 12,   # 0.50 m/m
		 20,  9,   # 0.10 m/m
		 40,  6,   # 0.05 m/m
       );  # 0.01 m/m
}
   
my ($unit_lengthX,  $unit_lengthY) = (0,0);
if ($direction eq 'v') { $unit_lengthY = $unit_length;}
else                   { $unit_lengthX = $unit_length;}

# -----------------------------------------------------
#    draw lines
# -----------------------------------------------------
foreach my $nn ( 0 .. int($length/$unit_length) - 1 ) {

    my ($shiftX, $shiftY) = (0, 0);
    if ($direction eq 'v') { $shiftY = $nn * 2000;}
    else		   { $shiftX = $nn * 2000;}    
    
# ---  Main scale, 2m/m x any ---
if ($dense) { 
    $gds2File -> printPath(
                -layer=>0,
                -pathType=>0,
                -width=> $width,	# 0.1um
                -xy=>[$OffsetX + $shiftX,                  $OffsetY + $shiftY, 
		      $OffsetX + $shiftX + $unit_lengthX,  $OffsetY + $shiftY + $unit_lengthY ], 
	);
    }
# --- segments --- (scale mark)
    foreach my $i ( keys %table) {  # equivalent to (2,4,20,200)
	##    count,     length, segment length, width, direction, offsetX, offsetY
	segments($i,    $unit_length, $table{$i}, $width,  $direction, $gds2File, $OffsetX + $shiftX, $OffsetY + $shiftY);
	#  segments($i,    $unit_length, $table{$i}, $width,  'y', $gds2File, $OffsetX, $OffsetY);
    }

}
# --------------------------------------------------
# ruler steps, count and segment length table (mark of vertical line to the axis)

#               count, length of marks  
# -----------------------------------------------------
#          P L A C E   L A B E L S
# -----------------------------------------------------

# place the structure (text) prepared by above,
# Y axis label
my($every) = 100;  # mark in every 100 micron
my($range) = int($length/ $every);

my($X_adjust_label) = 16;
my($Y_adjust_label) =  1;  # half of character height

foreach my $i ( 0 ..  $range) {

    my($value) =  $i * $every - ($length / 2); # offset, center should 0;

    my($hi) = int($value/1000); 
    my($lo) = $value - $hi * 1000;
    
    if  ($hi < 0)   { $lo = abs($lo);}
    if  ($hi == 0 ) { $hi = '';}
    else            { $hi = sprintf "%d,", $hi;}
    my($label) = sprintf("%s%03d", $hi, $lo);

    my ($X, $Y);
    if ($direction eq 'v'){
	$X = $OffsetX +      $length/5000;
	$Y = $OffsetY + $i * $every - 5;
    } else {
	$X = $OffsetX + $i * $every - 5,
	$Y = $OffsetY +      $length/5000,
    }
    place_text($label, $X + $X_adjust_label, $Y + $Y_adjust_label, 6, $gds2File);
}

# place filename id
if ($direction eq 'v' ) {
    if ($label_orientation eq 'V') {
    $gds2File -> printSref(
	-name=>'filename',
        -xy=>[$OffsetX - 40 * $width, 10 * $width],
	-angle => 90
	);
    } else {
    $gds2File -> printSref(
	-name=>'filename',
        -xy=>[$OffsetX - 30 * $width - 110, $label_offset - 4 * $width],
	-angle => 0
	);
    }
} else {
    $gds2File -> printSref(
	-name=>'filename',
        -xy=>[$OffsetY + 30 * $width , -40 * $width],
	-angle => 0
	);
}    

$gds2File -> printEndstr;

$gds2File -> printEndlib();
__END__
pathType
  0 = square end
  1 = round end
  2 = square - extended 1/2 width
  4 = custom plus variable path extension...

; please note I have copy in ~/.emacs-sub/time-stamp-setup.el

(require 'time-stamp)
(add-hook 'write-file-hooks 'time-stamp)
(setq time-stamp-active t)
;; (setq time-stamp-time-zone "UTC")
(setq time-stamp-time-zone nil)
(setq time-stamp-format "%04y-%02m-%02d %02H:%02M");
(setq time-stamp-start "$VERSION = \"") ;
(setq time-stamp-end "\"") ;
(setq time-stamp-line-limit 20) ; ; default is 8

