pkg://t1accent-19980521-3.src.rpm:91402/t1accent.tar.gz
info downloads
t1accent/ 40755 150 144 0 6530761471 11047 5 ustar olsak math1 t1accent/README 100666 150 144 5015 6530761115 12024 0 ustar olsak math1
Program t1accent -- pridavani akcentu na urovni Type1 formatu fontu (pfb)
=========================================================================
Petr Olsak <olsak@math.feld.cvut.cz> 11.4.1998
Tento program je free software, muzete jej dale distribuovat nebo
modifikovat podle podminek GNU General Public License, ktera byla
publikovana Free Software Foundation; bud ve verzi 2 teto licence nebo
(podle Vasi volby) libovolne pozdejsi verze.
Tento program je distribuovan s pranim, aby byl uzitecny, ale
BEZ ZADNE ZARUKY. Podrobneji viz GNU General Public License, soubor
COPYING.
Mel byste dostat kopii GNU General Public License spolecne s timto
programem. Protoze se jedna o licenci navrzenou Americkou
Free Software Foundation, Inc., (59 Temple Place, Suite 330, Boston, MA
02111-1307 USA), je tato licnece pouze v anglickem jazyce.
Vystupy z programu (upravene fonty) se samozrejme ridi licenci
puvodnich fontu.
Obsah balicku:
--------------
README ... tento soubor
README.eng ... anglicka varianta souboru README
COPYING ... plne zneni GNU General Public License
t1accent.doc ... dokumentace k programu
t1accent.eng ... anglicka dokumentace k programu
t1accent.c ... zdrojovy soubor k programu
t1accent.exe ... behova forma programu pro DOS
Makefile ... soubor pro instalaci programu na UNIXu
*.tab ... konfiguracni soubory k programu, pouzite na vytvoreni
pfb formatu CSfontu
*.enc ... kodovaci soubory pro CSfonty
Instalace
---------
1. Na UNIXu.
Program vyzaduje gcc kompilator.
make
su
make install
make zkompiluje program t1accent do behove podoby a make install
instaluje jediny soubor (binarni t1accent) do /usr/local/bin.
2. Na DOSu.
Zkopirujte si t1accent.exe mezi ostatni *.exe programy.
Provoz programu
---------------
Viz soubor t1accent.doc nebo t1accent.eng.
Primarni zdroj
--------------
ftp://math.feld.cvut.cz/pub/olsak/t1accent/
viz tez
http://math.feld.cvut.cz/olsak/
Pro provoz programu je take potreba t1asm z baliku t1utils, ktery
napsal I. Lee Hetherington, viz:
CTAN/fonts/utilities/t1utils/
Doporucuji durazne pred kompilaci programu t1asm zmenit radek 244
zdrojoveho t1asm.c z puvodniho:
for (i = 0; i < 7; i++) {
na
for (i = 0; i < 8; i++) {
Je totiz nutne, aby program t1asm generoval pfb format, na jehoz konci
je 8 radku nul (nikoli jen 7). 8 radku nul je pozadovano ve
specifikaci Adobe Type1 formatu. Je-li ve vyslednem fontu jen 7 radku
nul, muze nahodne nektery PostScriptovy RIP havarovat.
t1accent/csr.enc 100666 150 144 3761 6530761307 12433 0 ustar olsak math1 % CSfont encoding, csr10, 9, 8, 7, 6, 12, 17, csbx10, 12, etc...
/il2Encoding [
/Gamma /Delta /Theta /Lambda /Xi /Pi /Sigma /Upsilon
/Phi /Psi /Omega /ff /fi /fl /ffi /ffl
/dotlessi /dotlessj /grave /acute /caron /breve /macron /ring
/cedilla /germandbls /ae /oe /oslash /AE /OE /Oslash
/polishlcross /exclam /quotedblright /numbersign /dollar % /sterling
/percent /ampersand /quoteright
/parenleft /parenright /asterisk /plus /comma /hyphen /period /slash
/zero /one /two /three /four /five /six /seven
/eight /nine /colon /semicolon /exclamdown /equal /questiondown /question
/at /A /B /C /D /E /F /G
/H /I /J /K /L /M /N /O
/P /Q /R /S /T /U /V /W
/X /Y /Z /bracketleft /quotedblleft /bracketright /circumflex /dotaccent
/quoteleft /a /b /c /d /e /f /g
/h /i /j /k /l /m /n /o
/p /q /r /s /t /u /v /w
/x /y /z /endash /emdash /hungarumlaut /tilde /dieresis
/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
/.notdef /.notdef /.notdef /.notdef /.notdef /perthousand /.notdef /.notdef
/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
/Agrave /.notdef /.notdef /.notdef /althyphen /ogonek /guillemotleft /guillemotright
/.notdef /.notdef /.notdef /.notdef /.notdef /Lcaron /.notdef /.notdef
/.notdef /Scaron /.notdef /Tcaron /.notdef /.notdef /Zcaron /.notdef
/.notdef /.notdef /.notdef /.notdef /.notdef /lcaron /.notdef /.notdef
/agrave /scaron /.notdef /tcaron /.notdef /.notdef /zcaron /.notdef
/Racute /Aacute /.notdef /.notdef /Adieresis /Lacute /.notdef /.notdef
/Ccaron /Eacute /.notdef /.notdef /Ecaron /Iacute /.notdef /Dcaron
/.notdef /.notdef /Ncaron /Oacute /Ocircumflex /.notdef /Odieresis /.notdef
/Rcaron /Uring /Uacute /.notdef /Udieresis /Yacute /.notdef /.notdef
/racute /aacute /.notdef /.notdef /adieresis /lacute /.notdef /.notdef
/ccaron /eacute /.notdef /.notdef /ecaron /iacute /.notdef /dcaron
/.notdef /.notdef /ncaron /oacute /ocircumflex /.notdef /odieresis /.notdef
/rcaron /uring /uacute /.notdef /udieresis /yacute /quotedblbase /csquotedblright
] def
t1accent/csr.tab 100666 150 144 26653 6530016760 12455 0 ustar olsak math1
% This is a configuration file for t1accent program
% (c) Petr Olsak April 1998
% This configuration file was used for generation CSfonts in pfb format
% from BaKoMa CM fonts:
REM "CSfonts -- pfb ver.Apr.1998, generated from BaKoMa fonts. NO WARRANTY."
REM "Accents are added using t1accent program, (c) Petr Olsak, 1998"
% The set of fonts generated with the same configuration file:
IN cmr10 cmr12 cmr17 cmr9 cmr8 cmr7 cmr6
NAME cmr -> csr
ENC csr
% When cmr5 font is generated, we have to use different encoding vector:
% IN cmr5
% NAME cmr -> csr
% ENC csr1
% The csu has the same encoding vector as csr because the sterling
% character has the name /dollar in BaKoMa fonts
% IN cmu10
% NAME cmu -> csu
% ENC csr
SRC /usr/local/share/texmf/fonts/type1/public/cm/
% Many parts of this configuration file were copied from METAPOST output
% on csr10 with ljfour mode:
% mpost '&mfplain \mode=ljfour; input csr10'
VAR /factor 100 def % scale factor from ljfour mode to Type1
% coordinate system
VAR /capshift 240 def % The shift of dieresis for uppercase letters
SUB /lc-caron { % source from MPost output, code 232
factor factor scaled
0.8877 6.58267 moveto
2.41693 4.96025 lineto
3.94618 6.58267 lineto
3.81114 6.72845 lineto
2.41693 5.64326 lineto
1.02274 6.72845 lineto
closepath
}
SUB /lc-grave { % source from MPost output, code 184
factor factor scaled
1.70787 6.3322 moveto
3.20189 5.09796 lineto
3.34709 5.23363 lineto
2.21706 6.80794 lineto
1.90622 7.241 1.2969 6.67172 1.70787 6.3322 curveto closepath
}
SUB /lc-acute { % source from MPost output, code 225
factor factor scaled
3.0199 6.80794 moveto
1.88986 5.23361 lineto
2.03506 5.09796 lineto
3.52908 6.3322 lineto
3.94005 6.67172 3.33073 7.241 3.0199 6.80794 curveto
closepath
}
SUB /lc-cflex { % source from MPost output, code 244
factor factor scaled
1.01884 4.9843 moveto
2.48067 5.87569 lineto
3.94247 4.9843 lineto
4.06299 5.14232 lineto
2.48067 6.57254 lineto
0.89833 5.14232 lineto
closepath
}
SUB /lc-ring { % source from MPost output, code 249
factor factor scaled
2.81273 6.91849 moveto
2.55664 6.91849 2.31104 6.81676 2.12994 6.63567 curveto
1.94887 6.45459 1.84714 6.20898 1.84714 5.9529 curveto
1.84714 5.6968 1.94887 5.45119 2.12994 5.27011 curveto
2.31104 5.08902 2.55664 4.98729 2.81273 4.98729 curveto
3.06882 4.98729 3.31442 5.08902 3.49551 5.27011 curveto
3.67659 5.45119 3.77832 5.6968 3.77832 5.9529 curveto
3.77832 6.20898 3.67659 6.45459 3.49551 6.63567 curveto
3.31442 6.81676 3.06882 6.91849 2.81273 6.91849 curveto closepath
2.81273 6.60907 moveto
2.98676 6.60907 3.15366 6.53993 3.27672 6.41687 curveto
3.39978 6.29382 3.4689 6.12692 3.4689 5.9529 curveto
3.4689 5.77885 3.39978 5.61195 3.27672 5.4889 curveto
3.15366 5.36584 2.98676 5.2967 2.81273 5.2967 curveto
2.6387 5.2967 2.4718 5.36584 2.34874 5.4889 curveto
2.22568 5.61195 2.15656 5.77885 2.15656 5.9529 curveto
2.15656 6.12692 2.22568 6.29382 2.34874 6.41687 curveto
2.4718 6.53993 2.6387 6.60907 2.81273 6.60907 curveto closepath
2.81273 6.91849 moveto
}
SUB /uc-grave { % source from MPost output, code 152
factor factor scaled
-4.63695 8.50084 moveto
-5.02283 8.81955 -5.4519 8.17175 -5.00792 7.94077 curveto
-3.01181 6.90231 lineto
-2.90207 7.068 lineto
closepath
}
SUB /uc-acute { % source from MPost output, code 193
factor factor scaled
4.63695 8.50084 moveto
2.90207 7.068 lineto
3.01181 6.90231 lineto
5.00792 7.94077 lineto
5.4519 8.17175 5.02283 8.81955 4.63695 8.50084 curveto closepath
}
SUB /uc-caron { % source from MPost output, code 200
factor factor scaled
2.62624 8.22226 moveto
4.14088 7.0448 lineto
5.65553 8.22226 lineto
5.54968 8.39043 lineto
4.14088 7.72781 lineto
2.73209 8.39043 lineto
closepath
}
SUB /uc-cflex { % source from MPost output, code 212
factor factor scaled
2.24478 7.46649 moveto
3.86436 7.95792 lineto
5.48393 7.46649 lineto
5.56567 7.64763 lineto
3.86436 8.65477 lineto
2.16306 7.64763 lineto
closepath
}
SUB /uc-ring { % source from MPost output, code 217
factor factor scaled
3.91917 8.40846 moveto
3.66309 8.40846 3.41748 8.30673 3.23639 8.12564 curveto
3.05531 7.94456 2.95358 7.69896 2.95358 7.44287 curveto
2.95358 7.18678 3.05531 6.94118 3.23639 6.76009 curveto
3.41748 6.57901 3.66309 6.47728 3.91917 6.47728 curveto
4.17526 6.47728 4.42087 6.57901 4.60194 6.76009 curveto
4.78304 6.94118 4.88477 7.18678 4.88477 7.44287 curveto
4.88477 7.69896 4.78304 7.94456 4.60194 8.12564 curveto
4.42087 8.30673 4.17526 8.40846 3.91917 8.40846 curveto closepath
3.91917 8.09904 moveto
4.0932 8.09904 4.2601 8.0299 4.38316 7.90686 curveto
4.50621 7.7838 4.57535 7.6169 4.57535 7.44287 curveto
4.57535 7.26884 4.50621 7.10194 4.38316 6.97888 curveto
4.2601 6.85582 4.0932 6.7867 3.91917 6.7867 curveto
3.74515 6.7867 3.57825 6.85582 3.45518 6.97888 curveto
3.33212 7.10194 3.263 7.26884 3.263 7.44287 curveto
3.263 7.6169 3.33212 7.7838 3.45518 7.90686 curveto
3.57825 8.0299 3.74515 8.09904 3.91917 8.09904 curveto closepath
3.91917 8.40846 moveto
}
SUB /sub-comma { % source from cm*.pfb, /comma, scaled
-50 520 rmoveto
1 .666 scaled
-6 8 -8 7 vhcurveto
2 0 2 1 2 1 rrcurveto
53 52 32 69 0 75 rrcurveto
1 1.5 scaled
42 -13 64 -53 vhcurveto
-31 -24 -24 -31 hvcurveto
-31 24 -24 31 vhcurveto
15 0 14 5 11 11 rrcurveto
0 -4 0 -4 0 -4 rrcurveto
1 .666 scaled
0 -67 -28 -63 -48 -46 rrcurveto
-2 -2 -2 -3 0 -3 rrcurveto
closepath
}
SUB /percent-zero { % source from cm*.pfb, /percent
-197 -55 rmoveto
93 36 126 76 hvcurveto
75 -36 126 -93 vhcurveto
-100 -48 -117 -84 hvcurveto
-85 48 -117 100 vhcurveto
closepath
26 vmoveto
-75 -7 122 53 hvcurveto
52 6 124 76 vhcurveto
74 26 -118 -57 hvcurveto
-58 -26 -118 -74 vhcurveto
closepath
-26 vmoveto
}
SUB /dot-dieresis { % source from cm*.pfb, subroutine for /dieresis
-28 23 -24 29 vhcurveto
28 24 24 28 hvcurveto
28 -24 24 -28 vhcurveto
-29 -23 -24 -28 hvcurveto
closepath
}
SUB /s-dieresis {
557 vmoveto
160 vvaxis % 216/2 + diameter of a dot
dot-dieresis callsubr
216 hmoveto
dot-dieresis callsubr
}
SUB /U-dieresis { % For Udiereis
567 vmoveto
248 vvaxis
dot-dieresis callsubr
392 hmoveto
dot-dieresis callsubr
}
SUB /guill-left { % source from MPost output, code 158
factor factor scaled
2.53435 4.71841 moveto
2.23581 3.8509 1.74669 3.06131 1.10294 2.40764 curveto
1.74669 1.75397 2.23581 0.96437 2.53435 0.09686 curveto
2.59138 -0.06885 2.78053 -0.00386 2.75735 0.09686 curveto
2.569 0.91504 2.24536 1.69604 1.79979 2.40764 curveto
2.24536 3.11923 2.569 3.90024 2.75735 4.71841 curveto
2.78053 4.81914 2.59138 4.88412 2.53435 4.71841 curveto closepath
}
SUB /guill-right { % source from MPost output, code 159
factor factor scaled
2.75745 4.71841 moveto
2.9458 3.90024 3.26944 3.11923 3.71501 2.40764 curveto
3.26944 1.69604 2.9458 0.91504 2.75745 0.09686 curveto
2.73425 -0.00386 2.92342 -0.06885 2.98044 0.09686 curveto
3.27899 0.96437 3.76811 1.75397 4.41185 2.40764 curveto
3.76811 3.06131 3.27899 3.8509 2.98044 4.71841 curveto
2.92342 4.88412 2.73425 4.81914 2.75745 4.71841 curveto closepath
}
CHAR /Aacute /A /uc-acute 0 0 putcenter
CHAR /Adieresis /A /s-dieresis 0 capshift putcenter
CHAR /Agrave /A /uc-grave 0 0 putcenter
CHAR /aacute /a /lc-acute 20 0 putcenter
CHAR /adieresis /a /s-dieresis 0 0 putcenter
CHAR /agrave /a /lc-grave 0 0 putcenter
CHAR /Ccaron /C /uc-caron 60 0 putcenter
CHAR /ccaron /c /lc-caron 30 0 putcenter
CHAR /Dcaron /D /uc-caron -55 0 putcenter
CHAR /dcaron /d /sub-comma 0 0 putafter
CHAR /Ecaron /E /uc-caron 0 0 putcenter
CHAR /Eacute /E /uc-acute 20 0 putcenter
CHAR /ecaron /e /lc-caron 20 0 putcenter
CHAR /eacute /e /lc-acute 50 0 putcenter
CHAR /Iacute /I /uc-acute 0 0 putcenter
CHAR /iacute /dotlessi /lc-acute 0 0 putcenter
CHAR /Lcaron /L /sub-comma 150 0 putcenter
CHAR /Lacute /L /uc-acute 0 0 putcenter
CHAR /lcaron /l /sub-comma 0 0 putafter
CHAR /lacute /l /uc-acute 0 0 putcenter
CHAR /Ncaron /N /uc-caron 0 0 putcenter
CHAR /ncaron /n /lc-caron 0 0 putcenter
CHAR /Ocircumflex /O /uc-cflex 0 0 putcenter
CHAR /Odieresis /O /s-dieresis 0 capshift putcenter
CHAR /Oacute /O /uc-acute 20 10 putcenter
CHAR /ocircumflex /o /lc-cflex 0 0 putcenter
CHAR /odieresis /o /s-dieresis 0 0 putcenter
CHAR /oacute /o /lc-acute 60 0 putcenter
CHAR /Rcaron /R /uc-caron -55 0 putcenter
CHAR /Racute /R /uc-acute 0 0 putcenter
CHAR /rcaron /r /lc-caron 0 0 putcenter
CHAR /racute /r /lc-acute 0 0 putcenter
CHAR /Scaron /S /uc-caron 0 0 putcenter
CHAR /scaron /s /lc-caron 0 0 putcenter
CHAR /Tcaron /T /uc-caron 0 0 putcenter
CHAR /tcaron /t /sub-comma 90 0 putcenter
CHAR /Udieresis /U /U-dieresis 0 capshift putcenter
CHAR /Uring /U /uc-ring 20 0 putcenter
CHAR /Uacute /U /uc-acute 0 0 putcenter
CHAR /udieresis /u /s-dieresis 0 0 putcenter
CHAR /uring /u /lc-ring 0 0 putcenter
CHAR /uacute /u /lc-acute 0 0 putcenter
CHAR /Yacute /Y /uc-acute 0 0 putcenter
CHAR /yacute /y /lc-acute 0 2 putcenter
CHAR /Zcaron /Z /uc-caron 0 0 putcenter
CHAR /zcaron /z /lc-caron 0 0 putcenter
CHAR /perthousand /percent 0 0 333 correct
/percent-zero 0 0 putafter
BBOX 0 0 1111 0 % perthousand is the most wide character
CHAR /quotedblbase /quotedblright 100 -589 0 correct /.noinsert
CHAR /csquotedblright /quotedblleft -100 0 0 correct /.noinsert
CHAR /guillemotleft {
0 10000 18 div
hsbw
-50 hmoveto
guill-left callsubr
160 hmoveto
guill-left callsubr
endchar
}
CHAR /guillemotright {
0 10000 18 div
hsbw
-150 hmoveto
guill-right callsubr
160 hmoveto
guill-right callsubr
endchar
}
CHAR /ogonek { % source from MPost output, code 157
0 8000 18 div hsbw
factor factor scaled
2.91527 0.27509 moveto
2.75847 0.06808 2.5632 -0.2994 2.47942 -0.54518 curveto
2.36871 -0.86987 2.37071 -1.22849 2.5418 -1.52486 curveto
2.71553 -1.82579 3.04385 -2.01228 3.38138 -1.94936 curveto
3.79468 -1.87231 4.2983 -1.40714 4.40784 -1.00124 curveto
4.2344 -0.8557 lineto
4.14986 -1.1711 3.70605 -1.47543 3.38138 -1.44069 curveto
3.19162 -1.42038 3.04582 -1.27519 2.96802 -1.09863 curveto
2.89162 -0.92528 2.87985 -0.73207 2.91058 -0.54518 curveto
2.94463 -0.3382 3.04984 -0.01895 3.14554 0.16771 curveto
2.91527 0.27509 lineto
}
% dvips has a bug: it is impossible to have the two same names in the
% Encoding vector:
CHAR /althyphen /hyphen /.noinsert
% End of configuration file
t1accent/csti.tab 100666 150 144 30041 6530761226 12616 0 ustar olsak math1
% This is a configuration file for t1accent program
% (c) Petr Olsak April 1998
% This configuration file was used for generation CSfonts in pfb format
% from BaKoMa CM fonts:
REM "CSfonts -- pfb ver.Apr.1998, generated from BaKoMa fonts. NO WARRANTY."
REM "Accents are added using t1accent program, (c) Petr Olsak, 1998"
% The set of fonts generated with the same configuration file:
IN cmti10 cmti12 cmti9 cmti8 cmti7
NAME cmti -> csti
ENC csr % the /sterling is named as /dollar in BaKoMa fonts
SRC /usr/local/share/texmf/fonts/type1/public/cm/
% Many parts of this configuration file were copied from METAPOST output
% on csti10 with ljfour mode:
% mpost '&mfplain \mode=ljfour; input csti10'
VAR /factor 100 def % scale factor from ljfour mode to Type1
% coordinate system
VAR /capshift 240 def % The shift of dieresis for uppercase letters
SUB /lc-caron { % source from MPost output, code 232
factor factor scaled
2.82332 6.47057 moveto
-.2 vvaxis
3.76883 5.02779 lineto
3.80063 4.97925 3.87686 4.97925 3.93294 5.02779 curveto
5.59984 6.47057 lineto
5.71756 6.57246 5.61653 6.71707 5.4899 6.63202 curveto
4.00215 5.63289 lineto
3.01399 6.63202 lineto
2.92989 6.71707 2.75655 6.57246 2.82332 6.47057 curveto closepath
}
SUB /lc-grave { % source from MPost output, code 184
factor factor scaled
3.03157 6.39104 moveto
-.5 vvaxis
4.07487 5.09445 lineto
4.1484 5.00308 4.32596 5.12668 4.27985 5.23712 curveto
3.62544 6.80444 lineto
3.4583 7.20476 2.76509 6.72221 3.03157 6.39104 curveto closepath
}
SUB /lc-acute { % source from MPost output, code 225
factor factor scaled
4.722 6.80444 moveto
-2.2 vvaxis
3.28394 5.23712 lineto
3.1826 5.12668 3.29836 5.00308 3.41756 5.09445 curveto
5.10916 6.39104 lineto
5.54123 6.72221 5.0893 7.20476 4.722 6.80444 curveto closepath
}
SUB /lc-cflex { % source from MPost output, code 244
factor factor scaled
2.53552 5.3518 moveto
0 vvaxis
4.10522 6.27698 lineto
5.21234 5.3518 lineto
5.30411 5.27513 5.46819 5.42767 5.39424 5.52289 curveto
4.33499 6.88707 lineto
4.30247 6.92894 4.23396 6.92894 4.18051 6.88707 curveto
2.43916 5.52289 lineto
2.31761 5.42767 2.40541 5.27513 2.53552 5.3518 curveto closepath
}
SUB /lc-ring { % source from MPost output, code 249
factor factor scaled
4.3929 6.91849 moveto
-1.6 vvaxis
4.15259 6.91849 3.89499 6.85056 3.68297 6.68094 curveto
3.47095 6.51132 3.34286 6.2707 3.28278 6.03038 curveto
3.2227 5.79007 3.23047 5.54945 3.35768 5.37984 curveto
3.4849 5.21022 3.70854 5.14229 3.94885 5.14229 curveto
4.18916 5.14229 4.44678 5.21022 4.65878 5.37984 curveto
4.8708 5.54945 4.9989 5.79007 5.05898 6.03038 curveto
5.11905 6.2707 5.11128 6.51132 4.98407 6.68094 curveto
4.85686 6.85056 4.63321 6.91849 4.3929 6.91849 curveto closepath
4.31555 6.60907 moveto
4.47395 6.60907 4.62679 6.57387 4.71057 6.46214 curveto
4.79437 6.35043 4.78915 6.1888 4.74956 6.03038 curveto
4.70996 5.87198 4.63434 5.71034 4.49469 5.59862 curveto
4.35506 5.48691 4.18462 5.4517 4.0262 5.4517 curveto
3.8678 5.4517 3.71497 5.48691 3.63118 5.59862 curveto
3.5474 5.71034 3.5526 5.87198 3.5922 6.03038 curveto
3.63179 6.1888 3.70741 6.35043 3.84706 6.46214 curveto
3.9867 6.57387 4.15714 6.60907 4.31555 6.60907 curveto closepath
}
SUB /uc-grave { % source from MPost output, code 152
factor factor scaled
5.51263 8.17542 moveto
-2 vvaxis
6.38731 7.3295 lineto
6.46077 7.25847 6.29266 7.27441 6.199 7.34769 curveto
5.08865 8.21637 lineto
4.8968 8.36647 5.31451 8.367 5.51263 8.17542 curveto closepath
}
SUB /uc-acute { % source from MPost output, code 193
factor factor scaled
6.69305 8.4725 moveto
-3 vvaxis
4.807 7.43762 lineto
4.67613 7.36581 4.7194 7.1924 4.85643 7.23956 curveto
6.83113 7.91927 lineto
7.30173 8.08125 7.14253 8.71915 6.69305 8.4725 curveto closepath
}
SUB /uc-caron { % source from MPost output, code 200
factor factor scaled
4.69678 8.0546 moveto
-.5 vvaxis
5.7573 7.07188 lineto
5.78929 7.04222 5.84357 7.04222 5.8904 7.07188 curveto
7.44228 8.0546 lineto
7.5674 8.13383 7.51251 8.2973 7.37946 8.24472 curveto
5.97867 7.69115 lineto
4.85466 8.24472 lineto
4.7479 8.2973 4.61127 8.13383 4.69678 8.0546 curveto closepath
}
SUB /uc-cflex { % source from MPost output, code 212
factor factor scaled
4.15549 7.36937 moveto
-0.5 vvaxis
5.76456 7.82231 lineto
7.14714 7.36937 lineto
7.26346 7.33127 7.38249 7.5057 7.28456 7.5714 curveto
5.9764 8.44908 lineto
5.94714 8.4687 5.90515 8.4687 5.8661 8.44908 curveto
4.11908 7.5714 lineto
3.98831 7.5057 4.02013 7.33127 4.15549 7.36937 curveto closepath
}
SUB /uc-ring { % source from MPost output, code 217
factor factor scaled
5.97255 8.40846 moveto
-2.2 vvaxis
5.737 8.40846 5.48772 8.3149 5.27953 8.14835 curveto
5.07135 7.9818 4.92131 7.7559 4.86243 7.52037 curveto
4.80354 7.28482 4.84064 7.05893 4.96555 6.89238 curveto
5.09045 6.72583 5.29295 6.63226 5.52849 6.63226 curveto
5.76404 6.63226 6.01332 6.72583 6.2215 6.89238 curveto
6.42969 7.05893 6.57973 7.28482 6.63861 7.52037 curveto
6.6975 7.7559 6.6604 7.9818 6.53549 8.14835 curveto
6.41058 8.3149 6.20808 8.40846 5.97255 8.40846 curveto closepath
5.89519 8.09904 moveto
6.04866 8.09904 6.18062 8.03807 6.26201 7.92955 curveto
6.3434 7.82103 6.36757 7.67384 6.3292 7.52037 curveto
6.29083 7.36688 6.19307 7.2197 6.0574 7.11118 curveto
5.92175 7.00266 5.75932 6.94168 5.60585 6.94168 curveto
5.45238 6.94168 5.32042 7.00266 5.23903 7.11118 curveto
5.15764 7.2197 5.13347 7.36688 5.17184 7.52037 curveto
5.2102 7.67384 5.30797 7.82103 5.44362 7.92955 curveto
5.57928 8.03807 5.74171 8.09904 5.89519 8.09904 curveto closepath
}
SUB /sub-comma { % source from cm*.pfb, /comma, scaled
50 500 rmoveto
-70 vvaxis
1 .8 scaled
2 0 2 1 2 1 rrcurveto
68 54 67 97 0 90 rrcurveto
1 1.25 scaled
30 -12 31 -35 vhcurveto
-36 -32 -31 -36 hvcurveto
-26 20 -17 25 vhcurveto
14 0 14 5 12 8 rrcurveto
1 .8 scaled
-16 -73 -47 -66 -58 -46 rrcurveto
-2 -2 -1 -3 0 -3 rrcurveto
-6 6 -8 7 vhcurveto
closepath
}
SUB /percent-zero { % source from cm*.pfb, /percent
-250 -55 rmoveto
108 71 186 92 hvcurveto
51 -20 74 -63 vhcurveto
-114 -78 -172 -99 hvcurveto
-58 26 -74 70 vhcurveto
closepath
1 26 rmoveto
-36 -7 47 27 hvcurveto
66 50 211 86 vhcurveto
42 8 -64 -31 hvcurveto
0 -54 -15 -55 -24 -48 rrcurveto
-18 -36 -40 -63 -46 0 rrcurveto
closepath
}
SUB /dot-dieresis { % source from cm*.pfb, subroutine for /dieresis
-28 23 -24 29 vhcurveto
28 24 24 28 hvcurveto
28 -24 24 -28 vhcurveto
-29 -23 -24 -28 hvcurveto
closepath
}
SUB /s-dieresis {
557 vmoveto
0 vvaxis % 216/2 + diameter of a dot
dot-dieresis callsubr
170 hmoveto
dot-dieresis callsubr
}
SUB /U-dieresis { % For Udiereis
567 vmoveto
0 vvaxis
dot-dieresis callsubr
310 hmoveto
dot-dieresis callsubr
}
SUB /guill-left { % source from MPost output, code 158
factor factor scaled
3.74707 4.71841 moveto
3.2677 3.8657 2.62851 3.07845 1.87091 2.40764 curveto
2.2931 1.73683 2.53867 0.94957 2.59169 0.09686 curveto
2.60202 -0.0693 2.81082 -0.00749 2.81482 0.09686 curveto
2.84598 0.90813 2.74396 1.68773 2.5124 2.40764 curveto
3.10391 3.12755 3.59573 3.90715 3.97021 4.71841 curveto
4.01839 4.82277 3.84048 4.88457 3.74707 4.71841 curveto closepath
}
SUB /guill-right { % source from MPost output, code 159
factor factor scaled
3.97015 4.71841 moveto
3.939 3.90715 4.04102 3.12755 4.27257 2.40764 curveto
3.68106 1.68773 3.18924 0.90813 2.81476 0.09686 curveto
2.76659 -0.00749 2.94449 -0.0693 3.0379 0.09686 curveto
3.51727 0.94957 4.15646 1.73683 4.91406 2.40764 curveto
4.49187 3.07845 4.2463 3.8657 4.19328 4.71841 curveto
4.18295 4.88457 3.97417 4.82277 3.97015 4.71841 curveto closepath
}
CHAR /Aacute /A /uc-acute 0 0 putcenter
CHAR /Adieresis /A /s-dieresis 50 capshift putcenter
CHAR /Agrave /A /uc-grave 0 0 putcenter
CHAR /aacute /a /lc-acute 20 0 putcenter
CHAR /adieresis /a /s-dieresis 0 0 putcenter
CHAR /agrave /a /lc-grave 0 0 putcenter
CHAR /Ccaron /C /uc-caron 60 0 putcenter
CHAR /ccaron /c /lc-caron 30 0 putcenter
CHAR /Dcaron /D /uc-caron -55 0 putcenter
CHAR /dcaron /d /sub-comma 0 0 putafter
CHAR /Ecaron /E /uc-caron 0 0 putcenter
CHAR /Eacute /E /uc-acute 20 0 putcenter
CHAR /ecaron /e /lc-caron 20 0 putcenter
CHAR /eacute /e /lc-acute 50 0 putcenter
CHAR /Iacute /I /uc-acute 0 0 putcenter
CHAR /iacute /dotlessi /lc-acute 0 0 putcenter
CHAR /Lcaron /L /sub-comma 150 0 putcenter
CHAR /Lacute /L /uc-acute 0 0 putcenter
CHAR /lcaron /l /sub-comma 0 0 putafter
CHAR /lacute /l /uc-acute 0 0 putcenter
CHAR /Ncaron /N /uc-caron 0 0 putcenter
CHAR /ncaron /n /lc-caron 0 0 putcenter
CHAR /Ocircumflex /O /uc-cflex 0 0 putcenter
CHAR /Odieresis /O /s-dieresis 60 capshift putcenter
CHAR /Oacute /O /uc-acute 20 10 putcenter
CHAR /ocircumflex /o /lc-cflex 0 0 putcenter
CHAR /odieresis /o /s-dieresis 0 0 putcenter
CHAR /oacute /o /lc-acute 60 0 putcenter
CHAR /Rcaron /R /uc-caron -55 0 putcenter
CHAR /Racute /R /uc-acute 0 0 putcenter
CHAR /rcaron /r /lc-caron -20 0 putcenter
CHAR /racute /r /lc-acute 0 0 putcenter
CHAR /Scaron /S /uc-caron 0 0 putcenter
CHAR /scaron /s /lc-caron 0 0 putcenter
CHAR /Tcaron /T /uc-caron 0 0 putcenter
CHAR /tcaron /t /sub-comma 90 0 putcenter
CHAR /Udieresis /U /U-dieresis 0 capshift putcenter
CHAR /Uring /U /uc-ring 20 0 putcenter
CHAR /Uacute /U /uc-acute 0 0 putcenter
CHAR /udieresis /u /s-dieresis 0 0 putcenter
CHAR /uring /u /lc-ring 0 0 putcenter
CHAR /uacute /u /lc-acute 0 0 putcenter
CHAR /Yacute /Y /uc-acute 0 0 putcenter
CHAR /yacute /y /lc-acute 0 2 putcenter
CHAR /Zcaron /Z /uc-caron 0 0 putcenter
CHAR /zcaron /z /lc-caron 0 0 putcenter
CHAR /perthousand /percent 0 0 333 correct
/percent-zero 0 0 putafter
BBOX 0 0 1111 0 % perthousand is the most wide character
CHAR /quotedblbase /quotedblright -50 -589 0 correct /.noinsert
CHAR /csquotedblright /quotedblleft -100 0 0 correct /.noinsert
CHAR /guillemotleft {
0 10000 18 div
hsbw
-50 hmoveto
guill-left callsubr
150 hmoveto
guill-left callsubr
endchar
}
CHAR /guillemotright {
0 10000 18 div
hsbw
-150 hmoveto
guill-right callsubr
150 hmoveto
guill-right callsubr
endchar
}
CHAR /ogonek { % source from MPost output, code 157
0 8000 18 div hsbw
factor factor scaled
3.0892 0.3507 moveto
2.91359 0.14494 2.66704 -0.20552 2.5368 -0.43448 curveto
2.37033 -0.72716 2.26974 -1.04625 2.33884 -1.32022 curveto
2.40495 -1.58244 2.62724 -1.75932 2.92322 -1.71136 curveto
3.31334 -1.64815 3.85483 -1.1965 3.99263 -0.81938 curveto
3.9896 -0.81616 lineto
3.84193 -1.14627 3.31595 -1.48253 2.98672 -1.45729 curveto
2.78296 -1.44167 2.66602 -1.27835 2.63678 -1.08186 curveto
2.6063 -0.87694 2.66455 -0.6515 2.75766 -0.43448 curveto
2.84921 -0.22112 3.02847 0.11241 3.15968 0.31349 curveto
closepath
}
% dvips has a bug: it is impossible to have the two same names in the
% Encoding vector:
CHAR /althyphen /hyphen /.noinsert
% End of configuration file
t1accent/cstt.tab 100666 150 144 31303 6526001046 12623 0 ustar olsak math1
% This is a configuration file for t1accent program
% (c) Petr Olsak April 1998
% This configuration file was used for generation CSfonts in pfb format
% from BaKoMa CM fonts:
REM "CSfonts -- pfb ver.Apr.1998, generated from BaKoMa fonts. NO WARRANTY."
REM "Accents are added using t1accent program, (c) Petr Olsak, 1998"
% The set of fonts generated with the same configuration file:
IN cmtt10 cmtt12 cmtt9 cmtt8
NAME cmtt -> cstt
ENC cstt
SRC /usr/local/share/texmf/fonts/type1/public/cm/
% Many parts of this configuration file were copied from METAPOST output
% on cstt10 with ljfour mode:
% mpost '&mfplain \mode=ljfour; input cstt10'
VAR /factor 102 def % scale factor from ljfour mode to Type1
% coordinate system
VAR /capshift 240 def % The shift of dieresis for uppercase letters
SUB /lc-caron { % source from MPost output, code 232
factor factor scaled
1.35356 5.37851 moveto
2.5162 4.63626 lineto
2.60896 4.57704 2.72768 4.57704 2.82043 4.63626 curveto
3.98308 5.37851 lineto
4.31343 5.5894 4.00655 6.07751 3.68146 5.88084 curveto
2.66832 5.26794 lineto
1.65518 5.88084 lineto
1.3301 6.07751 1.02321 5.5894 1.35356 5.37851 curveto closepath
}
SUB /lc-grave { % source from MPost output, code 184
factor factor scaled
1.98543 5.42342 moveto
3.40361 4.83084 lineto
3.75163 4.68542 3.98558 5.19308 3.64893 5.36317 curveto
2.27707 6.05629 lineto
1.84694 6.27362 1.54077 5.6092 1.98543 5.42342 curveto closepath
}
SUB /lc-acute { % source from MPost output, code 225
factor factor scaled
3.38045 6.05629 moveto
2.00859 5.36317 lineto
1.67194 5.19308 1.90588 4.68542 2.2539 4.83084 curveto
3.67209 5.42342 lineto
4.11674 5.6092 3.81058 6.27362 3.38045 6.05629 curveto closepath
}
SUB /lc-cflex { % source from MPost output, code 244
factor factor scaled
1.1207 4.74454 moveto
2.60516 5.39142 lineto
4.08963 4.74454 lineto
4.43782 4.5928 4.67761 5.10942 4.33153 5.2782 curveto
2.72908 6.05966 lineto
2.65088 6.0978 2.55946 6.0978 2.48126 6.05966 curveto
0.87881 5.2782 lineto
0.53271 5.10942 0.7725 4.5928 1.1207 4.74454 curveto closepath
}
SUB /lc-ring { % source from MPost output, code 249
factor factor scaled
2.60516 6.08827 moveto
2.33072 6.08827 2.06754 5.97925 1.87347 5.7852 curveto
1.67941 5.59114 1.5704 5.32794 1.5704 5.05351 curveto
1.5704 4.77907 1.67941 4.51587 1.87347 4.32182 curveto
2.06754 4.12776 2.33072 4.01875 2.60516 4.01875 curveto
2.8796 4.01875 3.14279 4.12776 3.33685 4.32182 curveto
3.5309 4.51587 3.63992 4.77907 3.63992 5.05351 curveto
3.63992 5.32794 3.5309 5.59114 3.33685 5.7852 curveto
3.14279 5.97925 2.8796 6.08827 2.60516 6.08827 curveto closepath
2.60516 5.61934 moveto
2.75523 5.61934 2.89915 5.55972 3.00526 5.45361 curveto
3.11137 5.34749 3.17099 5.20357 3.17099 5.05351 curveto
3.17099 4.90344 3.11137 4.75952 3.00526 4.65341 curveto
2.89915 4.54729 2.75523 4.48767 2.60516 4.48767 curveto
2.4551 4.48767 2.31117 4.54729 2.20506 4.65341 curveto
2.09895 4.75952 2.03934 4.90344 2.03934 5.05351 curveto
2.03934 5.20357 2.09895 5.34749 2.20506 5.45361 curveto
2.31117 5.55972 2.4551 5.61934 2.60516 5.61934 curveto closepath
}
SUB /uc-grave { % source from /uc-acute, negate x-coordinate and reverse
factor factor scaled
2.1153 6.59407 moveto
3.5585 6.60803 lineto
3.94676 6.61179 3.94672 7.17253 3.58234 7.18349 curveto
2.23552 7.22395 lineto
1.7283 7.2392 1.75708 6.59059 2.1153 6.59407 curveto closepath
}
SUB /uc-acute { % source from MPost output, code 193
factor factor scaled
3.79266 7.2518 moveto
1.82646 6.83568 lineto
1.4544 6.75694 1.55615 6.20097 1.93198 6.25911 curveto
3.9181 6.56635 lineto
4.39021 6.63937 4.26003 7.35071 3.79266 7.2518 curveto closepath
}
SUB /uc-caron { % source from MPost output, code 200
factor factor scaled
1.57979 6.51971 moveto
2.74034 6.09322 lineto
2.80328 6.07008 2.8724 6.07008 2.93536 6.09322 curveto
4.0959 6.51971 lineto
4.45372 6.65121 4.27429 7.18521 3.91298 7.07623 curveto
2.83784 6.75197 lineto
1.76271 7.07623 lineto
1.4014 7.18521 1.22197 6.65121 1.57979 6.51971 curveto closepath
}
SUB /uc-cflex { % source from MPost output, code 212
factor factor scaled
0.91142 6.15277 moveto
2.60516 6.4465 lineto
4.29889 6.15277 lineto
4.67238 6.088 4.7851 6.64035 4.41515 6.727 curveto
2.66963 7.1359 lineto
2.62723 7.14583 2.5831 7.14583 2.54068 7.1359 curveto
0.79518 6.727 lineto
0.42523 6.64035 0.53793 6.088 0.91142 6.15277 curveto closepath
}
SUB /uc-ring { % source from MPost output, code 217
90 75 scaled
2.75719 7.27307 moveto
2.48276 7.27307 2.21956 7.16405 2.0255 6.96999 curveto
1.83144 6.77594 1.72243 6.51274 1.72243 6.2383 curveto
1.72243 5.96387 1.83144 5.70067 2.0255 5.50662 curveto
2.21956 5.31256 2.48276 5.20354 2.75719 5.20354 curveto
3.03162 5.20354 3.29482 5.31256 3.48888 5.50662 curveto
3.68292 5.70067 3.79195 5.96387 3.79195 6.2383 curveto
3.79195 6.51274 3.68292 6.77594 3.48888 6.96999 curveto
3.29482 7.16405 3.03162 7.27307 2.75719 7.27307 curveto closepath
2.75719 6.88217 moveto
2.92795 6.88217 3.09172 6.81433 3.21246 6.69359 curveto
3.33322 6.57285 3.40105 6.40907 3.40105 6.2383 curveto
3.40105 6.06754 3.33322 5.90376 3.21246 5.78302 curveto
3.09172 5.66228 2.92795 5.59444 2.75719 5.59444 curveto
2.58643 5.59444 2.42265 5.66228 2.3019 5.78302 curveto
2.18115 5.90376 2.11331 6.06754 2.11331 6.2383 curveto
2.11331 6.40907 2.18115 6.57285 2.3019 6.69359 curveto
2.42265 6.81433 2.58643 6.88217 2.75719 6.88217 curveto closepath
}
SUB /sub-comma { % source from cm*.pfb, /comma, scaled
-50 450 rmoveto
.8 .666 scaled
2 0 2 0 2 0 rrcurveto
76 23 54 63 0 81 rrcurveto
1 1.5 scaled
49 -32 52 -53 vhcurveto
-36 -29 -29 -35 hvcurveto
-37 29 -28 36 vhcurveto
2 0 3 0 3 0 rrcurveto
3 1 rlineto
6 1 rlineto
1 .666 scaled
-9 -39 -33 -31 -38 -9 rrcurveto
-12 -4 -9 -10 0 -14 rrcurveto
-17 16 -17 17 vhcurveto
closepath
}
SUB /percent-zero { % source from cm*.pfb, /percent
-197 -55 rmoveto
93 36 126 76 hvcurveto
75 -36 126 -93 vhcurveto
-100 -48 -117 -84 hvcurveto
-85 48 -117 100 vhcurveto
closepath
26 vmoveto
-75 -7 122 53 hvcurveto
52 6 124 76 vhcurveto
74 26 -118 -57 hvcurveto
-58 -26 -118 -74 vhcurveto
closepath
-26 vmoveto
}
SUB /dot-dieresis { % source from cm*.pfb, subroutine for /dieresis
-28 23 -24 29 vhcurveto
28 24 24 28 hvcurveto
28 -24 24 -28 vhcurveto
-29 -23 -24 -28 hvcurveto
closepath
}
SUB /s-dieresis {
557 vmoveto
160 vvaxis % 216/2 + diameter of a dot
dot-dieresis callsubr
216 hmoveto
dot-dieresis callsubr
}
SUB /uc-dieresis {
500 vmoveto
125 vvaxis
dot-dieresis callsubr
156 hmoveto
dot-dieresis callsubr
}
SUB /U-dieresis { % For Udiereis
500 vmoveto
198 vvaxis
dot-dieresis callsubr
292 hmoveto
dot-dieresis callsubr
}
SUB /guill-left { % source from dc*.pfb, scaled
130 -126 rlineto
4 -4 8 -4 6 0 rrcurveto
17 hlineto
16 2 12 12 0 16 rrcurveto
0 7 -3 8 -5 6 rrcurveto
-107 103 rlineto
106 103 rlineto
5 6 4 7 0 9 rrcurveto
0 16 -12 12 -16 2 rrcurveto
-17 hlineto
-6 0 -8 -4 -4 -4 rrcurveto
-128 -125 rlineto
-6 -5 -4 -8 0 -9 rrcurveto
0 -7 3 -8 5 -5 rrcurveto
closepath
return
}
SUB /guill-right { % source from dc*.pfb, scaled
17 hlineto
5 0 7 3 4 3 rrcurveto
158 124 rlineto
7 6 5 9 0 9 rrcurveto
0 8 -3 9 -6 5 rrcurveto
-161 127 rlineto
-4 3 -7 3 -5 0 rrcurveto
-17 hlineto
-16 -2 -12 -12 0 -16 rrcurveto
0 -8 3 -9 7 -5 rrcurveto
130 -103 rlineto
-128 -100 rlineto
-7 -6 -5 -8 0 -10 rrcurveto
0 -16 12 -12 16 -2 rrcurveto
closepath
return
}
CHAR /Aacute /A /uc-acute 0 0 putcenter
CHAR /Adieresis /A /uc-dieresis 0 capshift putcenter
CHAR /Agrave /A /uc-grave 0 0 putcenter
CHAR /aacute /a /lc-acute 20 0 putcenter
CHAR /adieresis /a /s-dieresis 0 0 putcenter
CHAR /agrave /a /lc-grave 0 0 putcenter
CHAR /Ccaron /C /uc-caron 25 10 putcenter
CHAR /ccaron /c /lc-caron 30 0 putcenter
CHAR /Dcaron /D /uc-caron -55 0 putcenter
CHAR /dcaron /d /sub-comma 0 0 putafter
CHAR /Ecaron /E /uc-caron 0 0 putcenter
CHAR /Eacute /E /uc-acute 20 0 putcenter
CHAR /ecaron /e /lc-caron 20 0 putcenter
CHAR /eacute /e /lc-acute 50 0 putcenter
CHAR /Iacute /I /uc-acute 0 0 putcenter
CHAR /iacute /dotlessi /lc-acute 0 0 putcenter
CHAR /Lcaron /L /sub-comma 130 0 putcenter
CHAR /Lacute /L /uc-acute 0 0 putcenter
CHAR /lcaron /l /sub-comma -80 0 putafter
CHAR /lacute /l /uc-acute 0 0 putcenter
CHAR /Ncaron /N /uc-caron 0 0 putcenter
CHAR /ncaron /n /lc-caron 0 0 putcenter
CHAR /Ocircumflex /O /uc-cflex 0 0 putcenter
CHAR /Odieresis /O /uc-dieresis 0 capshift putcenter
CHAR /Oacute /O /uc-acute 20 10 putcenter
CHAR /ocircumflex /o /lc-cflex 0 0 putcenter
CHAR /odieresis /o /s-dieresis 0 0 putcenter
CHAR /oacute /o /lc-acute 60 0 putcenter
CHAR /Rcaron /R /uc-caron -55 0 putcenter
CHAR /Racute /R /uc-acute 0 0 putcenter
CHAR /rcaron /r /lc-caron 0 0 putcenter
CHAR /racute /r /lc-acute 0 0 putcenter
CHAR /Scaron /S /uc-caron 0 10 putcenter
CHAR /scaron /s /lc-caron 0 0 putcenter
CHAR /Tcaron /T /uc-caron 0 0 putcenter
CHAR /tcaron /t /sub-comma 140 0 putcenter
CHAR /Udieresis /U /U-dieresis 0 capshift putcenter
CHAR /Uring /U /uc-ring 0 200 putcenter
CHAR /Uacute /U /uc-acute 0 0 putcenter
CHAR /udieresis /u /s-dieresis 0 0 putcenter
CHAR /uring /u /lc-ring 0 25 putcenter
CHAR /uacute /u /lc-acute 0 0 putcenter
CHAR /Yacute /Y /uc-acute 0 0 putcenter
CHAR /yacute /y /lc-acute 0 2 putcenter
CHAR /Zcaron /Z /uc-caron 0 0 putcenter
CHAR /zcaron /z /lc-caron 0 0 putcenter
CHAR /quotedblbase /quotedbl 50 -540 0 correct /.noinsert
CHAR /csquotedblright /quotedbl -50 0 0 correct /.noinsert
CHAR /guillemotleft {
0 525 hsbw
82 199 rmoveto
guill-left callsubr
175 hmoveto
guill-left callsubr
endchar
}
CHAR /guillemotright {
0 525 hsbw
102 65 rmoveto
guill-right callsubr
175 hmoveto
guill-right callsubr
endchar
}
CHAR /ogonek { % source from MPost output, code 157
20 525 hsbw
factor factor scaled
2.91527 0.27509 moveto
2.75847 0.06808 2.5632 -0.2994 2.47942 -0.54518 curveto
2.36871 -0.86987 2.37071 -1.22849 2.5418 -1.52486 curveto
2.71553 -1.82579 3.04385 -2.01228 3.38138 -1.94936 curveto
3.79468 -1.87231 4.2983 -1.40714 4.40784 -1.00124 curveto
4.2344 -0.8557 lineto
4.14986 -1.1711 3.70605 -1.47543 3.38138 -1.44069 curveto
3.19162 -1.42038 3.04582 -1.27519 2.96802 -1.09863 curveto
2.89162 -0.92528 2.87985 -0.73207 2.91058 -0.54518 curveto
2.94463 -0.3382 3.04984 -0.01895 3.14554 0.16771 curveto
2.91527 0.27509 lineto
}
% dvips has a bug: it is impossible to have the two same names in the
% Encoding vector:
CHAR /althyphen /hyphen /.noinsert
SUB /percent-white {
-19 5 -7 46 0 17 rrcurveto
16 8 52 20 vhcurveto
19 -5 7 -46 0 -17 rrcurveto
-16 -8 -52 -20 vhcurveto
closepath
}
CHAR /perthousand {
-30 525 hsbw
-83 65 hstem
118 65 hstem
427 267 hstem
0 60 vstem
114 60 vstem
280 60 vstem
394 60 vstem
52 -48 rmoveto
-19 16 -16 19 vhcurveto
15 0 10 8 7 12 rrcurveto
280 708 rlineto
2 4 1 5 0 5 rrcurveto
19 -16 16 -19 vhcurveto
-15 0 -10 -8 -7 -12 rrcurveto
-280 -708 rlineto
-2 -4 -1 -5 0 -5 rrcurveto
closepath
245 -35 rmoveto
64 0 13 20 7 60 rrcurveto
7 -60 13 -20 64 0 rrcurveto
64 23 81 52 hvcurveto
52 -23 81 -64 vhcurveto
-64 0 -13 -20 -7 -60 rrcurveto
-7 60 -13 20 -64 0 rrcurveto
-64 -23 -81 -52 hvcurveto
-52 23 -81 64 vhcurveto
closepath
-1 65 rmoveto
percent-white callsubr
174 hmoveto
percent-white callsubr
-349 445 rmoveto
64 23 82 52 hvcurveto
51 -23 82 -64 vhcurveto
-64 -23 -82 -51 hvcurveto
-52 23 -82 64 vhcurveto
closepath
-1 65 rmoveto
percent-white callsubr
endchar
}
% End of configuration file
t1accent/Makefile 100666 150 144 552 6530553570 12571 0 ustar olsak math1
DESTDIR=/usr/local
BINDIR=$(DESTDIR)/bin
CC=cc
INSTALL=install
MKDIR=mkdir -p
INSTPROGFLAGS=-s -m755
INSTEXECFLAGS=-m755
INSTDATAFLAGS=-m644
CFLAGS=-O -Wall
LFLAGS=
all: t1accent
t1accent: t1accent.c
$(CC) $(CFLAGS) $(LFLAGS) $? -o $@
install: all
$(INSTALL) $(INSTPROGFLAGS) t1accent $(BINDIR)/t1accent
clean:
rm -f *.o *~ *.bak core a.out t1accent
t1accent/t1accent.c 100666 150 144 140273 6530554046 13063 0 ustar olsak math1 /* t1accent -- adds the new accents into Type1 fonts
Copyright (C) 1998 Petr Olsak, <olsak@math.feld.cvut.cz>
Version April 1998
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#define MAXGBUF 30000 /* the size of array for all CharStrings */
#define MAXIMEM 8000 /* the work space for decrypted CharString */
#define MAXBUF 200 /* limit of the work buffer */
#define MAXSTACK 25 /* maximum of Type1 stack, sufficient */
#define MAXSUBS 300 /* maximum number of subroutines */
#define MAXINFILES 200 /* maximum number of processed pfb files */
#define MAXVARS 200 /* maximum number of VAR declared in conf file */
#define MAXNEWCHARS 200 /* maximum number of CHAR declared in conf file */
#define MAXREMARKS 20 /* maximum number of REM lines */
#define MAXCHARS 300 /* maximum number of chars in input pfb file */
/* main string memory will be allocated via malloc:
static char gbuf[MAXGBUF];
*/
unsigned char *pbuf, *gbuf, *fixpbuf;
unsigned char *csname[50]; /* the array of control sequences */
int cscode[50];
int last_csname, start_type1code;
char buf[MAXBUF]; /* temporary buffer */
char fname[MAXBUF];
char RDcommand[3], NDcommand[3], NPcommand[3];
char pattern[MAXBUF];
int pip, ispattern;
int lenIV;
int numfiles=0;
unsigned char *infile[MAXINFILES];
int imem[MAXIMEM]; /* the decrypted Chartrings */
unsigned int pim=1, fixpim, topim;
int numrems = 0;
unsigned char *remark[MAXREMARKS];
int srcisread = 0, nameisread = 0;
unsigned char *srcdir, *newname, *oriname;
int diffname;
int numsubs=0, pfbnumsubs, pfbchars;
struct subrtype { /* structure for new subroutine */
unsigned int code;
unsigned char *name;
int vvaxis, lx, ly, ux, uy ;
} subr[MAXSUBS];
int numvars=0;
struct varstruct { /* structure for variable declared by VAR */
unsigned char *name;
float value;
} variable[MAXVARS];
int numchars=0;
int sumchars;
struct newcharstruct { /* structure for new char declared by CHAR */
unsigned char *name, *origname, *origcode;
unsigned int owncode;
int origlen, nsub, x, y, dsbx, dwx, dy, type;
} newchar[MAXNEWCHARS];
struct savedsubrstruct { /* structure for /Subrs from pfb */
unsigned char *code;
int len;
} savedsubr[MAXSUBS];
struct savedcharstruct { /* structure for /CharStrings from pfb */
unsigned char *code, *name;
int len;
} savedchars[MAXCHARS];
unsigned char *encvector[256]; /* encoding vector */
int encisread=0;
int prst = 0;
float rs[MAXSTACK]; /* stack with real numbers */
float scaleX, scaleY, curX, curY; /* global variables */
int cX, cY, lX, lY, uX, uY, inpath, pX, pY, vvax, glX, glY, guX, guY;
int line=0;
FILE *fin, *fenc, *fpfb, *fpps;
#define VALUE 0
#define HSTEM 1
#define VSTEM 3
#define VMOVETO 4
#define RLINETO 5
#define HLINETO 6
#define VLINETO 7
#define RRCURVETO 8
#define CLOSEPATH 9
#define CALLSUBR 10
#define RETURN 11
#define ESCAPE 12
#define HSBW 13
#define ENDCHAR 14
#define RMOVETO 21
#define HMOVETO 22
#define VHCURVETO 30
#define HVCURVETO 31
#define DOTSECTION 1200
#define VSTEM3 1201
#define HSTEM3 1202
#define SEAC 1206
#define SBW 1207
#define DIV 1212
#define CALLOTHERSUBR 1216
#define POP 1217
#define SETCURRENTPOINT 1233
#define MOVETO 1301
#define LINETO 1302
#define CURVETO 1303
#define RCURVETO 1304
#define SCALED 1310
#define VVAXIS 1311
#define BGROUP 1401
#define EGROUP 1402
#define NUMSUB 1403
#define PUTORIGIN 1501
#define PUTSIDEBAR 1522
#define PUTCENTER 1503
#define PUTAFTER 1504
#define UNKNOWN 1599
#define MAGIC 31243
#define BEGIN 1
#define CLOSE 2
#define CURXY 3
#define CURX 4
#define CURY 5
#define CURXY6 6
#define CURHV4 7
#define CURVH4 8
#define SAVECHAR 1
#define SAVESUBR 2
void error (char* format, char* value)
{
/* prints an error message and exists
*/
if (line>0) fprintf(stderr,"\nError: (line %d) -- ", line);
else fprintf(stderr,"\nError: -- ");
if (value) fprintf(stderr, format, value);
else fprintf(stderr, format);
fprintf(stderr,"\n");
exit(2);
}
unsigned char* add_gbuf(unsigned char* p)
{
/* stores a new string in global buffer
*/
unsigned char *pp;
pp=pbuf;
pbuf += strlen(p)+1;
if (pbuf >= &gbuf[MAXGBUF])
error ("MAXGBUF (global string memory) overflows",NULL);
strcpy(pp, p);
return pp;
}
void store_gbuf(int c)
{
/* stores a new byte in global buffer
*/
if (pbuf >= &gbuf[MAXGBUF])
error ("MAXGBUF (global string memory) overflows",NULL);
pbuf[0] = c;
pbuf++;
}
void init_csnames(void)
{
/* initialises standard operator names in global buffer
*/
int i=0;
gbuf = pbuf = (unsigned char*) malloc(MAXGBUF);
if (!gbuf) error ("cannot allocated main strig memory", NULL);
csname[i] = add_gbuf("{"); cscode[i++] = BGROUP;
csname[i] = add_gbuf("}"); cscode[i++] = EGROUP;
start_type1code = i;
csname[i] = add_gbuf("hstem"); cscode[i++] = HSTEM;
csname[i] = add_gbuf("vstem"); cscode[i++] = VSTEM;
csname[i] = add_gbuf("vmoveto"); cscode[i++] = VMOVETO;
csname[i] = add_gbuf("rlineto"); cscode[i++] = RLINETO;
csname[i] = add_gbuf("hlineto"); cscode[i++] = HLINETO;
csname[i] = add_gbuf("vlineto"); cscode[i++] = VLINETO;
csname[i] = add_gbuf("rrcurveto"); cscode[i++] = RRCURVETO;
csname[i] = add_gbuf("closepath"); cscode[i++] = CLOSEPATH;
csname[i] = add_gbuf("callsubr"); cscode[i++] = CALLSUBR;
csname[i] = add_gbuf("return"); cscode[i++] = RETURN;
csname[i] = add_gbuf("escape"); cscode[i++] = ESCAPE;
csname[i] = add_gbuf("hsbw"); cscode[i++] = HSBW;
csname[i] = add_gbuf("endchar"); cscode[i++] = ENDCHAR;
csname[i] = add_gbuf("rmoveto"); cscode[i++] = RMOVETO;
csname[i] = add_gbuf("hmoveto"); cscode[i++] = HMOVETO;
csname[i] = add_gbuf("vhcurveto"); cscode[i++] = VHCURVETO;
csname[i] = add_gbuf("hvcurveto"); cscode[i++] = HVCURVETO;
csname[i] = add_gbuf("dotsection"); cscode[i++] = DOTSECTION;
csname[i] = add_gbuf("vstem3"); cscode[i++] = VSTEM3;
csname[i] = add_gbuf("hstem3"); cscode[i++] = HSTEM3;
csname[i] = add_gbuf("seac"); cscode[i++] = SEAC;
csname[i] = add_gbuf("sbw"); cscode[i++] = SBW;
csname[i] = add_gbuf("div"); cscode[i++] = DIV;
csname[i] = add_gbuf("callothersubr"); cscode[i++] = CALLOTHERSUBR;
csname[i] = add_gbuf("pop"); cscode[i++] = POP;
csname[i] = add_gbuf("setcurrentpoint"); cscode[i++] = SETCURRENTPOINT;
csname[i] = add_gbuf("moveto"); cscode[i++] = MOVETO;
csname[i] = add_gbuf("lineto"); cscode[i++] = LINETO;
csname[i] = add_gbuf("curveto"); cscode[i++] = CURVETO;
csname[i] = add_gbuf("rcurveto"); cscode[i++] = RCURVETO;
csname[i] = add_gbuf("scaled"); cscode[i++] = SCALED;
csname[i] = add_gbuf("vvaxis"); cscode[i++] = VVAXIS;
last_csname=i-1;
buf[MAXBUF-1] = 0;
}
/* The decrypting algorithm from pfb is token over the t1disasm from t1utils
by I. Lee Hetherington */
int immediate_eexec;
/* int32 must be at least 32-bit and uint16 must be at least 16-bit */
#if INT_MAX >= 0x7FFFFFFFUL
typedef int int32;
#else
typedef long int32;
#endif
#if USHRT_MAX >= 0xFFFFUL
typedef unsigned short uint16;
#else
typedef unsigned int uint16;
#endif
typedef unsigned char byte;
static uint16 er, cr;
static uint16 c1 = 52845, c2 = 22719;
int first_byte;
int is_pfb;
int32 pfb_remaining;
int in_eexec;
int savedchar, is_textspace;
#define cgetc() cdecrypt((byte) (egetc() & 0xff))
static int bgetc()
{
/* returns a single character at a time from a PFB file.
This stream is mixed ASCII and binary bytes. The section
headers are removed, and \r is replaced by \n in ASCII sections.
*/
int c;
c = fgetc(fpfb);
if (c == EOF) {
fprintf(stderr,"remaining = %d", pfb_remaining);
return EOF;
}
if (first_byte) {
/* Determine if this is a PFB file by looking at first byte. */
if (c != 0x80) error ("the file %s is not in pfb format", fname);
first_byte = 0;
}
/* PFB */
if (pfb_remaining == 0) {
/* beginning of block---we know c == 0x80 at this point */
c = fgetc(fpfb);
switch (c) {
case 1:
is_pfb = 1;
break;
case 2:
is_pfb = 2;
break;
case 3:
return EOF;
default: error("the file %s is not in PFB format", fname);
}
/* get block length */
pfb_remaining = (int32) (fgetc(fpfb) & 0xff);
pfb_remaining |= (int32) (fgetc(fpfb) & 0xff) << 8;
pfb_remaining |= (int32) (fgetc(fpfb) & 0xff) << 16;
pfb_remaining |= (int32) (fgetc(fpfb) & 0xff) << 24;
/* get character */
c = fgetc(fpfb);
if (c == EOF)
return EOF;
}
--pfb_remaining;
/* in ASCII section change return to newline */
if (is_pfb == 1 && c == '\r') {
c = fgetc(fpfb);
if (c != '\n') {
ungetc(c, fpfb);
c = '\n' ;
} else --pfb_remaining;
}
return c;
}
static byte edecrypt(byte cipher)
{
/* an eexec decryption
*/
byte plain;
plain = (byte) (cipher ^ (er >> 8));
er = (uint16) ((cipher + er) * c1 + c2);
return plain;
}
static byte cdecrypt(byte cipher)
{
/* a CharString decryption
*/
byte plain;
plain = (byte) (cipher ^ (cr >> 8));
cr = (uint16) ((cipher + cr) * c1 + c2);
return plain;
}
static int egetc()
{
/* returns a single byte at a time through (possible) eexec
decryption. When immediate_eexec is 1 it fires up the eexec decryption
machinery.
*/
int c;
if (savedchar >= 0) {
c = savedchar;
savedchar = -1;
return c;
}
if ((c = bgetc()) == EOF) return EOF;
if (!in_eexec) {
if (immediate_eexec) {
/* start eexec decryption */
in_eexec = 1;
er = 55665;
/* toss out four random bytes */
(void) edecrypt((byte) (bgetc() & 0xff));
(void) edecrypt((byte) (bgetc() & 0xff));
(void) edecrypt((byte) (bgetc() & 0xff));
(void) edecrypt((byte) (bgetc() & 0xff));
}
return c;
} else {
c = edecrypt((byte) (c & 0xff));
if (is_textspace && c == '\r') {
if ((c = bgetc()) == EOF) return EOF;
c = edecrypt((byte) (c & 0xff));
if (c!='\n') {
savedchar = c;
c = '\n';
}
}
return c;
}
}
int Fgetc (FILE *fh)
{
/* This is a low level input filter for config file. It transforms
white space to space and ignores a % comment
*/
int c;
restart:
c = fgetc(fh);
if (c=='\n') line++;
if (c=='\t' || c=='\r' || c=='\n' || c==0) c = ' ';
if (c=='%') {
while (c!='\n' && c!=EOF) c = fgetc(fh);
line++;
if (c=='\n') goto restart;
}
return c;
}
void store_stack(float val)
{
/* stores one value to rs[] stack
*/
if (prst>=MAXSTACK) error ("stack overflow", NULL);
rs[prst++] = val;
}
int read_token(FILE *fh, int status)
{
/* reads one token (word or number separated by white space)
from input stream. If status then function returns the number of
control sequence. The value stores into stack.
*/
int c, p;
c = ' ';
buf[0] = 0;
while (c==' ') c = Fgetc(fh);
if (c==EOF) return EOF;
p = 0;
while (c!=' ' && c!=EOF) {
if (p>MAXBUF-2) error("control sequence '%s' too long", buf);
buf[p++] = c;
c = Fgetc(fh);
}
buf[p] = 0;
if (status == 0) return 0;
p = 0;
if (buf[0] == '-') p = 1;
if (isdigit(buf[p]) || (buf[p]=='.' && isdigit(buf[p+1]))) {
store_stack (atof(buf));
return VALUE;
}
for (p=0;p<numvars;p++)
if (strcmp(buf,variable[p].name)==0) {
store_stack (variable[p].value);
return VALUE;
}
for (p=0;p<=last_csname;p++)
if (strcmp(buf,csname[p])==0) return cscode[p];
return UNKNOWN;
}
void save_code(int num, int code)
{
/* stores a decrypted part of code to imem[] in the form
<num> operands from rs[] stack plus one operator declared by 'code'.
save_code() does an optimalisation of code (rlineto -> hlineto) too.
*/
int i, x, y;
if (MAXIMEM-pim<num+2) error ("MAXIMEM exceeded", NULL);
if (num > prst) num = prst;
prst -= num;
switch (code) { /* optimalisation */
case RMOVETO: x = rs[prst]; y = rs[prst+1];
if (x==0 && y==0) break;
if (x==0) {
imem[pim++] = y;
imem[pim++] = MAGIC; imem[pim++] = VMOVETO;
}
if (y==0) {
imem[pim++] = x;
imem[pim++] = MAGIC; imem[pim++] = HMOVETO;
}
if (x!=0 && y!=0) {
imem[pim++] = x; imem[pim++] = y;
imem[pim++] = MAGIC; imem[pim++] = RMOVETO;
}
break;
case RLINETO: x = rs[prst]; y = rs[prst+1];
if (x==0 && y==0) break;
if (x==0) {
imem[pim++] = y;
imem[pim++] = MAGIC; imem[pim++] = VLINETO;
}
if (y==0) {
imem[pim++] = x;
imem[pim++] = MAGIC; imem[pim++] = HLINETO;
}
if (x!=0 && y!=0) {
imem[pim++] = x; imem[pim++] = y;
imem[pim++] = MAGIC; imem[pim++] = RLINETO;
}
break;
case RRCURVETO: x = rs[prst]; y = rs[prst+5];
if (x==0 && y==0) {
imem[pim++] = rs[prst+1]; imem[pim++] = rs[prst+2];
imem[pim++] = rs[prst+3]; imem[pim++] = rs[prst+4];
imem[pim++] = MAGIC; imem[pim++] = VHCURVETO;
break; }
y = rs[prst+1]; x = rs[prst+4];
if (x==0 && y==0) {
imem[pim++] = rs[prst]; imem[pim++] = rs[prst+2];
imem[pim++] = rs[prst+3]; imem[pim++] = rs[prst+5];
imem[pim++] = MAGIC; imem[pim++] = HVCURVETO;
break; }
default: for (i=0;i<num;i++) imem[pim++] = rs[prst+i];
imem[pim++] = MAGIC; imem[pim++] = code;
}
}
void setpath (int status)
{
/* If BEGIN, sets the global pX, pY to current point. If CLOSE, restores
current point to stored position
*/
switch (status) {
case BEGIN: inpath = 1;
pX = cX; pY = cY;
if (lX == MAGIC) {
lX = uX = cX;
lY = uY = cY;
}
break;
case CLOSE: inpath = 0;
break;
}
}
void setbbox (int status)
{
/* moves the current point and, if path is currently drawn, setbbox()
actualises the BoundingBox values
*/
int dx, dy;
switch (status) {
case CURXY: dx = rs[prst-2]; cX += dx;
dy = rs[prst-1]; cY += dy;
break;
case CURX: dx = rs[prst-1]; cX += dx;
break;
case CURY: dy = rs[prst-1]; cY += dy;
break;
case CURXY6: dx = rs[prst-6]; cX += dx;
dy = rs[prst-5]; cY += dy;
dx = rs[prst-4]; cX += dx;
dy = rs[prst-3]; cY += dy;
dx = rs[prst-2]; cX += dx;
dy = rs[prst-1]; cY += dy;
break;
case CURHV4: dx = rs[prst-4]; cX += dx;
dx = rs[prst-3]; cX += dx;
dy = rs[prst-2]; cY += dy;
dy = rs[prst-1]; cY += dy;
break;
case CURVH4: dy = rs[prst-4]; cY += dy;
dx = rs[prst-3]; cX += dx;
dy = rs[prst-2]; cY += dy;
dx = rs[prst-1]; cX += dx;
break;
}
if (inpath) {
lX = min (lX, cX); lY = min (lY, cY);
uX = max (uX, cX); uY = max (uY, cY);
}
}
void teststack(int num)
{
if (prst<num) error ("stack underflow", NULL);
return;
}
void read_code(int status)
{
/* reads code of SUB from config file and stores it to
imem[] by save_code()
*/
int i, code, addtail;
float curXtmp, curYtmp;
if (status) /* status == 1 , SUB declaration */
subr[numsubs].code = pim; /* budeme ukladat kod procedury do imem */
else /* status == 0 , CHAR declaration */
newchar[numchars].owncode = pim;
scaleX = scaleY = 1;
curX = curY = 0;
vvax = lX = lY = uX = uY = MAGIC;
inpath = 0;
cX = cY = 0;
prst = 0; addtail = 1;
while ((code=read_token(fin, 1)) != EGROUP) {
switch (code) {
case EOF: error ("unexpected end of conf. file", NULL);
case RETURN: addtail = 0; save_code(0, RETURN);
break;
case ENDCHAR: if (status) error("not allowed operator (%s)", buf);
addtail = 0; save_code(0, ENDCHAR);
break;
case UNKNOWN:
for (i=0; i<numsubs; i++) if (strcmp(buf,subr[i].name)==0) {
save_code(0, NUMSUB);
store_stack((float)i);
break;
}
if (i==numsubs) error ("unknown operator '%s' in SUB", buf);
case VALUE: break; /* value is stored in rs[] by read_token() */
case HSBW: save_code(2, HSBW); break;
case SBW: save_code(4, SBW); break;
case SEAC: if (status) error("not allowed operator (%s)", buf);
save_code(5, SEAC); break;
case HSTEM: teststack(2);
rs[prst-2] *= scaleY; rs[prst-1] *= scaleY;
save_code(2, code); break;
case VSTEM: teststack(2);
rs[prst-2] *= scaleX; rs[prst-1] *= scaleX;
save_code(2, code); break;
case HSTEM3: teststack(6);
for (i=0; i<6; i++) rs[prst-6+i] *= scaleY;
save_code(6, code); break;
case VSTEM3: teststack(6);
for (i=0; i<6; i++) rs[prst-6+i] *= scaleX;
save_code(6, code); break;
case DIV: save_code(MAXSTACK, DIV); /* save the previous number too */
break;
case CALLOTHERSUBR: save_code(MAXSTACK, CALLOTHERSUBR); break;
case POP: save_code (0, POP); break;
case SETCURRENTPOINT: save_code(2, code); break;
case MOVETO:
teststack(2);
rs[prst-2] -= curX; rs[prst-1] -= curY;
case RMOVETO:
teststack(2);
curX += rs[prst-2]; curY += rs[prst-1];
rs[prst-2] *= scaleX; rs[prst-1] *= scaleY;
setbbox(CURXY);
save_code(2, RMOVETO);
break;
case HMOVETO:
teststack(1);
curX += rs[prst-1];
rs[prst-1] *= scaleX;
setbbox(CURX);
save_code(1, HMOVETO);
break;
case VMOVETO:
teststack(1);
curY += rs[prst-1];
rs[prst-1] *= scaleY;
setbbox(CURY);
save_code(1, VMOVETO);
break;
case LINETO:
teststack(2);
rs[prst-2] -= curX; rs[prst-1] -= curY;
case RLINETO:
teststack(2);
curX += rs[prst-2]; curY += rs[prst-1];
rs[prst-2] *= scaleX; rs[prst-1] *= scaleY;
if (!inpath) setpath(BEGIN);
setbbox(CURXY);
save_code(2, RLINETO);
break;
case HLINETO:
teststack(1);
curX += rs[prst-1];
rs[prst-1] *= scaleX;
if (!inpath) setpath(BEGIN);
setbbox(CURX);
save_code(1, HLINETO);
break;
case VLINETO:
teststack(1);
curY += rs[prst-1];
rs[prst-1] *= scaleY;
if (!inpath) setpath(BEGIN);
setbbox(CURY);
save_code(1, VLINETO);
break;
case CURVETO:
teststack(6);
rs[prst-6] -= curX; rs[prst-5] -= curY;
curX += rs[prst-6]; curY += rs[prst-5];
rs[prst-6] *= scaleX; rs[prst-5] *= scaleY;
rs[prst-4] -= curX; rs[prst-3] -= curY;
curX += rs[prst-4]; curY += rs[prst-3];
rs[prst-4] *= scaleX; rs[prst-3] *= scaleY;
rs[prst-2] -= curX; rs[prst-1] -= curY;
curX += rs[prst-2]; curY += rs[prst-1];
rs[prst-2] *= scaleX; rs[prst-1] *= scaleY;
if (!inpath) setpath(BEGIN);
setbbox(CURXY6);
save_code(6, RRCURVETO);
break;
case RCURVETO:
teststack(6);
curXtmp = curX; curYtmp = curY;
curX += rs[prst-6]; curY += rs[prst-5];
rs[prst-6] *= scaleX; rs[prst-5] *= scaleY;
rs[prst-4] -= curXtmp - curX; rs[prst-3] -= curYtmp - curY;
curX += rs[prst-4]; curY += rs[prst-3];
rs[prst-4] *= scaleX; rs[prst-3] *= scaleY;
rs[prst-2] -= curXtmp - curX; rs[prst-1] -= curYtmp - curY;
curX += rs[prst-2]; curY += rs[prst-1];
rs[prst-2] *= scaleX; rs[prst-1] *= scaleY;
if (!inpath) setpath(BEGIN);
setbbox(CURXY6);
save_code(6, RRCURVETO);
break;
case RRCURVETO:
teststack(6);
curX += rs[prst-6]; curY += rs[prst-5];
rs[prst-6] *= scaleX; rs[prst-5] *= scaleY;
curX += rs[prst-4]; curY += rs[prst-3];
rs[prst-4] *= scaleX; rs[prst-3] *= scaleY;
curX += rs[prst-2]; curY += rs[prst-1];
rs[prst-2] *= scaleX; rs[prst-1] *= scaleY;
if (!inpath) setpath(BEGIN);
setbbox(CURXY6);
save_code(6, RRCURVETO);
break;
case HVCURVETO:
teststack(4);
curX += rs[prst-4];
rs[prst-4] *= scaleX;
curX += rs[prst-3]; curY += rs[prst-2];
rs[prst-3] *= scaleX; rs[prst-2] *= scaleY;
curY += rs[prst-1];
rs[prst-1] *= scaleY;
if (!inpath) setpath(BEGIN);
setbbox(CURHV4);
save_code(4, HVCURVETO);
break;
case VHCURVETO:
teststack(4);
curY += rs[prst-4];
rs[prst-4] *= scaleY;
curX += rs[prst-3]; curY += rs[prst-2];
rs[prst-3] *= scaleX; rs[prst-2] *= scaleY;
curX += rs[prst-1];
rs[prst-1] *= scaleX;
if (!inpath) setpath(BEGIN);
setbbox(CURVH4);
save_code(4, VHCURVETO);
break;
case CALLSUBR:
save_code(1, CALLSUBR);
break;
case SCALED:
teststack(2);
prst -= 2;
if (prst<0) error ("stack underflow", NULL);
scaleX = scaleX * rs[prst]; scaleY = scaleY * rs[prst+1];
break;
case VVAXIS:
teststack(1);
prst -= 1;
if (prst<0) error ("stack underflow", NULL);
vvax = cX + scaleX * rs[prst];
break;
case CLOSEPATH: setpath(CLOSE);
case DOTSECTION:
save_code(0, code);
break;
default: error("'%s' not allowed in SUB\n", buf);
}
}
if (addtail)
if (status) {
if (inpath) save_code (0, CLOSEPATH);
rs[prst++] = -cX; rs[prst++] = -cY;
save_code (2, RMOVETO);
save_code (0, RETURN);
} else {
if (inpath) save_code (0, CLOSEPATH);
save_code (0, ENDCHAR);
}
save_code (0, MAGIC); /* the end signature */
if (status) {
if (lX == MAGIC) lX = lY = uX = uY = 0;
subr[numsubs].lx = lX;
subr[numsubs].ly = lY;
subr[numsubs].ux = uX;
subr[numsubs].uy = uY;
if (vvax == MAGIC) subr[numsubs].vvaxis = (lX + uX) / 2 ;
else subr[numsubs].vvaxis = vvax ;
numsubs++;
}
return;
}
void print_code(unsigned int i)
{
/* print_code() prints the CharString or Subrs code from imem[]
to pps output in readable form
*/
unsigned j=0;
char tabchar;
tabchar = '\t';
while (1) {
if (imem[i]==MAGIC) {
switch (imem[++i]) {
case MAGIC: return;
case HSTEM: j=0; break;
case VSTEM: j=1; break;
case VMOVETO: j=2; break;
case RLINETO: j=3; break;
case HLINETO: j=4; break;
case VLINETO: j=5; break;
case RRCURVETO: j=6; break;
case CLOSEPATH: j=7; break;
case CALLSUBR: j=8; break;
case RETURN: j=9; break;
case ESCAPE: j=10; break;
case HSBW: j=11; break;
case ENDCHAR: j=12; break;
case RMOVETO: j=13; break;
case HMOVETO: j=14; break;
case VHCURVETO: j=15; break;
case HVCURVETO: j=16; break;
case DOTSECTION: j=17; break;
case VSTEM3: j=18; break;
case HSTEM3: j=19; break;
case SEAC: j=20; break;
case SBW: j=21; break;
case DIV: j=22; break;
case CALLOTHERSUBR: j=23; break;
case POP: j=24; break;
case SETCURRENTPOINT: j=25; break;
case NUMSUB: j=30; break;
}
if (j==30) {
fprintf(fpps, "%c%d", tabchar, imem[++i]+pfbnumsubs);
tabchar = ' ';
} else {
j += start_type1code;
fprintf(fpps, "%c%s\n", tabchar, csname[j]);
tabchar = '\t';
}
}
else {
fprintf(fpps, "%c%d", tabchar, imem[i]);
tabchar = ' ';
}
i++;
}
}
void print_encoding(void)
{
/* prints the encoding vector to pps file
*/
int code;
for(code=0;code<256;code++)
if (encvector[code]!=NULL)
fprintf(fpps, "dup %d /%s put\n", code, encvector[code]);
}
void read_in(void)
{
/* reads an IN list of input files
*/
while (1) {
if(read_token(fin,0)==EOF) return;
if (strcmp(buf,"END")==0 ||
strcmp(buf,"ENC")==0 ||
strcmp(buf,"REM")==0 ||
strcmp(buf,"SRC")==0 ||
strcmp(buf,"NAME")==0 ||
strcmp(buf,"VAR")==0 ||
strcmp(buf,"SUB")==0 ||
strcmp(buf,"CHAR")==0) return;
if (strcmp(buf,"IN")==0) { read_in(); return; }
if (numfiles>MAXINFILES-2)
error ("MAXINFILES (max number of IN files) overflow", NULL);
infile[numfiles++] = add_gbuf(buf);
}
}
void read_enc(void)
{
/* reads an ENC declaration plus .enc file
*/
int c, p, code, saveline;
if(encisread) error("second ENC declaration is not allowed", NULL);
if(read_token(fin,0)==EOF) error("unexcepted end of file", NULL);
if(strlen(buf) > MAXBUF-5) error("ENC file name is too long (%s)", buf);
strcat(buf, ".enc"); strcpy(fname, buf);
fenc = fopen(fname, "r");
if (!fenc) error("cannot open %s for reading\n", fname);
saveline = line; line = 1;
c = 0;
while (c!='[' && c!=EOF) c = Fgetc(fenc);
if (c==EOF) error ("no '[' in encoding file %s", fname);
code = 0;
while (1) {
while (c!='/' && c!=']' && c!=EOF) c = Fgetc(fenc);
if (c==EOF) error ("unexpected end of encoding file %s", fname);
if (c==']' && code==256) break;
if (c==']') error ("less than 256 entries in encoding vector (/%s)",buf);
p=0;
c = Fgetc(fenc);
while (c!=' ' && c!='/' && c!=EOF) {
if (p>MAXBUF-2) error ("too long char name (%s) in enc file", buf);
buf[p++] = c;
c = Fgetc(fenc);
}
if (p==0) error ("empty char name in enc. file %s", fname);
if (code > 255)
error ("more than 256 entries in encoding vector (/%s)",buf);
buf[p] = 0;
if (strcmp(buf,".notdef")==0) encvector[code++] = NULL;
else encvector[code++] = add_gbuf(buf);
}
fclose(fenc);
line = saveline;
encisread=1;
}
void read_rem(void)
{
/* reads a remark string
*/
int c;
c = ' ';
while (c==' ') c = Fgetc(fin);
if (c != '"') error ("the '\"' (begin of string) after REM expected", NULL);
if (numrems >= MAXREMARKS)
error ("MAXREMARKS (maximum REM lines) exceeded", NULL);
remark[numrems++] = pbuf;
while ((c=Fgetc(fin)) != '"' && c != EOF && pbuf < &gbuf[MAXGBUF]) {
pbuf[0] = c;
pbuf++;
}
if (c == EOF) error ("the REM string is unterminated", NULL);
if (pbuf == &gbuf[MAXGBUF])
error ("MAXGBUF overflow during REM reading", NULL);
store_gbuf(0);
}
void read_var(void)
{
/* reads the VAR declaration from config file
*/
int c;
c = ' ';
while (c==' ') c = Fgetc(fin);
if (c!='/') error("the /name of variable expected", NULL);
read_token(fin, 0);
if (buf[0]==0) error("empty /name of variable", NULL);
variable[numvars].name = add_gbuf(buf);
if (read_token(fin,1) != VALUE) error("the number expected (%s)", buf);
variable[numvars++].value = rs[--prst];
return;
}
void read_src(void)
{
if(srcisread) error("second SRC declaration is not allowed", NULL);
read_token(fin, 0);
srcdir = add_gbuf(buf);
srcisread = 1;
}
void read_name(void)
{
if(nameisread) error("second NAME declaration is not allowed", NULL);
read_token(fin, 0);
oriname = add_gbuf(buf);
read_token(fin, 0);
if (strcmp (buf, "->") != 0) error("the '->' expected", NULL);
read_token(fin, 0);
newname = add_gbuf(buf);
diffname = strlen(newname) - strlen(oriname);
nameisread = 1;
}
void read_bbox(void)
{
int i=0;
if (read_token(fin,1) != VALUE) i = 1;
if (read_token(fin,1) != VALUE) i = 1;
if (read_token(fin,1) != VALUE) i = 1;
if (read_token(fin,1) != VALUE) i = 1;
if (i) error("the number expected (%s)", buf);
glX = min(glX, rs[prst-4]);
glY = min(glY, rs[prst-3]);
guX = max(guX, rs[prst-2]);
guY = max(guY, rs[prst-1]);
prst = 0;
}
void read_sub(void)
{
/* reads the SUB declaration from config file
*/
int c;
c = ' ';
while (c==' ') c = Fgetc(fin);
if (c!='/') error("the /name of subroutine expected", NULL);
read_token(fin, 0);
if (buf[0]==0) error("empty /name of subroutine", NULL);
if (numsubs>=MAXSUBS) error ("MAXSUBS (number of SUB's) exceeded", NULL);
subr[numsubs].name = add_gbuf(buf);
c = ' ';
while (c==' ') c = Fgetc(fin);
if (c!='{') error("the '{' expected", NULL);
read_code(1);
return;
}
void read_char(void)
{
/* reads the CHAR declaration from config file
*/
int c, p;
c = ' ';
while (c==' ') c = Fgetc(fin);
if (c!='/') error("the /name of new char expected", NULL);
read_token(fin, 0);
if (buf[0]==0) error("empty /name new char", NULL);
newchar[numchars].name = add_gbuf(buf);
c = ' ';
while (c==' ') c = Fgetc(fin);
if (c=='{') {
read_code(0);
newchar[numchars].nsub = -1;
newchar[numchars++].origname = NULL;
return;
}
if (c!='/') error("the /name of base char or '{' expected", NULL);
read_token(fin, 0);
if (buf[0]==0) error("empty /name of base char", NULL);
newchar[numchars].origname = add_gbuf(buf);
newchar[numchars].owncode = 0;
c = ' ';
while (c==' ') c = Fgetc(fin);
if (c!='/') {
ungetc(c, fin);
if (read_token(fin, 1) != VALUE)
error("value or /name of subroutine expected (%s)", buf);
if (read_token(fin, 1) != VALUE) error("value expected (%s)", buf);
if (read_token(fin, 1) != VALUE) error("value expected (%s)", buf);
prst -= 3;
newchar[numchars].dsbx = rs[prst];
newchar[numchars].dy = rs[prst+1];
newchar[numchars].dwx = rs[prst+2];
read_token(fin, 0);
if (strcmp(buf,"correct")!=0)
error("the correct operator expected (%s)", buf);
c = ' ';
while (c==' ') c = Fgetc(fin);
} else
newchar[numchars].dsbx = newchar[numchars].dwx = newchar[numchars].dy = 0;
if (c!='/') error("the /name of subroutine expected (%s)", buf);
read_token(fin, 0);
if (buf[0]==0) error("empty /name of subroutine", NULL);
newchar[numchars].nsub = -1;
if (strcmp(buf,".noinsert")==0) { numchars++; return; }
for(p=0;p<numsubs;p++) if (strcmp(buf,subr[p].name)==0) {
newchar[numchars].nsub = p;
break;
}
if (newchar[numchars].nsub == -1)
error("unknown name of subroutine /%s", buf);
if (read_token(fin, 1) != VALUE) error("value expected (%s)", buf);
if (read_token(fin, 1) != VALUE) error("value expected (%s)", buf);
prst -= 2;
newchar[numchars].x = rs[prst]; newchar[numchars].y = rs[prst+1];
read_token(fin, 0);
p = -1;
if (strcmp(buf,"putorigin")==0) p = PUTORIGIN;
if (strcmp(buf,"putsidebar")==0) p = PUTSIDEBAR;
if (strcmp(buf,"putcenter")==0) p = PUTCENTER;
if (strcmp(buf,"putafter")==0) p = PUTAFTER;
if (p == -1) error("unknown put- operator (%s)", buf);
newchar[numchars++].type = p;
return;
}
void read_config(void)
{
/* reads the whole config file
*/
while (1) {
if(read_token(fin,0)==EOF) return;
if (strcmp(buf,"IN")==0) read_in();
if (strcmp(buf,"END")==0) return;
if (strcmp(buf,"ENC")==0) read_enc();
if (strcmp(buf,"REM")==0) read_rem();
if (strcmp(buf,"VAR")==0) read_var();
if (strcmp(buf,"SRC")==0) read_src();
if (strcmp(buf,"NAME")==0) read_name();
if (strcmp(buf,"SUB")==0) read_sub();
if (strcmp(buf,"CHAR")==0) read_char();
if (strcmp(buf,"BBOX")==0) read_bbox();
}
}
void globalbbox(void)
{
/* computes the global glY and guY of BoundingBox.
*/
int i;
for (i=0; i<numchars; i++) if (newchar[i].nsub>=0) {
glY = min(glY, subr[newchar[i].nsub].ly + newchar[i].y + newchar[i].dy);
guY = max(guY, subr[newchar[i].nsub].uy + newchar[i].y + newchar[i].dy);
}
}
unsigned int convert_code(unsigned char* st, int l)
{
/* converts the decrypted CharString or Subrs from
per-byte format to imem[] format.
*/
int p;
int32 val;
int b;
unsigned int out;
out = pim;
for (p=0; p<l; p++) {
b = st[p];
if (b >= 32) {
if (b >= 32 && b <= 246) val = b - 139;
else if (b >= 247 && b <= 250) val = (b - 247)*256 + 108 + st[++p];
else if (b >= 251 && b <= 254) val = -(b - 251)*256 - 108 - st[++p];
else {
val = (st[++p] & 0xff) << 24;
val |= (st[++p] & 0xff) << 16;
val |= (st[++p] & 0xff) << 8;
val |= (st[++p] & 0xff) << 0;
/* in case an int32 is larger than four bytes---sign extend */
#if MAX_INT > 0x7FFFFFFFUL
for (i = 4; i < sizeof(int32); i++)
val |= 0xff << (i * 8);
#endif
}
imem[pim++] = val;
} else {
imem[pim++] = MAGIC;
if (b==12) b = 100*b + st[++p];
imem[pim++] = b;
}
if (pim >= MAXIMEM-5) error ("imem[MAXIMEM] overflow", NULL);
}
imem[pim++] = MAGIC; imem[pim++] = MAGIC;
topim = pim;
return out;
}
void insert_newcode (unsigned int pim, int p)
{
/* insert a new code: dx dy rmoveto num callsubr -dx -dy rmoveto
into code at imem[i] and does some optimalisation
*/
unsigned int npim, lpim, i;
int dx, dy, wx, sbx, c, shift;
int tmem[] = {0, 0, MAGIC, RMOVETO,
0, MAGIC, CALLSUBR,
0, 0, MAGIC, RMOVETO};
lpim = 11;
wx = MAGIC; sbx = 0;
while (1) {
c = imem[pim++];
if (c != MAGIC) continue;
c = imem[pim++];
if (c==VSTEM || c==VSTEM3 || c==DIV) continue;
if (c==HSTEM) {
imem[pim-4] += newchar[p].dy;
continue;
}
if (c==HSTEM3) {
imem[pim-8] += newchar[p].dy;
imem[pim-6] += newchar[p].dy;
imem[pim-4] += newchar[p].dy;
continue;
}
if (c==HSBW) {
if (imem[pim-4]==MAGIC && imem[pim-3]==DIV) {
imem[pim-6] += newchar[p].dwx * imem[pim-5];
wx = imem[pim-6] / imem[pim-5];
imem[pim-7] += newchar[p].dsbx;
sbx = imem[pim-7];
} else {
imem[pim-3] += newchar[p].dwx; wx = imem[pim-3];
imem[pim-4] += newchar[p].dsbx; sbx = imem[pim-4];
}
continue;
}
if (c==SEAC || c==SBW) {
fprintf
(stderr,"\nWarning: seac or sbw in base char, /%s unchanged\n",
newchar[p].name);
return;
}
if (c==MAGIC) {
fprintf(stderr, "\nWarning: the /%s is unchanged\n", newchar[p].name);
return;
}
if (wx==MAGIC) {
fprintf
(stderr,"\nWarning: hsbw not found in base char, /%s unchanged\n",
newchar[p].name);
return;
}
if (newchar[p].nsub == -1) {
if (newchar[p].dy == 0) return;
tmem[0] = 0; tmem[1] = newchar[p].dy;
tmem[2] = MAGIC; tmem[3] = RMOVETO;
lpim = 4;
} else {
dx = newchar[p].x; dy = newchar[p].y + newchar[p].dy;
if (newchar[p].type == PUTORIGIN) dx -= sbx;
if (newchar[p].type == PUTCENTER)
dx += wx/2 - sbx - subr[newchar[p].nsub].vvaxis;
if (newchar[p].type == PUTAFTER) dx += wx-sbx;
if (dx == 0 && dy == 0) { /* remove rmoveto */
tmem[0] = newchar[p].nsub + pfbnumsubs;
tmem[1] = MAGIC; tmem[2] = CALLSUBR;
tmem[3] = 0; tmem[4] = newchar[p].dy;
tmem[5] = MAGIC; tmem[6] = RMOVETO;
lpim = 7;
}
else if (dx == 0) { /* rmoveto -> vmoveto */
tmem[0] = dy;
tmem[1] = MAGIC; tmem[2] = VMOVETO;
tmem[3] = newchar[p].nsub + pfbnumsubs;
tmem[4] = MAGIC; tmem[5] = CALLSUBR;
tmem[6] = 0; tmem[7] = -dy + newchar[p].dy;
tmem[8] = MAGIC; tmem[9] = RMOVETO;
lpim = 10;
}
else if (dy == 0) { /* rmoveto -> hmoveto */
tmem[0] = dx;
tmem[1] = MAGIC; tmem[2] = HMOVETO;
tmem[3] = newchar[p].nsub + pfbnumsubs;
tmem[4] = MAGIC; tmem[5] = CALLSUBR;
tmem[6] = -dx; tmem[7] = newchar[p].dy;
tmem[8] = MAGIC; tmem[9] = RMOVETO;
lpim = 10;
} else { /* default */
tmem[0] = dx; tmem[1] = dy;
tmem[4] = newchar[p].nsub + pfbnumsubs;
tmem[7] = -dx; tmem[8] = -dy + newchar[p].dy;
}
}
if (c==RMOVETO) { /* next command is rmoveto */
tmem[lpim-4] += imem[pim-4] ;
tmem[lpim-3] += imem[pim-3] ;
npim = pim - 4;
}
else if (c==VMOVETO) { /* next command is vmoveto */
tmem[lpim-3] += imem[pim-3] ;
npim = pim - 3;
}
else if (c==HMOVETO) { /* next command is hmoveto */
tmem[lpim-4] += imem[pim-3];
npim = pim - 3;
}
else { /* next command is another */
pim -= 3;
while (imem[pim] != MAGIC && pim >= fixpim) pim--;
if (imem[pim] != MAGIC) error ("something wrong", NULL);
pim += 2;
npim = pim;
}
dx = tmem[lpim-4]; dy = tmem[lpim-3];
if (dx == 0 && dy == 0) lpim -=4 ; /* new rmoveto is irrelevant */
else if (dx == 0) { /* new vmoveto */
tmem[lpim-4] = dy;
tmem[lpim-3] = MAGIC; tmem[lpim-2] = VMOVETO;
lpim--;
}
else if (dy == 0) { /* new hmoveto */
tmem[lpim-3] = MAGIC; tmem[lpim-2] = HMOVETO;
lpim--;
}
shift = lpim - (pim - npim);
if (topim+shift >= MAXIMEM) error ("MAXIMEM overflow", NULL);
if (shift < 0) for (i=pim; i<topim; i++) imem[i+shift] = imem[i];
if (shift > 0) for (i=topim-1; i>=pim; i--) imem[i+shift] = imem[i];
topim += shift;
for (i=0; i<lpim; i++) imem[npim+i] = tmem[i];
return;
}
}
void print_subrs(void)
{
/* prints all /Subrs (original plus new) to pps
*/
int p;
for (p=0;p<pfbnumsubs;p++) {
fprintf (fpps, "dup %d {\n", p);
fixpim = convert_code(savedsubr[p].code, savedsubr[p].len);
print_code (fixpim);
fprintf (fpps, "\t} %s\n", NPcommand);
pim = fixpim;
}
for (p=0;p<numsubs;p++) {
fprintf (fpps, "dup %d {\n", p + pfbnumsubs);
print_code (subr[p].code);
fprintf (fpps, "\t} %s\n", NPcommand);
}
}
void print_chars(void)
{
/* prints all /CharStrings (original plus new) to pps
*/
int p;
for (p=0; p<pfbchars; p++) if (savedchars[p].name) {
fprintf (fpps, "/%s {\n", savedchars[p].name);
fixpim = convert_code(savedchars[p].code, savedchars[p].len);
print_code (fixpim);
fprintf (fpps, "\t} %s\n", NDcommand);
pim = fixpim;
}
for (p=0; p<numchars; p++)
if (!newchar[p].origname || newchar[p].origcode) {
fprintf (fpps, "/%s {\n", newchar[p].name);
if (newchar[p].origname == NULL)
print_code (newchar[p].owncode);
else {
fixpim = convert_code(newchar[p].origcode, newchar[p].origlen);
insert_newcode (fixpim, p);
print_code (fixpim);
pim = fixpim;
}
fprintf (fpps, "\t} %s\n", NDcommand);
}
}
void check_doublechars()
{
/* checks the chars from pfbchars \cap newchars.
If not empty, does the warning. Then check_doublechars() sets the
origcode to newchar array and calculates the sumchars ... the number
of pfbchars \cup newchars
*/
int i, j, empty;
empty = 1;
for (i=0; i<pfbchars; i++)
for (j=0; j<numchars; j++)
if (strcmp(savedchars[i].name,newchar[j].name)==0) {
empty = 0;
savedchars[i].code = NULL;
break;
}
if (!empty) { /* print warning */
fprintf(stderr, "\nWarning: the following CharNames will be replaced");
fprintf(stderr, " by new definition:\n");
for (i=0; i<pfbchars; i++)
if (savedchars[i].code == NULL) {
fprintf(stderr, " /%s", savedchars[i].name);
savedchars[i].name = NULL;
}
fprintf(stderr, "\n");
}
empty = 1;
for (j=0; j<numchars; j++) {
newchar[j].origcode = NULL;
for (i=0; i<pfbchars; i++)
if (newchar[j].origname &&
strcmp(newchar[j].origname,savedchars[i].name)==0) {
newchar[j].origcode = savedchars[i].code;
newchar[j].origlen = savedchars[i].len;
break;
}
if (newchar[j].origcode == NULL && newchar[j].origname != NULL) empty = 0;
}
if (!empty) { /* print warning */
fprintf(stderr, "\nWarning: the following CharNames will be ignored");
fprintf(stderr, " because of no basechar exists:\n");
for (j=0; j<numchars; j++)
if (newchar[j].origcode == NULL && newchar[j].origname != NULL)
fprintf(stderr, " /%s", newchar[j].name);
fprintf(stderr, "\n");
}
sumchars = 0;
for (i=0; i<pfbchars; i++)
if (savedchars[i].name != NULL) sumchars++;
for (j=0; j<numchars; j++)
if (newchar[j].origcode != NULL || newchar[j].origname == NULL) sumchars++;
return;
}
int getpfb(void)
{
/* getpfb() gets new byte from pfb, decrypts it and check the pattern
*/
int c;
c = egetc();
if (c==EOF) error ("text '%s' not found", pattern);
if (c==pattern[pip]) {
pip++;
if (pattern[pip]==0) ispattern = 1;
}
else pip = 0;
return c;
}
void set_pattern(char *pat)
{
/* new pattern is set for checking the input from pfb
*/
ispattern = 0; pip = 0;
strcpy (pattern, pat);
}
void save_string(num, status)
{
/* save_string stores the decrypted per-byte CharString or Subr
from pfb to global buffer
*/
int c, p, l;
set_pattern(RDcommand);
p = 0;
while(!ispattern) buf[p++] = getpfb();
p -= 4;
while(p>0 && buf[p] != ' ') p--;
if (p==0) error ("the %s parameter not found", RDcommand);
l = atoi (&buf[p]);
l -= lenIV;
getpfb(); /* ignore the space after RDcommand */
if (status==SAVECHAR) {
while(p>=0 && buf[p] == ' ') p--;
if (p<0) error ("the CharName not found", NULL);
buf[p+1] = 0;
savedchars[num].name = add_gbuf(buf);
savedchars[num].code = pbuf;
savedchars[num].len = l;
} else {
savedsubr[num].len = l;
savedsubr[num].code = pbuf;
}
is_textspace = 0;
cr = 4330;
for (p=0; p<lenIV; p++) (void) cgetc();
for (p=0; p<l; p++) {
c = cgetc();
store_gbuf(c);
}
is_textspace = 1;
}
void find_text (char *text, char *command)
{
/* searchs the text in gbuf and save the /string preceeded this text
to command.
*/
unsigned char *found;
int p;
found = strstr(pbuf, text);
if (!found) error ("string '%s' not found", text);
while (found > pbuf && found[0]!='/') found--;
if (found==pbuf) error ("'/?? {%s...' not found",text);
found++;
p = 0;
while (p<3 && found[p]!=' ' && found[p]!='{') command[p] = found[p++];
if (p==3) error ("'/?? {%s...' must be two character string", text);
command[p] = 0;
}
void replace_name (void)
{
unsigned char *lbuf;
int i, len;
if (!nameisread) return;
lbuf = strstr (pbuf, oriname);
while (lbuf) {
if (diffname > 0) {
i = strlen(lbuf);
while (i>0) lbuf[i+diffname] = lbuf[i--];
}
if (diffname < 0) {
i = -diffname;
while (lbuf[i]) lbuf[i+diffname] = lbuf[i++];
lbuf[i+diffname] = 0;
}
len = strlen(newname);
for (i=0; i<len; i++) lbuf[i] = newname[i];
lbuf = &lbuf[len];
lbuf = strstr (lbuf, oriname);
}
}
void convert_pfb(void)
{
/* does the main work. Converts the pfb input to pps output.
*/
char *found;
char dupbuf[4];
int c, p, i, bb[4];
immediate_eexec = 0; in_eexec = 0;
first_byte = 1;
pfb_remaining = 0;
savedchar = -1;
is_textspace = 1;
fixpbuf = pbuf;
lenIV = 4;
set_pattern("\n");
while (!ispattern) store_gbuf (getpfb());
pbuf[0] = 0; pbuf = fixpbuf;
replace_name ();
fputs (pbuf, fpps);
for (i=0; i<numrems; i++) fprintf (fpps, "%% %s\n", remark[i]);
set_pattern("/Encoding");
while (!ispattern) store_gbuf (getpfb());
pbuf[0] = 0; pbuf = fixpbuf;
replace_name ();
fputs (pbuf, fpps);
set_pattern(" def");
while (!ispattern) getpfb();
fprintf (fpps, " 256 array\n0 1 255 {1 index exch /.notdef put} for\n");
print_encoding();
fprintf (fpps, "readonly def");
set_pattern("/FontBBox");
while (!ispattern) fputc(getpfb(), fpps);
c = ' '; p = 0;
while (c!=']' && c!='}' && c!='\n') c = buf[p++] = getpfb();
buf[p] = 0; p = 0;
for (i=0; i<4; i++) {
while (buf[p] && !isdigit(buf[p]) && buf[p]!='-') p++;
if (buf[p]==0) error("cannot able to read FontBBox (%s)", buf);
bb[i] = atoi(&buf[p]);
while (buf[p] && buf[p]!=' ') p++;
}
fprintf (fpps, " [%d %d %d %d]",
min(bb[0],glX), min(bb[1],glY), max(bb[2],guX), max(bb[3],guY));
set_pattern("currentfile eexec");
while (!ispattern) fputc(getpfb(), fpps);
immediate_eexec = 1;
set_pattern("/Subrs");
while (!ispattern) {
c = getpfb();
store_gbuf(c);
fputc(c, fpps);
}
pbuf[0] = 0; pbuf = fixpbuf;
find_text ("string currentfile", RDcommand);
find_text ("noaccess def", NDcommand);
find_text ("noaccess put", NPcommand);
found = strstr(pbuf, "/lenIV ");
if (found && isdigit(found[7])) lenIV = atoi(found + 7);
pfbnumsubs = 0;
fixpim = pim;
while (1) {
set_pattern("\n");
while (!ispattern) getpfb();
for (p=0;p<3;p++) dupbuf[p] = getpfb();
dupbuf[3] = 0;
if (strcmp(dupbuf,"dup") != 0) break;
save_string (pfbnumsubs++, SAVESUBR);
}
p = pfbnumsubs + numsubs;
fprintf(fpps, " %d array\n", p);
print_subrs(); /* prints orig + new subrs in readable form */
fputs (dupbuf, fpps);
pbuf = fixpbuf;
pim = fixpim; /* restore gbuf and imem pointers */
set_pattern("/CharStrings");
while (!ispattern) fputc(getpfb(), fpps);
pfbchars = 0;
while (1) {
set_pattern("\n");
while (!ispattern) getpfb();
c = getpfb();
if (c != '/') break;
save_string (pfbchars++, SAVECHAR);
}
check_doublechars();
fprintf(fpps, " %d dict dup begin\n", sumchars);
print_chars(); /* prints orig + new CharScrings in readable form */
fputc(c, fpps);
set_pattern("currentfile closefile");
while (!ispattern) fputc(getpfb(), fpps);
fprintf (fpps, "\n");
pbuf = fixpbuf;
pim = fixpim;
}
int main(int argc, char **argv)
{
int p;
fprintf(stderr, "This is t1accent, (c) Petr Olsak, Apr. 1998\n");
if (argc < 2) {
fprintf (stderr, " usage: t1accent config.file.\n"
" see t1accent.doc for more details.\n");
return 1;
}
fin = fopen(argv[1], "r");
if (!fin) error("cannot open config file %s for reading", argv[1]);
init_csnames();
line = 1;
glX = glY = 1000; guX = guY = -1000;
read_config();
globalbbox();
line = 0;
if (!encisread) error("no ENC declaration in config file %s", argv[1]);
for(p=0;p<numfiles;p++) {
strcpy(fname, infile[p]);
if(strlen(fname) > MAXBUF-5) error("pfb file name is too long (%s)",fname);
strcat(fname, ".pfb");
if (srcisread) {
if (strlen(srcdir)+strlen(fname) >= MAXBUF)
error("dirname+pfb file name is too long (%s)",srcdir);
strcpy (buf, fname);
strcpy (fname, srcdir);
strcat (fname, buf);
}
fpfb = fopen(fname, "rb");
if (!fpfb) error("cannot open pfb file %s", fname);
fprintf (stderr, "(%s", fname);
strcpy (buf, infile[p]); strcat(buf,".pps");
fpps = fopen(buf, "w");
if (!fpps) error("cannot write to file %s", buf);
convert_pfb();
fclose(fpfb);
fclose(fpps);
fprintf (stderr, "->%s.pps)\n", infile[p]);
}
return 0;
}
t1accent/t1accent.doc 100666 150 144 147626 6530761656 13426 0 ustar olsak math1
Program t1accent -- přidávání akcentů na úrovni Type1 formátu fontů (pfb)
=========================================================================
Petr Olšák 11.4.1998
Program čte font ve formátu pfb (Type1) a přidává do něj nové znaky.
Tyto nové znaky jsou odvozeny z původních znaků fontu, ke kterým je doplněn
akcent. Činnost programu je řízena konfiguračním souborem, ve kterém lze
uvést názvy nových znaků, kódování nového fontu, deklarace poloh akcentů
vzhledem k původním znakům a konečně tvar akcentu, který je definován
prostřednictvím běžných povelů PostScriptu (moveto, lineto, curveto, ...).
Výstupem programu je textový pseudo-PostScriptový soubor (přípona pps).
V něm je možné dělat další úpravy manuálně nebo prostřednictvím
jednoduchých filtrů (změna názvu fontu a dalších parametrů). Soubor *.pps
lze nakonec převést do formátu pfb prostřednictvím programu t1asm
z veřejného balíku t1utils.
Většina znaků v Type1 fontu je opatřena tzv. "hintovacími informacemi",
které obsahují nápovědu pro rastrovací algoritmus PostScriptu, jak si
počínat při rastrování zejména pro nízká rozlišení. To je důležité při
zobrazení znaků na obrazovce počítače. Hintovací informace o novém znaku
definovaném programem t1accent se přebírají z hintovacích informací
původního znaku. Akcent většinou nepřidává žádné další hintovací informace.
Akcenty jsou prostřednictvím t1accent umístěny vždy prostřednictvím Type1
operátoru callsubr. Operátor seac není využit, protože má nevyhovující
omezení: všechny akcenty by musely mít svou pozici v StandardEncoding
vektoru, takže by nešlo sestrojovat například různý tvar háčku pro malá a
velká písmena.
Program bohužel neřeší tzv. "overlapping". To znamená, že obrysová křivka
pro akcent musí být nazávislá na obrysové křivce pro výchozí znak a tyto
křivky se nesmějí protínat. Pokud se protínají, chování PostScriptového
RIPu není definováno (někdy je výsledek na průniku černý a někdy bílý).
Pro češtinu a slovenštinu to není žádný problém, protože akcenty jsou
umístěny v uctivé vzdálenosti od základového znaku. Pro jiné jazyky
(například škrtátko pro polské l) mohou nastat problémy, které je nutno
řešit dodatečným opracováním fontu ve Fontographeru či podobném nástroji.
Tato dokumentace obsahuje kromě popisu chování programu též stručný popis
formátu Type1 fontů, aby program mohl okamžitě použít kdokoli, kdo si chce
vytvořit pozměněný Type1 font obsahující akcentované znaky.
0. Obsah
--------
1. Spuštění programu
2. Příprava nového fontu
3. Formát konfiguračního souboru
- Klíčové slovo NAME, změna názvu fontu
- Klíčové slovo SRC, adresář se vstupními soubory
- Klíčové slovo IN, seznam vstupních souborů
- Klíčové slovo ENC, kódování fontu
- Klíčové slovo VAR, deklarování proměnných
- Klíčové slovo SUB, deklarování procedur
- Klíčové slovo CHAR, deklarace znaku
- Klíčové slovo REM, zanesení poznámky
- Klíčové slovo BBOX, vymezení FontBBoxu
- Klíčové slovo END, konec konfiguračního souboru
4. Záchytné body ve fontu
5. Základy Type1 formátu
6. Doporučení a pravidla pro Type1 formát
7. Reference
1. Spuštění programu
--------------------
se provede z příkazové řádky:
t1accent konf.soubor
Na příkazové řádce je tedy nutné uvést plné jméno konfiguračního souboru.
Další činnost programu je řízena obsahem konfiguračního souboru. Žádné
další přepínače nebo parametry příkazového řádku nejsou implementovány.
2. Příprava nového fontu
------------------------
Přípravu pfb fontu s doplněnými akcenty můžeme rozdělit do několika kroků.
Předpokládejme, že máme font.pfb a chceme z něj vyrobit csfont.pfb.
1. Konvertujeme font.pfb do pseudo-Postscriptu pomocí t1disasm z t1utils:
t1disasm font.pfb font.ps
2. Připravíme konfigurační soubor pro t1accent. Můžeme přitom využít části
souboru font.ps pro procedury v konfiguračním souboru. Například
popis znaku /caron nazveme SUB /lc-caron a tentýž popis zkopírujeme
ještě jednou, doplníme dopředu jiné parametry pro moveto, vložíme
případné transformace pomocí scaled (háček nad velkými písmeny bývá
většinou mělčí) a tuto proceduru nazveme /uc-caron. Sestavovací povely
CHAR a další údaje v konfiguračním souboru můžeme čerpat z ukázky
csr.tab přibalené do distribuce.
3. Rozhodneme o kódování našeho fontu volbou vhodného *.enc souboru a
případně jeho editací. Můžeme použít csr.enc přibalený do distribuce.
Poznamenejme, že implicitní kódování fontu může být později zaměněno
volbou explicitního encoding vektoru deklarovaného v psfonts.map
programu dvips. Na druhé straně upozorňujeme, že kompatibilita názvů
znaků s jejich tvary je nutná (pozor: některé DTP studia distribuují
fonty s naprosto nekompatibilními názvy znaků!).
4. Provedeme konverzi font.pfb na font.pps povelem:
t1accent konf.soubor
5. Editujeme font.pps (nebo jej filtrujeme automatickým filtrem).
Přidání (c) poznámek apod.
6. Konvertujeme font.pps na nový csfont.pfb povelem:
t1asm -b font.pps csfont.pfb
Pokud potřebujeme vytvořit metriku csfont.afm, je potřeba čerpat z font.afm
a můžeme použít program a2ac pro generování kerningových párů s novými
akcentovanými znaky. Doporučuji tento postup:
1. Editujeme cscorr.tab z distribuce a2ac (výchozí obsah cscorr.tab může být
vyhovující).
2. Vygenerujeme kerningové páry:
a2ac font.afm cscorr.tab font-kpx.afm
3. Vygenerujeme metriku, která respektuje kódování našeho nového fontu
použitím programu Ghostscript (gs) a souboru printafm.ps, který je
k dostání na Internetu (CTAN/dviware/dvitops/printafm.ps):
echo /Název-Našeho-Fontu printafm | gs printafm.ps > csfont.afm
4. Připojíme editorem k obsahu souboru csfont.afm část s řádky začínajícími
KPX z font-kpx.afm, tj. doplníme informace o kerningových párech.
5. Přidáme ligaturní informace ke znaku f, pokud font ligatury obsahuje:
C 102 ; WX ... ; N f ; B . . . . ; L i fi ; L l fl ;
Analogicky můžeme přidat další ligaturní informace.
Nakonec budeme chtít zařadit nový csfont do nějakého sázecího systému. Na
sázecím systému nezáleží, protože formát Type1 by měl být použitelný všude.
Jako příklad uvádím zařazení csfontu do TeXu.
1. Předpokládejme, že nemáme metriku tfm, a potřebujeme ji vyrobit.
Použijeme program afm2tfm z distribuce dvips:
afm2tfm csfont.afm -T soubor.enc -v csfont rfont
Jako soubor.enc musíme načíst stejný soubor, jaký byl použit při
generování fontu programem t1accent. afm2tfm vytvoří metriku
rfont.tfm, která neobsahuje informace o kerningových párech, takže ji
můžeme s klidem vymazat.
2. V předchozím kroku vzniká soubor csfont.vpl, který použijeme:
vptovf csfont.vpl csfont.vf csfont.tfm
Nyní už vzniká metrika včetně kerningových párů csfont.tfm, kterou
instalujeme do TeXového systému. Virtuální font csfont.vf musíme
bezpodmínečně vymazat jako zbytečný vedlejší produkt.
3. V souboru psfonts.map v TeXové instalaci napíšeme:
csfont Název-Našeho-Fontu <csfont.pfb
První údaj je jméno metriky tfm, druhý údaj je jméno fontu použité
jako /Fontname (viz krok 5 přípravy pfb formátu) a za menšítkem je název
souboru pfb.
4. csfont.pfb zařadíme do TeXového systému, obvykle do:
texmf/fonts/type1/název-písmolijny/název-rodiny
Od této chvíle můžeme použít font v TeXu. Například v souboru pokus.tex
připravíme:
\font\test=csfont \test Tady je nějaký český text \end
Po zpracování TeXem:
csplain pokus
a programem dvips:
dvips pokus
máme ve výstupním PostScriptovém kódu pokus.ps nový font zaveden a
připraven k vytištění. Můžeme se o tom přesvědčit například
Ghostscriptem:
gs pokus.ps
Na unixových instalacích máme možnost vidět font i v xdvi, protože tento
program si nechá vyrastrovat bitmapu fontu Ghostscriptem přímo
z instalovaného pfb souboru v právě požadovaném rozlišení.
3. Formát konfiguračního souboru
--------------------------------
Konfigurační soubor programu t1accent je textový. Konce řádku jsou
interpretovány jako mezery. Znak % znamená zahájení komentáře až do konce
řádku, včetně tohoto konce, (tj. je ignorována i mezera z konce řádku).
Tabelátory a znaky "carrigue return" jsou rovněž interpretovány jako
mezery. Skupina více mezer je interpretována jako jediná mezera.
Konfigurační soubor obsahuje klíčová slova NAME, SRC, IN, ENC, REM, VAR,
SUB, CHAR, BBOX a END (psáno nutně velkými písmeny). Každé klíčové slovo
musí být ukončeno mezerou. Za klíčovými slovy je informace strukturovaná
smluveným způsobem. Každé klíčové slovo tedy uvozuje určitý typ informace.
Na pořadí klíčových slov nezáleží. Toto pravidlo má následující vyjímky:
* Klíčové slovo END ukončuje čtení konfiguračního souboru.
* Pokud se použije proměnná, musí být dříve deklarována pomocí VAR.
* Pokud se použije název procedury, musí být tato procedura dříve deklarována
pomocí SUB.
* Pořadí procedur SUB určuje výsledné pořadí těchto procedur ve výstupním
fontu (což nakonec nemá žádný vliv) a pořadí deklarací CHAR určuje
výsledné pořadí popisů těchto znaků ve výstupním fontu (což také nemá
žádný vliv na chování fontu).
***** Klíčové slovo NAME, změna názvu fontu
NAME Origilalni-Nazev-Fonu -> Novy-Nazev-Fontu
Za klíčovým slovem NAME jsou tři úseky textu odděleny mezerami. První úsek
označuje "původní název fontu", druhým úsekem musí být značka "->" a třetí
úsek označuje "nový název fontu".
Program vyhledá v úvodní části vstupního fontu (až po slovo /Encoding)
sekvenci "původní název fontu" a nahradí jej "novým názvem fontu", který
zapíše do výstupu. "Původní název fontu" se může ve vyhledávané oblasti
vyskytovat vícekrát. Všechny výskyty jsou zaměněny. Pokud máte složitější
požadavky na "najdi a nahraď" v textu fontu, použijte sed, awk, perl či
jiný filtr až poté, co program t1accent vytvoří výstupní textový soubor.
Klíčové slovo NAME se může v konfiguračním souboru vyskytovat nejvýše
jednou. Pokud není použito vůbec, program nenahrazuje žádné vstupní
sekvence alternativami.
Příklad:
NAME Times-Roman -> Times-Roman-CZ
***** Klíčové slovo SRC, adresář se vstupními soubory
SRC /adresar/kde/nalezt/vstupni/soubory/
Za slovem SRC je zapsán adresář, kde bude program hledat vstupní soubory
*.pfb. Tento adresář musí být ukončen znakem '/' (v UNIXu) nebo znakem '\'
(v DOSu). Klíčové slovo SRC lze použít nejvýše jednou. Není-li SRC použito
vůbec, program hledá vstupní soubory v aktuálním adresáři. Příklady:
SRC /usr/local/share/texmf/fonts/type1/public/cm/
nebo
SRC d:\emtex\fonts\type1\cm\
***** Klíčové slovo IN, seznam vstupních souborů
IN jméno jméno jméno ...
Za IN následuje seznam jmen oddělený mezerami. V seznamu je nutné uvést
aspoň jedno jméno.
Jména odpovídají jménům postupně načítaných souborů *.pfb. Přípona .pfb se
nesmí psát -- program ji doplní automaticky. Je-li uvedeno více než jedno
jméno, program postupně provede konverzi pro všechny vstupní soubory *.pfb.
Ke každému vstupnímu souboru *.pfb vytvoří výstupní *.pps. Adresář se
vstupními soubory je deklarován klíčovým slovem SRC a výstupní soubory
*.pps jsou ukládány vždy do aktuálního adresáře.
Seznam jmen je ukončen výskytem nového klíčového slova (NAME, SRC, IN, ENC,
REM, VAR, SUB, CHAR, BBOX nebo END), které samo o sobě už není považováno
za jméno vstupního souboru.
Opakované použití IN má stejný efekt, jako jedno IN se seznamem všech
souborů. Například:
IN jméno1
IN jméno2
END
je totéž jako:
IN jméno1 jméno2
END
***** Klíčové slovo ENC, kódování fontu
ENC jméno
Za slovem ENC následuje jméno ukončené mezerou. Veškerý další text až po
výskyt dalšího klíčového slova je ignorován.
Jméno odpovídá jménu souboru *.enc, které obsahuje definici kódování
výstupního fontu. Kódování vstupního fontu je nepodstatné a je programem
ignorováno. Přípona .enc se nesmí psát -- program ji doplní automaticky.
Kódování fontu je v souboru .enc definováno obvyklým způsobem (viz třeba
.enc soubory z dvips). Je stanoveno pořadí názvů jednotlivých znaků. Tyto
názvy jsou uspořádány do 256 prvkového tzv. Encoding vektoru. Je-li některá
pozice prázdná, je pro ni vyhrazen název /.notdef . Celý Encoding vektor je
uzavřen do závorek [ ]. Text před a za těmito závorkami je programem
t1accent ignorován. O mezerách a znaku '%' platí totéž, co je uvedeno
v úvodu této kapitoly. Jednotlivé názvy musí být uvozeny lomítkem
a mohou (ale nemusí) být odděleny mezerami. Počet názvů musí být přesně
256.
V konfiguračním souboru musí být právě jedna deklarace ENC. Jinak program
ohlásí chybu.
***** Klíčové slovo VAR, deklarování proměnných
VAR /název číslo
Název musí být uvozen lomítkem a nesmí být použit ve významu žádného znaku
nebo názvu procedury. Číslo je desetinné číslo s nepovinným znaménkem minus
vpředu a s nepovinnou desetinnou tečkou někde v řadě cifer. Číslo nesmí
obsahovat mezery. Za mezerou ukončující číslo program ignoruje vše až po
další klíčové slovo.
Za číslem doporučuji psát (v éto verzi zatím zbytečné) slovo def, aby
konfigurační soubory byly kompatibilní s budoucí verzí programu t1accent,
kde plánuji implementovat aritmetiský parser s postfixovými operátory
ukončený operátorm def. V současné verzi tedy můžeme psát:
VAR /ac-shift 250 def
zatímco do budoucna se plánuje implementovat něco takového:
VAR /new-variable 250 old-variable add dup mul neg def
% new-variable = - (250 + old-variable)^2
Program do proměnné "název" uloží hodnotu čísla. Kdekoli dále v těle
procedury SUB nebo v deklaraci CHAR, kde se používá numerický operand,
je možno nahradit tento numerický operand názvem proměnné, tentokrát bez
použití lomítka na začátku.
Opakované VAR se stejným názvem proměnné není možné v této verzi programu
použít, tj. nejedná se o proměnné v pravém slova smyslu, ale jen o jakési
konstanty.
***** Klíčové slovo SUB, deklarování procedur
SUB /název { popis procedury }
Vše, co následuje za zavírací složenou závorkou až po následující klíčové
slovo je programem t1accent ignorováno. Můžete tam třeba formálně uvést
slůvko "def", aby to vypadalo jako PostScriptová definice.
Název procedury musí být uvozen lomítkem a nesmí být použit ve významu
názvu žádného znaku použitého ve fontu ani proměnné. Obsah procedury
zahrnuje sekvenci některých z následujících postfixových operátorů.
Operandy musejí být desetinná čísla (s nepovinnou desetinnou tečkou a
případným znaménkem). V této dokumentaci jsou operandy zapisovány
v <takových> závorkách:
operandy operátory kde jsou definovány
---------------------------------------------------------------------
<sx> <sy> scaled ... t1accent
<dx> vvaxis ... t1accent
<x> <y> moveto ... PostScript
<dx> <dy> rmoveto ... PostScript, Type1
<x> <y> lineto ... PostScript
<dx> <dy> rlineto ... PostScript, Type1
<x1> <y1> <x2> <y2> <x> <y> curveto ... PostScript
<dx1> <dy1> <dx2> <dy2> <dx> <dy> rcurveto ... PostScript
closepath ... PostScript, Type1
Kromě toho procedura může obsahovat všechny Type1 operátory, které jsou
podrobněji popsány v kapitole 5 nebo v [1] a [2].
Program t1accent interpretuje operátory scaled a vvaxis, konvertuje
operátory moveto, lineto, curveto a rcurveto do odpovídajících Type1
operátorů a pronásobí operandy pro Type1 operátory hlineto, hmoveto,
hvcurveto, rrcurveto, vhcurveto, vlineto a vmoveto podle aktuálního
koeficientu definovaného pomocí scaled. Výsledek zapíše do výstupu jako
novou Type1 proceduru fontu.
Program rovněž trasuje pohyb aktuálního bodu kresby a pokud není v závěru
procedury tento bod vrácen na výchozí místo a není použit povel return,
zařadí program automaticky povely:
<-x0> <-y0> rmoveto
return
kde (<x0>, <y0>) jsou souřadnice poslední pozice aktuálního bodu kresby.
Pokud nechceme, aby program takovou práci dělal, musíme uzavřít text
procedury explicitně povelem return.
Operátor scaled nastavuje koexicient pronásobení <sx> pro všechny
následující údaje <dx> a koeficient <sy> pro všechny následující údaje
<dy>. Na počátku každé procedury se inicializuje <sx> = <sy> = 1.
Operátor scaled lze použít kdekoli, ale doporučuje se jej použít před
zahájením tahu (pomocí lineto, curveto a alternativ). Je možné jej použít
dokonce vícekrát za sebou). Nové použití je relativní vzhledem
k předchozímu nastavení:
SUB /ac-accent {
100 100 scaled % nastavení globálního poměru
2 7 moveto % aktuální bod kresby má souřadnice (200,700)
1 .5 scaled % celá křivka bude vzhledem bodu (200,700)
% na výšku deformovaná na polovinu
5 5 lineto % ve skutečnosti se provede:
% 100*(5-2) 0.5*100*(5-7) rlineto
8 7 lineto % provede se 100*(8-5) 0.5*100*(7-5) rlineto
5 5.5 lineto
closepath
}
Program t1accent vytvoří z tohoto popisu následující proceduru (popsanou
v pseudo-PostScriptovém jazyce prostřednictvím Type1 operátorů):
dup <číslo proc.> {
200 700 rmoveto
300 -100 rlineto
300 100 rlineto
-300 -75 rlineto
closepath
-500 -625 rmoveto
return
} NP
Program zaokrouhlí výsledné numerické hodnoty operandů na celá čísla.
Všimneme si, že "návratové" -500 -625 rmoveto odpovídá poslední poloze
aktuálního bodu před operátorem closepath. Aktuální bod kresby
není povelem closepath (na rozdíl od PostScriptového closepath) v Type1
formátu měněn, takže "návratové" rmoveto je v pořádku.
Operátor vvaxis nastavuje vizuální vertikální osu akcentu na danou hodnotu
podle <dx>. Vizuální osa bude od aktuálního bodu kresby vzdálena o
<dx>*<sx> doprava (<sx> je transformace ze scaled). Není-li operátor vvaxis
použit, program považuje za střed akcentu přesný střed mezi pravým a levým
extrémem při konstrukci křivky. Tento údaj se využije při usazování akcentu
v deklaracích CHAR při použití operátoru putcenter.
V předchozím příkladě není vvaxis použito, tj. vizuální vertikální osa
má souřadnici 200+800/2 = 500. Pokud bychom použili například ".5 vvaxis"
před prvním moveto, měla by osa souřadnici 50. Při použití ".5 vvaxis"
za prvním moveto a před prvním lineto, bude mít osa souřadnici 250.
Konečně třeba ".5 vvaxis" za "5 5 lineto" nastaví osu na souřadnici 550.
Pro nakloněná písma doporučuji nastavit vvaxis vlevo od skutečné osy,
protože program vůbec nepočítá s nakloněním osy znaku. Druhou možností je
řídit vychýlení prostřednictvím parametrů operátoru putcenter v deklaraci
CHAR.
Kromě numerických operandů, dříve deklarovaných proměnných pomocí VAR a
operátorů je možné v proceduře použít název dříve deklarované procedury.
Program tento název převede na aktuální číslo dané procedury. Například:
SUB /one-dot {
200 700 moveto
200 670 225 645 255 645 curveto
285 645 310 670 310 700 curveto
310 730 285 755 255 755 curveto
225 755 200 730 200 700 curveto
}
SUB /lc-dieresis {
155 vvaxis % osa bude mít souřadnici 200/2 + poloměr tečky
one-dot callsubr
200 hmoveto
one-dot callsubr
}
Program vytvoří tento výstup:
dup <číslo procedury one-dot> {
200 700 rmoveto
-30 25 -25 30 vhcurveto
30 25 25 30 hvcurveto
30 -25 25 -30 vhcurveto
-30 -25 -25 -30 hvcurveto
closepath
-200 -700 rmoveto
return
} |
dup <číslo procedury lc-dieresis> {
<číslo procedury one-dot> callsubr
200 hmoveto
<číslo procedury one-dot> callsubr
-200 hmoveto
return
} |
Z ukázky si můžeme všimnout několik věcí.
1. program automaticky doplní operátor closepath na konci procedury, pokud
jsme použili operátory pro kresbu. Jestliže nám tato inteligence programu
nevyhovuje, můžeme napsat do procedury na její konec slovo return. Pak máme
jistotu, že program nedoplní na konec procedury vůbec nic.
2. Při trasování pohybu aktuálního bodu kresby program nevstupuje do volaných
procedur a předpokládá, že procedura nezmění polohu aktuálního bodu kresby.
V našem příkladě program za střed akcentu /lc-dieresis předpokládá
implicitně bod (0,0), protože v této proceduře není nic přímo kresleno
(do volaných procedur při vyhodnocování středu kresby program nevstupuje).
To je pro náš znak přehlásky nevyhovující, a proto musíme nastavit osu
akcentu ručně pomocí vvaxis.
***** Klíčové slovo CHAR, deklarace znaku
Existují tři možnosti, jak použít klíčové slovo CHAR.
1. Vložení akcentu:
CHAR /nový-název /původní-název /název-procedury <x> <y> put-operátor
2. Korekce původního znaku a případné vložení akcentu:
CHAR /nový-název /původní-název <dsbx> <dy> <dwx> correct
/název-procedury <x> <y> put-operátor
3. Definice nového znaku:
CHAR /nový-název { popis znaku }
"Nový-název" je název nově deklarovaného znaku, "původní-název" je název
znaku, ze kerého se vychází (dále budeme říkat "výchozí znak") a
"název-procedury" odpovídá názvu procedury (deklarované dříve pomocí SUB)
pro vykreslení akcentu. Volání této procedury se přidá do popisu výchozího
znaku, přičemž se podle parametrů "put-operátoru" připraví poloha kreslícího
bodu před voláním procedury pro akcent na požadované místo.
V místě sekvence "/název-procedury" může být použito smluvené slovo
"/.noinsert" za kterým už není nutné psát konstrukci "<x> <y> put-operátor".
Pak se k výchozímu znaku nepřidává volání žádné procedury pro akcent.
Použijeme například tehdy, když chceme pouze změnit parametry znaku pomocí
"<dsbx> <dy> <dwx> correct", ale nepotřebujeme přidat akcent.
Výchozí znak musí být obsažen ve vstupním pfb fontu. Není možno použít znak
deklarovaný dříve pomocí CHAR.
Ve třetím případě "CHAR /nový-název { popis znaku }" musí popis znaku
obsahovat všechny náležitosti pro popis znaku (tj. hsbw nebo seac,
hstem, vstem apod.). Vynecháno může být jen závěrečné endchar, které
program (bez dalších operátorů) doplní automaticky.
Je možné použít navíc operátory moveto, lineto, curveto a rcurveto, které
program převede do Type1 operátorů analogicky, jako při deklaraci SUB.
Rovněž je možné použít volání procedur jménem a operátor scaled (parametry
operátoru hsbw ale nebudou použitím scaled změněny).
Parametry konstrukce "<dwx> <dy> <dsb> correct" jsou interpretovány takto:
<dsbx> ... změna polohy levostranného bodu: <sbx> = <původní sbx> + <dsbx>
<dwx> ... změna šířky znaku <wx>: <wx> = <původní wx> + <dwx>
<dy> ... posun kresby znaku o <dy> nahoru: <dy> vmoveto
První dva parametry <sbx> a <wx> jsou uvedeny v popisu výchozího znaku před
operátorem hsbw takto:
<sbx> <wx> hsbw
a t1accent tyto parametry jednoduše pozmění. Tím se změní celková šířka
znaku <wx> a případně se celá kresba znaku posune ve směru osy x o <dsbx>,
protože veškerá kresba znaku je vztažena k poloze levostranného bodu (angl.
left sidebearing point). Pokud se použije nenulové <dy>, program zařadí
posun aktuálního bodu kresby ve tvaru "<dy> vmoveto" před první kreslící
operátor a dále upraví parametry operátorů hstem a hstem3 podle nové
polohy kresby. Výsledným efektem je posun kresby znaku o hodnotu <dy> ve
směru osy y.
Není-li konstrukce "<dsbx> <dy> <dwx> correct" uvedena, program pracuje
stejně, jako při "0 0 0 correct".
"Put-operátor" je jedna ze čtyř možností:
putorigin ... podle počátku
putsidebar ... podle "left sidebearing" bodu
putcenter ... podle osy znaku a osy akcentu
putafter ... podle šířky znaku
Je-li <x> i <y> rovno nule, pak operátor putorigin ztotožní souřadnice
(0,0) akcentu s počátkem znaku. Operátor putsidebar ztotožní souřadnice
(0,0) akcentu s levohranným bodem a operátor putcenter realizuje posun ve
směru osy x tak, aby vizuální osa akcentu z vvaxis se kryla s geometrickou
osou znaku (origin + <wx>/2). Konečně putafter ztotožní souřadnice (0,0)
akcentu s bodem (<wx>, 0).
Posun ve směru osy y není při nulovém <y> žádným z těchto operátorů
realizován. Při nenulovém <x> nebo <y> se navíc posunuje celý akcent o <x>
doprava a o <y> nahoru (při záporných hodnotách doleva a dolu).
Umístění kresby akcentu z procedury popíšeme nyní přesněji. Nechť výchozí
znak obsahuje po korekci konstrukcí "<dsbx> <dy> <dwx> correct" povel:
<sbx> <wx> hsbw
Při <x> <y> putsidebar se do popisu pro kresbu znaku vloží:
<x> <y> rmoveto
<číslo proc.> callsubr
<-x> <-y> rmoveto
Při použití <x> <y> putorigin se vloží:
<x-sbx> <y> rmoveto
<číslo proc.> callsubr
<-x+sbx> <-y> rmoveto
Při použití <x> <y> putcenter dostáváme tento výsledek:
<x-sbx-cx+wx/2> <y> rmoveto
<číslo proc.> callsubr
<-x+sbx+cx-wx/2> <-y> rmoveto
kde <cx> je souřadnice vertikální osy akcentu z vvaxis.
Konečně při <x> <y> putafter dostáváme:
<x+wx-sbx> <y> rmoveto
<číslo proc.> callsubr
<-x-wx+sbx> <-y> rmoveto
Je-li některý z parametrů rmoveto nulový, je automaticky nahrazen
operátorem hmoveto resp. vmoveto. Jsou-li oba parametry rmoveto nulové,
není tento povel použit vůbec.
Uvedený popis se vkládá za deklarace hstem, vstem a hsbw, ale před první
operaci na posun bodu pro vykreslení výchozího znaku. To znamená, že volání
procedury pro kresbu akcentu je umístěno před první rmoveto, rlineto
případně další. V takové situaci je aktuální bod kresby podle standardu
Type1 inicializován do levostranného bodu. Je rovněž nutné, aby
procedura vrátila aktuální bod kresby do stejného místa, odkud si jej
vyzvedla, Jen tak se vrátí aktuální bod kresby do výchozího levostranného
bodu a kresba vlastního znaku se neposune nežádoucím způsobem.
Před voláním procedury je zařazen povel "<dy> vmoveto" z případné
konstrukce "<dsbx> <dy> <dwx> correct". Tím se posunuje o <dy> ve směru
osy y nejen výchozí znak, ale i akcent.
***** Klíčové slovo REM, zanesení poznámky
REM "text poznámky"
Program přidá za první řádek v každém výstupním souboru *.pps text poznámky
za jedno procento jako komentář. První řádek zůstává na prvním místě,
protože se předpokládá, že v něm je smluvená dvojice "%!" a název fontu.
Text poznámky je bezpodmínečně nutné uzavřít do uvozovek (které se do
výstupu nepřekreslují). Každý povel REM vytvoří právě jeden řádek navíc na
výstupu. Příklad:
REM "TestFonts -- pfb version 1.0, generated from XY fonts. NO WARRANTY."
REM "Accents are added using t1accent program, (c) Petr Olsak, 1998"
První tři řádky na výstupu pak vypadají třeba takto:
%!FontType1-1.0: TestFont-Roman-BoldItalic 12345
% TestFonts -- pfb version 1.0, generated from XY fonts. NO WARRANTY.
% Accents are added using t1accent program, (c) Petr Olsak, 1998
Doporučuji zařadit aspoň dva komentářové řádky podobné výše uvedeným. Na
jednom řádku uveďte, ze kterého zdroje byl font generován a na druhém
uveďte jméno programu, kterým byly do fontu přidány nové informace.
***** Klíčové slovo BBOX, vymezení FontBBoxu
BBOX <lx> <ly> <ux> <uy>
Parametry <lx>, <ly>, <ux>, <uy> jsou numerické hodnoty, které určují
souřadnice levého dolního rohu (<lx>, <ly>) a pravého horního rohu
(<ux>, <uy>) pomyslného obdélníku, který teoreticky oblopuje nějaký znak ve
fontu. Opakované použití BBOX deklaruje další obdélníky a program nakonec
spočítá "sjednocení" těchto obdélníků (minima všech <lx>, <ly> a maxima
všech <ux>, <uy>). Dále program přečte údaje z FontBBox jakoby šlo o další
povel BBOX. Výsledné "sjednocení" všech obdélníků (včetně tohoto
posledního) zapíše do FontBBox na výstupu.
Program automaticky počítá BBOX každého akcentu a při použití povelu CHAR,
který začleňuje akcent, započítá do celkového BBOXu <ly> a <uy> akcentu
včetně možného posunutí o <dy> pomocí correct a o "<y> put-operátor".
Program ale nezapočítává do celkového BBOXu <lx> a <ux> akcentu, protože
by musel být implemetován dvojí průchod nad vstupním pfb souborem, což
není. Většinou ale <lx> a <ux> základového znaku bývá významnější a je už
zahrnut do vstupního FontBBox, takže tento nedostatek není příliš velkým
handicapem. Pokud ale potřebujeme sdělit programu nějaké důležité výjimky
(například promile v CSfontech), použijeme klíčové slovo BBOX.
***** Klíčové slovo END, konec konfiguračního souboru
Toto slovo ukončuje čtení konfiguračního souboru. Vše za tímto slovem bude
ignorováno. Stejně tak je čtení konfiguračního souboru ukončeno skutečným
koncem souboru. Klíčové slovo END můžeme použít například hned za slovem
ENC, pokud přechodně nechceme generovat nový font, ale jen rozkryptovat
stávající font z pfb formátu do čitelného pseudo-PostScriptu.
4. Záchytné body ve fontu
-------------------------
Program t1accent neinterpretuje PostScriptový kód fontu jako PostScriptový RIP.
V textu fontu se proto orientuje jen pomocí tzv. záchytných bodů
-- sekvencí znaků (patterns). Nejsou-li tyto záchytné body ve
fontu přítomny, nebo jsou-li uvedeny v jiném pořadí, program t1accent může
havarovat. V takovém případě doporučuji dekryptovat font pomocí t1disasm
z t1utils, prohlédnout si strukturu fontu a koncepci záchytných bodů. Je
možné případně pozměnit funkci convert_pfb v t1accent.c a program pro
speciální font kompilovat znova. Implementovaná funkce convert_pfb počítá s
těmito záchytnými body (ve stanoveném pořadí):
1. "\n" ... konec prvního řádku
Za tento záchytný bod přidá program texty poznámek deklarované pomocí REM
2. "/Encoding" ... vložení encoding vektoru podle deklarace ENC
Za tento text program přidá:
a) " 256 array\n0 1 255 {1 index exch /.notdef put} for\n"
b) "dup <kód znaku> /<název znaku> put\n" (256krát podle ENC)
c) "readonly def"
Vstupní text fontu za "/Encoding" až po výskyt " def" je ignorován.
3. "/FontBBox" ... aktualizace FontBBox
Program přečte (ale nepřepisuje do výstupu) hodnoty <lx>, <ly>, <ux> a
<uy>, které mohou mít na vstupu dvojí formát:
{<lx> <ly> <ux> <uy>} nebo [<lx> <ly> <ux> <uy>]
Dále upraví <lx>, <ly>, <ux> a <uy> na případně nové hodnoty.
Nakonec program vypíše do výstupu pozměněné hodnoty ve formátu:
" [<lx> <ly> <ux> <uy>]".
4. "currentfile eexec" ... přechod na zakryptovanou část fontu
Po výskytu tohoto záchytného bodu program zapne dekryptovací algoritmy
zařazené do vstupních rutin. Vše přepisuje do výstupu.
5. "/Subrs" ... kontrola deklarací v zakryptované části
Vše od "currentfile eexec" až po "/Subrs" přepisuje program v
rozkryptované formě do výstupu, ale navíc si text uchová v paměti
pro zpětné prohledání. Vyhledá tyto výskyty textu:
a) "string currentfile" ... zjistí tzv. RDcommand
b) "noaccess def" ... zjistí tzv. NDcommand
c) "noaccess put" ... zjistí tzv. NPcommand
d) "/lenIV" ... zjistí případný počet úvodních bytů pro CharStrings
V případech a) až c) postupuje takto:
(i) vyhledá smluvený text,
(ii) posune se doleva na první výskyt znaku "/",
(iii) první nejvýše dva nemezerové znaky různé od "{" za znakem "/" jsou
hledané RD, ND nebo NPcommand.
RDcommand použije program dále v orientaci
v CharStrings a Subrs, NPcommand přidá na konec každé rozkryptované
procedury a NDcommand analogicky přidá na konec každé definice
znaku. Vyhledání a) až c) musí být úspěšné, jinak program
nemůže dále pracovat.
V případě d) program přečte číslo zapsané za "/lenIV" pro potřeby
dekryprovacího algoritmu. Není-li "/lenIV" přítomno, program implicitně
předpokládá lenIV rovno čtyřem.
Dále program přečte do paměti (bez přepisování do výstupu) popisy všech
procedur takto:
(i) ignoruje vše až do konce řádku "\n"
(ii) začíná-li nový řádek sekvencí "dup" načte novou proceduru, jinak
cyklus ukončí
(iii) opakuje cyklus až do načtení všech procedur
Jednotlivou proceduru načítá program takto:
(i) za sekvencí "dup" očekává: "cokoli <počet bytů> <RDcommand>"
Není-li zjistitelný <počet bytů> nebo <RDcommand>, program
havaruje.
(ii) odebere ze vstupu <počet bytů> bytů za přečteným <RDcommand> a
dešifruje je jako proceduru.
Konečně program zapíše do výstupu:
a) " <nový počet procedur> array\n"
b) Původní a pak nové popisy procedur v rozkryptovaném tvaru. Tyto
popisy procedur jsou zapsány ve formátu:
"dup <číslo procedury> {\n"
"\t<vlastní popis procedury -- opernady a operátory>\n"
"\t} <NPcommand>\n"
6. "/CharStrings"
Vše po poslední proceduře až po "/Charstrings" je přepisováno do
výstupu. Pak program přečte popisy všech znaků ze vstupu bez
přepisování do výstupu analogicky, jako četl popisy procedur.
Jen místo "dup" na začátku řádku očekává znak "/". Do výstupu uloží:
a) " <nový počet znaků fontu> dict dup begin\n"
b) Původní a pak nové popisy znaků fontu v rozkryptovaném tvaru.
Popisy znaků jsou zapsány ve formátu:
"/<název znaku> {\n"
"\t<vlastní popis znaku -- opernady a operátory>\n"
"\t} <NDcommand>\n"
7. "currentfile closefile" ... konec souboru
vše za definicemi znaků až po "currentfile closefile" včetně je
přepisováno do výstupu.
5. Základy Type1 formátu
------------------------
Text uvedený výše považuji za dostatečnou dokumentaci k programu t1accent.
Pokud ale někdo nemá okamžitý přístup k informacím z [1] a zvláště z [2],
je možné, že se zatím příliš mnoho věcí nedozvěděl. Pro takové uživatele
připisuji následující velmi stručný výtah z popisu formátu Type1.
Především zcela vynechám definici binárního formátu pfb o dvojnásobně
kryptovaných informacích pomocí PostScriptového operátoru eexec a dále
pomocí stringů CharStrings. Pro další potřeby pracujme jen s "rozkrytou"
variantou popisu fontu v tzv. pseudo-PostScriptovém jazyce, tak jak ji
generují programy t1disasm nebo t1accent. Vyzkoušejte si nějaký pfb formát
těmito programy rozkrýt a podívat se na výsledek. Jazyk nazýváme
pseudo-PostScriptový proto, že obsahuje jednak standardní PostScriptové
operátory a dále operátory definované jen v jazyce Type1 fontů, které
PostScriptový RIP není schopen v tomto (rozkrytém) tvaru akceptovat.
Pokud se nepodařilo pfb dobře rozkrýt, je to nejspíš tím, že binární
soubor podlehl nějaké nevhodné konverzi typu DOS->UNIX, MAC->DOS nebo
podobné. Pokud lze font interpretovat RIPem, ale nejde rozkrýt ani t1disasm
ani t1accent, je to velmi podezřelé.
V úvodu fontu jsou (po vynechání prvních šesti binárních bytů nutných pro
fomát pfb) znaky '%!', které oznamují, že se jedná o PostScriptový soubor.
Řádky uvozené procentem jsou komentáře. Významný komentář je %%VMusage,
za kterým následují dvě čísla <první zavedení> <opakované zavedení>.
Jedná se o informace o paměťových nárocích fontu, pokud jej PostScriptový
RIP zavede do své paměti. Pomocí PostScriptového operátoru vmstatus můžeme
zjistit, jak vypadá paměťový prostor RIPu před zavedením fontu, po jeho
zavedení a po opakovaném zavedení fontu. Číslo <první zavedení> by mělo
vyjářovat rozdíl výstupu vmstatus před a po zavedení fontu a
<opakované zavedení> rozdíl před zavedením a po opakovaném zavedení fontu.
Některé inteligentnější implementace RIPu mohou číst údaje z poznámky
%%VMusage a podle toho předem rozhodnout, zda font je možné zavést, nebo se
o to ani nemají pokoušet. Bohužel, program t1accent údaje z %%VMstatus
němění, ačkoliv nový font bude mít zřejmě větší paměťové nároky, než
původní. Zatím jsem se ale nesetkal se situací, kdy by to mělo vadit.
Jazyk PostScriptu je postfixový, tj. nejprve přicházejí operandy (do
zásobníku) a pak vlastní operátor. Prostřednictvím operátoru def se do
standardních proměnných definují v rámci standardních fontových
slovníků (řízených operátory dict, begin, end) jednotlivé údaje.
Uvedeme si významy nejdůležitějších údajů.
V rámci hlavního slovníku fontu (font dictionary) se definují
slovníky /FontInfo, /Private a /CharStrings. O jejich obsahu, viz níže.
Dále se v hlavním slovníku definují:
/FontName /název_fontu def
Nezapomeňte po konverzi změnit název fontu!
/Encoding kódování_fontu readonly def
Kódování_fontu se deklaruje jako pole o 256 prvcích (viz "256 array")
které se implicitně naplní prázdným identifikátorem /.notdef
(viz "0 1 255 {1 index exch /.notdef put} for"). Dále se
jednotlivé názvy znaků do pole vkládají na příslušnou pozici
smluvenou konstrukcí "dup <číslo_pozice> /jméno_znaku put".
Tvar znaku je dále definován ve slovníku /CharStrings jako
tzv. "popis znaku", ke kterému je připojeno jméno_znaku. Na pořadí
popisů znaků v /CharStrings nezáleží. Pokud je v /CharStrings definován
popis znaku, který nemá své místo v kódování_fontu, je znak ve fontu
přesto vylovitelný a aplikace jej může používat, pokud si deklaruje
PostScriptovými prostředky svůj vlastní /Encoding vektor. Pokud naopak
je v kódování_fontu název, který není deklarován v /CharStrings a je na
něj odkaz při tisku, inteligentní PostScriptový RIP jej nahradí popisem
/.notdef, který musí být bezpodmínečně definován v každém fontu.
/FontType 1 def ... to je pro Type1 povinné
/PaintType 0 def ... výplň, 2 ... obtahy
/FontMatrix [0.001 0 0 0.001 0 0] readonly def
Transformační matice. Nedoporučuje se tento údaj měnit. Označuje
skutečnost, že font zavedený ve velikosti n bodů je ve skutečnosti
popsán souřadnicemi, ve kterých těchto n bodů má hodnotu 1000
jednotek jak pro směr x tak pro směr y. Říkáme jim jednotky kresby
a jsou ve fontu udávány pouze v celých číslech. Všechny následující
souřadnice předpokládají tuto jednotku.
/FontBBox [<lx> <ly> <ux> <uy>] readonly def
Představte si, že položíme na sebe všechny znaky fontu tak, že se kryjí
počátky každého znaku. Pak <lx> a <ly> jsou souřadnice levého dolního
rohu minimálního obdélníku (se stranami kolmými a rovnoběžnými k účaří)
orámujícího tento soubor všech znaků a <ux>, <uy> jsou souřadnice
horního pravého rohu tohoto obdélníku.
/UniqueID číslo def
Je-li toto číslo v rozsahu 4 000 000 až 4 999 999, znamená to, že
font není u Adobe registrován. Většina aplikací na tvorbu Type1 fontů
přiřazuje UniqueID v tomto rozsahu náhodně. Čísla mimo tento interval
naznačují, že je font registrován. V případě, že RIP zavede v jedné
tiskové úloze dva fonty se stejným UniqueID, a přitom tyto fonty nemají
na množině procedur z /CharStrings společný průnik, může dojít ke
kolizím. Nové fonty generované prostřednictvím t1accent mají
s původními společný průnik. Nevadí tedy, když ponecháme stejné UniqueID.
/StrokeWidth číslo def
Šířka obrysů. Doporučuje se ponechat nulu.
Kromě toho mohou být v hlavním slovníku uloženy další informace o fontu,
například slovník /Metrics, údaj /FID.
Ve slovníku /FontInfo jsou doplňující údaje:
/version (text) readonly def
/Notice (Copyrightová poznámka) readonly def
/FullName (Případně delší název fontu) readonly def
/FamilyName (rodina fontu) readonly def
/Weight (Regular nebo Bold nebo Bold Extended) readonly def
/ItalicAngle číslo_ve_stupních def ... úhel hlavní osy znaků
/IsFixedPitch true nebo false def ... zda je font neproporcionální
/UnderlinePosition číslo def ... doporučená poloha podtržení
/UnderlineThickness číslo def ... doporučená tlošťka podtržení
/XHeight číslo def ... střední výška písma (písmene x)
/Ascender číslo def ... výška písmen d, l, k
/Descender číslo def ... hloubka písmen y, g, j
/CapHeight číslo def ... výška kapitálek A, B, C
Slovník Private je již skryt za hranicí kryptovacího operátoru eexec.
Zóna tohoto operátoru je ukončena sekvencí "currentfile closefile", která
je v *.pps souborech zcela na konci. Ve slovníku Private jsou obvykle
definovány následující objekty:
/RD {string currentfile exch readstring pop} executeonly def
... zkratka pro přečtení jednoho stringu se zakryptovanými popisy
procedury nebo znaku. Místo RD bývá obvyklé též použití zkratky -|.
/ND {noaccess def} executeonly def
... zkratka pro definování popisu znaku. Místo ND bývá obvyklé též použití
zkratky |-.
/NP {noaccess put} executeonly def
... zkratka pro definování popisu procedury. Místo NP bývá obvyklé též
použití zkratky |.
/Subrs
... pole procedur. Každá procedura je definována jako jeden prvek pole
Subrs takto: dup <číslo prvku> { popis procedury } NP
Procedury číslo 0 až 4 mají rezervovaný obsah. Od čísla 5 může font
deklarovat vlastní procedury.
/OtherSubrs
... pole dalších procedur. Na rozdíl od pole procedur Subrs není popis
procedury kryptován a neobsahuje Type1 operátory, ale libovolné
PostScriptové operátory.
/UniqueID ... viz výše
/BlueValues ... hintovací informace o důležitých mezích na ose y fontu
(účaří, přetahy přes účaří, střední výška písma, přetahy přes střední
výšku písma apod.)
/OtherBlues ... doplňující hintovací informace
/FamilyBlues ... hintovací informace společné celé rodině fontu
/FamilyOtherBlues ... doplňující hintovací informace pro rodinu fontu
/BlueScale ... koeficient pro interpretaci hintovacích informací
/BlueShift ... možnost přesahu v rámci hintovacích informací
/BlueFuzz ... možnost nepřesnosti v rámci hintovacích informací
/StdHW ... dominantní šířka horizontálních tahů písma
/StdVW ... dominantní šířka vertikálních tahů písma
/StemSnapH ... doplňující šířky horizontálních tahů
/StemSnapV ... doplňující šířky vertikálních tahů
/ForceBold ... zda vynutit větší duktus písma i při šíři tahu jeden pixel
/LanguageGroup ... skupina jazyků pro které je písmo vhodné (latinka,
řečtina, Cyrilice a podobné mají skupinu nula).
/password 5839 ... toto číslo je neměnné, použije je dekryptovací algoritmus.
/lenIV ... počet úvodních bytů v CharStings pro dekryptovací algoritmus,
implicitně je roven čtyřmi.
/MinFeature {16 16} def ... neměnná a povinná definice
Konečně /CharStrings obsahuje definice popisů znaků ve formátu:
/název-znaku { popis znaku } ND
Popis znaku je interpretován speciálním Type1 BuildChar procesem, který
PostScriptový RIP inicializuje vždy, když potřebuje rastrovat znak s názvem
"název-znaku". Tomuto procesu RIP předá popis znaku ve formě stringu a
proces BuildChar jej dovede rozkrýt a interpretovat. Výstupy programů t1disasm
a t1accent obsahují odpovídající popisy pro BuildChar už rozkryté do čitelné
podoby.
Proces BuildChar otevírá vlastní zásobník operandů nezávislý na vnějším
zásobníku operandů PostScriptového RIPu. V popisu znaku pro BuildChar je
definována uzavřená cesta (nebo více uzavřených cest) pomocí množiny
speciálních operátorů. Na závěr procesu BuildChar vyvolá RIP automaticky
povel fill nebo stroke (v závislosti na hodnotě PaintType) na vyplnění
ohraničené oblasti rastrem (fill) nebo na vykreslení obrysu (stroke).
Výstupem procesu BuildCHar pak je rastr požadovaného znaku, který si RIP
uloží do VM (virtual memory) a dále jej opakovaně používá, kdykoli je
potřeba rastr znaku vložit do výstupního rastru znova.
Proces BuildChar bývá v dobrých implementacích RIPu naprogramován tak, aby
byly akceptovány všechny hintovací informace fontu pro případ rastrování
znaků do nízkých rozlišení.
Některé programy mohou obsahovat jen podmnožinu skutečného PostScriptového
RIPu, která implementuje pouze proces BuildChar. Příkladem je ATM (Adobe
Type1 Manager) pro Windows.
Proces Type1 BuildChar umí interpretovat v popisu znaku následující
operátory (a žádné jiné). Vpravo od názvu operátoru je uveden operátor
znova, tentokrát se svými numerickými operandy. Operandy mohou být jen celá
čísla. Znak "-" značí, že operátor nemá žádný operand.
A) Vymezující operátory
hsbw <sbx> <wx> hsbw
Definuje šířku znaku <wx> a vzdálenost levostranného bodu (left
sidebearing point) od počátku <sbx>. Po umístění znaku do sazby RIP
posune aktuální bod sazby z původního počátku o <wx> doprava. Tím je
určena poloha počátku následujícího znaku. Levostranný bod je určen
průsečíkem účaří s levou hranicí kresby znaku. Nemusí být nutně
totožný s počátkem znaku. X-ová souřadnice levostranného bodu vzhledem
k počátku je rovna <sbx>. Veškeré další souřadnice kresby znaku jsou
vztaženy nikoli k počátku, ale k levostrannému bodu. Aktuální bod kresby
se pro každý znak automaticky inicializuje do levostranného bodu.
sbw <sbx> <sby> <wx> <wy> sbw
Při sazbě písma jinak než na účaří (třeba shora dolů) je pro písmo
použit obecnější sbw místo hsbw. (<wx>, <wy>) je vektor posunu
aktuálního bodu sazby po vykreslení znaku a (<sbx>, <sby>) jsou
souřadnice levostranného bodu vzhledem k počátku. Operátor sbx nebo hsbx
nebo seac musí být v každém popisu znaku uveden. Program t1accent
předpokládá pouze použití operátoru hsbx a nikoli sbx ve fontu (není
tedy určen pro čínské znaky).
endchar - endchar
poslední operátor popisu znaku. Povinný.
callsubr <číslo procedury> callsubr
odskok do procedury. Další informace o popisu znaku budou čteny z
procedury Subr. Po ukončení procedury bude BuildChar pokračovat z místa,
kde byla procedura yvolána. V proceduře je možné nové volání callsubr,
ale množství vnořených procedur je omezen na 10.
return - return
poslední operátor popisu procedury. Povinný.
seac <asb> <adx> <ady> <bchar> <achar> seac
znak bude komponován jako kompozitní -- základový znak a akcent.
Hodnota <asb> musí být totožná s hodnotou <sbx> u hsbw operátoru
akcentu. (<adx>, <ady>) jsou souřadnice počátku akcentu vzhledem
k počátku základového znaku. <bchar>, resp. <achar>, je kód
základového znaku, resp. akcentu, který musí být v obou případech v
souladu s Adobe StandardEncoding (viz například dodatek F v [3]).
Rovněž tyto kódy musejí být v souladu s kódováním fontu. Právě to je
velmi omezující, a proto nebyl tento operand pro generování akcentů
programem t1accent použit. Je-li použit operátor seac, nesmí být
v popisu znaku žádný další operátor s výjimkou endchar.
B) Operátory pro deklaraci křivky
closepath - closepath
uzavření cesty. Aktuální bod kresby se na rozdíl od klasického
PostScriptového operátoru closepath nehýbe. Poslední část křivky se
uzavře úsečkou. Všechny části křivky musejí být bezpodmínečně
v Type1 BuildChar uzavřeny.
rmoveto <dx> <dy> rmoveto
Aktuální bod kresby se posune na nové místo o vektor (<dx>, <dy>).
Takový pohyb bodu je možný jen mezi částmi křivky, které jsou uzavřeny.
Není tedy možné kreslit křivku třeba pomocí rlineto, neuzavřít ji pomocí
closepath, a přitom použít rmoveto.
hmoveto <dx> hmoveto
zkratka za <dx> 0 rmoveto.
vmoveto <dy> vmoveto
zkratka za 0 <dy> rmoveto.
rlineto <dx> <dy> rlineto
nechť je aktuální bod kresby v místě (<cx>, <cy>). Vytvoří se úsečka
(<cx>, <cy>) -- (<cx>+<dx>, <cy>+<dy>) a aktuální bod kresby se posune
na nový konec této úsečky.
hlineto <dx> hlineto
zkratka za <dx> 0 rlineto
vlineto <dy> vlineto
zkratka za 0 <dy> rlineto
rrcurveto <dx1> <dy1> <dx2> <dy2> <dx3> <dy3> rrcurveto
nechť je aktuální bod kresby v místě (<cx>, <cy>). Vypočítají se
souřadnice kontrolních bodů (<x1>, <y1>) a (<x2>, <y2>)
a koncového bodu (<x>, <y>) takto:
<x1> = <cx> + <dx1>, <y1> = <cy> + <dy1>,
<x2> = <x1> + <dx2>, <y2> = <y1> + <dy2>,
<x> = <x2> + <dx3>, <y> = <y2> + <dy3>
Vytvoří se Bézierova křivka třetího řádu s počátkem (<cx>, <cy>),
koncem (<x>, <y>) a kontrolními body (<x1>, <y1>) a (<x2>, <y2>).
Aktuální bod kresby se posune do koncového bodu křivky.
Ekvivalent k PostScriptovému <x1> <y1> <x2> <y2> <x> <y> curveto.
hvcurveto <dx1> <dx2> <dy2> <dy3> hvcurveto
zkratka za <dx1> 0 <dx2> <dy2> 0 <dy3> rrcurveto
vhcurveto <dy1> <dx2> <dy2> <dx3> vhcurveto
zkratka za 0 <dy1> <dx2> <dy2> <dx3> 0 rrcurveto
Poznámka. PostScriptové operátory moveto, lineto, curveto a rcurveto nejsou
v Type1 BuildChar implementovány, ale lze je snadno převést na operátory,
které Type1 BuildChar zná. Nechť (<cx>, <cy>) je poloha aktuálního bodu
kresby. Pak:
<x> <y> moveto ... je totéž jako ... <x-cx> <y-cy> rmoveto
<x> <y> lineto ... je totéž jako ... <x-cx> <y-cy> rlineto
C) Hintovací operátory
dotsection - dotsection
operátor vymezuje takovou část křivky, která má být rastrována vždy
stejně jako tečka (například ve znacích i, j, !). Operátor se musí
použít dvakrát. Nejprve před zahájením kresby křivky a potom na jejím
konci.
hstem <y> <dy> hstem
deklaruje skutečnost, že v kresbě znaku bude horizontální tah, který
bude mít spodní okraj v pozici <y> a bude mít šířku <dy>. Takových tahů,
které se vzájemně horizontálně nepřekrývají, může být deklarováno pomocí
dalších operátorů hstem v popisu znaku více.
hstem3 <y0> <dy0> <y1> <dy1> <y2> <dy2> hstem3
deklaruje skutečnost, že v kresbě znaku budou tři rovnoběžné
horizontální tahy, první a poslední stejné šířky a prostřední přesně
uprostřed mezi nimi. i-tý tah má spodní okraj v poloze <yi> a má šířku
<dyi>. Musí platit: <dy0>=<dy2> a <y1-y0-dy0> = <y2-y1-dy1>. Druhá
rovnost popisuje, že prostřední tah má být přesně uprostřed.
vstem <x> <dx> vstem
analogile k hstem, ale pro vertikální tahy podchycené svými x-ovými
souřadnicemi.
vstem3 <x0> <dx0> <x1> <dx1> <y2> <dy2> vstem3
analogie k hstem3, ale pro trojici vertikálních tahů podchycenou svými
x-ovými souřadnicemi. Vhodné například pro písmeno m.
D) Ostatní operátory
div <num1> <num2> div
vrací do zásobníku operandů procesu BuildChar výsledek dělení num1/num2.
Implementováno pro případ, kdy celočíselné násobky tisícin velikosti
písma nejsou pro daný údaj dostatečně přesné. Div je možno použít jen
v kontextu s operátorem sbx nebo hsbx pro přesnější určení hodnoty <wx>
nebo <wy>.
callothersubr <arg1> ... <argn> <n> <číslo procedury> callothersubr
Proces BuildChar pošle do PostScriptového zásobníku operandů <argn> až
<arg1> a vyvolá proceduru <číslo procedury>, ve které mohou být uvedeny
libovolné operátory PostScriptového RIPu (nikoli Type1 operátory). Cílem
této procedury je vytvořit "výsledek výpočtu" v PostScriptovém zásobníku
operandů. Proces BuildChar může pak takový "výsledek výpočtu" převzít
z PostScriptového zásobníku do svého interního zásobníku prostřednictvím
operátoru pop.
pop - pop
operátor sejme z externího PostScriptového zásobníku operandů numerickou
hodnotu a vrátí ji do interního zásobníku operandů procesu BuildChar.
setcurrentpoint <x> <y> setcurrentpoint
nastaví aktuální bod kresby na absolutní souřadnice (<x>, <y>). Používá
se jen ve spolupráci s callothersubr.
6. Doporučení a pravidla pro Type1 formát
-----------------------------------------
Při tvorbě křivek v popisech znaků je vhodné dodržovat určitá doporučení a
pravidla.
A) Tvar křivky
Tvar znaku musí být kopírován nejmenším počtem tahů. Například pro písmeno
C musí bezpodmínečně stačit jeden tah (jedna uzavřená křivka), zatímco pro
písmeno R potřebujeme křivky dvě -- vnější a vnitřní. Vnitřní pro vymezení
bílého místa v bříšku znaku. Písmeno B potřebuje tři křivky.
Kamenem úrazu jsou METAFONTové zdrojové texty fontů, které toto pravidlo
nerespektují. Tam se dopředu předpokládá, že tahy budou jedině vyplněny
a nebudou nikdy kresleny obrysem. Proto se i jednoduché tvary skládají
z mnoha subploch, každá z nich má svůj vlastní obrys a tyto plochy se
překrývají. To je pro Type1 nepřijatelné.
B) Orientace křivky
Vše, co má být vyplněno inkoustem, musí být obehnáno křivkou probíhající
proti směru hodinových ručiček. Vše, co má zůstat bílé uvnitř již vyplněné
plochy musí být obehnáno křivkou probíhající ve směru hodinových ručiček.
Například vnější křivka písmene R je proti směru hodinových ručiček a
vnitřní křivka, vymezující bílé místo v bříšku, je ve směru hodinových
ručiček.
C) Jednoduchost
Doporučuje se vytýčit křivku co nejmenším počtem kotevních bodů. Rovněž se
doporučuje využívat zkratek hlineto, vlineto, hvcurveto a vhcurveto všude
tam, kde se to dá. Například pro vymezení kruhu je vhodné vymezit čtyři
kotevní body vlevo, dole, vpravo a nahoře a použít zkratky hvcurveto a
vhcuvreto. Viz například SUB /one-dot v dokumentaci klíčového slova SUB.
D) Lámat křivky jen v opodstatněnných případech
Kontrolní body Bézierových křivek určují směry těchto křivek v kotevních
bodech. Jednotlivé Bézierovy křivky by proto na sebe měly navazovat hladce
bez zubů (tj. směr předchozí křivky v jejím koncovém bodě by měl být shodný
se směrem navazující křivky v jejím počátečním bodě).
E) Kroutit křivku jen do 90 stupňů
Bézierova křivka sice může mít libovolný průběh, ale v Type1 se doporučuje,
aby jedna křivka změnila svůj směr nejvýše o 90 stupňů. Ačkoli by se
dal obrys tečky aproximovat třeba jen dvěma Bézierovými křivkami, je nutné
použít aspoň 4 křivky, a vzhledem k bodu C) se doporučuje použít právě čtyři
křivky.
7. Reference
------------
[1] Adobe Systems Incorporated. PostScript Language Reference Manual (Red
Book), Addison Wesley, 2nd edition, 1990.
[2] Adobe Systems Incorporated. Adobe Type1 Font Format (Black Book),
Addison Wesley, 1990. Plné znění tohoto textu je k dispozici na
ftp.adobe.com v PDF formátu.
[3] Olšák Petr. Typografický systém TeX, CSTUG, Praha 1995.
t1accent/t1accent.eng 100666 150 144 52301 6530761734 13370 0 ustar olsak math1
Program t1accent -- adds a new accents into Type1 fonts (pfb)
=============================================================
Petr Ol\v{s}\'ak April 1998
The program t1accent reads the font in Type1 format (pfb) and adds new
accented letters using callsubr Type1 operator. The program behavior is
controlled by configuration file. The following information is stored
here:
-- the names of new characters
-- the file with encoding vector of new generated font,
-- the declaration of the position of accents with respect of the base
characters,
-- the accent shape defined as PostScript procedure (using moveto, lineto,
curveto, rmoveto...)
The output of the program is the text file with the pseudo-PostScript
language of the new font in the same format, as the output from t1disasm
(the program from free t1utils package). You can add another modification
into this file manually (or by common text filters) and then you can
convert the result into pfb file using t1asm (from t1utils package).
The hinting information for the new accented character is copied from base
character. Usually, new accents need not the new hinting.
The callsubr Type1 operator for accents is more flexible than seac operator
because of strictly given Standard Encoding for accents and base characters
in seac operator. Two different shapes of the same accent is usually
needed for lowercase/uppercase letters, but it is impossible via seac
operator.
The "overlapping" problem is not solved in t1accent program. It means, that
new accents have to have their own path independent on the path of the base
character. If these paths are overlapped, the behavior of rendering
algorithm of PostScript RIP is undefined (the overlapped area is sometimes
white and sometimes black). This limit of t1accent program has no matter for
Czech and Slovak accented letters, but it become more important for another
languages (such as Polish). If overlapping exist, you can use Fontographer
or such similar program for corrections of this problem manually.
1. Running of t1accent
----------------------
You can start the t1accent from command line with one parameter: the name
of configuration file:
t1accent config.file
The behavior of the program is defined in configuration file including the
names of input *.pfb files. No another command line options are implemented
in this version of the program.
2. The recommended action for making a new font with accented letters
---------------------------------------------------------------------
Suppose, we have the "font.pfb" and "font.afm" files of some original Type1
font without accents. We prepare the new font with information about it
stored in files "csfont.pfb", "csfont.afm" and "csfont.tfm". The story is
divided into several steps and several programs from public domain is used.
1. Convert the font.pfb into human readable form using t1disasm from
t1utils:
t1disasm font.pfb font.tmp
2. Prepare the t1accent configuration file. You can use the *.tab files
from t1accent package and modify it for your purposes. You can copy some
parts of code from font.tmp (for example the code of caron accent may be
included as new procedure /lc-caron and /uc-caron may be derived from
the same code, but modified (using 1 0.7 scaled, for example), because
the caron form capital letters has a different shape.
3. Choose the implicit encoding vector of the new font using appropriate
*.enc file (see ENC declaration in configuration file). Note: the
implicit encoding vector of the font is irrelevant for processing of TeX
dvi files using dvips, because the needed encoding vector can be set in
psfont.map (configuration file of the dvips). On the other hand, the
compatibility of names with the shapes of the characters are important
(Attention: some DTP studios produced fonts with absolutely incompatible
names!)
4. Convert the font.pfb to font.pps using:
t1accent config.file
5. Edit the font.pps: You can add some copyright notices and so on.
6. Convert the font.pps into a new csfont.pfb using t1asm from t1utils:
t1asm -b font.pps csfont.pfb
If you need to prepare a new csfont.afm file, you can use the free
printafm.ps and process it using Ghostscript. The resulting csfont.afm file
has a good implicit encoding but the kern information is missing. You can
use some programs to add kern information from original font.afm (my
program a2ac, for instance), but the result has bad implicit encoding. If
you combine and merge both results of previous processes, you can get the
csfont.afm with right implicit encoding and with correct kern information.
If you need to prepare the csfont.tfm file, use fontinst or afm2tfm on the
file csfont.afm from previous step. The afm2tfm have to be processed to
make the unused virtual font in order to save the kern information in tfm
properly:
afm2tfm csfont.afm -T file.enc -v csfont rfont
file.enc have to be the same as encoding file used in step 3 and 4 above.
The resulting rfont.tfm has no kerning information and can be removed.
vptovf csfont.vpl csfont.vf csfont.tfm
csfont.vf is only a by-product and is not needed. Remove it:
rm rfont.tfm csfont.vpl csfont.vf rfont.tfm
3. The format of the configuration file
---------------------------------------
The configuration file of the t1accent is text file. The end of line is
interpreted as a space. The '%' is a comment character -- all characters
from '%' to the first end of line (including this one) are ignored.
The tab marks, carrigue return marks (visible from DOS file in UNIX)
are interpreted as spaces. More consecutive spaces are interpreted as one
space.
The keywords NAME, SRC, IN, ENC, REM, VAR, SUB, CHAR, BBOX and END (the
uppercase letters are necessary) can be included into configuration file.
The keyword have to be separated by space. The information after these
words has a special format (described below). If the information after any
keyword is completed, another keyword can be used or the same keyword can
be used repeatedly (excluding the keywords NAME, SRC, ENC and END).
The order of the keywords are irrelevant with this exceptions:
* The END keyword ends the reading of configuration file.
* If some variable is used, the declaration VAR of this variable
have to be _before_ this point.
* If some name of subroutine is used, the declaration SUB of this
subroutine have to be _before_ this point.
* The ordering of the SUBs and CHARs in configuration file is the same as
the ordering of relevant information in *.pps output. But this has no
matter on behavior of the new font.
Now, the syntax and semantic of all keywords will be described in detail.
***** The NAME keyword
has the form:
NAME Original-Name -> New-Name
The symbol "->" surrounded by spaces is necessary.
Program replaces all occurrences of sequences "Original-Name" by sequence
"New-Name" in the first part of font text (this part is ended by
"/Encoding" sequence). If you need the more complicated "find+replace"
behavior, you can use sed, awk, perl or some similar on the output text
file *.pps after t1accent processing.
Example:
NAME Times-Roman -> Times-Roman-CZ
***** The SRC keyword
has the form:
SRC /directory/with/source/files/
The text after SRC keyword declares the directory, where the *.pfb input
files will be found. The character '/' (in UNIX) or '\' (in DOS) is
necessary at the end of the directory text. The SRC keyword may be
presented at most once in configuration file. If SRC declaration is
absented, program opens input files in current directory.
Examples:
SRC /usr/local/share/texmf/fonts/type1/public/cm/
or
SRC d:\emtex\fonts\type1\cm\
***** The IN keyword
has the form:
IN name1 name2 ...
The no-empty list of names is separated by spaces. The list is delimited
by an occurrence of a new keyword NAME, SRC, IN, ENC, REM, VAR, SUB, CHAR,
BBOX or END. Thus, the keyword itself cannot be the element of the list.
The elements of the list are names of input *.pfb files (without extension!).
The program t1accent is able to read these files, if they are present in the
directory declared by SRC keyword. Program creates an output file with
extension .ppf for every input file listed in the list in the current
directory.
If you use IN repeatedly, this has the same effect as using IN only once
with all names specified. For example:
IN name1
IN name2
END
is the same as:
IN name1 name2
END
***** The ENC keyword
has the form:
ENC name
All another information after "name" (separated by space) is ignored until
a new keyword occurs. The ENC keyword have to be present exactly once in
configuration file.
The "name" is the name of *.enc file (without extension!). The implicit
encoding vector of a new created font is defined in this *.enc file. The
format of *.enc file is the same, as a format of *.enc files in dvips package.
The t1accent reads the information only between [ and ] brackets in this
file. The number of charnames between these brackets have to be exactly
256.
***** The VAR declaration
has the form:
VAR /name value
The name of a new declared variable have to be preceded by slash and "value"
is the usual real number (possibly with a minus sign and/or decimal point).
The different name of the variable from charnames in the font and SUBs in
the configuration file is strongly recommended.
The another information after "value" (separated by space) is ignored until
a new keyword occurs. The using of def operator after "value" is recommended
because the arithmetic parser with postfix operators ended by def is
planned to implement into a future version of t1accent. You can write
for example:
VAR /ac-shift 250 def
and the form of:
VAR /new-variable old-variable dup mul neg def
is planned in a future version.
The "value" is stored into variable width the name "name" for future use in
SUB or CHAR declarations.
***** The SUB keyword -- a declaration of a new subroutine
has the form:
SUB /name { subroutine text }
All information after the closing '}' is ignored until a new keyword occurs.
You can add the def operator after closing '}' only for a more "elegance".
The "name" of the procedure have to be preceded by slash and delimited
by space. The "subroutine text" is the sequence of a postfix operators
with is operands. The following operators are possible:
1. The special t1accent operators:
<sx> <sy> scaled
<dx> vvaxis
2. The PostScript operators:
<x> <y> moveto
<x> <y> lineto
<x1> <y1> <x2> <y2> <x> <y> curveto
<dx1> <dy1> <dx2> <dy2> <dx> <dy> rcurveto
3. All Type1 Buildchar operators:
<sbx> <wx> hsbw
<sbx> <sby> <wx> <wy> sbw
<number> callsubr
return
<asb> <adx> <ady> <bchar> <achar> seac
closepath
<dx> <dy> rmoveto
<dx> hmoveto
<dy> vmoveto
<dx> <dy> rlineto
<dx> hlineto
<dy> vlineto
<dx1> <dy1> <dx2> <dy2> <dx3> <dy3> rrcurveto
<dx1> <dx2> <dy2> <dy3> hvcurveto
<dy1> <dx2> <dy2> <dx3> vhcurveto
dotsection
<y> <dy> hstem
<y0> <dy0> <y1> <dy1> <y2> <dy2> hstem3
<x> <dx> vstem
<x0> <dx0> <x1> <dx1> <y2> <dy2> vstem3
<num1> <num2> div
<arg1> ... <argn> <n> <number> callothersubr
pop
<x> <y> setcurrentpoint
For more information about PostScript and Type1 operators see the [1] and
[2].
Program t1accent transforms the PostScript operators into Type1 Buildchar
operators and interprets the scaled and vvaxis operators. The subroutine
text is written into output (after conversion) as a new Type1 subroutine.
Program t1accent calculates the position of current point. If you does not
use the return operator in subroutine text, program adds the two operators
on the output:
<-x0> <-y0> rmoveto
return
where (<-x0>, <-y0>) are coordinates of current point. The result is: the
current point has the same position before and after subroutine is
executed. If you need not this "intelligence", you can write return
operator explicitly in subroutine text.
The scaled operator sets the actual coefficients <sx> and <sy> of scale of
all relative dimensions in operands of Type1 operators. The initial values
is (1, 1) at the start of SUB. The repeatedly used scaled operator changes
<sx> and <sy> relatively with previous values. For example:
SUB /ac-accent {
100 100 scaled % the global scaled factor
2 7 moveto % current point = (200,700)
1 .5 scaled % the whole path will be deformed with respect
% to the point (200,700) in the y-axis direcion
5 5 lineto % this will be transformed to:
% 100*(5-2) 0.5*100*(5-7) rlineto
8 7 lineto % this is: 100*(8-5) 0.5*100*(7-5) rlineto
5 5.5 lineto
closepath
}
Program converts this subroutine text into new Type1 subroutine
described in pseudo-PostScript language:
dup <number of proc.> {
200 700 rmoveto
300 -100 rlineto
300 100 rlineto
-300 -75 rlineto
closepath
-500 -625 rmoveto
return
} NP
Note, that the -500 -626 rmoveto returns the current point to (0,0),
because the Type1 closepath does not move the current point (in opposite to
the same named PostScript operator).
The vvaxis operator sets x-coordinate of the position of visual vertical
axis of the accent. This information will be used by putcenter operator in
CHAR declaration. If vvaxis is not used, the position of the visual axis
is calculated as the center of bounding box of the path drawn by the
procedure. From the previous example, the vvaxis is not used, thus the
x-coordinate of visual axis is 200+800/2 = 500.
The vvaxis sets the new value with respect to the current point and <sx>
scaled factor, but current point is not moved. For example, the .5 vvaxis
before the first moveto and after the first scaled sets the x-coordinate of
the visual axis to 50. The same .5 vvaxis after the first moveto sets the
value to 250 and .5 vvaxis after the 5 5 lineto sets the value to 550.
It is recommended to set the vvaxis of the accents with respect to the slant
factor of the font, because the putcenter operator in CHAR does not
calculate the slant factor.
You can use the numeric operands or variable names or subroutine names
in subroutine text. For example:
SUB /one-dot {
200 700 moveto
200 670 225 645 255 645 curveto
285 645 310 670 310 700 curveto
310 730 285 755 255 755 curveto
225 755 200 730 200 700 curveto
}
SUB /lc-dieresis {
155 vvaxis % x-coordinate of the vvaxis: 200/2 + radius of the dot
one-dot callsubr
200 hmoveto
one-dot callsubr
}
yields to:
dup <the number of the subroutine one-dot> {
200 700 rmoveto
-30 25 -25 30 vhcurveto
30 25 25 30 hvcurveto
30 -25 25 -30 vhcurveto
-30 -25 -25 -30 hvcurveto
closepath
-200 -700 rmoveto
return
} |
dup <the number of the subroutine lc-dieresis> {
<the number of the subroutine one-dot> callsubr
200 hmoveto
<the number of the subroutine one-dot> callsubr
-200 hmoveto
return
} |
Note that:
1. The t1accent automatically inserts the closepath operator, if this
operator and return is not used explicitly and if the subroutine uses
some "drawing" operator (rlineto, rrcurveto, ...).
2. When the t1accent calculates the current point in a subroutine, it never
inputs into nested subroutines, thus the calculation of bounding box
may by incorrect. The explicit vvaxis is recommended for such situations.
***** The CHAR keyword -- a declaration of a new character
There exist three variants of using the CHAR declaration:
1. Inserting an accent:
CHAR /new-name /base-name /sub-name <x> <y> put-operator
2. Correction of values of base character and (possibly) inserting a new
accent:
CHAR /new-name /base-name <dsbx> <dy> <dwx> correct
/sub-name <x> <y> put-operator
3. Definition of an new character:
CHAR /new-name { character text }
"new-name" is the name of a new declared character, "base-name" is the name
of the base character (it have to be present in input *.pfb font) and
"sub-name" is a name of procedure for accent. You can use the reserved
name ".noinsert" (write /.noinsert including slash) instead "sub-name",
iff no accent is needed to insert.
The character text (see the alternative 3) can include the same information
as the subroutine text in SUB declaration. Only return operator is not
allowed and endchar operator is possible. If the endchar operator is not
present, t1accent includes this operator (and may be closepath)
automatically. The hsbw or seac or sbw is needed in character text (see [2]
for more details).
The correct operator (see the alternative 2) interprets its operands in
following way:
<dsbx> ... left sidebearing point is changed: <sbx> = <original sbx> + <dsbx>
<dy> ... the glyph of character is shifted: <dy> vmoveto
<dwx> ... <wx> parameter of hsbw is changed: <wx> = <original wx> + <dwx>
Note: shifting of a glyph in x-axis direction is performed via changing
of left sidebearing point because the current point is initialized to the
left sidebearing point at the begin of all characters.
The correct operator reads the parameters of the hsbw operator in base
character and changes its operands <sbx>, <wx> and includes the
<dy> vmoveto before the first "drawing" operator. It changes the operators
of hstem and hstem3 with respect to <dy> parameter of shifting of the
glyph.
The put-operator is one from following words:
putorigin ... puts the accent from the procedure with respect to the origin
putsidebar ... puts the accent from the procedure with respect to the left
sidebearing point
putcenter ... puts the accent from the procedure with respect to the
center of the character and vvaxis of the accent
putafter ... puts the accent from the procedure with respect to the next
character origin calculated from character width.
The put-operator has two numeric operands <x> and <y>. The accent is
shifted by <x> to right and by <y> to up.
Let us describe the inserting of the procedure more precisely now.
Let the base character has hsbw operator with operands (possibly corrected
by correct operator):
<sbx> <wx> hsbw
If <x> <y> putsidebar is used, then program copies the base character
text into new character text and inserts the following text
before the first callsubr or first "drawing" operator:
<x> <y> rmoveto
<number sub.> callsubr
<-x> <-y> rmoveto
The <x> <y> putorigin inserts:
<x-sbx> <y> rmoveto
<number sub.> callsubr
<-x+sbx> <-y> rmoveto
When <x> <y> putcenter is used, we