addxchar.ps 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. % Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
  2. %
  3. % This software is provided AS-IS with no warranty, either express or
  4. % implied.
  5. %
  6. % This software is distributed under license and may not be copied,
  7. % modified or distributed except as expressly authorized under the terms
  8. % of the license contained in the file LICENSE in this distribution.
  9. %
  10. % For more information about licensing, please refer to
  11. % http://www.ghostscript.com/licensing/. For information on
  12. % commercial licensing, go to http://www.artifex.com/licensing/ or
  13. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  14. % San Rafael, CA 94903, U.S.A., +1(415)492-9861.
  15. % $Id: addxchar.ps,v 1.4 2002/02/21 21:49:28 giles Exp $
  16. % Add the Central European and other Adobe extended Latin characters to a
  17. % Type 1 font.
  18. % Requires -dWRITESYSTEMDICT to disable access protection.
  19. (type1ops.ps) runlibfile
  20. % ---------------- Utilities ---------------- %
  21. /addce_dict 50 dict def
  22. addce_dict begin
  23. % Define the added copyright notice.
  24. /addednotice (. Portions Copyright (C) 1999 Aladdin Enterprises.) def
  25. % Open a font for modification by removing the FID and changing the
  26. % FontName. Removing UniqueID and XUID is not necessary, since we
  27. % will only be adding characters.
  28. /openfont { % <name> <font> openfont <name> <font'>
  29. dup length dict copy
  30. dup /FID undef
  31. dup /FontName 3 index put
  32. } def
  33. % Do the equivalent of false charpath for a glyph.
  34. % This should really be an operator!
  35. /glyphpath { % <glyph> glyphpath -
  36. currentfont /Encoding get 0 3 -1 roll put
  37. <00> false charpath
  38. } def
  39. % Do the equivalent of charpath + pathbbox for a glyph.
  40. /glyphbbox { % <glyph> glyphbbox <llx> <lly> <urx> <ury>
  41. % We cache this value, because it's expensive to compute.
  42. BBoxes 1 index .knownget {
  43. exch pop
  44. } {
  45. gsave newpath 0 0 moveto dup glyphpath [pathbbox] grestore
  46. BBoxes 3 -1 roll 2 index put
  47. } ifelse aload pop
  48. } def
  49. % Get the side bearing and width for a glyph.
  50. /glyphsbw { % <glyph> glyphsbw <lsbx> <wx>
  51. % We cache this value, because it's expensive to compute.
  52. SBW 1 index .knownget {
  53. exch pop
  54. } {
  55. dup glyphcs { dup /hsbw eq { pop exit } if } forall
  56. 2 array astore
  57. SBW 3 -1 roll 2 index put
  58. } ifelse aload pop
  59. } def
  60. % Get the CharString for a glyph, as an array.
  61. /glyphcs { % <glyph> glyphcs <array>
  62. CharStrings exch get
  63. 4330 exch dup length string .type1decrypt exch pop
  64. dup length lenIV sub lenIV exch getinterval
  65. 0 () /SubFileDecode filter [ exch charstack_read ]
  66. } def
  67. % Find an occurrence of a value in an array.
  68. /asearch { % <array> <value> asearch <index> true
  69. % <array> <value> asearch false
  70. false 0 4 2 roll exch {
  71. % Stack: false index value element
  72. 2 copy eq { pop pop exch not exch dup exit } if
  73. exch 1 add exch
  74. } forall pop pop
  75. } def
  76. % Convert an array back to a CharString.
  77. /csdef { % <glyph> <array> csdef -
  78. charproc_string
  79. 4330 exch dup .type1encrypt exch pop readonly
  80. CharStrings 3 1 roll put
  81. } def
  82. % Split an accented character name.
  83. /splitaccented { % <Baccent> splitaccented <Baccent> <B> <accent>
  84. dup =string cvs
  85. dup 0 1 getinterval cvn
  86. exch dup length 1 sub 1 exch getinterval cvn
  87. } def
  88. % Begin the definition of a 'seac' character.
  89. % Defines accent, base, abox, bbox.
  90. % The initial dx lines up the origins of the base and the accent.
  91. /beginseac { % <bchar> <achar> beginseac
  92. % -mark- <lsbx> <wx> /hsbw <asb> <dx>
  93. /accent exch def /base exch def
  94. /abox [accent glyphbbox] def
  95. /bbox [base glyphbbox] def
  96. [ base glyphsbw /hsbw accent glyphsbw pop
  97. dup 4 index sub
  98. } def
  99. % Center the accent over the base of a 'seac' character.
  100. /centeraccent { % <dx> centeraccent <adx>
  101. bbox 2 get bbox 0 get add 2 div
  102. abox 2 get abox 0 get add 2 div
  103. sub add
  104. } def
  105. % Finish the definition of a 'seac' character.
  106. /finishseac { % <charname> -mark- ... <adx> <ady> finishseac -
  107. exch cvi exch cvi
  108. charindex base get charindex accent get /seac ] csdef
  109. } def
  110. % ---------------- Main program ---------------- %
  111. % Define accented characters that can be made with seac,
  112. % with the accent centered over the character.
  113. /seacchars [
  114. /Abreve /Amacron
  115. /Cacute /Ccaron /Dcaron
  116. /Ecaron /Edotaccent /Emacron
  117. /Gbreve
  118. /Idotaccent /Imacron
  119. /Lacute
  120. /Nacute /Ncaron
  121. /Ohungarumlaut /Omacron
  122. /Racute /Rcaron
  123. /Sacute /Scedilla
  124. /Tcaron
  125. /Uhungarumlaut /Umacron /Uogonek /Uring
  126. /Zacute /Zdotaccent
  127. /abreve /amacron
  128. /cacute /ccaron
  129. /ecaron /edotaccent /emacron
  130. /gbreve
  131. /lacute
  132. /nacute /ncaron
  133. /ohungarumlaut /omacron
  134. /racute /rcaron
  135. /sacute /scedilla
  136. /uhungarumlaut /umacron /uring
  137. /zacute /zdotaccent
  138. ] def
  139. % Define seac characters where the accent lines up with the right
  140. % edge of the character.
  141. /seacrightchars [
  142. /Aogonek /Eogonek /Iogonek /aogonek /eogonek /iogonek /uogonek
  143. ] def
  144. % Define seac characters where the caron becomes an appended quoteright.
  145. /seaccaronchars [
  146. /dcaron /lcaron /tcaron
  147. ] def
  148. % Define seac characters using commaaccent.
  149. /seaccommachars [
  150. /Gcommaaccent /Kcommaaccent /Lcommaaccent /Ncommaaccent /Rcommaaccent
  151. /Scommaaccent /Tcommaaccent
  152. /gcommaaccent /kcommaaccent /lcommaaccent /ncommaaccent /rcommaaccent
  153. /scommaaccent /tcommaaccent
  154. ] def
  155. % Define the characters copied from the Symbol font.
  156. /symbolchars [
  157. /Delta /greaterequal /lessequal /lozenge /notequal /partialdiff
  158. /summation
  159. ] def
  160. % Define the procedures for editing the commaaccent character.
  161. % Delete all the hints, since it's too hard to adjust them.
  162. /caedit mark
  163. /rmoveto { exch commatop sub cvi exch }
  164. /hstem { pop pop pop }
  165. /vstem 1 index
  166. /callothersubr {
  167. dup 3 eq { 4 { pop } repeat /skip true def } if
  168. }
  169. /pop { skip { pop /skip false def } if }
  170. .dicttomark def
  171. /addce { % <name> <font> addce <font'>
  172. 20 dict begin
  173. /origfont 1 index def
  174. openfont
  175. dup /CharStrings 2 copy get dup length dict copy put
  176. dup /Encoding 2 copy get dup length array copy put
  177. dup /FontInfo 2 copy get dup length dict copy put
  178. definefont /font exch def
  179. currentdict font end begin begin
  180. font 1000 scalefont setfont
  181. /symbolfont /Symbol findfont def
  182. /BBoxes CharStrings length dict def
  183. /SBW CharStrings length dict def
  184. /italfactor FontInfo /ItalicAngle .knownget {
  185. neg dup sin exch cos div
  186. } {
  187. 0
  188. } ifelse def
  189. % Invert the Encoding (needed for seac).
  190. /charindex 256 dict def
  191. 0 1 255 {
  192. charindex exch Encoding 1 index get exch put
  193. } for
  194. % Add the commaaccent character, by moving the comma downward.
  195. /comma glyphbbox /commatop exch def pop pop pop
  196. /comma glyphcs
  197. /skip false def
  198. [ exch { caedit 1 index .knownget { exec } if } forall ]
  199. /commaaccent exch csdef
  200. % Add the accented characters that can be made with seac.
  201. seacchars {
  202. splitaccented beginseac
  203. centeraccent
  204. % If the accent would collide with the base character,
  205. % raise it a little.
  206. abox 1 get bbox 3 get sub dup 0 le {
  207. % ... but not if the accent is in the low position.
  208. abox 1 get 0 gt {
  209. neg 60 add
  210. % Adjust the X position if italic.
  211. dup italfactor mul 3 -1 roll add exch
  212. } {
  213. pop 0
  214. } ifelse
  215. } {
  216. pop 0
  217. } ifelse
  218. finishseac
  219. } forall
  220. seacrightchars {
  221. splitaccented beginseac
  222. bbox 2 get abox 2 get sub add % line up right edges
  223. 0 finishseac
  224. } forall
  225. /dcroat /d /hyphen beginseac
  226. bbox 2 get abox 2 get sub add % line up right edges
  227. 0 finishseac
  228. /imacron /dotlessi /macron beginseac
  229. centeraccent
  230. 0 finishseac
  231. /Lcaron /L /quoteright beginseac
  232. bbox 2 get abox 2 get sub add % line up right edges
  233. 0 finishseac
  234. seaccaronchars {
  235. dup =string cvs 0 1 getinterval cvn /quoteright beginseac
  236. % Move the quote to the right of the character.
  237. bbox 2 get abox 0 get sub 50 add add
  238. % Adjust the character width as well.
  239. 4 -1 roll abox 2 get abox 0 get sub 50 add add cvi 4 1 roll
  240. 0 finishseac
  241. } forall
  242. seaccommachars {
  243. dup =string cvs 0 1 getinterval cvn /comma beginseac
  244. centeraccent
  245. commatop neg
  246. % Lower the accent if the character extends below
  247. % the baseline
  248. bbox 1 get 0 .min add
  249. finishseac
  250. } forall
  251. % Add the characters from the Symbol font.
  252. % We should scale them to match the FontBBox, but we don't.
  253. symbolchars {
  254. symbolfont /CharStrings get 1 index get
  255. CharStrings 3 1 roll put
  256. } forall
  257. % Add the one remaining character.
  258. CharStrings /Dcroat CharStrings /Eth get put
  259. % Recompute the FontBBox, since some of the accented characters
  260. % may have enlarged it.
  261. /llx 1000 def /lly 1000 def /urx 0 def /ury 0 def
  262. CharStrings {
  263. pop glyphbbox
  264. ury .max /ury exch def urx .max /urx exch def
  265. lly .min /lly exch def llx .min /llx exch def
  266. } forall
  267. /FontBBox llx cvi lly cvi urx ceiling cvi ury ceiling cvi 4 packedarray def
  268. % Restore the Encoding and wrap up.
  269. [/Copyright /Notice] {
  270. FontInfo 1 index .knownget {
  271. addednotice concatstrings FontInfo 3 1 roll put
  272. } {
  273. pop
  274. } ifelse
  275. } forall
  276. FontName font openfont
  277. dup /Encoding origfont /Encoding get put
  278. definefont
  279. end end
  280. } def
  281. currentdict end readonly pop % addce_dict
  282. /addce { addce_dict begin addce end } def
  283. % ---------------- Integration ---------------- %
  284. % We would like to patch the font loader so that it adds the extended
  285. % Latin characters automatically. We haven't done this yet.
  286. % ---------------- Test program ---------------- %
  287. /TEST where { pop TEST } { false } ifelse {
  288. /FONT where { pop } { /FONT /Palatino-Italic def } ifelse
  289. (unprot.ps) runlibfile
  290. unprot
  291. (wrfont.ps) runlibfile
  292. wrfont_dict begin
  293. /eexec_encrypt true def
  294. /binary_CharStrings true def
  295. end
  296. save
  297. FONT findfont
  298. /Latin-CE exch addce setfont
  299. (t.ce.pfb) (w) file dup writefont closefile
  300. restore
  301. (prfont.ps) runlibfile
  302. (t.ce.pfb) (r) file .loadfont
  303. /Latin-CE DoFont
  304. quit
  305. } if