#! @@AWK@@ -f

BEGIN {
  ID    = "dclpsfont 1.0"
  DATE  = "2003/02/03 (T.Kagimoto; original code is by A.Numaguchi)"
  EX    = "convert dcl.ps characters into PostScript font"
  USAGE = "dclpsfont [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
  # 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 = ""
}
#-----------------------------------------------------------------------
# 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
}
/^%%Begin SZTX / {
    print
    sub("\\[", "", $3)
    sub( "\"", "", $8); 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
}
/^%%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_meta()

    linbound = 0
    if (retval == 0) {
        while ($0 != "%%End SZTXZ") {
            getline
            print
        }
        next
    } else {
        while ($0 != "%%End SZTXZ") {
            getline
            if ($NF == "W" || $NF == "RGB") {
                print
            } else if ($NF == "N") {
                getline
                linbound = 0
                if ($0 ~ /[0-9]*[LM]/) linbound = 1
            }
        }
    }
    if (linbound) { 
        if (retval == 1) {
            print "/" fon "-DCL findfont " sf " scalefont setfont"
        } else if (retval == 3) {
            sf = fwnc * rsize
            df = fhnc * rsize
            print "/Symbol" AI " findfont " sf " scalefont setfont"
        } else if (retval == 2) {
            sf = fwnc * rsize
            df = fhnc * rsize
            print "/OtherFont findfont " sf " scalefont setfont"
        }
        print "gsave"
        print "/sw 0 def"     
        print x " " y " moveto"
        print r+rot " rotate"
        if (cent != -1) {
            s = str
            while (s != "") {
                expand_sub()
                print "/str (" sx ") def"
                print "/sw sw str stringwidth pop add def"
                if (sup != 0) {
                    print "/str (" sy ") def"
                    print "/sw sw str stringwidth pop fsm mul add def"
                }
            }
            if (cent == 0) print "sw 2 div neg 0 rmoveto"
            if (cent == 1) print "sw neg 0 rmoveto"
        }

        print 0,-df/2 " rmoveto"

        s = str
        while (s != "") {
            expand_sub()
            print "/str (" sx ") def"
            print "str show"
            if (sup != 0) {
                print "/str (" sy ") def"
                print "gsave"
                if (sup == 1)
                    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_meta()
{
    ispr = 1
    while (i = match(str, "%[0-9][0-9][0-9]")) {
        j = substr(str, i+1, 3)
        if (tab[j+0] == 0)
            ispr = 0
        else if (tab[j+0] >= 2 && tab[j+0] <= 17)
            ispr = 2
        else if (tab[j+0] >= 500)
            ispr = 3
        else
            ispr = 1
        jj = "%" j
        if (ispr == 3) tab[j+0] -= 500
        h = dec2oct(tab[j+0])
        sub(jj, h, str)
    }

    if (ispr == 3 && str ~ /.*[a-z]+.*/) ispr = 0     # complex string will be left as it is

    return ispr
}
function dec2oct(dec) {
    return sprintf("\\%03o", dec)
}
function expand_sub() {
    u = index(s, isup)
    d = index(s, isub)
    t = index(s, irst)
    if (lcntl && u > 0 && (d == 0 || d > u)) {
        sx = substr(s, 1, u-1)
        if (t < u+1) t = length(s)
        sy = substr(s, u+1, t-u-1)
        sup = 1
        if (t < length(s))
            s = substr(s, t+1)
        else
            s = ""
    } else if (lcntl && d > 0 && (u == 0 || u < d)) {
        sx = substr(s, 1, d-1)
        if (t < d+1) t = length(s)
        sy = substr(s, d+1, t-d-1)
        sup = -1
        if (t < length(s))
            s = substr(s, t+1)
        else
            s = ""
      } else {
        sx = s
        sup = 0
        sy = ""
        s = ""
    }
}
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 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
}
