#! @@AWK@@ -f

BEGIN {
  ID    = "cdclpsfont 1.2"
  DATE  = "2007/10/03 (T.Kagimoto; original code is by A.Numaguchi)"
  EX    = "convert dcl.ps characters into PostScript font"
  USAGE = "cdclpsfont [f=<font id>..] [<option>=<value>...] <file>"

#-----------------------------------------------------------------------
# OPTION
    f="ccCChhHHHttTT"; q["f"]="font id (((idx,ifont),idx=1,imax),ifont=1,..) [ccCChhHHHttTT]"
    imax=4           ; q["imax"]="max. of index [4]"
    small=0.7        ; q["small"]="ratio of sub(super)script [0.7]"
    shift=0.3        ; q["shift"]="shift of sub(super)script [0.3]"
    lcntl=0          ; q["lcntl"]="1/0 : sub(super)script on/off [0]"
    isup="|"         ; q["isup"]="begin superscript [|]"
    isub="_"         ; q["isub"]="begin subscript [_]"
    irst="\""        ; q["irst"]="end sub(super)script [\"]"
    fact=7500        ; q["fact"]="scale factor [7500]"
    fwt=1            ; q["fwt"]="text width scale factor [1]"
    fht=1            ; q["fht"]="text hight scale factor [1]"
    fwnc=1           ; q["fwnc"]="width scale factor for non-standard char [1]"
    fhnc=1           ; q["fhnc"]="hight scale factor for non-standard char [1]"
    ai=0             ; q["ai"]="SymbolMT font is used for Adobe Illustrator 9.x or later [0]"

    font["c"]="Courier";                 fwf["c"]=1.00; fhf["c"]=0.7
    font["C"]="Courier-Bold";            fwf["C"]=1.00; fhf["C"]=0.7
    font["o"]="Courier-Oblique";         fwf["o"]=1.00; fhf["o"]=0.7
    font["O"]="Courier-BoldOblique";     fwf["O"]=1.00; fhf["O"]=0.7
    font["h"]="Helvetica";               fwf["h"]=0.85; fhf["h"]=0.7
    font["H"]="Helvetica-Bold";          fwf["H"]=0.85; fhf["H"]=0.7
    font["s"]="Helvetica-Oblique";       fwf["s"]=0.85; fhf["s"]=0.7
    font["S"]="Helvetica-BoldOblique";   fwf["S"]=0.85; fhf["S"]=0.7
    font["t"]="Times-Roman";             fwf["t"]=0.95; fhf["t"]=0.7
    font["T"]="Times-Bold";              fwf["T"]=0.95; fhf["T"]=0.7
    font["i"]="Times-Italic";            fwf["i"]=0.95; fhf["i"]=0.7
    font["I"]="Times-BoldItalic";        fwf["I"]=0.95; fhf["I"]=0.7
    font["a"]="AvantGarde-Book";         fwf["a"]=0.95; fhf["a"]=0.7
    font["A"]="AvantGarde-Demi";         fwf["A"]=0.95; fhf["A"]=0.7
    font["b"]="Bookman-Light";           fwf["b"]=0.95; fhf["b"]=0.7
    font["B"]="Bookman-Demi";            fwf["B"]=0.95; fhf["B"]=0.7
    font["n"]="NewCenturySchlbk-Roman";  fwf["n"]=0.95; fhf["n"]=0.7
    font["N"]="NewCenturySchlbk-Bold";   fwf["N"]=0.95; fhf["N"]=0.7
    font["p"]="Palatino-Roman";          fwf["p"]=0.95; fhf["p"]=0.7
    font["P"]="Palatino-Bold";           fwf["P"]=0.95; fhf["P"]=0.7
    font["z"]="ZapfChancery";            fwf["z"]=1.00; fhf["z"]=0.7
    font["Z"]="ZapfChancery-Bold";       fwf["Z"]=1.00; fhf["Z"]=0.7

#
# font table for reencoded composite font
#
    for (i = 0; i < 256; i++) tab[i] = 0
    for (i = 2; i <= 17; i++) tab[i] = i
    for (i = 32; i <= 127; i++) tab[i] = i
    tab[177] = 18; tab[178] = 19
    tab[207] = 20; tab[208] = 21; tab[209] = 22
    tab[224] = 23; tab[225] = 24

# Symbol (Font number + 500)
  # greek
    tab[128] = 565; tab[129] = 566; tab[130] = 571; tab[131] = 568
    tab[132] = 569; tab[133] = 590; tab[134] = 572; tab[135] = 581
    tab[136] = 573; tab[137] = 575; tab[138] = 576; tab[139] = 577
    tab[140] = 578; tab[141] = 588; tab[142] = 579; tab[143] = 580
    tab[144] = 582; tab[145] = 583; tab[146] = 584; tab[147] = 585
    tab[148] = 570; tab[149] = 567; tab[150] = 589; tab[151] = 587
    for (i = 152; i <= 175; i++) tab[i] = tab[i-24] + 32
  # theta
    tab[159] = 574
    tab[241] = 613
  # omega
    tab[242] = 618
  # sigma
    tab[244] = 586
  # phi
    tab[172] = 606
    tab[245] = 602
  # Upsilon
    tab[147] = 661
  # other symbol
    tab[179] = 674; tab[180] = 673; tab[181] = 672; tab[182] = 675
    tab[184] = 594; tab[185] = 708; tab[186] = 592; tab[189] = 665
    tab[190] = 545; tab[191] = 543; tab[192] = 677; tab[194] = 680
    tab[195] = 715; tab[196] = 684; tab[197] = 561; tab[198] = 685
    tab[199] = 686; tab[200] = 560; tab[201] = 562; tab[202] = 663
    tab[203] = 679; tab[204] = 681; tab[205] = 626; tab[206] = 717
    tab[210] = 714; tab[211] = 704; tab[212] = 700; tab[213] = 701
    tab[214] = 699; tab[215] = 706; tab[216] = 682; tab[217] = 709
    tab[218] = 742
#
    if (ARGV[1] == "-help" || ARGV[1] == "help") print_usage()
    AI = ""
#
#   other parameters
#
    fn_composite = 1; fn_others    = 2; fn_symbol    = 3
    str_super    = 1; str_normal   = 0; str_sub      = -1
    error        = 1; no_error     = 0
}
#-----------------------------------------------------------------------
# add myself to Creator
#-----------------------------------------------------------------------
/^%%Creator/ {
    print $0 " | " ID
    if (ai) AI = "MT"
    next
}
#-----------------------------------------------------------------------
# check transformation
#-----------------------------------------------------------------------
/^%%Orientation/ {
    print
    if ($2 == "Portrait") angle = -90
    next
}
#-----------------------------------------------------------------------
# add composite font definition
#-----------------------------------------------------------------------
/^%%BeginProlog/ {
    print
    print "/fsm " small " def"
    print "/fsu " (1-small)/2+shift " def"
    print "/fsd " (1-small)/2-shift " def"

    reencode_font()
    for (i = 1; i <= length(f); i++) {
        fn = font[substr(f, i, 1)]
        if (fn != "" && ! cf[fn]) {
            make_cf(fn)
            cf[fn] = 1
        }
    }
    next
}
#-----------------------------------------------------------------------
# set attributes of strings
#     (size, rotation, justification, thickness, font)
#-----------------------------------------------------------------------
/^%%Begin SZTX / {
    print
    sub("\\[", "", $3)
    sub("\\]$", "", $8)
    rsize = $3 * fact
    rot   = $4 + angle
    cent  = $5 + 0
    idx   = $6 + 0
    fn    = $7 + 0; if (fn <= 0) fn = 1
    iws   = $8 + 0; if (iws < 0) rot = rot - 90

    i = int((length(f)+imax-1)/imax)
    if (fn <= i)
        fx = substr(f, (fn-1)*imax+1, imax)
    else
        fx = substr(f, (i-1)*imax+1, imax)
    id = idx
    if (idx > length(fx)) id = length(fx)
    fi = substr(fx, id, 1)

    if (font[fi] != "") {                                    # set font
        fon = font[fi]
        sf  = fwt * fwf[fi] * rsize
        df  = fht * fhf[fi] * rsize
    } else if (fi == "X") {                                  # remove text
        while ($0 != "%%End SZTX") {
            getline
            if ($NF == "W" || $NF == "RGB") print
        }
    } else {                                                 # no conversion
        while ($0 != "%%End SZTX") {
            getline
            print
        }
    }
    next
}
#-----------------------------------------------------------------------
# replace a DCL font with a PostScript font
#-----------------------------------------------------------------------
/^%%Begin SZTXZ / {
    print
    sub("\\[", "", $3)
    x = $3; y = $4
    i = index($0, "\"")
    str = substr($0, i+1); sub("\"\\]$", "", str)

    gsub(/\\/, "\\\\", str)
    gsub(/\(/, "\\(", str)
    gsub(/\)/, "\\)", str)
  
    retval = expand_string()

    linbound = 0
    if (retval == error) {                                 # no conversion
        while ($0 != "%%End SZTXZ") {
            getline
            print
        }
        next
    } else {
        while ($0 != "%%End SZTXZ") {                      # remove text
            getline
            if ($NF == "W" || $NF == "RGB") {
                print
            } else if ($NF == "N") {
                getline
                linbound = 0
                if ($0 ~ /[0-9]*[LM]/) linbound = 1
            }
        }
    }
    #
    # calculate width of strings
    #
    print "gsave"
    print "/sw 0 def"     
    print x " " y " moveto"
    print r+rot " rotate"
    for (n = 0; n < n_strings; n++) {
        str = str_array[n]
        fno = fn_array[n]
        pos = str_pos[n]
        if (str == "") continue

        if (linbound) { 
            set_font()
            if (cent != -1) {
                s = str
                if (pos == str_normal) {
                    print "/str (" str ") def"
                    print "/sw sw str stringwidth pop add def"
                } else {
                    print "/str (" str ") def"
                    print "/sw sw str stringwidth pop fsm mul add def"
                }
            }
        }
    }

    if (cent == 0)                             # centering
        print "sw 2 div neg",-df/2,"rmoveto"
    else if (cent == 1)                        # flush right
        print "sw neg",-df/2,"rmoveto"
    #
    # print strings
    #
    for (n = 0; n < n_strings; n++) {
        str = str_array[n]
        fno = fn_array[n]
        pos = str_pos[n]
        if (str == "") continue

        if (linbound) { 
            set_font()
            if (pos == str_normal) {
                print "/str (" str ") def"
                print "str show"
            } else {
                print "/str (" str ") def"
                print "gsave"
                if (pos == str_super)
                    print 0, df " fsu mul rmoveto"
                else
                    print 0, df " fsd mul rmoveto"
                print "fsm fsm scale"
                print "str show"
                print "grestore"
                print "str stringwidth pop fsm mul 0 rmoveto"
            }
        }
    }
    print "grestore"
    print
    next
}

{
    print
}

#-----------------------------------------------------------------------
# definition of functions
#-----------------------------------------------------------------------
function expand_string()
{
    n_strings    = 0
    end_pos      = length(str)
    bool_percent = 0
    bool_script  = 0
    undef        = -999
#
#   initialze str_array[:], str_pos[:]
#
    for (i = 0; i < end_pos; i++) {
        str_array[i] = ""
        str_pos[i]   = undef
    }
#
#   parse string letter by letter
#
    str_pos[n_strings] = str_normal
    for (i = 1; i <= end_pos; i++) {
        cur_str = substr(str,i,1)
        if (lcntl && cur_str == isup) {
            n_strings++
            str_pos[n_strings] = str_super
            bool_script = 1
            continue
        } else if (lcntl && cur_str == isub) {
            n_strings++
            str_pos[n_strings] = str_sub
            bool_script = 1
            continue
        } else if (lcntl && cur_str == irst) {
            if (i == end_pos) break
            n_strings++
            str_pos[n_strings] = str_normal
            bool_script = 1
            continue
        }
        if (cur_str == "%") {
            if (i != 1 && ! bool_script) n_strings++
            retval = expand_meta(substr(str,i+1,3)+0)
            if (retval) return error
            if (str_pos[n_strings] == undef) str_pos[n_strings] = str_pos[n_strings-1]
            i+=3
            bool_percent = 1
        } else {
            if (bool_percent && ! bool_script) {
                n_strings++
                if (str_pos[n_strings] == undef) str_pos[n_strings] = str_pos[n_strings-1]
            }
            str_array[n_strings] = str_array[n_strings] cur_str
            fn_array[n_strings] = fn_composite
            bool_percent = 0
        }
        bool_script = 0
    }
    n_strings++
    return no_error
}
function expand_meta(strno)
{
    if (tab[strno] == 0) {
        n_strings = 0
        return error
    } else if (tab[strno] >= 2 && tab[strno] <= 17) {
        fn_array[n_strings] = fn_others
        str_array[n_strings] = dec2oct(tab[strno])
    } else if (tab[strno] >= 500) {
        fn_array[n_strings] = fn_symbol
        str_array[n_strings] = dec2oct(tab[strno]-500)
    } else {
        fn_array[n_strings] = fn_composite
        str_array[n_strings] = dec2oct(tab[strno])
    }

    return no_error
}
function dec2oct(dec) {
    return sprintf("\\%03o", dec)
}
function reencode_font() {
    print "/reencsmalldict 12 dict def"
    print "/ReEncodeSmall"
    print "{ reencsmalldict begin"
    print "  /newcodesandnames exch def"
    print "  /newfontname exch def"
    print "  /basefontname exch def"
    print "  /basefontdict basefontname findfont def"
    print "  /newfont basefontdict maxlength dict def"
    print ""
    print "  basefontdict"
    print "  { exch dup /FID ne"
    print "    { dup /Encoding eq"
    print "      { exch dup length array copy"
    print "        newfont 3 1 roll put }"
    print "      { exch newfont 3 1 roll put }"
    print "      ifelse"
    print "    }"
    print "    { pop pop }"
    print "    ifelse"
    print "  } forall"
    print ""
    print "  newfont /FontName newfontname put"
    print "  newcodesandnames aload pop"
    print "  newcodesandnames length 2 idiv"
    print "  { newfont /Encoding get 3 1 roll put }"
    print "  repeat"
    print ""
    print "  newfontname newfont definefont pop"
    print "  end"
    print "} def"
    print ""
    print "/standardsymvec ["
    print "  8#022 /quoteleft"
    print "  8#023 /quoteright       8#024 /acute"
    print "  8#025 /grave            8#026 /breve"
    print "  8#027 /perthousand      8#030 /Aring"
    print "] def"
    print ""
    print "/OtherFont"
    print "8 dict begin"
    print "  /FontName 1 index def"
    print "  /FontType 3 def"
    print "  /FontMatrix [.001 0 0 .001 0 0] def"
    print "  /FontBBox [0 0 1000 1000] def"
    print "  /Encoding 256 array def"
    print "  0 1 255 { Encoding exch /.notdef put } for"
    print "  Encoding 2 /plus put"
    print "  Encoding 3 /asterisk put"
    print "  Encoding 4 /circle put"
    print "  Encoding 5 /cross put"
    print "  Encoding 6 /square put"
    print "  Encoding 7 /triangle put"
    print "  Encoding 8 /lozenge put"
    print "  Encoding 9 /star put"
    print "  Encoding 10 /bullet put"
    print "  Encoding 11 /blacksquare put"
    print "  Encoding 12 /blacktriangleup put"
    print "  Encoding 13 /blacktriangleleft put"
    print "  Encoding 14 /blacktriangledown put"
    print "  Encoding 15 /blacktriangleright put"
    print "  Encoding 16 /blackstar put"
    print "  Encoding 17 /flag put"
    print "  /CharProcs 18 dict def"
    print "  CharProcs begin"
    print "    /.notdef {} def"
    print "    /plus"
    print "    { 0 setlinecap"
    print "      500 365 moveto 500 635 lineto 20 setlinewidth stroke"
    print "      365 500 moveto 635 500 lineto 20 setlinewidth stroke } bind def"
    print "    /asterisk"
    print "    { 0 setlinecap"
    print "      500 365 moveto 500 635 lineto 20 setlinewidth stroke"
    print "      383 437.5 moveto 617 572.5 lineto 20 setlinewidth stroke"
    print "      383 572.5 moveto 617 437.5 lineto 20 setlinewidth stroke"
    print "    } bind def"
    print "    /circle"
    print "    { newpath 500 500 135 0 360 arc"
    print "      20 setlinewidth closepath stroke } bind def"
    print "    /cross"
    print "    { 0 setlinecap"
    print "      365 365 moveto 635 635 lineto 20 setlinewidth stroke"
    print "      365 635 moveto 635 365 lineto 20 setlinewidth stroke } bind def"
    print "    /square"
    print "    { 365 365 moveto 635 365 lineto 635 635 lineto"
    print "      365 635 lineto 20 setlinewidth"
    print "      0 setlinejoin closepath stroke } bind def"
    print "    /triangle"
    print "    { 365 365 moveto 500 599 lineto 635 365 lineto"
    print "      0 setlinejoin 20 setlinewidth closepath stroke } bind def"
    print "    /lozenge"
    print "    { 370.5 500 moveto 500 635 lineto"
    print "      629.5 500 lineto 500 365 lineto 20 setlinewidth"
    print "      0 setlinejoin closepath stroke } bind def"
    print "    /star"
    print "    { 500 635 moveto 465 533 lineto 365 533 lineto 449 465 lineto"
    print "      413 365 lineto 500 433 lineto 581 365 lineto 546 465 lineto"
    print "      635 533 lineto 530 533 lineto"
    print "      20 setlinewidth 0 setlinejoin closepath stroke } bind def"
    print "    /bullet"
    print "    { newpath 500 500 135 0 360 arc"
    print "      closepath fill } bind def"
    print "    /blacksquare"
    print "    { 365 365 moveto 635 365 lineto 635 635 lineto"
    print "      365 635 lineto 20 setlinewidth"
    print "      0 setlinejoin closepath fill } bind def"
    print "    /blacktriangleup"
    print "    { 365 365 moveto 500 599 lineto 635 365 lineto"
    print "      0 setlinejoin 20 setlinewidth closepath fill } bind def"
    print "    /blacktriangleleft"
    print "    { 401 500 moveto 635 635 lineto 635 365 lineto"
    print "      closepath fill } bind def"
    print "    /blacktriangledown"
    print "    { 365 635 moveto 635 635 lineto 500 401 lineto"
    print "      closepath fill } bind def"
    print "    /blacktriangleright"
    print "    { 365 635 moveto 599 500 lineto 365 365 lineto"
    print "      closepath fill } bind def"
    print "    /blackstar"
    print "    { 500 635 moveto 465 533 lineto 365 533 lineto 449 465 lineto"
    print "      413 365 lineto 500 433 lineto 581 365 lineto 546 465 lineto"
    print "      635 533 lineto 530 533 lineto"
    print "      20 setlinewidth 0 setlinejoin closepath fill } bind def"
    print "    /flag"
    print "    { 500 365 moveto 500 635 lineto 20 setlinewidth stroke"
    print "      500 635 moveto"
    print "      634 576 lineto 500 517 lineto closepath fill } bind def"
    print "  end"
    print "  /BuildGlyph"
    print "  { 1000 0                  % string width"
    print "    125 125 875 875         % bounding box"
    print "    setcachedevice exch /CharProcs get exch"
    print "    2 copy known not { pop /.notdef }if"
    print "    get exec"
    print "  } bind def"
    print "  /BuildChar"
    print "  { 1 index /Encoding get exch get"
    print "    1 index /BuildGlyph get exec"
    print "  } bind def"
    print "  currentdict"
    print "end"
    print "definefont pop"
}

function make_cf(f) {
    print "/" f " /" f "-DCL standardsymvec ReEncodeSmall"
}

function set_font() {
    if (fno == fn_composite) {
        print "/" fon "-DCL findfont " sf " scalefont setfont"
    } else if (fno == fn_symbol) {
        sf = fwnc * rsize
        df = fhnc * rsize
        print "/Symbol" AI " findfont " sf " scalefont setfont"
    } else if (fno == fn_others) {
        sf = fwnc * rsize
        df = fhnc * rsize
        print "/OtherFont findfont " sf " scalefont setfont"
    }
}

function print_usage() {
    if (ENVIRON["PAGER"] != "")
        filt = "sort -f | " ENVIRON["PAGER"]
    else
        filt = "sort -f | more"

    print "  " ID,DATE | filt
    print " --- " EX | filt
    print " usage : " USAGE | filt

    print "*** Options are:" | filt
    for (i in q) printf("+ %8s : %s\n", i, q[i]) | filt

    print "+** Font id are:" | filt
    for (i in font)
        if(match(i, "[A-Z]")) 
            printf("- %1s ::  %s\n", i, font[i]) | filt
        else
            printf("- %1s :   %s\n", i, font[i]) | filt
    exit
}
