diff options
author | Mike Gabriel <mike.gabriel@das-netzwerkteam.de> | 2015-02-02 15:02:49 +0100 |
---|---|---|
committer | Mike Gabriel <mike.gabriel@das-netzwerkteam.de> | 2015-02-02 15:02:49 +0100 |
commit | b16b9e4656e7199c2aec74a4c8ebc7a875d3ba73 (patch) | |
tree | 4361edef0d42d5bf5ac984ef72b4fac35426eae7 /nx-X11/extras/ttf2pt1 | |
parent | 0d5a83e986f39982c0924652a3662e60b1f23162 (diff) | |
download | nx-libs-b16b9e4656e7199c2aec74a4c8ebc7a875d3ba73.tar.gz nx-libs-b16b9e4656e7199c2aec74a4c8ebc7a875d3ba73.tar.bz2 nx-libs-b16b9e4656e7199c2aec74a4c8ebc7a875d3ba73.zip |
massive reduction of unneeded files
Diffstat (limited to 'nx-X11/extras/ttf2pt1')
26 files changed, 0 insertions, 22034 deletions
diff --git a/nx-X11/extras/ttf2pt1/CHANGES.html b/nx-X11/extras/ttf2pt1/CHANGES.html deleted file mode 100644 index 9b51d1bc8..000000000 --- a/nx-X11/extras/ttf2pt1/CHANGES.html +++ /dev/null @@ -1,805 +0,0 @@ -<HTML> -<HEAD> -<TITLE> -TTF2PT1 - CHANGES history -</TITLE> -</HEAD> -<BODY> -<H2> -TTF2PT1 - CHANGES history -</H2> - -<! -(Do not edit this file, it is generated from CHANGES.html!!!) -> - -<H4> -3.4.4-SNAP-030526 -</H4> -<! -------- -> - -<b>New features:</b> -<ul> -<li> Improved the auto-vectoring (-OV) alrogithm. -</ul> - -<b>Bug fixes:</b> -<ul> -<li> Fix to build all the features on Windows MS C++, by Tomoo Amano. -</ul> - -<H4> -3.4.3 -- December 2, 2002 -</H4> -<! -------- -> - -<b>New features:</b> -<ul> -<li> <tt>scripts/forceiso</tt> got an optional argument to select the - format of the names for glyphs without standard Latin-1 names. -</ul> - -<b>Bug fixes:</b> -<ul> -<li> Changed the glyph names in scripts/forceiso to match those in ttf2pt1. -<li> Included the missing directory app/TeX. -</ul> - -<H4> -3.4.2 -- August 30, 2002 -</H4> -<! -------- -> - -<b>New features:</b> -<ul> -<li> New map for T2A_compat encoding (for Cyrillic LaTeX) by Mikhail - Umorin. -<li> Scripts supporting font conversion for CJK-LaTeX, by Mike Fabian - from SuSE. -</ul> - -<b>Bug fixes:</b> -<ul> -<li> Explicit owner/group/permissions are used to install directories. -<li> In scripts/convert fixed the addition of encoding name to the font - name for the external encoding maps, was missing "/" at the start. -<li> Fixed the divergence between two copies of UniqueID. -<li> Fixed the recovery after defective empty contours. -</ul> - -<H4> -3.4.1 -- June 13, 2002 -</H4> -<! -------- -> - -<b>New features:</b> -<ul> -<li> Added Autotrace support for the bitmap fonts (-OZ). It's horrible. -<li> Added vectorization of bitmap fonts (-OV) - functionally the same thing as - autotrace but home-grown. Works mostly decently but still with large - space for impprovement. -<li> Relaxed the conditions for warnings about long glyphs. -</ul> - -<b>Bug fixes:</b> -<ul> -<li> Fix by Rob Kolstad for a crash in the new outline smoothing - code (on small thin contours) and diagnostic for another crash. -<li> Fix by Holger Huesing for a crash on degenerate contours. -<li> Fix for bitmaps of zero dimensions. -<li> The BDF reader does not fail on redefintion of the properties. -<li> Fix for reading of BDF glyphs with 0 size. -<li> Fix for a hang when guessing the boldness of some fonts. -<li> Fix by Adriano Konzen for scaling coefficients in composite glyphs. -</ul> - -<H4> -3.4.0 -- November 24, 2001 -</H4> -<! -------- -> - -<b>New features:</b> -<ul> -<li> Parser for the BDF bitmap fonts. -<li> Vastly improved the smoothing of the outlines. -<li> The options are saved as a comment in the output file. -<li> New script <tt>other/showdf</tt> for visual comparison of the fonts. -<li> New option <b>-G</b> to select the file types to generate. -<li> Creation of the dvips encoding files (by Rigel). -<li> More glyphs in the Chinese maps (by Rigel). -<li> Made the assignment of ISO8859/1 glyph names to the glyphs in the - fonts without PostScript names in them dependent on the original - encoding: no change for the 8-bit encodings, for the Unicode encoding - the names are assigned to the glyph with the codes 0-255 in Unicode, - and for the other 16-bit encodings the 8859/1 names are not assigned - at all. -</ul> - -<b>Bug fixes:</b> -<ul> -<li> Added a check for spaces in the PostScript font name in the FreeType - parser. -<li> Made "-" a valid character in the glyph names. -<li> Fixed handling of the Unicode names returned by FreeType, though - not perfectly. -<li> Changed the build for FreeType-2.0.4. -<li> Fixed the handling and printing of bad glyph names. -<li> Fixed the bug with duplicated glyph names when more than 256 glyphs are - extracted from a font that has no PostScript glyph names defined. -<li> Added ability to map a glyph to more than one code when unisng the - native parser (-pttf). -</ul> - -<H4> -3.3.5 -- September 12, 2001 -</H4> -<! -------- -> - -Packaged by Sergey Babkin. -<p> - -<b>Bug fixes:</b> -<ul> -<li> Fixed the scaling of Ascender and Descender in the AFM file. -<li> Fixed the brekage of "-l adobestd". -</ul> - -<H4> -3.3.4 -- June 4, 2001 -</H4> -<! -------- -> - -Packaged by Sergey Babkin. -<p> - -<b>New features:</b> -<ul> -<li> Cyrillic (full set of glyphs) language tables (by Zvezdan Petkovic). - Now the languages "russian" and "bulgarian" are provided for compatibility - only, use the common language "cyrillic" instead. -<li> More information in <a href="FONTS.html">FONTS</a> on using Cyrillic fonts with - Netscape (by Zvezdan Petkovic) -<li> In the Netscape print filter added removal of the clipping path command: - otherwise Netscape tends to cut off a large piece of the rightmost column - of the tables. -<li> One more script for printing from Netscape (by Zvezdan Petkovic). -<li> Added selection of the base TTF encoding by pid/eid in the external maps. -<li> Improved the recognition of substituted stems for intersecting contours. -<li> Improved the substituted hints to make the horizontal positioning of - the points at the same height more uniform at small pixel sizes. -<li> Made the algorithm for calculation of standard stem widths more - selective. -<li> Added link to the GnuWin32 project. -</ul> - -<b>Bug fixes:</b> -<ul> -<li> TH: Print out metrics of un-encoded glyphs even without "-a" option. -<li> Added missing "/" in Fontmap generation in convert (by Zvezdan Petkovic). -<li> Removed unneccessary "\n" in messages in x2gs. -<li> Removed the broken overoptimisation of "0 0 rmoveto". -<li> Removed the useless warnings about multiple codes for a glyph. -<li> Changed the FreeType2 include directory in the Makefile to match the - FreeType's default. -</ul> - -<H4> -3.3.3 -- March 4, 2001 -</H4> -<! -------- -> - -Packaged by Sergey Babkin. -<p> - -<b>New features:</b> -<ul> -<li> TH: Added printing of front-end parser in the header of the font file. -<li> Tested build with FreeType 2.0 Release. -</ul> - -<b>Bug fixes:</b> -<ul> -<li> Changed the installation script which on some versions of bash - copied all files into the share directory. -<li> Fixed the close sequences of html2man comments in the HTML files, - now they should display correctly with <tt>lynx</tt>. -<li> Restored the ability to include un-encoded characters into the - customised maps (those with codes over 255). -<li> Fixed the Unicode mapping of the Cyrillic letters "YO" and "yo" - (by Yuri Shemanin). -<li> Fixed the spurious aborts when the conversion-by-plane function - gets called for auto-guessing of encoding. -</ul> - -<H4> -3.3.2 -- November 20, 2000 -</H4> -<! --------------------------- -> - -Packaged by Sergey Babkin. -<p> - -<b>New features:</b> -<ul> -<li> Added generation of man pages. -<li> Added "make install" and "make uninstall". -<li> Added language option "-l plane". -<li> In <tt>other/showg</tt> added better support of comparison files: -<ul> - <li> printing of the comparison file legend; - <li> guessing of missing glyph names in a comparison file by code; - <li> bounding boxes of all comparison files are used for page layout. -</ul> -<li> Added ability to use external t1asm instead of compiling it in. -<li> Renamed the fonts installation guide from INSTALL*html to FONTS*html - to avoid confusion with installation of ttf2pt1 itself. -</ul> - -<b>Bug fixes:</b> -<ul> -<li> Removed erroneous extra fclose(pfa_file). -<li> Fixed random memory corruption that manifested with crash on Linux - when converting fonts not containing glyph names. -<li> Removed from the output file the comments that confused dvips. Changed - <tt>other/showg</tt> to work without them. -<li> In <tt>other/showg</tt> added better checks for missing glyphs, now it - gives warnings about them and the output file does not crash PostScript. -</ul> - -<b>Other:</b> -<ul> -<li> <tt>ttf2pfa</tt> is no longer included, people interested in history - should look for it in the older versions. -</ul> - -<H4> -3.3.1 -- October 22, 2000 -</H4> -<! -------------------------- -> - -Packaged by Sergey Babkin. -<p> - -<b>New features:</b> -<ul> -<li> Added front-end parser based on the FreeType-2 library. See Makefile -for build instructions. -<li> Changed the handling of encodings to accomodate the FreeType model. -<li> Further cleaned up the front-end parser interface. -</ul> - -<b>Bug fixes:</b> -<ul> -<li> Fixed a bug that caused core dump on Alpha machines. -<li> Fixed a bug in the outline smoothing that occasionally caused core dump. -<li> Cleaned up warnings from picky compilers -<li> Fixed more bugs in the Windows port (by Stefan Bauer). -<li> Fixed the RPM spec file (suggested by Brian Armstrong). -</ul> -<p> - -<H4> -3.3.0 -- September 22, 2000 -</H4> -<! ---------------------------- -> - -Packaged by Sergey Babkin. -<p> - -<b>New features:</b> -<ul> -<li> Converted most of the outlines' processing to floating point -arithmetic. -<li> Added splitting of curves crossing the quadrant boundaries (no gross -damage is done any more to the Marvosym font and others like it). -<li> Added modular interface for front-end font parsers and option to control -their selection at run time. -<li> Grouped the outline processing control options into one to reduce the -options namespace pollution. -<li> Thomas moved the Chinese maps into a separate module, chinese-maps. -<li> Thomas added option -V to print version number. In addition, the version -number is put in the header of the font file. -<li> Added long option names (suggested by Thomas). -<li> Added support for multi-level composite glyphs. -<li> TH: Made <fontname> command-line argument optional; default to <ttf-file> -with suffix replaced. -<li> In <tt>other/showg</tt> added more ways to specify glyphs and the comparison option. -</ul> - -<b>Bug fixes:</b> -<ul> -<li> Fixed the VC++ batch file, added batch file for Cygnus GCC on Windows. -<li> Removed parentheses from the Version string in AFM files because it does -not help StarOffice anyway. StarOffice 5.2 has been reported to have this -bug fixed. Added paragraph on StarOffice in FONTS.html. -<li> Made messages on the '?' option parameter more meaningful (by Johan Vromans). -<li> Changed the latin1 encoding table to include the Euro sign, Z and z with -caron (by Thomas Henlich). -<li> Improved the smoothing code which occasionally had problems with -joining curves. Also fixed a few minor bugs in it. -</ul> - -<H4> -3.22 -- May 23, 2000 -</H4> -<! --------------------- -> - -Packaged by Sergey Babkin. -<p> - -<b>New features:</b> -<ul> -<li> Included windows support by Frank Siegert (somewhat amended) -<li> Added control over verbosity of warnings. -<li> Added arguments and initialization functions to the language -translation routines. -<li> Added support of planes determined by arguments to the external -maps. -<li> Added compact external maps format (primarily for Eastern fonts). -<li> Added external maps for Chinese GBK and Big5 encodings (converted -from ttf2pfb) as well as maps for other Chinese encodings by Wang Lei. -<li> Added the idea of buckets to speed up the search in external maps. -<li> Changed the grouping algorithm for substituted hints: now it creates -a bit bigger files but requires smaller hint stack when being rendered. -<li> Added maximal limit of hint stack depth, glyphs requiring bigger -stack get generation of substituted hints disabled. This makes substituted -hints safe to use, no more lost glyphs due to hint stack overflow. -<li> Added the font dump program <tt>other/dumpf</tt>. -<li> Changed the testing HTML generator <tt>other/lst.pl</tt> to use tables. -<li> Added debugging script <tt>other/cntstems.pl</tt> to count required hint -stack depth for the glyphs. -</ul> - -<b>Bug fixes:</b> -<ul> -<li> Fixed printing of UID in script/trans. Changed the auto-generated UID to -be in range 4000000-4999999 which is reserved by Adobe for private use. -<li> Fixed handling of "cleartomark" in built-in t1asm. -<li> Added handling of "can't happen" case in straighten() routine -which actually happened on strange fonts and caused failure on assertion. -<li> Made it always include the glyph .notdef in the resulting font. -<li> Placed the version string in AFM file in parentheses, hopefully -that would fix the problem with StarOffice. -<li> Improved the smoothing code which occasionally had problems with -joining curves. -</ul> - -<H4> -3.21 -- March 1, 2000 -</H4> -<! ---------------------- -> - -Sergey Babkin: committed the changes by Petr Titera and -my bugfixes. -<p> - -<b>New features:</b> -<ul> -<li> New Unicode map format with glyph names, by Petr Titera. -<li> Option to force the Unicode encoding by Petr Titera - (I changed it to work on any MS encoding, not only Symbol). -<li> Slightly tweaked the calculation of hints, should be better now. -</ul> - -<b>Bug fixes:</b> -<ul> -<li> The unicode-sample.map with description of the map formats - was lost in the release process, restored and enhanced. -<li> Renamed the table ISOLatin1Encoding to Fmt3Encoding to reflect - the way it is used. Saved the original one for reference - purposes. In the new table renamed "quoteright" to "quotesingle" - as Thomas Henlich suggested (and he were right). -<li> In the ISOLatinEncoding table renamed the glyph "grave" - at octal 0140 to "quoteleft", "quotesingle" at octal 047 to - "quoteright" to conform to the standard as suggested by - Martin Trautner). -<li> Fixed bug in scripts/trans that corrupted the UniqueID record - in the translated fonts. -<li> Fixed bug in interaction of substituted hints with BlueZones. - Now the fonts with hint substitution seem to be always at least - not worse than without it (well, when they fit in the X11 - file size limit). -</ul> - - -<H4> -3.2 -- January 15, 2000 -</H4> -<! ------------------------ -> - -Sergey Babkin: combined my changes with the changes by -Thomas Henlich. The result deserves a not-so-minor version -increase. -<p> - -<b>New features:</b> -<ul> -<li> Support of the external Unicode re-encoding maps - (by Thomas). -<li> Support for inclusion of all the glyphs from the - source file into the resulting file (inspired by - Thomas but I re-implemented it to remove the limitation - of his implementation: not more than 1024 glyphs). -<li> The hints substitution. It's an experimental feature - yet and needs further work. -<li> Support for UniqueID and its auto-generation. -<li> Support for the name-based conversions from Unicode - in general and the adobestd "language" in particular. -<li> Started the split of the source code into multiple - files. This needs more work to do it in a cleaner - way. -<li> Better framework for the debugging printout - in the converter. -<li> Utilities to install the fonts in Netscape - Navigator/Communicator 4.x. -<li> Patches for bigger font files in the X11 rasterizer. -<li> Linux RPM spec-file (by Johan Vromans). -<li> Added the COPYRIGHT file (BSD-style, as we discussed - on the mailing list earlier) and the CHANGES file. -<li> Creation of the <tt>.pfb</tt> files from the <tt>convert</tt> - script. -<li> Changed the <tt>.notdef</tt>-s in the built-in - ISOLatin1Encoding table to some valid names (by Thomas). - Thomas also suggested replacing `<tt>quoteright</tt>' by - `<tt>quotesingle</tt>' but this seems to be against the - Adobe ISOLatin1 table. -<li> New aliases <tt>windows-1251</tt> and <tt>cp-866</tt> for - the Russian encodings: those are expected by Netscape - navigator. -<li> The font comparison program <tt>other/cmpf</tt>. -<li> The "magnifying glass" program for glyph outlines: - <tt>other/showg</tt>. -<li> Other updates of the tools in the `<tt>other</tt>' subdirectory. -<li> Added a link to T1LIB in README. -<li> A few new options in <tt>convert.cfg</tt>. -</ul> - -<b>Bux fixes:</b> -<ul> -<li> A bug in the outline smoothing code that corrupted some - of the fonts (for example, Microsoft Verdana). -<li> Added explicit `<tt>cleartomark</tt>' to the end of file, - this seems to be compatible with both old and new version - of <tt>t1asm</tt> (suggested by Thomas). -<li> Added the <tt>FontEncoding</tt> statement to the AFM files - (techincally this was not a bug because this statement - is optional but some programs want it). -<li> A coredump when the converter tried to print a warning - (rather ironically) about a weird glyph width. -<li> Changed the underscores in the font names to dashes (this - has been proposed long time ago by Johan Vromans). -<li> No more glyph names of font names staring with a digit. -<li> The names of the fonts in font and AFM files are now the - same as in the generated Ghostscript <tt>Fontmap</tt> file.<br> - <b>Warning:</b> the names in <tt>Fontmap</tt> have been - changed. -<li> The <tt>forceiso</tt> script does not corrupt the character - and kerning pairs counts any more, and is optional at all. -<li> Fix for a loop going to 254 instead of 255 (by Thomas). -<li> Added ':' in the font header (by Thomas). -<li> A coredump when wrong language name is given (this was - also fixed by Thomas but I noticed it too late, after - I already fixed it by myself). -<li> Fixed the links to the Adobe documents in README. -</ul> - - -<H4> -3.13 -- October 18, 1999 -</H4> -<! ------------------------- -> - -Packaged by Sergey Babkin. -<p> - -<b>New features:</b> -<ul> -<li> New option -v for automatic re-scaling based on the vertical size of the font -<li> Changed the code to use getopt() instead of a home-made version of it. -<li> Latin2 language support by Szalay Tamas. -</ul> - -<b>Bux fixes:</b> -<ul> -<li> Fix for the bug that made possible calls of malloc(0). -<li> Refinement of the option -w to prevent extra wide spacing -</ul> - -<H4> -3.12 -- October 2, 1999 -</H4> -<! ------------------------ -> - -Packaged by Sergey Babkin. -<p> - -<b>New features:</b> -<ul> -<li> Added support for the Bulgarian language (actually, for now just an alias -of Russian). -<li> Added option -w that tries to make sure that the character widths are not -too narrow. -<li> Added the concept of aliased encodings. -<li> Now the conversion scripts create and install the .afm files too. -<li> The conversion script removes the intermediate files after installation. -<li> Added tunables to the conversion script. -<li> Installation of the Ghostscript fonts can now be done automatically -together with the X11 fonts. -</ul> - -<b>Bux fixes:</b> -<ul> -<li> (FINALLY!!!) A correct fix for the infamous Red Hat 6.0 stdio "feature". -<li> A number of little bugs discovered by a picky SGI compiler (well, maybe -some day I'll try to run it through the UnixWare lint and see what happens). -<li> A diagnostic message about the empty encodings in the convert script was -made less cryptic and a bug in the awk sub-script was fixed. -<li> The .afm creation code now considers the option -t. -</ul> - -<H4> -3.11 -- May 24, 1999 -</H4> -<! --------------------- -> - -Packaged by Sergey Babkin. -<p> - -<b>New features:</b> -<ul> -<li> It includes the Turkish (Latin5, ISO8859/9) -language support by Turgut Uyar and Baltic (ISO8859/4) languages support by -Rihardas Hepas. -<li> Also the installation script got updated: the configuration parameters -are moved to a separate file and the generated fonts.dir files should now be -compatible with Xfsft. -</ul> - -<H4> -3.1 -- March 28, 1999 -</H4> -<! ---------------------- -> - -Packaged by Sergey Babkin. -<p> - -<b>New features:</b> -<ul> -<li> Improved the interaction of the character-level hints and font-level hints -</ul> - - -<H4> -3.0 -- March 6, 1999 -</H4> -<! --------------------- -> - -Packaged by Sergey Babkin. -<p> - -<b>New features:</b> -<ul> -<li> Added HTML documents. -</ul> - -<H4> -3.0beta2 -- February 14, 1999 -</H4> -<! ------------------------------ -> - -Packaged by Sergey Babkin. -<p> - -<b>New features:</b> -<ul> -<li> Added ability to print the .afm file instead of the font to STDOUT. -<li> Added the guessing of the /ForceBold parameter that proved to be useful. -</ul> - -<b>Bux fixes:</b> -<ul> -<li> Removed the force-fixed option that proved to be troublesome. -</ul> - -<H4> -3.0beta1 -- December 11, 1998 -</H4> -<! ------------------------------ -> - -By Andrew Weeks. -<p> - -<b>New features:</b> -<ul> -<li> Added option (passed to t1asm) to create a compressed binary -version of the font (A PFB file). -</ul> - -<b>Bux fixes:</b> -<ul> -<li> Versions of handle_post and handle_cmap that deal with some -problems with buggy fonts. -<li> Minor Bug Fixes. -</ul> - -<H4> -3.0beta-afm -- December 5, 1998 -</H4> -<! -------------------------------- -> - -By Thomas Henlich. -<p> - -<b>New features:</b> -<ul> -<li> Integration of AFM file creation. -</ul> - -<H4> -3.0beta -- November 15, 1998 -</H4> -<! ----------------------------- -> - -By Sergey Babkin. -<p> - -<b>New features:</b> -<ul> -<li> Added the auto-calculation of the italic angle. -</ul> - -<b>Bux fixes:</b> -<ul> -<li> Fixed a couple of bugs. -</ul> - -<H4> -3.0alpha -- October 19, 1998 -</H4> -<! ----------------------------- -> - -By Sergey Babkin. -<p> - -<b>New features:</b> -<ul> -<li> Improved (although still not perfect) handling of -scaling in composite glyphs -<li> Automatic correction of outlines to make them more -smooth (to correct both rounding errors introduced -during conversion and present in the original font) -<li> Automatic generation of hints (still has lots of -space for improvement) -<li> Automatic generation of BlueValues etc. -</ul> - -<b>Bux fixes:</b> -<ul> -<li> Scaling of fonts to 1000x1000 M-square required by -Type1 standard -<li> Printing out the contours in reverse direction, because -TTF directions are different from Type1 ones (that was -the major reason why the fonts generated by -version 2.2 were rendered so badly in small sizes) -</ul> - -<H4> -June 22, 1998 (AKA 2.2) -</H4> -<! -------------- -> - -By Thomas Henlich. -<p> - -<b>Bux fixes:</b> -<ul> -<li> "width" should be "short int" because otherwise: -characters with negative widths (e.g. -4) become *very* wide (65532) -<li> The number of /CharStrings is numglyphs and not numglyphs+1 -</ul> - -<H4> -February 13, 1998 -</H4> -<! ------------------ -> - -By Mark Heath. -<p> - -<b>Bux fixes:</b> -<ul> -<li> An original Bug Reported by Frank, which was just incorrect syntax in the -Type 1 header, managed to creep back into the Feb 04 Version. This has been -Fixed in the Feb 13 Version. -</ul> - -<H4> -February 4, 1998 -</H4> -<! ----------------- -> - -By Mark Heath. -<p> - -<b>Bux fixes:</b> -<ul> -<li> A workaround was implemented in ttf2pfa by altering the matrix. I suspect -I will have to calculate the correct values, as matrix ops are probably not -allowed in Type 1 format. -</ul> - -<! ---------------------------------------------- -> -<H4> -The older history seems to be lost. -</H4> - -<I> -(S.B.: The story how we got the version numbers is rather funny. Initially -there were no version umbers, the releases were marked by dates. The version -from June 22 1998 untarred itself into a directory "<tt>ttf2pt1-22</tt>". When I -made my changes to it I assumed that this was the version number meaning -version 2.2. Since Mark asked me to send him a complete archive I supposed -that I have to bump the version number. And I bumped it to 3.0 because the -changes were rather extensive. Mark silently agreed and released the new -version as 3.0. And that's the end of the story about how we got this -Microsoft-like high version number.) -</I> - -</BODY> -</HTML> diff --git a/nx-X11/extras/ttf2pt1/COPYRIGHT b/nx-X11/extras/ttf2pt1/COPYRIGHT deleted file mode 100644 index 85950856b..000000000 --- a/nx-X11/extras/ttf2pt1/COPYRIGHT +++ /dev/null @@ -1,87 +0,0 @@ -The following copyright notice applies to all the files provided -in this distribution unless explicitly noted otherwise -(the most notable exception being t1asm.c). - - Copyright (c) 1997-2002 by the AUTHORS: - Andrew Weeks <ccsaw@bath.ac.uk> - Frank M. Siegert <fms@this.net> - Mark Heath <mheath@netspace.net.au> - Thomas Henlich <thenlich@rcs.urz.tu-dresden.de> - Sergey Babkin <babkin@users.sourceforge.net>, <sab123@hotmail.com> - Turgut Uyar <uyar@cs.itu.edu.tr> - Rihardas Hepas <rch@WriteMe.Com> - Szalay Tamas <tomek@elender.hu> - Johan Vromans <jvromans@squirrel.nl> - Petr Titera <P.Titera@sh.cvut.cz> - Lei Wang <lwang@amath8.amt.ac.cn> - Chen Xiangyang <chenxy@sun.ihep.ac.cn> - Zvezdan Petkovic <z.petkovic@computer.org> - Rigel <rigel863@yahoo.com> - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - This product includes software developed by the TTF2PT1 Project - and its contributors. - - THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - -For the approximate list of the AUTHORS' responsibilities see the -project history. - -Other contributions to the project are: - -Turgut Uyar <uyar@cs.itu.edu.tr> - The Unicode translation table for the Turkish language. - -Rihardas Hepas <rch@WriteMe.Com> - The Unicode translation table for the Baltic languages. - -Szalay Tamas <tomek@elender.hu> - The Unicode translation table for the Central European languages. - -Johan Vromans <jvromans@squirrel.nl> - The RPM file. - -Petr Titera <P.Titera@sh.cvut.cz> - The Unicode map format with names, the forced Unicode option. - -Frank M. Siegert <frank@this.net> - Port to Windows - -Lei Wang <lwang@amath8.amt.ac.cn> -Chen Xiangyang <chenxy@sun.ihep.ac.cn> - Translation maps for Chinese fonts. - -Zvezdan Petkovic <z.petkovic@computer.org> - The Unicode translation tables for the Cyrillic alphabet. - -Rigel <rigel863@yahoo.com> - Generation of the dvips encoding files, modification to the Chinese maps. - -I. Lee Hetherington <ilh@lcs.mit.edu> - The Type1 assembler (from the package 't1utils'), its full copyright - notice: - Copyright (c) 1992 by I. Lee Hetherington, all rights reserved. - Permission is hereby granted to use, modify, and distribute this program - for any purpose provided this copyright notice and the one below remain - intact. - diff --git a/nx-X11/extras/ttf2pt1/FONTS.hpux.html b/nx-X11/extras/ttf2pt1/FONTS.hpux.html deleted file mode 100644 index 80889cae2..000000000 --- a/nx-X11/extras/ttf2pt1/FONTS.hpux.html +++ /dev/null @@ -1,197 +0,0 @@ -<HTML> -<HEAD> -<TITLE> -How to install new Type1 fonts on an HP-UX 10.20 machine -</TITLE> -</HEAD> -<BODY> -Sergey A. Babkin -<br> -<A HREF="mailto:babkin@bellatlantic.net"> -<babkin@bellatlantic.net></A> or <A HREF="mailto:sab123@hotmail.com"><sab123@hotmail.com></A> -<p> -<! -(Do not edit this file, it is generated from FONTS.hpux.html!!!) -> - -<H3> -How to install new Type1 fonts on an HP-UX 10.20 machine -</H3> -<! --------------------------------------------------------- -> - -1. Add the font files to <tt>/usr/lib/X11/fonts/type1.st/typefaces</tt>. -<p> - -2. Add the font descriptions to -<tt>/usr/lib/X11/fonts/type1.st/typefaces/fonts.scale</tt>. Run `mkfontdir' -in <tt>/usr/lib/X11/fonts/type1.st/typefaces</tt>. In the descriptions -you have to specify the font manufacturer as `misc', like: -<p> - -<tt> - -misc-courier-... -</tt> -<p> - -3. Copy <tt>/usr/lib/X11/fonts/type1.st/typefaces/fonts.dir</tt> to -<tt>/usr/lib/X11/fonts/type1.st/licenses/STSYSTEM/DISPLAYS/fonts.dir</tt>. -Better yet, create a symbolic link. -<p> - -4. For each font encoding you are going to use create a description -file in <tt>/usr/lib/X11/fonts/stadmin/type1/charsets</tt>. Of course, if you -are going to use the same fonts in several encodings, the best way -would be to create fair descriptions of charsets and really store -only one encoding in typefaces, all the others will be produced -automatically. That's not difficult at all. -But the simplest way is to just copy the file <tt>cp.iso8859-1</tt> -to <tt>cp.<i><your-encoding-name></i></tt>, like <tt>cp.koi8-r</tt>. -<p> - -5. Restart you X server and/or font server. -<p> - -<H4> -What if you don't have the `root' privileges ? -</H4> -<! ----------------------------------------------- -> - -You still can run the font server and configure your X server -to get the fonts from it. -<p> - -Further let's suppose that the name on which you are going -to run the font server is named `somehost'. Login to it -and configure the font server. -<p> - -First, choose some unused port. Numbers around 9000 are a good -choice. Verify that this port is not used by somebody else -by entering -<p> - -<blockquote><tt> - netstat -naf inet |grep 9000 -</tt></blockquote> - -and look what happens. If you get nothing, that's good, this -port is unused. If you get some lines of data, try abother port. -<p> - -Go to you home directory <tt>$HOME</tt> and create some directory for -your font server, say, <tt>$HOME/fs</tt>. Copy the directory structure -of <tt>/usr/lib/X11/fonts/type1.st</tt> into <tt>$HOME/fs</tt>, so that in result -you get <tt>$HOME/fs/type1.st/<i><whatever was there></i></tt>. Copy the directory -structure of <tt>/usr/lib/X11/fonts/stadmin/type1/charsets</tt> into <tt>$HOME/fs</tt>, -so that in result you get <tt>$HOME/fs/charsets/<i><whatever was there></i></tt>. -Install the new fonts in these directorues as described above. -<p> - -Then create the fontserver configuration file, say, <tt>$HOME/fs/xfs.cfg</tt>. -The sample contents (supposing that my <tt>$HOME</tt> is equal to <tt>/home/babkin</tt>) -is: -<p> - -<! ---------------8<----------- cut here ----------------------------- -> -<hr> -<tt> -# font server configuration file -<br> -# $XConsortium: config.cpp,v 1.7 91/08/22 11:39:59 rws Exp $ -<br> - -<br> -rasterizers = /usr/lib/X11/fs/ufstrast.sl,/usr/lib/X11/fs/iforast.sl -<br> - -<br> -clone-self = off -<br> -use-syslog = off -<br> -catalogue = /home/babkin/fs/type1.st -<br> -# in decipoints -<br> -default-point-size = 120 -<br> -default-resolutions = 100,100,75,75 -<br> -port=9000 -<br> -error-file=/home/babkin/fs/fs.err -</tt> -<hr> -<! ---------------8<----------- cut here ----------------------------- -> -<p> - -Then create the script to start your font server, say, <tt>$HOME/fs/runme</tt>: -<p> - -<! ---------------8<----------- cut here ----------------------------- -> -<hr> -<tt> -TYPE1_CODEPAGE_DIR=$HOME/fs/charsets -<br> -export TYPE1_CODEPAGE_DIR -<br> -kill `ps -ef | grep $HOME/\[f\]s/xfs.cfg | awk '{print $2}'`; -<br> -nohup xfs -config $HOME/fs/xfs.cfg & -</tt> -<hr> -<! ---------------8<----------- cut here ----------------------------- -> -<p> - -Don't forget to make <tt>$HOME/fs/runme</tt> executable. Then you can -execute it manually or from you .profile. -<p> - -After you get your font server running, just execute the following -command (with proper host name and port number) in your X session -<p> - -<blockquote><tt> - xset fp+ tcp/somehost:9000 -</tt></blockquote> - -to get the access to your private font server. You can add this -information to the configuration data of your X server or just -put it also into your .profile. In the latter case the best way -to do that would be like: -<p> - -<! ---------------8<----------- cut here ----------------------------- -> -<hr> -<tt> -... -<br> -$HOME/fs/runme -<br> -sleep 2 # give it some time to start -<br> -xset fp+ tcp/somehost:9000 -<br> -... -</tt> -<hr> -<! ---------------8<----------- cut here ----------------------------- -> -<p> -</BODY> -</HTML> diff --git a/nx-X11/extras/ttf2pt1/FONTS.html b/nx-X11/extras/ttf2pt1/FONTS.html deleted file mode 100644 index 352bd0693..000000000 --- a/nx-X11/extras/ttf2pt1/FONTS.html +++ /dev/null @@ -1,708 +0,0 @@ -<HTML> -<HEAD> -<TITLE> -The ttf2pt1 font installation guide -</TITLE> -</HEAD> -<BODY> -Sergey A. Babkin -<br> -<A HREF="mailto:babkin@users.sourceforge.net"> -<babkin@bellatlantic.net></A> or <A HREF="mailto:sab123@hotmail.com"><sab123@hotmail.com></A> -<p> -<! -(Do not edit this file, it is generated from FONTS.html!!!) -> - -<!-- =defdoc cv ttf2pt1_convert 1 --> -<!-- =defdoc gs ttf2pt1_x2gs 1 --> -<H2> -THE FONT INSTALLATION GUIDE -<br> -for the TTF to Type1 converter and fonts generated by it -</H2> -<! -======================================================== -> - -There is historically a number of problems with the support of the 8-bit -character encodings. This installation guide pays a lot of attention -to the 8-bit issues, because these issues are responsible for the -most of troubles during the installation of fonts. But they are -not the only things covered in this guide, so it's worth reading -even if all you need is plain ASCII. For convenience of reading -I have marked the paragraphs dealing solely with 8-bit problems -with characters <FONT COLOR="#3333FF"><FONT SIZE=-1>*8*</FONT></FONT>. -<p> - -To simplify this installation the distribution package of the -converter contains a number of scripts written in shell and -Perl. So, to run them you will need a shell interpreter (Bourne-shell, -POSIX-shell, Korn-shell are OK, ba-shell is probably also OK but not -tested yet). The Perl scripts were tested with Perl5 but probably -should work with Perl4 too. All the scripts are located in the -`scripts' subdirectory. -<p> - -This guide considers the following issues of installation of the -fonts: -<p> - -<b> -<ul> -<li> <A HREF="#X11">X11</A><br> -<li> <A HREF="#gs">Ghostscript</A><br> -<li> <A HREF="#win">MS Windows</A><br> -<li> <A HREF="#netscape">Netscape Navigator/Communicator</A><br> -<li> <A HREF="#rpm">Linux RPM package</A><br> -<li> <A HREF="#framemaker">FrameMaker</A><br> -<li> <A HREF="#soffice">StarOffice</A><br> -</ul> -</b><p> - -<A NAME="X11"></A> -<H3> -X11 -</H3> -<! -=== -> - -<!-- =section cv NAME --> -<!-- =text B<ttf2pt1_convert> - convenience font conversion script --> -<!-- =stop --> -To simplify the conversion a set of scripts is provided with <b>ttf2pt1</b>. -They are collected in the `<TT>scripts</TT>' subdirectory. -<p> - -<!-- =section cv DESCRIPTION --> -`<b>Convert</b>' is the master conversion script provided with ttf2pt1. -When installed into a public directory it's named `<b>ttf2pt1_convert</b>' -to avoid name collisions with the other programs. -<p> -<!-- =stop --> - -It's called as: -<p> - -<!-- =section cv SYNOPSIS --> -<!-- =text ttf2pt1_convert B<[config-file]> --> -<!-- =stop --> -<blockquote> - convert <i>[config-file]</i> -</blockquote> - -<!-- =section cv DESCRIPTION --> -If the configuration file is not specified as an argument then the file -`<TT>convert.cfg</TT>' in the current directory is used. This file contains -a set of configuration variables. The distribution contains a sample file -file `<TT>convert.cfg.sample</TT>'. Please copy it to `<TT>convert.cfg</TT>', -look inside it and change the configuration variables. The more stable -configuration variables, such as the path names of the scripts and -encoding files are located in `<TT>convert</TT>' itself, they are -automatically updated when installing <b>ttf2pt1</b>. -<p> - -Put all the TTF fonts you want to convert into some directory (this -may be just the directory that already contains all the Windows -fonts on a mounted FAT filesystem). If you have fonts in different -source encoding then put the fonts in each of the encodings -into a separate directory. Up to 10 source directories are -supported. If you (in a rather unlikely case) have more source -directories then you can make two separate runs of the converter, -converting up to 10 directories at a time. -<p> - -The variables in the configuration file are: -<p> - -<!-- ==over 2 --> -<!-- ==item * --> -<B><tt>SRCDIRS</tt></B> - the list of directories (with absolute paths) with - TTF fonts. Each line contains at least 3 fields: the name of the directory, - the language of the fonts in it (if you have fonts for different - languages you have to put them into the separate directories) and the - encoding of the fonts. Again, if you have some of the TTF typefaces in - one encoding, and some in another (say, CP-1251 and KOI-8), you have - to put them into the separate source directories. Some lines may contain - 4 fields. Then the fourth field is the name of the external map to - convert the Unicode fonts into the desirable encoding. This map is - used instead of the built-in map for the specified language. -<p> - -<FONT COLOR="#3333FF"><FONT SIZE=-1>*8*</FONT></FONT> -An interesting thing is that some languages have more than one -widely used character encodings. For example, the widely used -encodings for Russian are IBM CP-866 (MS-DOS and Unix), KOI-8 -(Unix and VAX, also the standard Internet encoding), IBM CP-1251 (MS Windows). -That's why I have provided the means to generate the converted fonts -in more than one encoding. See the file <A HREF="encodings/README.html">encodings/README</A> for -details about the encoding tables. Actually, if you plan to use -these fonts with Netscape Navigator better use the aliases -cp-866 instead of ibm-866 and windows-1251 instead of ibm-1251 -because that's what Netscape wants. -<p> - -<!-- ==item * --> -<b><tt>DSTDIR</tt></b> - directory for the resulting Type1 fonts. Be careful! - This directory gets completely wiped out before conversion, - so don't use any already existing directory for this purpose. -<p> - -<!-- ==item * --> -<b><tt>DSTENC<i>{language}</i></tt></b> - the list of encodings in which the destination - fonts will be generated for each language. Each font of that - language will be generated in each of the specified - encodings. If you don't want any translation, just specify both - <tt>SRCENC</tt> and <tt>DSTENC</tt> as iso8859-1 (or if you want any other encoding - specified in the fonts.dir, copy the description of 8859-1 with - new name and use this new name for <tt>SRCENC</tt> and <tt>DSTENC</tt>). -<p> - -<!-- ==item * --> -<b><tt>FOUNDRY</tt></b> - the foundry name to be used in the fonts.dir file. I have - set it to `fromttf' to avoid name conflicts with any existing font for - sure. But this foundry name is not registered in X11 standards and - if you want to get the full standard compliance or have a font server - that enforces such a compliance, use `misc'. -<p> -<!-- ==back --> - -The next few parameters control the general behavior of the converter. -They default values are set to something reasonable. -<p> - -<!-- ==over 2 --> -<!-- ==item * --> -<b><tt>CORRECTWIDTH</tt></b> - if the value is set to <b><tt>YES</tt></b> then use the - converter option <tt><b>-w</b></tt>, otherwise don't use it. See the description of - this option in the <A HREF="README.html">README</A> file. -<p> - -<!-- ==item * --> -<b><tt>REMOVET1A</tt></b> - if the value is set to <b><tt>YES</tt></b> then after - conversion remove the un-encoded <tt>.t1a</tt> font files and the - intermediate <tt>.xpfa</tt> font metric files. -<p> - -<!-- ==item * --> -<b><tt>INSTALLFONTMAP</tt></b> - a Ghostscript parameter, if the value is set to - <b><tt>YES</tt></b> then install the entries for the new fonts - right into the main <tt>Fontmap</tt> file. Otherwise just leave - the file <tt>Fontmap.ttf</tt> in the Ghostscript configuration - directory. -<p> - -<!-- ==item * --> -<b><tt>HINTSUBST</tt></b> - if the value is set to <b><tt>YES</tt></b> use the option - <tt><b>-H</b></tt>, otherwise don't use it. This option enables the - hint substitution technique. If you have not installed the X11 patch - described above, use this option with great caution. See further - description of this option in the <A HREF="README.html">README</A> file. -<p> - -<!-- ==item * --> -<b><tt>ENFORCEISO</tt></b> - if the value is set to <b><tt>YES</tt></b> then - disguise the resulting fonts as the fonts in ISOLatin1 encoding. Historically - this was neccessary due to the way the installer scripts created the - X11 font configuration files. It is not neccessary any more for this - purpose. But if you plan to use these fonts with some other application - that expects ISOLatin1 encoding then better enable this option. -<p> - -<!-- ==item * --> -<b><tt>ALLGLYPHS</tt></b> - if the value is set to <b><tt>YES</tt></b> then - include all the glyphs from the source fonts into the resulting fonts, even - if these glyphs are inaccessible. If it's set to <b><tt>NO</tt></b> then - include only the glyphs which have codes assigned to them. The glyphs - without codes can not be used directly. But some clever programs, - such as the Type 1 library from XFree86 3.9 and higher can change - the encoding on the fly and use another set of glyphs. If you have not - installed the X11 patch described above, use this option with great - caution. See further description of the option option <tt><b>-a</b></tt> in the - <A HREF="README.html">README</A> file. -<p> - -<!-- ==item * --> -<b><tt>GENUID</tt></b> - if the value is set to <b><tt>YES</tt></b> then use - the option <tt><b>-uA</b></tt> of the converter to generate UniqueIDs for - the converted fonts. The standard X11 Type 1 library does not use - this ID, so it may only be neccessary for the other applications. - The script is clever enough to generate different UniqueID for the - same font converted to multiple encodings. Also after conversion it - checks all the fonts generacted during the session for duplicated - UniqueID and shows those. Still, this does not quarantee that these - UniqueIDs won't overlap with some other fonts. The UniqueIDs are - generated as hash values from the font names, so it's guaranteed - that if the `<tt>convert</tt>' script runs multiple times it will - generate the same UniqueIDs during each run. See further description - of this option in the <A HREF="README.html">README</A> file. -<p> - -<!-- ==item * --> -<b><tt>GENUID</tt></b> - if the value is set to <b><tt>YES</tt></b> then create - the <tt>.pfb</tt> files, otherwise the <tt>.pfa</tt> files. The <tt>.pfb</tt> - files are more compact but contain binary data, so you may experience some - troubles when transferring them through the network. -<p> -<!-- ==back --> - -The following parameters are used to locate the other scripts and -configuration files. By default the scripts do a bit of guessing for them: -they search in the <b>ttf2pt1</b> installation directory if <b>ttf2pt1</b> -was installed or otherwise suppose that you are running `<tt>convert</tt>' with -`<tt>scripts</tt>' subdirectory being the current directory. -<p> - -<!-- ==over 2 --> -<!-- ==item * --> -<b><tt>ENCDIR</tt></b> - directory containing the descriptions of encodings -<br> -<!-- ==item * --> -<b><tt>MAPDIR</tt></b> - directory containing the external map files -<p> -<!-- ==back --> - -Besides that a few parameters are built into the `<tt>convert</tt>' script itself. -You probably won't need to change them: -<p> - -<!-- ==over 2 --> -<!-- ==item * --> -<tt><b>T1ASM</b></tt>, <tt><b>TTF2PT1</b></tt>, <tt><b>TRANS</b></tt>, <tt><b>T1FDIR</b></tt>, <tt><b>FORCEISO</b></tt> - paths to the other script -<p> -<!-- ==back --> - -Also there are a few parameters controlling the installation of -fonts for Ghostscript. Please look at their description in the -<A HREF="#gs">Ghostscript</a> section of documentation or in the <b>ttf2pt1_x2gs(1)</b> -manual page before running `<tt>convert</tt>'. If these parameters are -set, `<tt>convert</tt>' will call the `<tt>x2gs</tt>' script automatically -to install the newly converted fonts in Ghostscript. -<p> - -After creating the configuration file run the `<tt>convert</tt>' script. Look at -the result and the log file in <tt>DSTDIR</tt>. -<p> - -Add the directory with newly converted fonts to the configuration -of X server or font server. For most of the systems this step is -very straightforward. For HP-UX it's rather tricky and poorly -documented, so the file <A HREF="FONTS.hpux.html">FONTS.hpux</A> gives a short description. -<p> - -If you don't have the privileges of the root user, you still can -configure your private font server. Just use some non-standard -port number (see <A HREF="FONTS.hpux.html">FONTS.hpux</A> for an example, exept that you won't -need all the HP-related stuff on any other system). -<p> -<!-- =stop --> - -<H4> -Known Problems -</H4> -<! --------------- -> -<!-- =section cv BUGS --> -<!-- ==head2 Known problems --> - -<ul> -<li> One catch is that the X11 Type 1 font library has a rather low limit - on the font size. Because of this the fonts with more complicated - outlines and the enabled hint substitution may not fit into - this limit. The same applies to the fonts with very complicated - outlines or with very many glyphs (especially the fonts with - over 256 glyphs). So you will need to excercise caution with - these options if you plan using these fonts with X11. Some vendors - such as HP provide the Type 1 implementation licensed from Adobe - which should have no such problem. -<p> - - But there is a solution even for the generic X11. A patch located - in the subdirectory `<tt>app/X11</tt>' fixes this problem as well - as some other minor problems. Its description is provided in - <A HREF="app/X11/README.html">app/X11/README</A>. -<p> - - To fix the X11 font library, you have to get the X11 sources. I - can recommend the ftp sites of the XFree86 project <A HREF="ftp://ftp.xfree86.org">ftp://ftp.xfree86.org</A> - or of the Open Group <A HREF="ftp://ftp.x.org">ftp://ftp.x.org</A>. This patch was made on the sources - of XFree86 so you may have better success with applying it to the - XFree86 distribution. After you have got the sources, make sure - that you can compile them. Then apply the patch as described. - Make sure that it was applied properly. Compile the sources again - (actually, you need only the fonts library, the fonts server, and - possibly the X server). It would be prudent now to save your old - font library, font server and, possibly, X server. Then install - the new recently compiled versions of these files. Of course, - if you know someone who already has compiled these files for the - same OS as yours, you can just copy the binary fles from him. -<p> - - Alas, building the X11 system from the source code is not the - easiest thing in the world and if you have no experience it - can be quite difficult. In this case just avoid the aforementioned - features or check each converted font to make sure that it - works properly. -<p> - -<li> The Type1 font library from the standard X11 distribution - does not work on HP-UX (at least, up to 10.01). The font server - supplied with HP-UX up to 10.01 is also broken. Starting from - HP-UX 10.20 (I don't know about 10.10) they supply a proprietary font - library and the converted fonts work fine with it, provided that - they are configured properly (see the file <A HREF="FONTS.hpux.html">FONTS.hpux</A>). -<p> - -<li> The <tt>fonts.scale</tt> files created by the older versions of the - <tt>ttf2pt1</tt> installation program (up to release 3.1) have conflicted - with the language definitions of the <tt>Xfsft</tt> font server and - parts of it included into XFree86. To overcome this incompatibility - the never versions creats the <tt>fonts.scale</tt> file describing all the - fonts as belonging to the <tt>adobe-fontspecific</tt> encoding and - the <tt>fonts.alias</tt> file with the proper names. The drawback of - this solution is that <tt>xlsfonts</tt> gives the list of twice more - fonts. But as a side effect the option <tt><b>ENFORCEISO</b></tt> in - `<tt>convert.cfg</tt>' is not required for X11 any more. -<p> - -<li> The conversion script has no support for Eastern multi-plane fonts. - Contribution of such a support would be welcome. -<p> -</ul> -<!-- =stop --> -<!-- =section cv FILES --> -<!-- ==over 2 --> -<!-- ==item * --> -<!-- =text TTF2PT1_SHAREDIR/scripts/convert.cfg.sample --> -<!-- ==item * --> -<!-- =text TTF2PT1_SHAREDIR/scripts/* --> -<!-- ==item * --> -<!-- =text TTF2PT1_SHAREDIR/README --> -<!-- ==item * --> -<!-- =text TTF2PT1_SHAREDIR/FONTS --> -<!-- ==item * --> -<!-- =text TTF2PT1_SHAREDIR/* --> -<!-- ==item * --> -<!-- =text TTF2PT1_BINDIR/ttf2pt1 --> -<!-- ==back --> -<!-- =stop --> -<!-- =section cv SEE ALSO --> -<!-- ==over 4 --> -<!-- ==item * --> -<!-- =text L<ttf2pt1(1)> --> -<!-- ==item * --> -<!-- =text L<ttf2pt1_x2gs(1)> --> -<!-- ==item * --> -<!-- =text L<t1asm(1)> --> -<!-- ==back --> -<!-- =stop --> - -<A NAME="gs"></A> -<H3> -Ghostscript -</H3> -<! -=========== -> -<!-- =section gs NAME --> -<!-- =text B<ttf2pt1_x2gs> - font installer for Ghostscript --> -<!-- =stop --> - -<!-- =section gs DESCRIPTION --> -The fonts generated with <b>ttf2pt1</b> work fine with Ghostscript by -themselves. The script `<b>x2gs</b>' (or `<b>ttf2pt1_x2gs</b>' when installed -into a public directory, to avoid name conflicts with other -programs) links the font files from the X11 direcotry into the Ghostscript -directory and automatically creates the description file (<tt>Fontmap</tt>) -in Ghostscript format. -<!-- =stop --> - -It's called as: -<p> - -<!-- =section gs SYNOPSIS --> -<!-- =text ttf2pt1_x2gs B<[config-file]> --> -<!-- =stop --> -<blockquote> - x2gs <i>[config-file]</i> -</blockquote> - -<!-- =section gs DESCRIPTION --> -If the configuration file is not specified as an argument then the file -`<TT>convert.cfg</TT>' in the current directory is used, just like the -`<tt>convert</tt>' script does. Indeed, this configuration file is used for -both scripts. -<p> - -The Ghostscript-related parameters in the configuration file are: -<p> - -<b><tt>DSTDIR</tt></b> - the X11 font directory used by `<tt>x2gs</tt>' as the - source of the fonts. This parameter is common with the X11 - configuration. -<p> - -<b><tt>GSDIR</tt></b> - the base directory of Ghostsript. If this - parameter is set to an empty string then `<tt>convert</tt>' won't - call `<tt>x2gs</tt>'. So if you want to get only the X11 fonts - installed then set this parameter to an empty string. This - directory may vary on various system, so please check your - system and set this value accordingly before running the script. -<p> - -<b><tt>GSFONTDIR</tt></b> - the font directory of Ghostscript. In the standard - Ghostscript installation it's a subdirectory of <tt>GSDIR</tt> - but some systems may use completely different directories. -<p> - -<b><tt>GSCONFDIR</tt></b> - the configuration subdirectory of Ghostscript - that contains the <tt>Fontmap</tt> file. -<p> - -<b><tt>INSTALLFONTMAP</tt></b> - if the value is set to <b><tt>YES</tt></b> then - install the entries for the new fonts right into the main - <tt>Fontmap</tt> file. Otherwise just leave the file <tt>Fontmap.ttf</tt> - in the Ghostscript configuration directory. -<p> - - -After preparing the configuration file run the script. It symbolicaly links -all the font files and creates the description file <tt>Fontmap.ttf</tt> in -<tt>GSCONDFIR</tt>. After that there are two choices. -<p> - -If the option <tt>INSTALLFONTMAP</tt> was set to <tt>YES</tt> then -the font descriptions are also automatically installed into the -master <tt>Fontmap</tt> file. The script is clever enough to -detect if it was run multiple times with the same directories -and if so it replaces the old <tt>Fontmap</tt> entries with -the new ones instead of just accumulating all of them. You -may also run it multiple times for multiple X11 directories -and all the results will be properly collected in the <tt>Fontmap</tt>. -But it's your responsibility to watch that the names of the -font files don't overlap. If the X11 font directory gets -renamed then you have to remove its font entries from the -<tt>Fontmap</tt> and only after that re-run `<tt>x2gs</tt>' -for the new directory. -<p> - -On the other hand if the option <tt>INSTALLFONTMAP</tt> was set to -<tt>NO</tt> then go to the <tt>GSCONFDIR</tt> directory and insert the -contents of <tt>Fontmap.ttf</tt> into the <tt>Fontmap</tt> file -manually. This step may be left manual to make the installation -a little bit more safe. -<p> - -After that you may also want to redefine some of the aliases in -<tt>Fontmap</tt> to refer to the newly installed fonts. -But the redefinition of the aliases may be dangerous if the width of -characters in the new font will be different from the old font. -Alas, there is no visible solution of this problem yet. -<p> -<!-- =stop --> -<!-- =section gs FILES --> -<!-- ==over 2 --> -<!-- ==item * --> -<!-- =text TTF2PT1_SHAREDIR/scripts/convert.cfg.sample --> -<!-- ==item * --> -<!-- =text TTF2PT1_SHAREDIR/scripts/* --> -<!-- ==item * --> -<!-- =text TTF2PT1_SHAREDIR/README --> -<!-- ==item * --> -<!-- =text TTF2PT1_SHAREDIR/FONTS --> -<!-- ==item * --> -<!-- =text TTF2PT1_SHAREDIR/* --> -<!-- ==item * --> -<!-- =text TTF2PT1_BINDIR/ttf2pt1 --> -<!-- ==back --> -<!-- =stop --> -<!-- =section gs SEE ALSO --> -<!-- ==over 4 --> -<!-- ==item * --> -<!-- =text L<ttf2pt1(1)> --> -<!-- ==item * --> -<!-- =text L<ttf2pt1_convert(1)> --> -<!-- ==item * --> -<!-- =text L<t1asm(1)> --> -<!-- ==back --> -<!-- =stop --> - -<A NAME="win"></A> -<H3> -MS Windows -</H3> -<! -=========== -> - -<b>Ttf2pt1</b> can be built on Windows either with native compiler or in -POSIX emulation mode. -<p> - -Native MS Windows compilers require a different way to build the converter -instead of the Makefile (their <tt>make</tt> programs commonly are quite weird -and limited in capabilities). An example of batch file <tt>winbuild.bat</tt> -is provided for MS Visual C/C++. Probably it can be easily adapted for other -32-bit Windows and DOS compilers. The important part is to define the -preprocessor symbol WINDOWS during compilation. -<p> - -Cygnus <tt>make</tt> almost supports full Makefiles but not quite. Seems -like its POSIX support is also of the same quality "almost but not quite". -So another command file <tt>cygbuild.sh</tt> is provided for Cygnus GNU C, also -with the preprocessor symbol WINDOWS defined. It is intended to be run from -the Cygnus BASH shell. To run the programs produced by the Cygnus compiler -the Cygnus library file <tt>CYGWIN1.DLL</tt> should be copied first into -<tt>C:\WINDOWS</tt>. -<p> - -To run the accompanying scripts Perl for Windows will be required as well as -other tools from the Cygnus set. -<p> - -The Windows support was not particularly tested, so in case of problems with -building or running the converter please let us know. -<p> - -The pre-built code (possibly of an older version) of ttf2pt1 for MS Windows is -available from the GnuWin32 project from - -<A HREF="http://gnuwin32.sourceforge.net/packages/ttf2pt1.htm">http://gnuwin32.sourceforge.net/packages/ttf2pt1.htm</A> -<p> - -<A NAME="netscape"></a> -<H3> -Netscape Navigator/Communicator -</H3> -<! -=============================== -> - -Basically, the biggest problem with Netscape Navigator is that -it has built-in fixed PostScript font names and built-in fixed -glyph tables for them. Oh, no, that's two! Let's start over: -basically the two biggest problems of Netscape Navigator are -that (one)it has built-in fixed PostScript font names and (two) -built-in fixed glyph tables for them and (three) it always -assumes that the fonts have ISOLatin1 encoding. OK, let's -start over again: basically the three biggest problems of Netscape -Navigator are that (one) it has built-in fixed PostScript font names, -(two) built-in fixed glyph tables for them and (three) it always -assumes that the fonts have ISOLatin1 encoding and (four) it -does not remember the scaled font size between the sessions. -You did not expect such a Spanish Inquisition, did you ? (<A HREF="#nsfn1">*</a>) -<p> - -Luckily, we have solutions for all of these problems. They are -located in the subdirectory `<tt>app/netscape</tt>' and described -in <A HREF="app/netscape/README.html">app/netscape/README</a>. -<p> - -<A NAME="nsfn1"></a> - -------<br> - <FONT SIZE=-1>*) See Monty Python's Flying Circus, episode 15</FONT></FONT> -<p> - -<FONT COLOR="#3333FF"><FONT SIZE=-1>*8*</FONT></FONT> -<H4> -Netscape and cyrillic fonts<br> -<! ---------------------------- -> -(courtesy of Zvezdan Petkovic) -</H4> - -If you use TrueType fonts in your X, as I do, and you always get -KOI8-R encoded pages, then your Netscape does not recognise windows-1251 -encoding. Microsoft TrueType fonts simply declare all encodings they -can support including KOI8-R. For some reason, KOI8-R always wins over -ISO-8859-5 in Netscape under X. If you are reading other cyrillic -languages besides Russian, you might want to either erase KOI8-R entries -from the fonts.dir and fonts.scale files, or alternatively fix Netscape. -I put this line in my .Xdefaults. -<p> - -<blockquote><tt> - Netscape*documentFonts.charset*koi8-r: iso-8859-5 -</tt></blockquote> -<p> - -Notice that you can still read Russian sites without trouble because -Netscape translates KOI8-R to ISO-8859-5 on the fly. I read both Russian -and Serbian sites with no trouble. -<p> - -<b>Note:</b> <i>If anybody knows the way to tell Netscape under Unix how to -recognise {windows,ibm,cp}-1251 encoded fonts, I'd like to hear about that.</i> -<p> - -<A NAME="rpm"></a> -<H3> -Linux RPM package -</H3> -<! -================= -> - -The spec file for the creation of a Linux RPM package is located in -<tt>app/RPM</tt>. It has been contributed by Johan Vromans. When -<tt>make all</tt> is ran in the main directory it among the other -things creates the version of itself adapted to Linux in <tt>app/RPM</tt>, -you may want to copy that version back to the main directory. -<p> - -<B>Warning:</B> Please note that the install section is incomplete, and -the installed scripts won't work until the paths inside them -are corrected. -<p> - -<A NAME="framemaker"></a> -<H3> -FrameMaker -</H3> -<! -========== -> - -The fonts and AFM files generated by the version 3.2 and higher -should work with Framemaker without problems. The AFM files -generated by the previous versions of the converter require a -line added to them: -<p> - - <tt>EncodingScheme FontSpecific</tt> -<p> - -And the underscores in the font names of the font and AFM files -generated by the older versions may need to be changed to dashes. -<p> - -<B>NOTE by Jason Baietto:</B> Ignore the directions in the Frame on-line docs -that say to put a "serverdict begin 0 exitserver" line in the pfa files. -Doing this caused both my printer and ghostscript to choke on the resulting -output from FrameMaker, so I would not advise doing this (though your -mileage may vary). -<p> - -<A NAME="soffice"></a> -<H3> -StarOffice -</H3> -<! -========== -> - -StarOffice 5.1x has been reported to crash if the <tt>.afm</tt> file contains -spaces in the values of such statements as <b>Version</b>, <b>Weight</b> etc. -These spaces are permitted by the Adobe spec, so this is a problem of -StarOffice. The easiest way to fix these <tt>.afm</tt> files for StarOffice -is to remove spaces in these strings or remove these strings (in case if -they are optional) at all. This can be done automatically with a <tt>sed</tt> -script. It seems that StarOffice 5.2 has this problem fixed, so we decided to -spend no efforts on providing workarounds for 5.1 with <tt>ttf2pt1</tt>. -<p> - -</BODY> -</HTML> diff --git a/nx-X11/extras/ttf2pt1/Makefile b/nx-X11/extras/ttf2pt1/Makefile deleted file mode 100644 index 2616d4687..000000000 --- a/nx-X11/extras/ttf2pt1/Makefile +++ /dev/null @@ -1,279 +0,0 @@ - -# This file should be configured before running `make'. -# Uncomment or change the values that are relevant for your OS. - -# The preferred C compiler (by default use the OS-specific default value). -# For BSD/OS, FreeBSD, Linux (all flavors), NetBSD, OpenBSD the default -# compiler is GNU C. -# (Note please the politically correct ordering by alphabet ! :-) -# -# Use GNU C even if it's not the default compiler -# -#CC=gcc -# -# Use the standard ANSI C compiler on HP-UX even if it's not default -# -#CC=c89 - -# -# The system-dependent flags for the C compiler -# -# Default - -CFLAGS_SYS= -O - -# For GNU C -# -#CFLAGS_SYS= -O2 -# -# For GNU C with long options support library (Linux etc.) -# -#CFLAGS_SYS= -O2 -D_GNU_SOURCE -# -# For GNU C on HP-UX/PA-RISC 1.1 -# -#CFLAGS_SYS= -O2 -Wa,-w -# -# For the standard ANSI C on HP-UX -# -#CFLAGS_SYS= +O2 -D_HPUX_SOURCE - -# -# The system-dependent libraries -# -# Defalut (for the BSD-style OSes) - -LIBS_SYS= -lm - -# For SystemV (such as SCO, UnixWare, Solaris, but _NOT_ Linux or HP-UX) -# -#LIBS_SYS= -lm -lsocket - -# -# The flags for C compiler for the FreeType-2 library (disabled by default). -# This WON'T BUILD with FT2-beta8, use the FreeType release 2.0.4 -# http://download.sourceforge.net/freetype/freetype-2.0.4.tar.gz - -CFLAGS_FT= - -# To enable use of the FreeType-2 library -# (if the include and lib directory do not match your installation, -# modify them), also uncomment LIBS_FT -# -#CFLAGS_FT = -DUSE_FREETYPE -I/usr/local/include/freetype2 -I/usr/local/include - -# -# The FreeType-2 library flags (disabled by default) - -LIBS_FT= - -# To enable use of the FreeType-2 library -# (if the include and lib directory do not match your installation, -# modify them), also uncomment CFLAGS_FT -# -#LIBS_FT= -L/usr/local/lib -lfreetype - -# -# The flags for C compiler for the Autotrace library (disabled by default). -# USE OF THIS FEATURE IS STRONGLY DISCOURAGED, THE BUILT-IN TRACING -# (AKA VECTORIZATION) PROVIDES MUCH BETTER RESULTS. -# The tested version is 0.29a (and the fonts produced with it are -# absolutely not usable). -# http://download.sourceforge.net/autotrace/autotrace-0.29.tar.gz - -CFLAGS_AT= - -# To enable use of the Autotrace library -# (if the include and lib directory do not match your installation, -# modify them), also uncomment LIBS_AT -# -#CFLAGS_AT = -DUSE_AUTOTRACE -I/usr/local/include - -# -# The Autotrace library flags (disabled by default) - -LIBS_AT= - -# To enable use of the Autotrace library -# (if the include and lib directory do not match your installation, -# modify them), also uncomment CFLAGS_AT -# -#LIBS_AT= -L/usr/local/lib -lautotrace - -# -# Preference of front-ends if multiple parsers match a file -# (by default the build-in front-end takes preference over FreeType) - -CFLAGS_PREF= - -# To prefer FreeType (if enabled): -# -#CFLAGS_PREF= -DPREFER_FREETYPE - -# Uncomment the second line to not compile t1asm into ttf2pt1 -CFLAGS_EXTT1ASM= -#CFLAGS_EXTT1ASM= -DEXTERNAL_T1ASM - -CFLAGS= $(CFLAGS_SYS) $(CFLAGS_FT) $(CFLAGS_AT) $(CFLAGS_PREF) -LIBS= $(LIBS_SYS) $(LIBS_FT) $(LIBS_AT) - -# Installation-related stuff -# -# The base dir for installation and subdirs in it -INSTDIR = /usr/local -# for binaries -BINDIR = $(INSTDIR)/bin -# for binaries of little general interest -LIBXDIR = $(INSTDIR)/libexec/ttf2pt1 -# for scripts, maps/encodings etc. -SHAREDIR = $(INSTDIR)/share/ttf2pt1 -MANDIR = $(INSTDIR)/man - -# owner and group of installed files -OWNER = root -GROUP = bin - -# After you have configured the Makefile, comment out the following -# definition: -warning: docs - @echo >&2 - @echo " You have to configure the Makefile before running make!" >&2 - @echo "(or if you are lazy and hope that it will work as is run \`make all')">&2 - @echo >&2 - -DOCS=CHANGES README FONTS FONTS.hpux encodings/README other/README \ - app/X11/README app/netscape/README app/TeX/README - -SUBDIRS = app encodings maps scripts other -TXTFILES = README* FONTS* CHANGES* COPYRIGHT - -MANS1=ttf2pt1.1 ttf2pt1_convert.1 ttf2pt1_x2gs.1 -MANS=$(MANS1) $(MANS5) - -all: t1asm ttf2pt1 docs mans rpm - -docs: $(DOCS) - -mans: $(MANS) - -clean: - rm -f t1asm ttf2pt1 *.o app/RPM/Makefile app/RPM/*.spec *.core core.* core - ( cd other && make clean; ) - ( cd app/netscape && make clean; ) - -veryclean: clean - rm -f $(DOCS) $(MANS) - -rpm: app/RPM/Makefile app/RPM/ttf2pt1.spec - -ttf2pt1.1: README.html - scripts/html2man . . <README.html - -ttf2pt1_convert.1 ttf2pt1_x2gs.1: FONTS.html - scripts/html2man . . <FONTS.html - -app/RPM/Makefile: Makefile - sed 's/^CFLAGS_SYS.*=.*$$/CFLAGS_SYS= -O2 -D_GNU_SOURCE/;/warning:/,/^$$/s/^/#/' <Makefile >app/RPM/Makefile - -app/RPM/ttf2pt1.spec: app/RPM/ttf2pt1.spec.src version.h - sed 's/^Version:.*/Version: '`grep TTF2PT1_VERSION version.h| cut -d\" -f2`'/' <app/RPM/ttf2pt1.spec.src >$@ - -t1asm: t1asm.c - $(CC) $(CFLAGS) -o t1asm -DSTANDALONE t1asm.c $(LIBS) - -ttf2pt1.o: ttf2pt1.c ttf.h pt1.h global.h version.h - $(CC) $(CFLAGS) -c ttf2pt1.c - -pt1.o: pt1.c ttf.h pt1.h global.h - $(CC) $(CFLAGS) -c pt1.c - -ttf.o: ttf.c ttf.h pt1.h global.h - $(CC) $(CFLAGS) -c ttf.c - -ft.o: ft.c pt1.h global.h - $(CC) $(CFLAGS) -c ft.c - -bdf.o: bdf.c pt1.h global.h - $(CC) $(CFLAGS) -c bdf.c - -bitmap.o: bitmap.c pt1.h global.h - $(CC) $(CFLAGS) -c bitmap.c - -runt1asm.o: runt1asm.c global.h - $(CC) $(CFLAGS) $(CFLAGS_EXTT1ASM) -c runt1asm.c - -ttf2pt1: ttf2pt1.o pt1.o runt1asm.o ttf.o ft.o bdf.o bitmap.o - $(CC) $(CFLAGS) -o ttf2pt1 ttf2pt1.o pt1.o runt1asm.o ttf.o ft.o bdf.o bitmap.o $(LIBS) - -CHANGES: CHANGES.html - scripts/unhtml <CHANGES.html >CHANGES - -README: README.html - scripts/unhtml <README.html >README - -encodings/README: encodings/README.html - scripts/unhtml <encodings/README.html >encodings/README - -other/README: other/README.html - scripts/unhtml <other/README.html >other/README - -app/X11/README: app/X11/README.html - scripts/unhtml <app/X11/README.html >app/X11/README - -app/netscape/README: app/netscape/README.html - scripts/unhtml <app/netscape/README.html >app/netscape/README - -app/TeX/README: app/TeX/README.html - scripts/unhtml <app/TeX/README.html >app/TeX/README - -FONTS: FONTS.html - scripts/unhtml <FONTS.html >FONTS - -FONTS.hpux: FONTS.hpux.html - scripts/unhtml <FONTS.hpux.html >FONTS.hpux - -install: all - scripts/inst_dir $(BINDIR) $(OWNER) $(GROUP) 0755 - scripts/inst_dir $(LIBXDIR) $(OWNER) $(GROUP) 0755 - scripts/inst_dir $(SHAREDIR) $(OWNER) $(GROUP) 0755 - scripts/inst_dir $(MANDIR)/man1 $(OWNER) $(GROUP) 0755 - scripts/inst_dir $(MANDIR)/man5 $(OWNER) $(GROUP) 0755 - cp -R $(TXTFILES) $(SUBDIRS) $(SHAREDIR) - chown -R $(OWNER) $(SHAREDIR) - chgrp -R $(GROUP) $(SHAREDIR) - chmod -R go-w $(SHAREDIR) - scripts/inst_file ttf2pt1 $(BINDIR)/ttf2pt1 $(OWNER) $(GROUP) 0755 - [ -f $(BINDIR)/t1asm ] || scripts/inst_file t1asm $(LIBXDIR)/t1asm $(OWNER) $(GROUP) 0755 - sed 's|^TTF2PT1_BINDIR=$$|TTF2PT1_BINDIR=$(BINDIR)|;\ - s|^TTF2PT1_LIBXDIR=$$|TTF2PT1_LIBXDIR=$(LIBXDIR)|;\ - s|^TTF2PT1_SHAREDIR=$$|TTF2PT1_SHAREDIR=$(SHAREDIR)|;' <scripts/convert >cvt.tmp - scripts/inst_file cvt.tmp $(BINDIR)/ttf2pt1_convert $(OWNER) $(GROUP) 0755 - scripts/inst_file cvt.tmp $(SHAREDIR)/scripts/convert $(OWNER) $(GROUP) 0755 - rm cvt.tmp - scripts/inst_file scripts/x2gs $(BINDIR)/ttf2pt1_x2gs $(OWNER) $(GROUP) 0755 - for i in $(MANS1); do { \ - sed 's|TTF2PT1_BINDIR|$(BINDIR)|;\ - s|TTF2PT1_LIBXDIR|$(LIBXDIR)|;\ - s|TTF2PT1_SHAREDIR|$(SHAREDIR)|;' <$$i >$(MANDIR)/man1/$$i \ - && chown $(OWNER) $(MANDIR)/man1/$$i \ - && chgrp $(GROUP) $(MANDIR)/man1/$$i \ - && chmod 0644 $(MANDIR)/man1/$$i \ - || exit 1; \ - } done - -uninstall: - rm -f $(BINDIR)/ttf2pt1 $(BINDIR)/ttf2pt1_convert $(BINDIR)/ttf2pt1_x2gs - rm -rf $(LIBXDIR) - rm -rf $(SHAREDIR) - for i in $(MANS1); do { \ - rm -f $(MANDIR)/man1/$$i $(MANDIR)/man1/$$i.gz; \ - } done - - -# targets for automatic generation of releases and snapshots - -snapshot: - scripts/mkrel snapshot - -release: - scripts/mkrel release diff --git a/nx-X11/extras/ttf2pt1/README.FIRST b/nx-X11/extras/ttf2pt1/README.FIRST deleted file mode 100644 index f89db2010..000000000 --- a/nx-X11/extras/ttf2pt1/README.FIRST +++ /dev/null @@ -1,4 +0,0 @@ -To get the plain-text README and installation guides run: - - make docs - diff --git a/nx-X11/extras/ttf2pt1/README.html b/nx-X11/extras/ttf2pt1/README.html deleted file mode 100644 index b1d6c9c22..000000000 --- a/nx-X11/extras/ttf2pt1/README.html +++ /dev/null @@ -1,1182 +0,0 @@ -<HTML> -<HEAD> -<TITLE> -TTF2PT1 - A True Type to PostScript Type 1 Converter -</TITLE> -</HEAD> -<BODY> -<!-- =defdoc t1 ttf2pt1 1 --> -<H2> -<!-- =section t1 NAME --> -TTF2PT1 - A True Type to PostScript Type 1 Font Converter -<!-- =stop --> -</H2> - -<! -(Do not edit this file, it is generated from README.html!!!) -> -<TT> -[ -<blockquote> -<!-- =section t1 HISTORY --> - Based on ttf2pfa by Andrew Weeks, and help from Frank Siegert. -<BR> - Modification by Mark Heath. -<BR> - Further modification by Sergey Babkin. -<BR> - The Type1 assembler by I. Lee Hetherington with modifications by - Kai-Uwe Herbing. -<!-- =stop --> -</blockquote> -] -</TT> -<p> - -Ever wanted to install a particular font on your XServer but only could find -the font you are after in True Type Format? -<p> - -Ever asked <TT>comp.fonts</TT> for a True Type to Type 1 converter and got a List -of Commercial software that doesn't run on your Operating System? -<p> - -Well, this program should be the answer. This program is written in C (so it -should be portable) and therefore should run on any OS. The only limitation -is that the program requires some method of converting Big endian integers into -local host integers so the network functions ntohs and ntohl are used. These -can be replaced by macros if your platform doesn't have them. -Of course the target platform requires a C compiler and command line ability. -<p> - -<!-- =section t1 DESCRIPTION --> -Ttf2pt1 is a font converter from the True Type format (and some other formats -supported by the FreeType library as well) to the Adobe Type1 format. -<p> - -The versions 3.0 and later got rather extensive post-processing algorithm that -brings the converted fonts to the requirements of the Type1 standard, tries to -correct the rounding errors introduced during conversions and some simple -kinds of bugs that are typical for the public domain TTF fonts. It -also generates the hints that enable much better rendering of fonts in -small sizes that are typical for the computer displays. But everything -has its price, and some of the optimizations may not work well for certain -fonts. That's why the options were added to the converter, to control -the performed optimizations. -<p> -<!-- =stop --> - -The converter is simple to run, just: -<p> - -<!-- =section t1 SYNOPSIS --> -<blockquote> - <tt>ttf2pt1 <i>[-options] ttffont.ttf [Fontname]</i></tt> -</blockquote> -or -<blockquote> - <tt>ttf2pt1 <i>[-options] ttffont.ttf -</i></tt> -</blockquote> -<!-- =stop --> -<p> - -<!-- =section t1 OPTIONS --> -The first variant creates the file <tt>Fontname.pfa</tt> (or <tt>Fontname.pfb</tt> if the -option '<b>-b</b>' was used) with the converted font and <tt>Fontname.afm</tt> with the -font metrics, the second one prints the font or another file (if the option -'<b>-G</b>' was used) on the standard output from where it can be immediately -piped through some filter. If no <tt>Fontname</tt> is specified for the first -variant, the name is generated from <tt>ttffont</tt> by replacing the <tt>.ttf</tt> -filename suffix. -<p> - -Most of the time no options are neccessary (with a possible exception -of '<b>-e</b>'). But if there are some troubles with the resulting font, they -may be used to control the conversion. -The <B>options</B> are: -<p> - -<!-- ==over 2 --> -<!-- ==item * --> -<TT><B>-a</TT></B> - Include all the glyphs from the source file into the converted - file. If this option is not specified then only the glyphs that have - been assigned some encoding are included, because the rest of glyphs - would be inaccessible anyway and would only consume the disk space. - But some applications are clever enough to change the encoding on - the fly and thus use the other glyphs, in this case they could - benefit from using this option. But there is a catch: the X11 library - has rather low limit for the font size. Including more glyphs increases - the file size and thus increases the chance of hitting this limit. - See <A HREF="app/X11/README.html"><tt>app/X11/README</tt></A> for the description of a - patch to X11 which fixes this problem. -<p> - -<!-- ==item * --> -<TT><B>-b</TT></B> - Encode the resulting font to produce a ready <tt>.pfb</tt> file. -<p> - -<!-- ==item * --> -<TT><B>-d <i>suboptions</i></TT></B> - Debugging options. The suboptions are: -<p> - -<blockquote> - <TT><B>a</TT></B> - Print out the absolute coordinates of dots in outlines. Such - a font can not be used by any program (that's why this option is - incompatible with '<b>-e</b>') but it has proven to be a valuable debuging - information. -<p> - - <TT><B>r</TT></B> - Do not reverse the direction of outlines. The TTF fonts have - the standard direction of outlines opposite to the Type1 fonts. So - they should be reversed during proper conversion. This option - may be used for debugging or to handle a TTF font with wrong - direction of outlines (possibly, converted in a broken way from - a Type1 font). The first signs of the wrong direction are the - letters like "P" or "B" without the unpainted "holes" inside. -<p> -</blockquote> - -<!-- ==item * --> -<TT><B>-e</TT></B> - Assemble the resulting font to produce a ready <tt>.pfa</tt> file. -<I> - [ </I>S.B.<I>: Personally I don't think that this option is particularly useful. - The same result may be achieved by piping the unassembled data - through t1asm, the Type 1 assembler. And, anyways, it's good to - have the t1utils package handy. But Mark and many users think that - this functionality is good and it took not much time to add this option. ] -</I> -<p> - -<!-- ==item * --> -<TT><B>-F</TT></B> - Force the Unicode encoding: any type of MS encoding specified - in the font is ignored and the font is treated like it has Unicode - encoding. <B>WARNING:</B> <I>this option is intended for buggy fonts - which actually are in Unicode but are marked as something else. The - effect on the other fonts is unpredictable.</I> -<p> - -<!-- ==item * --> -<TT><B>-G <i>suboptions</i></TT></B> - File generation options. The suboptions may be lowercase - or uppercase, the lowercase ones disable the generation of particular - files, the corresponding uppercase suboptions enable the generation of the - same kind of files. If the result of ttf2pt1 is requested to be printed on - the standard output, the last enabling suboption of <b>-G</b> determines - which file will be written to the standard output and the rest of files - will be discarded. For example, <b>-G A</b> will request the AFM file. - The suboptions to disable/enable the generation of the files are: -<p> - -<blockquote> - <TT><B>f/F</TT></B> - The font file. Depending on the other options this file - will have one of the suffixes <tt>.t1a</tt>, <tt>.pfa</tt> or <tt>.pfb</tt>. If the conversion result - is requested on the standard output ('<tt>-</tt>' is used as the output file name) - then the font file will also be written there by default, if not overwritten - by another suboption of <b>-G</b>. - <b>Default: enabled</b> -<p> - - <TT><B>a/A</TT></B> - The Adobe font metrics file (<tt>.afm</tt>). - <b>Default: enabled</b> -<p> - - <TT><B>e/E</TT></B> - The dvips encoding file (<tt>.enc</tt>). - <b>Default: disabled</b> -<p> - -</blockquote> - -<!-- ==item * --> -<TT><B>-l <I>language</I>[+<I>argument</I>]</TT></B> - Extract the fonts for the specified language from a - multi-language Unicode font. If this option is not used the converter - tries to guess the language by the values of the shell variable LANG. - If it is not able to guess the language by LANG it tries all the - languages in the order they are listed. -<p> - - After the plus sign an optional argument for the language extractor - may be specified. The format of the argument is absolutely up to - the particular language converter. The primary purpose of the - argument is to support selection of planes for the multi-plane - Eastern encodings but it can also be used in any other way. The - language extractor may decide to add the plane name in some form - to the name of the resulting font. None of the currently supported - languages make any use of the argument yet. -<p> - - As of now the following languages are supported: -<br> - <TT>latin1</TT> - for all the languages using the Latin-1 encoding -<br> - <TT>latin2</TT> - for the Central European languages -<br> - <TT>latin4</TT> - for the Baltic languages -<br> - <TT>latin5</TT> - for the Turkish language -<br> - <TT>cyrillic</TT> - for the languages with Cyrillic alphabet -<br> - <TT>russian</TT> - historic synonym for cyrillic -<br> - <TT>bulgarian</TT> - historic synonym for cyrillic -<br> - <TT>adobestd</TT> - for the AdobeStandard encoding used by TeX -<br> - <TT>plane+<i>argument</i></TT> - to select one plane from a multi-byte encoding -<p> - - The argument of the "<tt>plane</tt>" language may be in one of three forms: -<p> - <tt>plane+<b>pid=</b><i><pid></i><b>,eid=</b><i><eid></i></tt> -<br> - <tt>plane+<b>pid=</b><i><pid></i><b>,eid=</b><i><eid></i><b>,</b><i><plane_number></i></tt> -<br> - <tt>plane+<i><plane_number></i></tt> -<p> - - Pid (TTF platform id) and eid (TTF encoding id) select a particular - TTF encoding table in the original font. They are specified as decimal - numbers. If this particular encoding table is not present in the font - file then the conversion fails. The native ("ttf") front-end parser supports - only pid=3 (Windows platform), the FreeType-based ("ft") front-end supports - any platform. If pid/eid is not specified then the TTF encoding table is - determined as usual: Unicode encoding if it's first or an 8-bit encoding - if not (and for an 8-bit encoding the plane number is silently ignored). - To prevent the converter from falling back to an 8-bit encoding, specify - the Unicode pid/eid value explicitly. -<p> - - Plane_number is a hexadecimal (if starts with "<b>0x</b>") or decimal number. - It gives the values of upper bytes for which 256 characters will be - selected. If not specified, defaults to 0. It is also used as a font - name suffix (the leading "0x" is not included into the suffix). -<p> - -<!-- =stop --> - <B>NOTE:</B> -<!-- =section t1 BUGS --> - It seems that many Eastern fonts use features of the TTF format that are - not supported by the ttf2pt1's built-in front-end parser. Because of - this for now we recommend using the FreeType-based parser (option - '<b>-p ft</b>') with the "<tt>plane</tt>" language. -<p> -<!-- =stop --> - -<!-- =section t1 OPTIONS --> -<I> - <B>NOTE:</B> - You may notice that the language names are not uniform: some are the - names of particular languages and some are names of encodings. This - is because of the different approaches. The original idea was to - implement a conversion from Unicode to the appropriate Windows - encoding for a given language. And then use the translation tables - to generate the fonts in whatever final encodings are needed. This - would allow to pile together the Unicode fonts and the non-Unicode - Windows fonts for that language and let the program to sort them out - automatically. And then generate fonts in all the possible encodings - for that language. An example of this approach is the Russian language - support. But if there is no multiplicity of encodings used for some - languages and if the non-Unicode fonts are not considered important - by the users, another way would be simpler to implement: just provide - only one table for extraction of the target encoding from Unicode - and don't bother with the translation tables. The </I>latin*<I> "languages" - are examples of this approach. If somebody feels that he needs the - Type1 fonts both in Latin-* and Windows encodings he or she is absolutely - welcome to submit the code to implement it. -</I><p> - - <B>WARNING:</B> - Some of the glyphs included into the AdobeStandard encoding are not - included into the Unicode standard. The most typical examples of such - glyphs are ligatures like 'fi', 'fl' etc. Because of this the font - designers may place them at various places. The converter tries to - do its best, if the glyphs have honest Adobe names and/or are - placed at the same codes as in the Microsoft fonts they will be - picked up. Otherwise a possible solution is to use the option '<b>-L</b>' - with an external map. -<p> - -<!-- ==item * --> -<TT><B>-L <I>file</I>[+[pid=<I><pid></I>,eid=<I><eid></I>,][<I>plane</I>]]</TT></B> - Extract the fonts for the specified - language from a multi-language font using the map from this file. This is - rather like the option '<b>-l</b>' but the encoding map is not - compiled into the program, it's taken from that file, so it's - easy to edit. Examples of such files are provided in - <tt>maps/adobe-standard-encoding.map</tt>, <tt>CP1250.map</tt>. (<b>NOTE:</b> - <I>the 'standard encoding' map does not include all the glyphs of the - AdobeStandard encoding, it's provided only as an example</I>.) The - description of the supported map formats is in the file - <tt>maps/unicode-sample.map</tt>. -<p> - - Likewise to '<b>-l</b>', an argument may be specified after the map file - name. But in this case the argument has fixed meaning: it selects the - original TTF encoding table (the syntax is the same as in '<b>-l plane</b>') - and/or a plane of the map file. The plane name also gets added after dash - to the font name. The plane is a concept used in the Eastern fonts with big - number of glyphs: one TTF font gets divided into multiple Type1 fonts, - each containing one plane of up to 256 glyphs. But with a little - creativity this concept may be used for other purposes of combining - multiple translation maps into one file. To extract multiple planes - from a TTF font <tt>ttf2pt1</tt> must be run multiple times, each time with - a different plane name specified. -<p> - - The default original TTF encoding table used for the option '<b>-L</b>' is - Unicode. The map files may include directives to specify different original - TTF encodings. However if the pid/eid pair is specified with - it overrides any original encoding specified in the map file. -<p> - -<!-- ==item * --> -<TT><B>-m <i>type</i>=<i>value</i></TT></B> - Set maximal or minimal limits of resources. - These limits control the the font generation by limiting the resources - that the font is permitted to require from the PostScript interpreter. - The currently supported types of limits are: -<p> - -<blockquote> - <TT><B>h</TT></B> - the maximal hint stack depth for the substituted hints. - The default value is 128, according to the limitation in X11. This seems to - be the lowest (and thus the safest) widespread value. To display the - hint stack depth required by each glyph in a <tt>.t1a</tt> file use the script - <tt>scripts/cntstems.pl</tt>. -<p> -</blockquote> - -<!-- ==item * --> -<TT><B>-O <i>suboptions</i></TT></B> - Outline processing options. The suboptions - may be lowercase or uppercase, the lowercase ones disable the features, - the corresponding uppercase suboptions enable the same features. - The suboptions to disable/enable features are: -<p> - -<blockquote> - <TT><B>b/B</TT></B> - Guessing of the ForceBold parameter. This parameter helps - the Type1 engine to rasterize the bold fonts properly at small sizes. - But the algorithm used to guess the proper value of this flag makes - that guess based solely on the font name. In rare cases that may cause - errors, in these cases you may want to disable this guessing. - <b>Default: enabled</b> -<p> - - <TT><B>h/H</TT></B> - Autogeneration of hints. The really complex outlines - may confuse the algorithm, so theoretically it may be useful - sometimes to disable them. Although up to now it seems that - even bad hints are better than no hints at all. - <b>Default: enabled</b> -<p> - - <TT><B>u/U</TT></B> - Hint substitution. Hint substitution is a technique - permitting generation of more detailed hints for the rasterizer. It allows - to use different sets of hints for different parts of a glyph and change - these sets as neccessary during rasterization (that's why "substituted"). - So it should improve the quality of the fonts rendered at small sizes. - But there are two catches: First, the X11 library has rather low limit for - the font size. More detailed hints increase the file size and thus increase - the chance of hitting this limit (that does not mean that you shall hit it - but you may if your fonts are particularly big). This is especially - probable for Unicode fonts converted with option '<b>-a</b>', so you may want to - use '<b>-a</b>' together with '<b>-Ou</b>'. See <A HREF="app/X11/README.html"><tt>app/X11/README</tt></A> for the description of - a patch to X11 which fixes this problem. Second, some rasterizers (again, - X11 is the typical example) have a limitation for total number of hints - used when drawing a glyph (also known as the hint stack depth). If that - stack overflows the glyph is ignored. Starting from version 3.22 <tt>ttf2pt1</tt> - uses algorithms to minimizing this depth, with the trade-off of slightly - bigger font files. The glyphs which still exceed the limit set by option - '<b>-mh</b>' have all the substituted hints removed and only base hints left. - The algorithms seem to have been refined far enough to make the fonts with - substituted hints look better than the fonts without them or at least the - same. Still if the original fonts are not well-designed the detailed - hinting may emphasize the defects of the design, such as non-even thickness - of lines. So provided that you are not afraid of the X11 bug the best idea - would be to generate a font with this feature and without it, then compare - the results using the program <tt>other/cmpf</tt> (see the description - in <A HREF="other/README.html"><tt>other/README</tt></A>) and decide which one looks better. - <b>Default: enabled</b> -<p> - - <TT><B>o/O</TT></B> - Space optimization of the outlines' code. This kind of optimization - never hurts, and the only reason to disable this feature is for comparison - of the generated fonts with the fonts generated by the previous versions of - converter. Well, it _almost_ never hurts. As it turned out there exist - some brain-damaged printers which don't understand it. Actually this - feature does not change the outlines at all. The Type 1 font manual - provides a set of redundant operators that make font description shorter, - such as '10 hlineto' instead of '0 10 rlineto' to describe a horizontal - line. This feature enables use of these operators. - <b>Default: enabled</b> -<p> - - <TT><B>s/S</TT></B> - Smoothing of outlines. If the font is broken in some - way (even the ones that are not easily noticeable), such smoothing - may break it further. So disabling this feature is the first thing to be - tried if some font looks odd. But with smoothing off the hint generation - algorithms may not work properly too. - <b>Default: enabled</b> -<p> - - <TT><B>t/T</TT></B> - Auto-scaling to the 1000x1000 Type1 standard matrix. The - TTF fonts are described in terms of an arbitrary matrix up to - 4000x4000. The converted fonts must be scaled to conform to - the Type1 standard. But the scaling introduces additional rounding - errors, so it may be curious sometimes to look at the font in its - original scale. - <b>Default: enabled</b> -<p> - - <TT><B>v/V</TT></B> - Do vectorization on the bitmap fonts. Functionally - "vectorization" is the same thing as "autotracing", a different word is - used purely to differentiate it from the Autotrace library. It tries to - produce nice smooth outlines from bitmaps. This feature is still a work - in progress though the results are already mostly decent. - <b>Default: disabled</b> -<p> - - <TT><B>w/W</TT></B> - Glyphs' width corection. This option is designed to be - used on broken fonts which specify too narrow widths for the - letters. You can tell that a font can benefit from this option - if you see that the characters are smashed together without - any whitespace between them. This option causes the converter - to set the character widths to the actual width of this character - plus the width of a typical vertical stem. But on the other hand - the well-designed fonts may have characters that look better if - their widths are set slightly narrower. Such well-designed fonts - will benefit from disabling this feature. You may want to convert - a font with and without this feature, compare the results and - select the better one. This feature may be used only on proportional - fonts, it has no effect on the fixed-width fonts. - <b>Default: disabled</b> -<p> - - <TT><B>z/Z</TT></B> - Use the Autotrace library on the bitmap fonts. The results - are horrible and <b>the use of this option is not recommended</b>. This option is - present for experimental purposes. It may change or be removed in the - future. The working tracing can be achieved with option <tt><b>-OV</b></tt>. - <b>Default: disabled</b> -<p> -</blockquote> - -<!-- ==item * --> -<TT><B>-p <I>parser_name</I></TT></B> - Use the specified front-end parser to read the font file. - If this option is not used, ttf2pt1 selects the parser automatically based - on the suffix of the font file name, it uses the first parser in its - list that supports this font type. Now two parsers are supported: -<p> - - <TT>ttf</TT> - built-in parser for the ttf files (suffix <tt>.ttf</tt>) -<br> - <TT>bdf</TT> - built-in parser for the BDF files (suffix <tt>.bdf</tt>) -<br> - <TT>ft</TT> - parser based on the FreeType-2 library (suffixes <tt>.ttf</tt>, - <tt>.otf</tt>, <tt>.pfa</tt>, <tt>.pfb</tt>) -<p> - - The parser <tt>ft</tt> is <b>NOT</b> linked in by default. See <tt>Makefile</tt> - for instructions how to enable it. We do no support this parser on - Windows: probably it will work but nobody tried and nobody knows how - to build it. -<p> - - The conversion of the bitmap fonts (such as BDF) is simplistic yet, - producing jagged outlines. When converting such fonts, it might be - a good idea to turn off the hint substitution (using option <b>-Ou</b>) - because the hints produced will be huge but not adding much to the - quality of the fonts. -<p> - -<!-- ==item * --> -<TT><B>-u <I>number</I></TT></B> - Mark the font with this value as its - UniqueID. The UniqueID is used by the printers with the hard disks - to cache the rasterized characters and thus significantly - speed-up the printing. Some of those printers just can't - store the fonts without UniqueID on their disk.The problem - is that the ID is supposed to be unique, as it name says. And - there is no easy way to create a guaranteed unique ID. Adobe specifies - the range 4000000-4999999 for private IDs but still it's difficult - to guarantee the uniqueness within it. So if you don't really need the - UniqueID don't use it, it's optional. Luckily there are a few millions of - possible IDs, so the chances of collision are rather low. - If instead of the number a special value '<tt><b>A</b></tt>' is given - then the converter generates the value of UniqueID automatically, - as a hash of the font name. (<b>NOTE:</b> <i> in the version 3.22 the - algorithm for autogeneration of UniqueID was changed to fit the values - into the Adobe-spacified range. This means that if UniqueIDs were used - then the printer's cache may need to be flushed before replacing the - fonts converted by an old version with fonts converted by a newer version</i>). - A simple way to find if any of the fonts in a given directory have - duplicated UniqueIDs is to use the command: -<p> - - <tt> cat *.pf[ab] | grep UniqueID | sort | uniq -c | grep -v ' 1 '</tt> -<p> - - Or if you use <tt>scripts/convert</tt> it will do that for you automatically - plus it will also give the exact list of files with duplicate UIDs. -<p> - -<!-- ==item * --> -<TT><B>-v <I>size</I></TT></B> - Re-scale the font to get the size of a typical uppercase - letter somewhere around the specified size. Actually, it re-scales - the whole font to get the size of one language-dependent letter to be - at least of the specified size. Now this letter is "A" in all the - supported languages. The size is specified in the points of the - Type 1 coordinate grids, the maximal value is 1000. This is an - experimental option and should be used with caution. It tries to - increase the visible font size for a given point size and thus make - the font more readable. But if overused it may cause the fonts to - look out of scale. As of now the interesting values of size for - this option seem to be located mostly between 600 and 850. This - re-scaling may be quite useful but needs more experience to - understand the balance of its effects. -<p> - -<!-- ==item * --> -<TT><B>-W <i>level</i></TT></B> - Select the verbosity level of the warnings. - Currently the levels from 0 to 4 are supported. Level 0 means no warnings - at all, level 4 means all the possible warnings. The default level is 3. - Other levels may be added in the future, so using the level number 99 is - recommended to get all the possible warnings. Going below level 2 is - not generally recommended because you may miss valuable information about - the problems with the fonts being converted. -<p> - -<!-- ==item * --> -<B>Obsolete option:</B> -<TT><B>-A</TT></B> - Print the font metrics (.afm file) instead of the font on STDOUT. - Use <b>-GA</b> instead. -<p> - -<!-- ==item * --> -<B>Very obsolete option:</B> -<br> - The algorithm that implemented the forced fixed width had major - flaws, so it was disabled. The code is still in the program and - some day it will be refined and returned back. Meanwhile the - option name '<b>-f</b>' was reused for another option. The old version was: -<br> -<TT><B>-f</TT></B> - Don't try to force the fixed width of font. Normally the converter - considers the fonts in which the glyph width deviates by not more - than 5% as buggy fixed width fonts and forces them to have really - fixed width. If this is undesirable, it can be disabled by this option. -<p> -<!-- ==back --> - -The <tt>.pfa</tt> font format supposes that the description of the characters -is binary encoded and encrypted. This converter does not encode or -encrypt the data by default, you have to specify the option '<b>-e</b>' -or use the <tt>t1asm</tt> program to assemble (that means, encode and -encrypt) the font program. The <tt>t1asm</tt> program that is included with -the converter is actually a part of the <tt>t1utils</tt> package, rather old -version of which may be obtained from -<p> - -<blockquote> -<A HREF="http://ttf2pt1.sourceforge.net/t1utils.tar.gz"> - http://ttf2pt1.sourceforge.net/t1utils.tar.gz -</A> -</blockquote> -<p> - -Note that <tt>t1asm</tt> from the old version of that package won't work properly -with the files generated by <tt>ttf2pt1</tt> version 3.20 and later. Please use -<tt>t1asm</tt> packaged with <tt>ttf2pt1</tt> or from the new version <tt>t1utils</tt> -instead. For a newer version of <tt>t1utils</tt> please look at -<p> - -<blockquote> -<A HREF="http://www.lcdf.org/~eddietwo/type/"> - http://www.lcdf.org/~eddietwo/type/ -</A> -</blockquote> -<p> -<!-- =stop --> - -<!-- =section t1 EXAMPLES --> -So, the following command lines: -<p> - -<blockquote> - <tt>ttf2pt1 -e ttffont.ttf t1font</tt> -<br> - <tt>ttf2pt1 ttffont.ttf - | t1asm >t1font.pfa</tt> -</blockquote> -<p> - -represent two ways to get a working font. The benefit of the second form -is that other filters may be applied to the font between the converter -and assembler. -<p> -<!-- =stop --> - -<H4> -Installation and deinstallation of the converter -</H4> -<! ------------------------------------------------- -> - -The converter may be easily installed systemwide with - -<blockquote> - <tt>make install</tt> -</blockquote> - -and uninstalled with - -<blockquote> - <tt>make uninstall</tt> -</blockquote> - -By default the <tt>Makefile</tt> is configured to install in the hierarchy -of directory <tt>/usr/local</tt>. This destination directory as well as -the structure of the hierarchy may be changed by editing the <tt>Makefile</tt>. - -<H4> -Installation of the fonts -</H4> -<! -------------------------- -> - -Running the converter manually becomes somewhat boring if it has to -be applied to a few hundreds of fonts and then you have to generate the -<tt>fonts.scale</tt> and/or <tt>Fontmap</tt> files. The <A HREF="FONTS.html"><tt>FONTS</tt></A> file describes how to use -the supplied scripts to handle such cases easily. It also discusses -the installation of the fonts for a few widespread programs. -<p> - -<H4> -Other utilities -</H4> -<! ---------------- -> - -A few other small interesting programs that allow a cloase look at -the fonts are located in the subdirectory '<tt>other</tt>'. They -are described shortly in <A HREF="other/README.html">others/README</a>. -<p> - -<H4> -Optional packages -</H4> -<! ------------------ -> - -Some auxiliary files are not needed by everyone and are big enough that -moving them to a separate package speeds up the downloads of the main -package significantly. As of now we have one such optional package: -<p> - - <b>ttf2pt1-chinese</b> - contains the Chinese conversion maps -<p> - -The general versioning policy for the optional packages is the following: -These packages may have no direct dependency on the ttf2pt1 version. -But they may be updated in future, as well as some versions of optional -packages may have dependencies on certain versions of ttf2pt1. -To avoid unneccessary extra releases on one hand and keep the updates in -sync with the ttf2pt1 itself on the other hand, a new version of an optional -package will be released only if there are any changes to it and it will be -given the same version number as ttf2pt1 released at the same time. So not -every release of ttf2pt1 would have a corresponding release of all optional -packages. For example, to get the correct version of optional packages for an -imaginary release 8.3.4 of ttf2pt1 you would need to look for optional -packages of the highest version not higher than (but possibly equal to) 8.3.4. -<p> - -<H4> -TO DO: -</H4> -<! ------- -> - -<ul> -<li> Improve hinting. -<li> Improve the auto-tracing of bitmaps. -<li> Implement the family-level hints. -<li> Add generation of CID-fonts. -<li> Handle the composite glyphs with relative base points. -<li> Preserve the relative width of stems during scaling to 1000x1000 matrix. -<li> Add support for bitmap TTF fonts. -<li> Implement better support of Asian encodings. -<li> Implement automatic creation of ligatures. -</ul> - -<H4> -TROUBLESHOOTING AND BUG REPORTS -</H4> -<! -------------------------------- -> -<!-- =section t1 BUGS --> -<!-- ==head2 Troubleshooting and bug reports --> - -Have problems with conversion of some font ? The converter dumps core ? Or your -printer refuses to understand the converted fonts ? Or some characters are -missing ? Or some characters look strange ? -<p> - -Send the bug reports to the ttf2pt1 development mailing list at -<A HREF="mailto:ttf2pt1-devel@lists.sourceforge.net">ttf2pt1-devel@lists.sourceforge.net</A>. -<p> - -Try to collect more information about the problem and include it into -the bug report. (Of course, even better if you would provide a ready -fix, but just a detailed bug report is also good). Provide detailed -information about your problem, this will speed up the response greatly. -Don't just write "this font looks strange after conversion" but describe -what's exactly wrong with it: for example, what characters look wrong -and what exactly is wrong about their look. Providing a link to the -original font file would be also a good idea. Try to do a little -troublehooting and report its result. This not only would help with -the fix but may also give you a temporary work-around for the bug. -<p> - -First, enable full warnings with option '<b>-W99</b>', save them to -a file and read carefully. Sometimes the prolem is with a not implemented -feature which is reported in the warnings. Still, reporting about such -problems may be a good idea: some features were missed to cut corners, -in hope that no real font is using them. So a report about a font using -such a feature may motivate someone to implement it. Of course, you -may be the most motivated person: after all, you are the one wishing -to convert that font. ;-) Seriously, the philosophy "scrath your own itch" -seems to be the strongest moving force behind the Open Source software. -<p> - -The next step is playing with the options. This serves a dual purpose: -on one hand, it helps to localize the bug, on the other hand you may be -able to get a working version of the font for the meantime while the -bug is being fixed. The typical options to try out are: first '<b>-Ou</b>', if -it does not help then '<b>-Os</b>', then '<b>-Oh</b>', then '<b>-Oo</b>'. -They are described in a bit more detail above. Try them one by one -and in combinations. See if with them the resulting fonts look better. -<p> - -On some fonts ttf2pt1 just crashes. Commonly that happens because the -font being converted is highly defective (although sometimes the bug -is in ttf2pt1 itself). In any case it should not crash, so the reports -about such cases will help to handle these defects properly in future. -<p> - -We try to respond to the bug reports in a timely fashion but alas, this -may not always be possible, especially if the problem is complex. -This is a volunteer project and its resources are limited. Because -of this we would appreciate bug reports as detailed as possible, -and we would appreciate the ready fixes and contributions even more. -<p> -<!-- =stop --> -<!-- =section t1 FILES --> -<!-- ==over 2 --> -<!-- ==item * --> -<!-- =text TTF2PT1_LIBXDIR/t1asm --> -<!-- ==item * --> -<!-- =text TTF2PT1_SHAREDIR/* --> -<!-- ==item * --> -<!-- =text TTF2PT1_SHAREDIR/scripts/* --> -<!-- ==item * --> -<!-- =text TTF2PT1_SHAREDIR/other/* --> -<!-- ==item * --> -<!-- =text TTF2PT1_SHAREDIR/README --> -<!-- ==item * --> -<!-- =text TTF2PT1_SHAREDIR/FONTS --> -<!-- ==back --> -<!-- =stop --> - -<H4> -CONTACTS -</H4> -<! --------- -> -<!-- =section t1 SEE ALSO --> -<!-- ==over 4 --> -<!-- ==item * --> -<!-- =text L<ttf2pt1_convert(1)> --> -<!-- ==item * --> -<!-- =text L<ttf2pt1_x2gs(1)> --> -<!-- ==item * --> -<!-- =text L<t1asm(1)> --> - -<!-- ==item * --> -<A HREF="http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-announce"> -ttf2pt1-announce@lists.sourceforge.net -</A><br> - The mailing list with announcements about ttf2pt1. It is a moderated mailing - with extremely low traffic. Everyone is encouraged to subscribe to keep in - touch with the current status of project. To subscribe use the Web interface - at <A HREF="http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-announce">http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-announce</A>. - If you have only e-mail access to the Net then send a subscribe request to - the development mailing list ttf2pt1-devel@lists.sourceforge.net and somebody - will help you with subscription. -<p> - -<!-- ==item * --> -<A HREF="mailto:ttf2pt1-devel@lists.sourceforge.net"> -ttf2pt1-devel@lists.sourceforge.net -</A><br> -<A HREF="mailto:ttf2pt1-users@lists.sourceforge.net"> -ttf2pt1-users@lists.sourceforge.net -</A><br> - The ttf2pt1 mailing lists for development and users issues. They have not - that much traffic either. To subscribe use the Web interface at - <A HREF="http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-devel">http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-devel</A> - and <A HREF="http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-users">http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-users</A>. - If you have only e-mail access to the Net then send a subscribe request to - the development mailing list ttf2pt1-devel@lists.sourceforge.net and somebody - will help you with subscription. -<p> - -<!-- =stop --> -<A HREF="mailto:mheath@netspace.net.au"> -mheath@netspace.net.au -</A><br> - Mark Heath -<p> - -<A HREF="mailto:A.Weeks@mcc.ac.uk"> -A.Weeks@mcc.ac.uk -</A><br> - Andrew Weeks -<p> - -<A HREF="mailto:babkin@users.sourceforge.net"> -babkin@users.sourceforge.net</A> (preferred)<br> -<A HREF="mailto:sab123@hotmail.com"> -sab123@hotmail.com -</A><br> -<A HREF="http://members.bellatlantic.net/~babkin"> -http://members.bellatlantic.net/~babkin -</A><br> - Sergey Babkin -<p> - -<H4> -SEE ALSO -</H4> -<! --------- -> - -<!-- =section t1 SEE ALSO --> -<!-- ==item * --> -<A HREF="http://ttf2pt1.sourceforge.net"> -http://ttf2pt1.sourceforge.net -</A><br> - The main page of the project. -<p> - -<A HREF="http://www.netspace.net.au/~mheath/ttf2pt1/"> -http://www.netspace.net.au/~mheath/ttf2pt1/ -</A><br> - The old main page of the project. -<p> -<!-- ==back --> -<!-- =stop --> - -<A HREF="http://sourceforge.net/projects/gnuwin32"> -http://sourceforge.net/projects/gnuwin32 -</A><br> - Precompiled binaries for Windows. -<p> - -<A HREF="http://www.lcdf.org/~eddietwo/type/"> -http://www.lcdf.org/~eddietwo/type/ -</a><br> - The home page of the Type 1 utilities package. -<p> - -<A HREF="http://www.rightbrain.com/pages/books.html"> -http://www.rightbrain.com/pages/books.html -</a><br> - The first book about PostScript on the Web, "Thinking in PostScript". -<p> - -<A HREF="http://fonts.apple.com/TTRefMan/index.html"> -http://fonts.apple.com/TTRefMan/index.html -</a><br> - The True Type reference manual. -<p> - -<A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf"> -http://partners.adobe.com/asn/developer/PDFS/TN/PLRM.pdf -</a><br> - Adobe PostScript reference manual. -<p> - -<A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/T1_SPEC.PDF"> -http://partners.adobe.com/asn/developer/PDFS/TN/T1_SPEC.PDF -</a><br> - Specification of the Type 1 font format. -<p> - -<A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5015.Type1_Supp.pdf"> -http://partners.adobe.com/asn/developer/PDFS/TN/5015.Type1_Supp.pdf -</a><br> - The Type 1 font format supplement. -<p> - -<A HREF="http://partners.adobe.com/asn/developer/PDFS/TN/5004.AFM_Spec.pdf"> -http://partners.adobe.com/asn/developer/PDFS/TN/5004.AFM_Spec.pdf -</A><BR> - Specification of the Adobe font metrics file format. -<p> - -<A HREF="http://www.cs.wpi.edu/~matt/courses/cs563/talks/surface/bez_surf.html"> -http://www.cs.wpi.edu/~matt/courses/cs563/talks/surface/bez_surf.html -</A><BR> -<A HREF="http://www.cs.wpi.edu/~matt/courses/cs563/talks/curves.html"> -http://www.cs.wpi.edu/~matt/courses/cs563/talks/curves.html -</A><BR> - Information about the Bezier curves. -<p> - -<A HREF="http://www.neuroinformatik.ruhr-uni-bochum.de/ini/PEOPLE/rmz/t1lib/t1lib.html"> -http://www.neuroinformatik.ruhr-uni-bochum.de/ini/PEOPLE/rmz/t1lib/t1lib.html -</A><br> - A stand-alone library supporting the Type1 fonts. Is neccessary - to compile the programs <tt>other/cmpf</tt> and <tt>other/dmpf</tt>. -<p> - -<A HREF="http://www.freetype.org"> -http://www.freetype.org -</A><br> - A library supporting the TTF fonts. Also many useful TTF programs - are included with it. -<p> - -<A HREF="http://heliotrope.homestead.com/files/printsoft.html"> -http://heliotrope.homestead.com/files/printsoft.html -</A><br> - Moses Gold's collection of links to printing software. -<p> - -<A HREF="http://linuxartist.org/fonts/"> -http://linuxartist.org/fonts/ -</A><br> - Collection of font-related links. -<p> - -<HR> -<HR> -<! ----------------------------------------------------------------------- ----------------------------------------------------------------------- -> - -Following is the Readme of <tt>ttf2pfa</tt> (true type to type 3 font converter) It -covers other issues regarding the use of this software. Please note that -although <tt>ttf2pfa</tt> is a public domain software, <tt>ttf2pt1</tt> -is instead covered by an Open Source license. See the <tt>COPYRIGHT</tt> -file for details. -<p> - -Please note also that <tt>ttf2pfa</tt> has not been maintained for a long time. -All of its functionality has been integrated into <tt>ttf2pt1</tt> and all the -development moved to <tt>ttf2pt1</tt>, including Andrew Weeks, the author of -<tt>ttf2pfa</tt>. <tt>Ttf2pfa</tt> is provided for historical reasons only. Please use -<tt>ttf2pt1</tt> instead. - -<HR> -<! ----------------------------------------------------------------------- -> - -<H3> -True Type to Postscript Font converter -</H3> -<! --------------------------------------- -> - -My mind is still reeling from the discovery that I was able to write -this program. What it does is it reads a Microsoft TrueType font and -creates a Postscript font. '<I>_A_</I> postscript font', that is, not necessarily -the same font, you understand, but a fair imitation. -<p> - -Run it like this: -<p> - -<blockquote><tt> - ttf2pfa fontfile.ttf fontname -</tt></blockquote> -<p> - -The first parameter is the truetype filename, the second is a stem for -the output file names. The program will create a <tt>fontname.pfa</tt> containing -the Postscript font and a <tt>fontname.afm</tt> containing the metrics. -<p> - -The motivation behind this is that in Linux if you do not have a -Postscript printer, but only some other printer, you can only print -Postscript by using Ghostscript. But the fonts that come with -Ghostscript are very poor (they are converted from bitmaps and look -rather lumpy). This is rather frustrating as the PC running Linux -probably has MS-Windows as well and will therefore have truetype fonts, -but which are quite useless with Linux, X or Ghostscript. -<p> - -The program has been tested on over a hundred different TrueType fonts -from various sources, and seems to work fairly well. The converted -characters look OK, and the program doesn't seem to crash any more. I'm -not sure about the AFM files though, as I have no means to test them. -<p> - -The fonts generated will not work with X, as the font rasterizer that -comes with X only copes with Type 1 fonts. If I have the time I may -modify ttf2pfa to generate Type 1s. -<p> - -<H4> -Copyright issues -</H4> -<! ----------------- -> - -I am putting this program into the public domain, so don't bother -sending me any money, I'd only have to declare it for income tax. -<p> - -Copyright on fonts, however, is a difficult legal question. Any -copyright statements found in a font will be preserved in the output. -Whether you are entitled to translate them at all I don't know. -<p> - -If you have a license to run a software package, like say MS-Windows, on -your PC, then you probably have a right to use any part of it, including -fonts, on that PC, even if not using that package for its intended -purpose. -<p> - -I am not a lawyer, however, so this is not a legal opinion, and may be -garbage. -<p> - -There shouldn't be a any problem with public domain fonts. -<p> - -<H4> -About the Program -</H4> -<! ------------------ -> - -It was written in C on a IBM PC running Linux. -<p> - -The TrueType format was originally developed by Apple for the MAC, which -has opposite endianness to the PC, so to ensure compatibility 16 and 32 -bit fields are the wrong way round from the PC's point of view. This is -the reason for all the 'ntohs' and 'ntohl' calls. Doing it this way -means the program will also work on big-endian machines like Suns. -<p> - -I doubt whether it will work on a DOS-based PC though. -<p> - -The program produces what technically are Type 3 rather than Type 1 -fonts. They are not compressed or encrypted and are plain text. This is -so I (and you) can see what's going on, and (if you're a Postscript guru -and really want to) can alter the outlines. -<p> - -I only translate the outlines, not the 'instructions' that come with -them. This latter task is probably virtually impossible anyway. TrueType -outlines are B-splines rather than the Bezier curves that Postscript -uses. I believe that my conversion algorithm is reasonably correct, if -nothing else because the characters look right. -<p> - -<H4> -Problems that may occur -</H4> -<! ------------------------ -> - -Most seriously, very complex characters (with lots of outline segments) -can make Ghostscript releases 2.x.x fail with a 'limitcheck' error. It -is possible that this may happen with some older Postscript printers as -well. Such characters will be flagged by the program and there are -basically two things you can do. First is to edit the <tt>.pfa</tt> file to -simplify or remove the offending character. This is not really -recommended. The second is to use Ghostscript release 3, if you can get -it. This has much larger limits and does not seem to have any problems -with complex characters. -<p> - -Then there are buggy fonts (yes, a font can have bugs). I try to deal -with these in as sane a manner as possible, but it's not always -possible. -<p> - -<H4> -Encodings -</H4> -<! ---------- -> - -A postscript font must have a 256 element array, called an encoding, -each element of which is a name, which is also the name of a procedure -contained within the font. The 'BuildChar' command takes a byte and uses -it to index the encoding array to find a character name, and then looks -that up in the font's procedure table find the commands to draw the -glyph. However, not all characters need be in the encoding array. Those -that are not cannot be drawn (at least not using 'show'), however it is -possible to 're-encode' the font to enable these characters. There are -several standard encodings: Adobe's original, ISO-Latin1 and Symbol -being the most commonly encountered. -<p> - -TrueType fonts are organised differently. As well as the glyph -descriptions there are a number of tables. One of these is a mapping -from a character set into the glyph array, and another is a mapping from -the glyph array into a set of Postscript character names. The problems -are: -<p> - 1) Microsoft uses Unicode, a 16-bit system, to encode the font. -<br> - 2) that more than one glyph is given the same Postscript name. -<p> - -I deal with (1) by assuming a Latin1 encoding. The MS-Windows and -Unicode character sets are both supersets of ISO-8859-1. This usually -means that most characters will be properly encoded, but you should be -warned that some software may assume that fonts have an Adobe encoding. -Symbol, or Dingbat, fonts are in fact less of a problem, as they have -private encodings starting at 0xF000. It is easy to just lose the top -byte. -<p> - -Postscript fonts can be re-encoded, either manually, or by software. -Groff, for example, generates postscript that re-encodes fonts with the -Adobe encoding. The problem here is that not all characters in the Adobe -set are in the MS-Windows set. In particular there are no fi and fl -ligatures. This means that conversions of the versions of -Times-New-Roman and Arial that come with MS-Windows cannot be used -blindly as replacements for Adobe Times-Roman and Helvetica. You can get -expanded versions of MS fonts from Microsoft's web site which do contain -these ligatures (and a lot else besides). -<p> - -I deal with (2) by creating new character names. This can be error-prone -because I do not know which of them is the correct glyph to give the -name to. Some (buggy) fonts have large numbers of blank glyphs, all with -the same name. -<p> - -(almost every TrueType font has three glyphs called <tt>.notdef</tt>, one of them -is usually an empty square shape, one has no outline and has zero width, -and one has no outline and a positive width. This example is not really -a problem with well formed fonts since the <tt>.notdef</tt> characters are only -used for unprintable characters, which shouldn't occur in your documents -anyway). -<p> -</BODY> -</HTML> diff --git a/nx-X11/extras/ttf2pt1/bdf.c b/nx-X11/extras/ttf2pt1/bdf.c deleted file mode 100644 index 9f6c72720..000000000 --- a/nx-X11/extras/ttf2pt1/bdf.c +++ /dev/null @@ -1,660 +0,0 @@ -/* - * The font parser for the BDF files - * - * Copyright (c) 2001 by the TTF2PT1 project - * Copyright (c) 2001 by Sergey Babkin - * - * see COPYRIGHT for the full copyright notice - */ - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <ctype.h> -#include "pt1.h" -#include "global.h" - -/* prototypes of call entries */ -static void openfont(char *fname, char *arg); -static void closefont( void); -static int getnglyphs ( void); -static int glnames( GLYPH *glyph_list); -static void readglyphs( GLYPH *glyph_list); -static int glenc( GLYPH *glyph_list, int *encoding, int *unimap); -static void fnmetrics( struct font_metrics *fm); -static void glpath( int glyphno, GLYPH *glyph_list); -static void kerning( GLYPH *glyph_list); - -/* globals */ - -/* front-end descriptor */ -struct frontsw bdf_sw = { - /*name*/ "bdf", - /*descr*/ "BDF bitmapped fonts", - /*suffix*/ { "bdf" }, - /*open*/ openfont, - /*close*/ closefont, - /*nglyphs*/ getnglyphs, - /*glnames*/ glnames, - /*glmetrics*/ readglyphs, - /*glenc*/ glenc, - /*fnmetrics*/ fnmetrics, - /*glpath*/ glpath, - /*kerning*/ kerning, -}; - -/* statics */ - -#define MAXLINE 10240 /* maximal line length in the input file */ - -static int lineno; /* line number */ - -#define GETLEN(s) s, (sizeof(s)-1) -#define LENCMP(str, txt) strncmp(str, txt, sizeof(txt)-1) - -static FILE *bdf_file; -static int nglyphs; -static struct font_metrics fmet; - -/* many BDF fonts are of small pixel size, so we better try - * to scale them by an integer to keep the dimensions in - * whole pixels. However if the size is too big and a non- - * integer scaling is needed, we use the standard ttf2pt1's - * scaling abilities. - */ -static int pixel_size; -static int scale; -static int scale_external; - -static char *slant; -static char xlfdname[201]; -static char *spacing; -static char *charset_reg; -static char *charset_enc; -static char *fnwidth; -static int is_unicode = 0; - -/* tempoary storage for returning data to ttf2pt1 later on request */ -static int maxenc = 0; -static int *fontenc; -static GENTRY **glpaths; - -static int got_glyphs = 0; -static GLYPH *glyphs; -static int curgl; - -static int readfile(FILE *f, int (*strfunc)(int len, char *str)); - -/* - * Read the file and parse each string with strfunc(), - * until strfunc() returns !=0 or the end of file happens. - * Returns -1 on EOF or strfunc() returning <0, else 0 - */ - -static int -readfile( - FILE *f, - int (*strfunc)(int len, char *str) -) -{ - static char str[MAXLINE]; /* input line, maybe should be dynamic ? */ - char *s; - int len, c, res; - - len=0; - while(( c=getc(f) )!=EOF) { - if(c=='\n') { - str[len]=0; - - res = strfunc(len, str); - lineno++; - if(res<0) - return -1; - else if(res!=0) - return 0; - - len=0; - } else if(len<MAXLINE-1) { - if(c!='\r') - str[len++]=c; - } else { - fprintf(stderr, "**** bdf: line %d is too long (>%d)\n", lineno, MAXLINE-1); - exit(1); - } - } - return -1; /* EOF */ -} - -/* - * Parse the header of the font file. - * Stop after the line CHARS is encountered. Ignore the unknown lines. - */ - -struct line { - char *name; /* property name with trailing space */ - int namelen; /* length of the name string */ - enum { - ALLOW_REPEAT = 0x01, /* this property may be repeated in multiple lines */ - IS_SEEN = 0x02, /* this property has been seen already */ - MUST_SEE = 0x04, /* this property must be seen */ - IS_LAST = 0x08 /* this is the last property to be read */ - } flags; - char *fmt; /* format string for the arguments, NULL means a string arg */ - int nvals; /* number of values to be read by sscanf */ - void *vp[4]; /* pointers to values to be read */ -}; - -static struct line header[] = { - { GETLEN("FONT "), 0, " %200s", 1, {&xlfdname} }, - { GETLEN("SIZE "), MUST_SEE, " %d", 1, {&pixel_size} }, - { GETLEN("FONTBOUNDINGBOX "), MUST_SEE, " %hd %hd %hd %hd", 4, - {&fmet.bbox[2], &fmet.bbox[3], &fmet.bbox[0], &fmet.bbox[1]} }, - { GETLEN("FAMILY_NAME "), MUST_SEE, NULL, 1, {&fmet.name_family} }, - { GETLEN("WEIGHT_NAME "), MUST_SEE, NULL, 1, {&fmet.name_style} }, - { GETLEN("COPYRIGHT "), 0, NULL, 1, {&fmet.name_copyright} }, - { GETLEN("SLANT "), MUST_SEE, NULL, 1, {&slant} }, - { GETLEN("SPACING "), 0, NULL, 1, {&spacing} }, - { GETLEN("SETWIDTH_NAME "), 0, NULL, 1, {&fnwidth} }, - { GETLEN("CHARSET_REGISTRY "), 0, NULL, 1, {&charset_reg} }, - { GETLEN("CHARSET_ENCODING "), 0, NULL, 1, {&charset_enc} }, - { GETLEN("FONT_ASCENT "), 0, " %hd", 1, {&fmet.ascender} }, - { GETLEN("FONT_DESCENT "), 0, " %hd", 1, {&fmet.descender} }, - - /* these 2 must go in this order for post-processing */ - { GETLEN("UNDERLINE_THICKNESS "), 0, " %hd", 1, {&fmet.underline_thickness} }, - { GETLEN("UNDERLINE_POSITION "), 0, " %hd", 1, {&fmet.underline_position} }, - - { GETLEN("CHARS "), MUST_SEE|IS_LAST, " %d", 1, {&nglyphs} }, - { NULL, 0, 0 } /* end mark: name==NULL */ -}; - -static int -handle_header( - int len, - char *str -) -{ - struct line *cl; - char *s, *p; - int c; - -#if 0 - fprintf(stderr, "line: %s\n", str); -#endif - for(cl = header; cl->name != 0; cl++) { - if(strncmp(str, cl->name, cl->namelen)) - continue; -#if 0 - fprintf(stderr, "match: %s\n", cl->name); -#endif - if(cl->flags & IS_SEEN) { - if(cl->flags & ALLOW_REPEAT) - continue; - - fprintf(stderr, "**** input line %d redefines the property %s\n", lineno, cl->name); - exit(1); - } - cl->flags |= IS_SEEN; - if(cl->fmt == 0) { - s = malloc(len - cl->namelen + 1); - if(s == 0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - *((char **)(cl->vp[0])) = s; - - /* skip until a quote */ - for(p = str+cl->namelen; (c = *p)!=0; p++) { - if(c == '"') { - p++; - break; - } - } - for(; (c = *p)!=0; p++) { - if(c == '"') { - c = *++p; - if(c == '"') - *s++ = c; - else - break; - } else - *s++ = c; - } - *s = 0; /* end of line */ - } else { - c = sscanf(str+cl->namelen, cl->fmt, cl->vp[0], cl->vp[1], cl->vp[2], cl->vp[3]); - if(c != cl->nvals) { - fprintf(stderr, "**** property %s at input line %d must have %d arguments\n", - cl->name, lineno, cl->nvals); - exit(1); - } - } - if(cl->flags & IS_LAST) - return 1; - else - return 0; - } - return 0; -} - -/* - * Parse the description of the glyphs - */ - -static int -handle_glyphs( - int len, - char *str -) -{ - static int inbmap=0; - static char *bmap; - static int xsz, ysz, xoff, yoff; - static int curln; - int i, c; - char *p, *plim, *psz; - - if(!LENCMP(str, "ENDFONT")) { - if(curgl < nglyphs) { - fprintf(stderr, "**** unexpected end of font file after %d glyphs\n", curgl); - exit(1); - } else - return 1; - } - if(curgl >= nglyphs) { - fprintf(stderr, "**** file contains more glyphs than advertised (%d)\n", nglyphs); - exit(1); - } - if(!LENCMP(str, "STARTCHAR")) { - /* sizeof will count \0 instead of ' ' */ - for(i=sizeof("STARTCHAR"); str[i] == ' '; i++) - {} - - glyphs[curgl].name = strdup(str + i); - if(glyphs[curgl].name == 0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - } else if(!LENCMP(str, "ENCODING")) { - if(sscanf(str, "ENCODING %d", &fontenc[curgl])!=1) { - fprintf(stderr,"**** weird ENCODING statement at line %d\n", lineno); - exit(1); - } - if(fontenc[curgl] == -1) /* compatibility format */ - sscanf(str, "ENCODING -1 %d", &fontenc[curgl]); - if(fontenc[curgl] > maxenc) - maxenc = fontenc[curgl]; - } else if(!LENCMP(str, "DWIDTH")) { - if(sscanf(str, "DWIDTH %d %d", &xsz, &ysz)!=2) { - fprintf(stderr,"**** weird DWIDTH statement at line %d\n", lineno); - exit(1); - } - glyphs[curgl].width = xsz*scale; - } else if(!LENCMP(str, "BBX")) { - if(sscanf(str, "BBX %d %d %d %d", &xsz, &ysz, &xoff, &yoff)!=4) { - fprintf(stderr,"**** weird BBX statement at line %d\n", lineno); - exit(1); - } - bmap=malloc(xsz*ysz); - if(bmap==0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - glyphs[curgl].lsb = -xoff*scale; - glyphs[curgl].xMin = -xoff*scale; - glyphs[curgl].xMax = (xsz-xoff)*scale; - glyphs[curgl].yMin = -yoff*scale; - glyphs[curgl].yMax = (ysz-xoff)*scale; - } else if(!LENCMP(str, "BITMAP")) { - inbmap=1; - curln=ysz-1; /* the lowest line has index 0 */ - } else if(!LENCMP(str, "ENDCHAR")) { - inbmap=0; - if(bmap) { - glyphs[curgl].lastentry = 0; - glyphs[curgl].path = 0; - glyphs[curgl].entries = 0; - bmp_outline(&glyphs[curgl], scale, bmap, xsz, ysz, xoff, yoff); - free(bmap); - /* remember in a static table or it will be erased */ - glpaths[curgl] = glyphs[curgl].entries; - glyphs[curgl].entries = 0; - - if(glpaths[curgl]) - glyphs[curgl].ttf_pathlen = 1; - else - glyphs[curgl].ttf_pathlen = 0; - } - curgl++; - } else if(inbmap) { - if(curln<0) { - fprintf(stderr,"**** bitmap is longer than %d lines at line %d\n", ysz, lineno); - exit(1); - } - - i=0; - p=&bmap[curln*xsz]; psz=p+xsz; - while(i<len) { - c=str[i++]; - if(!isxdigit(c)) { - fprintf(stderr,"**** non-hex digit in bitmap at line %d\n", lineno); - exit(1); - } - if(c<='9') - c-='0'; - else - c= tolower(c)-'a'+10; - - for(plim=p+4; p<psz && p<plim; c<<=1) - *p++ = (( c & 0x08 )!=0); - } - if(p<psz) { - fprintf(stderr,"**** bitmap line is too short at line %d\n", lineno); - exit(1); - } - curln--; - } - return 0; -} - -/* - * Read all the possible information about the glyphs - */ - -static void -readglyphs( - GLYPH *glyph_list -) -{ - int i; - GLYPH *g; - - if(got_glyphs) - return; - - /* pass them to handle_glyphs() through statics */ - glyphs = glyph_list; - curgl = 2; /* skip the empty glyph and .notdef */ - - /* initialize the empty glyph and .notdef */ - - for(i=0; i<2; i++) { - g = &glyphs[i]; - g->lsb = 0; - g->width = fmet.bbox[2]; - g->xMin = 0; - g->yMin = 0; - } - g = &glyphs[0]; - g->name = ".notdef"; - g->xMax = fmet.bbox[2]*4/5; - g->yMax = fmet.bbox[3]*4/5; - g->entries = g->path = g->lastentry = 0; - /* make it look as a black square */ - fg_rmoveto(g, 0.0, 0.0); - fg_rlineto(g, 0.0, (double)g->yMax); - fg_rlineto(g, (double)g->xMax, (double)g->yMax); - fg_rlineto(g, (double)g->xMax, 0.0); - fg_rlineto(g, 0.0, 0.0); - g_closepath(g); - glpaths[0] = g->entries; - g->entries = 0; - g->ttf_pathlen = 4; - - g = &glyphs[1]; - g->name = ".null"; - g->xMax = g->yMax = 0; - g->ttf_pathlen = 0; - - if(readfile(bdf_file, handle_glyphs) < 0) { - fprintf(stderr, "**** file does not contain the ENDFONT line\n"); - exit(1); - } - got_glyphs = 1; -} - -/* - * Open font and prepare to return information to the main driver. - * May print error and warning messages. - * Exit on error. - */ - -static void -openfont( - char *fname, - char *arg /* unused now */ -) -{ - struct line *cl; - int i, l; - - if ((bdf_file = fopen(fname, "r")) == NULL) { - fprintf(stderr, "**** Cannot open file '%s'\n", fname); - exit(1); - } else { - WARNING_2 fprintf(stderr, "Processing file %s\n", fname); - } - - lineno = 1; - - for(cl = header; cl->name != 0; cl++) - cl->flags &= ~IS_SEEN; - if(readfile(bdf_file, handle_header) < 0) { - fprintf(stderr, "**** file does not contain the CHARS definition\n"); - exit(1); - } - for(cl = header; cl->name != 0; cl++) { - if( (cl->flags & MUST_SEE) && !(cl->flags & IS_SEEN) ) { - fprintf(stderr, "**** mandatory property %sis not found in the input line\n", - cl->name); /* cl->name has a space at the end */ - exit(1); - } - - /* set a few defaults */ - if( !(cl->flags & IS_SEEN) ) { - if(cl->vp[0] == &fmet.underline_thickness) { - fmet.underline_thickness = 1; - } else if(cl->vp[0] == &fmet.underline_position) { - fmet.underline_position = fmet.bbox[1] + fmet.underline_thickness - - (pixel_size - fmet.bbox[3]); - } else if(cl->vp[0] == &fmet.ascender) { - fmet.ascender = fmet.bbox[2] + fmet.bbox[0]; - } else if(cl->vp[0] == &fmet.descender) { - fmet.descender = fmet.bbox[0]; - } - } - } - - nglyphs += 2; /* add empty glyph and .notdef */ - - /* postprocessing to compensate for the differences in the metric formats */ - fmet.bbox[2] += fmet.bbox[0]; - fmet.bbox[3] += fmet.bbox[1]; - - scale = 1000/pixel_size; /* XXX ? */ - if(scale*pixel_size < 950) { - scale = 1; - scale_external = 1; - fmet.units_per_em = pixel_size; - } else { - scale_external = 0; - fmet.units_per_em = scale*pixel_size; - - fmet.underline_position *= scale; - fmet.underline_thickness *= scale; - fmet.ascender *= scale; - fmet.descender *= scale; - for(i=0; i<4; i++) - fmet.bbox[i] *= scale; - } - - fmet.italic_angle = 0.0; - if(spacing == 0 /* possibly an old font */ - || toupper(spacing[0]) != 'P') /* or anything non-proportional */ - fmet.is_fixed_pitch = 1; - else - fmet.is_fixed_pitch = 0; - - if(fmet.name_copyright==NULL) - fmet.name_copyright = ""; - - /* create the full name */ - l = strlen(fmet.name_family) - + (fmet.name_style? strlen(fmet.name_style) : 0) - + (fnwidth? strlen(fnwidth) : 0) - + strlen("Oblique") + 1; - - if(( fmet.name_full = malloc(l) )==NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - strcpy(fmet.name_full, fmet.name_family); - if(fnwidth && strcmp(fnwidth, "Normal")) { - strcat(fmet.name_full, fnwidth); - } - if(fmet.name_style && strcmp(fmet.name_style, "Medium")) { - strcat(fmet.name_full, fmet.name_style); - } - switch(toupper(slant[0])) { - case 'O': - strcat(fmet.name_full, "Oblique"); - break; - case 'I': - strcat(fmet.name_full, "Italic"); - break; - } - - fmet.name_ps = fmet.name_full; - fmet.name_version = "1.0"; - - if(charset_reg && charset_enc - && !strcmp(charset_reg, "iso10646") && !strcmp(charset_enc, "1")) - is_unicode = 1; - - if(( fontenc = calloc(nglyphs, sizeof *fontenc) )==NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - for(i=0; i<nglyphs; i++) - fontenc[i] = -1; - if(( glpaths = calloc(nglyphs, sizeof *glpaths) )==NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } -} - -/* - * Close font. - * Exit on error. - */ - -static void -closefont( - void -) -{ - if(fclose(bdf_file) < 0) { - WARNING_1 fprintf(stderr, "Errors when closing the font file, ignored\n"); - } -} - -/* - * Get the number of glyphs in font. - */ - -static int -getnglyphs ( - void -) -{ - return nglyphs; -} - -/* - * Get the names of the glyphs. - * Returns 0 if the names were assigned, non-zero if the font - * provides no glyph names. - */ - -static int -glnames( - GLYPH *glyph_list -) -{ - readglyphs(glyph_list); - return 0; -} - -/* - * Get the original encoding of the font. - * Returns 1 for if the original encoding is Unicode, 2 if the - * original encoding is other 16-bit, 0 if 8-bit. - */ - -static int -glenc( - GLYPH *glyph_list, - int *encoding, - int *unimap -) -{ - int i, douni, e; - - if(is_unicode || forcemap) - douni = 1; - else - douni = 0; - - for(i=0; i<nglyphs; i++) { - e = fontenc[i]; - if(douni) - e = unicode_rev_lookup(e); - if(e>=0 && e<ENCTABSZ && encoding[e] == -1) - encoding[e] = i; - } - - if(is_unicode) - return 1; - else if(maxenc > 255) - return 2; - else - return 0; -} - -/* - * Get the font metrics - */ -static void -fnmetrics( - struct font_metrics *fm -) -{ - *fm = fmet; -} - -/* - * Get the path of contrours for a glyph. - */ - -static void -glpath( - int glyphno, - GLYPH *glyf_list -) -{ - readglyphs(glyf_list); - glyf_list[glyphno].entries = glpaths[glyphno]; - glpaths[glyphno] = 0; -} - -/* - * Get the kerning data. - */ - -static void -kerning( - GLYPH *glyph_list -) -{ - return; /* no kerning in BDF */ -} diff --git a/nx-X11/extras/ttf2pt1/bitmap.c b/nx-X11/extras/ttf2pt1/bitmap.c deleted file mode 100644 index d2334e433..000000000 --- a/nx-X11/extras/ttf2pt1/bitmap.c +++ /dev/null @@ -1,2633 +0,0 @@ -/* - * Handling of the bitmapped glyphs - * - * Copyright (c) 2001 by the TTF2PT1 project - * Copyright (c) 2001 by Sergey Babkin - * - * see COPYRIGHT for the full copyright notice - */ - -#include <stdio.h> -#include <stdlib.h> -#include <math.h> -#include "pt1.h" -#include "global.h" - -/* possible values of limits */ -#define L_NONE 0 /* nothing here */ -#define L_ON 1 /* black is on up/right */ -#define L_OFF 2 /* black is on down/left */ - -static int warnedhints = 0; - - -#ifdef USE_AUTOTRACE -#include <autotrace/autotrace.h> - -/* - * Produce an autotraced outline from a bitmap. - * scale - factor to scale the sizes - * bmap - array of dots by lines, xsz * ysz - * xoff, yoff - offset of the bitmap's lower left corner - * from the logical position (0,0) - */ - -static void -autotraced_bmp_outline( - GLYPH *g, - int scale, - char *bmap, - int xsz, - int ysz, - int xoff, - int yoff -) -{ - at_bitmap_type atb; - at_splines_type *atsp; - at_fitting_opts_type *atoptsp; - at_spline_list_type *slp; - at_spline_type *sp; - int i, j, k; - double lastx, lasty; - double fscale; - char *xbmap; - - fscale = (double)scale; - - /* provide a white margin around the bitmap */ - xbmap = malloc((ysz+2)*(xsz+2)); - if(xbmap == 0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - memset(xbmap, 0, xsz+2); /* top margin */ - for(i=0, j=xsz+2; i<ysz; i++, j+=xsz+2) { - xbmap[j] = 0; /* left margin */ - memcpy(&xbmap[j+1], &bmap[xsz*(ysz-1-i)], xsz); /* a line of bitmap */ - xbmap[j+xsz+1] = 0; /* right margin */ - } - memset(xbmap+j, 0, xsz+2); /* bottom margin */ - xoff--; yoff-=2; /* compensate for the margins */ - - atoptsp = at_fitting_opts_new(); - - atb.width = xsz+2; - atb.height = ysz+2; - atb.np = 1; - atb.bitmap = xbmap; - - atsp = at_splines_new(&atb, atoptsp); - - lastx = lasty = -1.; - for(i=0; i<atsp->length; i++) { - slp = &atsp->data[i]; -#if 0 - fprintf(stderr, "%s: contour %d: %d entries clockwise=%d color=%02X%02X%02X\n", - g->name, i, slp->length, slp->clockwise, slp->color.r, slp->color.g, slp->color.b); -#endif - if(slp->length == 0) - continue; -#if 0 - if(slp->color.r + slp->color.g + slp->color.b == 0) - continue; -#endif - fg_rmoveto(g, fscale*(slp->data[0].v[0].x+xoff), fscale*(slp->data[0].v[0].y+yoff)); - for(j=0; j<slp->length; j++) { -#if 0 - fprintf(stderr, " "); - for(k=0; k<4; k++) - fprintf(stderr, "(%g %g) ", - fscale*(slp->data[j].v[k].x+xoff), - fscale*(ysz-slp->data[j].v[k].y+yoff) - ); - fprintf(stderr, "\n"); -#endif - fg_rrcurveto(g, - fscale*(slp->data[j].v[1].x+xoff), fscale*(slp->data[j].v[1].y+yoff), - fscale*(slp->data[j].v[2].x+xoff), fscale*(slp->data[j].v[2].y+yoff), - fscale*(slp->data[j].v[3].x+xoff), fscale*(slp->data[j].v[3].y+yoff) ); - } - g_closepath(g); - } - - at_splines_free(atsp); - at_fitting_opts_free(atoptsp); - free(xbmap); -} - -#endif /*USE_AUTOTRACE*/ - -/* an extension of gentry for description of the fragments */ -typedef struct gex_frag GEX_FRAG; -struct gex_frag { - /* indexes to len, the exact values and order are important */ -#define GEXFI_NONE -1 -#define GEXFI_CONVEX 0 -#define GEXFI_CONCAVE 1 -#define GEXFI_LINE 2 /* a line with steps varying by +-1 pixel */ -#define GEXFI_EXACTLINE 3 /* a line with exactly the same steps */ -#define GEXFI_SERIF 4 /* small serifs at the ends of stemsi - must be last */ -#define GEXFI_COUNT 5 /* maximal index + 1 */ - unsigned short len[GEXFI_COUNT]; /* length of various fragment types starting here */ - unsigned short lenback[GEXFI_COUNT]; /* length back to the start of curve */ - - signed char ixstart; /* index of the frag type that starts here */ - signed char ixcont; /* index of the frag type that continues here */ - - short flags; -#define GEXFF_HLINE 0x0001 /* the exact line is longer in "horizontal" dimension */ -#define GEXFF_EXTR 0x0002 /* this gentry is an extremum in some direction */ -#define GEXFF_CIRC 0x0004 /* the joint at this gentry is for a circular curve */ -#define GEXFF_DRAWCURVE 0x0008 /* vect[] describes a curve to draw */ -#define GEXFF_DRAWLINE 0x0010 /* vect[] describes a line to draw */ -#define GEXFF_SPLIT 0x0020 /* is a result of splitting a line */ -#define GEXFF_SYMNEXT 0x0040 /* this subfrag is symmetric with next one */ -#define GEXFF_DONE 0x0080 /* this subfrag has been vectorized */ -#define GEXFF_LONG 0x0100 /* this gentry is longer than 1 pixel */ - - unsigned short aidx; /* index of gentry in the array representing the contour */ - - unsigned short vectlen; /* number of gentries represented by vect[] */ - - /* coordinates for vectored replacement of this fragment */ - /* (already scaled because it's needed for curve approximation) */ - double vect[4 /*ref.points*/][2 /*X,Y*/]; - - double bbox[2 /*X,Y*/]; /* absolute sizes of bounding box of a subfragment */ - - /* used when splitting the curved frags into subfrags */ - GENTRY *prevsub; /* to gentries describing neighboring subfrags */ - GENTRY *nextsub; - GENTRY *ordersub; /* single-linked list describing the order of calculation */ - - int sublen; /* length of this subfrag */ - /* the symmetry across the subfrags */ - int symaxis; /* the symmetry axis, with next subfrag */ - int symxlen; /* min length of adjacent symmetric frags */ - /* the symmetry within this subfrag (the axis is always diagonal) */ - GENTRY *symge; /* symge->i{x,y}3 is the symmetry point of symge==0 if none */ - -}; -#define X_FRAG(ge) ((GEX_FRAG *)((ge)->ext)) - -/* various interesting tables related to GEX_FRAG */ -static char *gxf_name[GEXFI_COUNT] = {"Convex", "Concave", "Line", "ExLine", "Serif"}; -static int gxf_cvk[2] = {-1, 1}; /* coefficients of concaveness */ - -/* - * Dump the contents of X_EXT()->len and ->lenback for a contour - */ -static void -gex_dump_contour( - GENTRY *ge, - int clen -) -{ - int i, j; - - for(j = 0; j < GEXFI_COUNT; j++) { - fprintf(stderr, "%-8s", gxf_name[j]); - for(i = 0; i < clen; i++, ge = ge->frwd) - fprintf(stderr, " %2d", X_FRAG(ge)->len[j]); - fprintf(stderr, " %p\n (back) ", ge); - for(i = 0; i < clen; i++, ge = ge->frwd) - fprintf(stderr, " %2d", X_FRAG(ge)->lenback[j]); - fprintf(stderr, "\n"); - } -} - -/* - * Calculate values of X_EXT()->lenback[] for all entries in - * a contour. The contour is identified by: - * ge - any gentry of the contour - * clen - contour length - */ - -static void -gex_calc_lenback( - GENTRY *ge, - int clen -) -{ - int i, j; - int end; - GEX_FRAG *f; - int len[GEXFI_COUNT]; /* length of the most recent fragment */ - int count[GEXFI_COUNT]; /* steps since beginning of the fragment */ - - for(j = 0; j < GEXFI_COUNT; j++) - len[j] = count[j] = 0; - - end = clen; - for(i = 0; i < end; i++, ge = ge->frwd) { - f = X_FRAG(ge); - for(j = 0; j < GEXFI_COUNT; j++) { - if(len[j] != count[j]) { - f->lenback[j] = count[j]++; - } else - f->lenback[j] = 0; - if(f->len[j] != 0) { - len[j] = f->len[j]; - count[j] = 1; /* start with the next gentry */ - /* if the fragment will wrap over the start, process to its end */ - if(i < clen && i + len[j] > end) - end = i + len[j]; - } - } - } - gex_dump_contour(ge, clen); -} - -/* Limit a curve to not exceed the given coordinates - * at its given side - */ - -static void -limcurve( - double curve[4][2 /*X,Y*/], - double lim[2 /*X,Y*/], - int where /* 0 - start, 3 - end */ -) -{ - int other = 3-where; /* the other end */ - int sgn[2 /*X,Y*/]; /* sign for comparison */ - double t, from, to, nt, t2, nt2, tt[4]; - double val[2 /*X,Y*/]; - int i; - - for(i=0; i<2; i++) - sgn[i] = fsign(curve[other][i] - curve[where][i]); - -#if 0 - fprintf(stderr, " limit (%g,%g)-(%g,%g) at %d by (%g,%g), sgn(%d,%d)\n", - curve[0][0], curve[0][1], curve[3][0], curve[3][1], - where, lim[0], lim[1], sgn[0], sgn[1]); -#endif - /* a common special case */ - if( sgn[0]*(curve[where][0] - lim[0]) >= 0. - && sgn[1]*(curve[where][1] - lim[1]) >= 0. ) - return; /* nothing to do */ - - if(other==0) { - from = 0.; - to = 1.; - } else { - from = 1.; - to = 0.; - } -#if 0 - fprintf(stderr, "t="); -#endif - while( fabs(from-to) > 0.00001 ) { - t = 0.5 * (from+to); - t2 = t*t; - nt = 1.-t; - nt2 = nt*nt; - tt[0] = nt2*nt; - tt[1] = 3*nt2*t; - tt[2] = 3*nt*t2; - tt[3] = t*t2; - for(i=0; i<2; i++) - val[i] = curve[0][i]*tt[0] + curve[1][i]*tt[1] - + curve[2][i]*tt[2] + curve[3][i]*tt[3]; -#if 0 - fprintf(stderr, "%g(%g,%g) ", t, val[0], val[1]); -#endif - if(fabs(val[0] - lim[0]) < 0.1 - || fabs(val[1] - lim[1]) < 0.1) - break; - - if(sgn[0] * (val[0] - lim[0]) < 0. - || sgn[1] * (val[1] - lim[1]) < 0.) - to = t; - else - from = t; - } - /* now t is the point of splitting */ -#define SPLIT(pt1, pt2) ( (pt1) + t*((pt2)-(pt1)) ) /* order is important! */ - for(i=0; i<2; i++) { - double v11, v12, v13, v21, v22, v31; /* intermediate points */ - - v11 = SPLIT(curve[0][i], curve[1][i]); - v12 = SPLIT(curve[1][i], curve[2][i]); - v13 = SPLIT(curve[2][i], curve[3][i]); - v21 = SPLIT(v11, v12); - v22 = SPLIT(v12, v13); - v31 = SPLIT(v21, v22); - if(other==0) { - curve[1][i] = v11; - curve[2][i] = v21; - curve[3][i] = fabs(v31 - lim[i]) < 0.1 ? lim[i] : v31; - } else { - curve[0][i] = fabs(v31 - lim[i]) < 0.1 ? lim[i] : v31; - curve[1][i] = v22; - curve[2][i] = v13; - } - } -#undef SPLIT -#if 0 - fprintf(stderr, "\n"); -#endif -} - -/* - * Vectorize a subfragment of a curve fragment. All the data has been already - * collected by this time - */ - -static void -dosubfrag( - GLYPH *g, - int fti, /* fragment type index */ - GENTRY *firstge, /* first gentry of fragment */ - GENTRY *ge, /* first gentry of subfragment */ - double fscale -) -{ - GENTRY *gel, *gei; /* last gentry of this subfrag */ - GEX_FRAG *f, *ff, *lf, *pf, *xf; - /* maximal amount of space that can be used at the beginning and the end */ - double fixfront[2], fixend[2]; /* fixed points - used to show direction */ - double mvfront[2], mvend[2]; /* movable points */ - double limfront[2], limend[2]; /* limit of movement for movabel points */ - double sympt; - int outfront, outend; /* the beginning/end is going outwards */ - int symfront, symend; /* a ready symmetric fragment is present at front/end */ - int drnd[2 /*X,Y*/]; /* size of the round part */ - int i, j, a1, a2, ndots; - double avg2, max2; /* squared distances */ - struct dot_dist *dots, *usedots; - - ff = X_FRAG(firstge); - f = X_FRAG(ge); - gel = f->nextsub; - lf = X_FRAG(gel); - if(f->prevsub != 0) - pf = X_FRAG(f->prevsub); - else - pf = 0; - - for(i=0; i<2; i++) - drnd[i] = gel->bkwd->ipoints[i][2] - ge->ipoints[i][2]; - - if(f->prevsub==0 && f->ixcont == GEXFI_NONE) { - /* nothing to join with : may use the whole length */ - for(i = 0; i < 2; i++) - limfront[i] = ge->bkwd->ipoints[i][2]; - } else { - /* limit to a half */ - for(i = 0; i < 2; i++) - limfront[i] = 0.5 * (ge->ipoints[i][2] + ge->bkwd->ipoints[i][2]); - } - if( (ge->ix3 == ge->bkwd->ix3) /* vert */ - ^ (isign(ge->bkwd->ix3 - ge->frwd->ix3)==isign(ge->bkwd->iy3 - ge->frwd->iy3)) - ^ (fti == GEXFI_CONCAVE) /* counter-clockwise */ ) { - /* the beginning is not a flat 90-degree end */ - outfront = 1; - for(i = 0; i < 2; i++) - fixfront[i] = ge->frwd->ipoints[i][2]; - } else { - outfront = 0; - for(i = 0; i < 2; i++) - fixfront[i] = ge->ipoints[i][2]; - } - - if(lf->nextsub==0 && lf->ixstart == GEXFI_NONE) { - /* nothing to join with : may use the whole length */ - for(i = 0; i < 2; i++) - limend[i] = gel->ipoints[i][2]; - } else { - /* limit to a half */ - for(i = 0; i < 2; i++) - limend[i] = 0.5 * (gel->ipoints[i][2] + gel->bkwd->ipoints[i][2]); - } - gei = gel->bkwd->bkwd; - if( (gel->ix3 == gel->bkwd->ix3) /* vert */ - ^ (isign(gel->ix3 - gei->ix3)==isign(gel->iy3 - gei->iy3)) - ^ (fti == GEXFI_CONVEX) /* clockwise */ ) { - /* the end is not a flat 90-degree end */ - outend = 1; - for(i = 0; i < 2; i++) - fixend[i] = gel->bkwd->bkwd->ipoints[i][2]; - } else { - outend = 0; - for(i = 0; i < 2; i++) - fixend[i] = gel->bkwd->ipoints[i][2]; - } - - for(i = 0; i < 2; i++) { - fixfront[i] *= fscale; - limfront[i] *= fscale; - fixend[i] *= fscale; - limend[i] *= fscale; - } - - fprintf(stderr, " %d out(%d[%d %d %d],%d[%d %d %d]) drnd(%d, %d)\n", - fti, - outfront, - (ge->ix3 == ge->bkwd->ix3), - (isign(ge->bkwd->ix3 - ge->frwd->ix3)==isign(ge->bkwd->iy3 - ge->frwd->iy3)), - (fti == GEXFI_CONCAVE), - outend, - (gel->ix3 == gel->bkwd->ix3), - (isign(gel->ix3 - gei->ix3)==isign(gel->iy3 - gei->iy3)), - (fti == GEXFI_CONVEX), - drnd[0], drnd[1]); - - /* prepare to calculate the distances */ - ndots = f->sublen - 1; - dots = malloc(sizeof(*dots) * ndots); - if(dots == 0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - for(i = 0, gei = ge; i < ndots; i++, gei = gei->frwd) { - for(a1 = 0; a1 < 2; a1++) - dots[i].p[a1] = fscale * gei->ipoints[a1][2]; - } - - /* see if we can mirror a ready symmetric curve */ - - /* check symmetry with the fragment before this */ - symfront = (pf != 0 && (pf->flags & GEXFF_SYMNEXT) && (pf->flags & GEXFF_DONE) - && ( outend && f->sublen <= pf->sublen - || ( pf->sublen == f->sublen - && (lf->sublen == 0 - || ( abs(limfront[0]-limend[0]) >= abs(pf->vect[0][0]-pf->vect[3][0]) - && abs(limfront[1]-limend[1]) >= abs(pf->vect[0][1]-pf->vect[3][1]) )) - ) - ) - ); - /* check symmetry with the fragment after this */ - symend = ( (f->flags & GEXFF_SYMNEXT) && (lf->flags & GEXFF_DONE) - && ( outfront && f->sublen <= lf->sublen - || ( lf->sublen == f->sublen - && (pf == 0 - || ( abs(limfront[0]-limend[0]) >= abs(lf->vect[0][0]-lf->vect[3][0]) - && abs(limfront[1]-limend[1]) >= abs(lf->vect[0][1]-lf->vect[3][1]) )) - ) - ) - ); - if(symfront || symend) { - /* mirror the symmetric neighbour subfrag */ - if(symfront) { - a1 = (ge->ix3 != ge->bkwd->ix3); /* the symmetry axis */ - a2 = !a1; /* the other axis (goes along the extremum gentry) */ - - /* the symmetry point on a2 */ - sympt = fscale * 0.5 * (ge->ipoints[a2][2] + ge->bkwd->ipoints[a2][2]); - xf = pf; /* the symmetric fragment */ - } else { - a1 = (gel->ix3 != gel->bkwd->ix3); /* the symmetry axis */ - a2 = !a1; /* the other axis (goes along the extremum gentry) */ - - /* the symmetry point on a2 */ - sympt = fscale * 0.5 * (gel->ipoints[a2][2] + gel->bkwd->ipoints[a2][2]); - xf = lf; /* the symmetric fragment */ - } - fprintf(stderr, " sym with %p f=%d(%p) e=%d(%p) a1=%c a2=%c sympt=%g\n", - xf, symfront, pf, symend, lf, - a1 ? 'Y': 'X', a2 ? 'Y': 'X', sympt - ); - for(i=0; i<4; i++) { - f->vect[3-i][a1] = xf->vect[i][a1]; - f->vect[3-i][a2] = sympt - (xf->vect[i][a2]-sympt); - } - if(symfront) { - if(outend || lf->sublen==0) - limcurve(f->vect, limend, 3); - } else { - if(outfront || pf == 0) - limcurve(f->vect, limfront, 0); - } - avg2 = fdotcurvdist2(f->vect, dots, ndots, &max2); - fprintf(stderr, " avg=%g max=%g fscale=%g\n", sqrt(avg2), sqrt(max2), fscale); - if(max2 <= fscale*fscale) { - f->flags |= (GEXFF_DONE | GEXFF_DRAWCURVE); - f->vectlen = f->sublen; - free(dots); - return; - } - } - - if( !outfront && !outend && f->symge != 0) { - /* a special case: try a circle segment as an approximation */ - double lenfront, lenend, len, maxlen; - - /* coefficient for a Bezier approximation of a circle */ -#define CIRCLE_FRAC 0.55 - - a1 = (ge->ix3 == ge->bkwd->ix3); /* get the axis along the front */ - a2 = !a1; /* axis along the end */ - - lenfront = fixfront[a1] - limfront[a1]; - lenend = fixend[a2] - limend[a2]; - if(fabs(lenfront) < fabs(lenend)) - len = fabs(lenfront); - else - len = fabs(lenend); - - /* make it go close to the round shape */ - switch(f->sublen) { - case 2: - maxlen = fscale; - break; - case 4: - case 6: - maxlen = fscale * 2.; - break; - default: - maxlen = fscale * abs(ge->frwd->frwd->ipoints[a1][2] - - ge->ipoints[a1][2]); - break; - } - if(len > maxlen) - len = maxlen; - - mvfront[a1] = fixfront[a1] - fsign(lenfront) * len; - mvfront[a2] = limfront[a2]; - mvend[a2] = fixend[a2] - fsign(lenend) * len; - mvend[a1] = limend[a1]; - - for(i=0; i<2; i++) { - f->vect[0][i] = mvfront[i]; - f->vect[3][i] = mvend[i]; - } - f->vect[1][a1] = mvfront[a1] + CIRCLE_FRAC*(mvend[a1]-mvfront[a1]); - f->vect[1][a2] = mvfront[a2]; - f->vect[2][a1] = mvend[a1]; - f->vect[2][a2] = mvend[a2] + CIRCLE_FRAC*(mvfront[a2]-mvend[a2]); - - avg2 = fdotcurvdist2(f->vect, dots, ndots, &max2); - fprintf(stderr, " avg=%g max=%g fscale=%g\n", sqrt(avg2), sqrt(max2), fscale); - if(max2 <= fscale*fscale) { - f->flags |= (GEXFF_DONE | GEXFF_DRAWCURVE); - f->vectlen = f->sublen; - free(dots); - return; - } -#undef CIRCLE_FRAC - } - for(i=0; i<2; i++) { - f->vect[0][i] = limfront[i]; - f->vect[1][i] = fixfront[i]; - f->vect[2][i] = fixend[i]; - f->vect[3][i] = limend[i]; - } - usedots = dots; - if(outfront) { - usedots++; ndots--; - } - if(outend) - ndots--; - if( fcrossrayscv(f->vect, NULL, NULL) == 0) { - fprintf(stderr, "**** Internal error: rays must cross but don't at %p-%p\n", - ge, gel); - fprintf(stderr, " (%g, %g) (%g, %g) (%g, %g) (%g, %g)\n", - limfront[0], limfront[1], - fixfront[0], fixfront[1], - fixend[0], fixend[1], - limend[0], limend[1] - ); - dumppaths(g, NULL, NULL); - exit(1); - } else { - if(ndots != 0) - fapproxcurve(f->vect, usedots, ndots); - f->flags |= (GEXFF_DONE | GEXFF_DRAWCURVE); - f->vectlen = f->sublen; - } - free(dots); -} - -/* - * Subtract a list of gentries (covered by a fragment of higher - * priority) from the set of fragments of a given - * type. - * - * An example is subtraction of the long exact line fragments - * from the curve fragments which get overridden. - */ - -static void -frag_subtract( - GLYPH *g, - GENTRY **age, /* array of gentries for this contour */ - int clen, /* length of the contour */ - GENTRY *ge, /* first gentry to be subtracted */ - int slen, /* number of gentries in the list to be subtracted */ - int d /* type of fragments from which to subtract, as in GEXFI_... */ -) -{ - GENTRY *pge; - GEX_FRAG *f, *pf; - int len, i, j; - - f = X_FRAG(ge); - len = slen; - - /* check if we overlap the end of some fragment */ - if(f->lenback[d]) { - /* chop off the end of conflicting fragment */ - len = f->lenback[d]; - pge = age[(f->aidx + clen - len)%clen]; - pf = X_FRAG(pge); - if(pf->len[d] == clen+1 && pf->flags & GEXFF_CIRC) { - /* the conflicting fragment is self-connected */ - - pf->len[d] = 0; - /* calculate the new value for lenback */ - len = clen+1 - slen; - for(pge = ge; len > 0; pge = pge->bkwd, len--) - X_FRAG(pge)->lenback[d] = len; - /* now pge points to the last entry of the line, - * which is also the new first entry of the curve - */ - X_FRAG(pge)->len[d] = clen+2 - slen; - /* clean lenback of gentries covered by the line */ - for(pge = ge->frwd, j = slen-1; j > 0; pge = pge->frwd, j--) - X_FRAG(pge)->lenback[d] = 0; - fprintf(stderr, " cut %s circular frag to %p-%p\n", - gxf_name[d], pge, ge); - gex_dump_contour(ge, clen); - } else { - /* when we chop off a piece of fragment, we leave the remaining - * piece(s) overlapping with the beginning and possibly the end - * of the line fragment under consideration - */ - fprintf(stderr, " cut %s frag at %p from len=%d to len=%d (end %p)\n", - gxf_name[d], pge, pf->len[d], len+1, ge); - j = pf->len[d] - len - 1; /* how many gentries are chopped off */ - pf->len[d] = len + 1; - i = slen - 1; - for(pge = ge->frwd; j > 0 && i > 0; j--, i--, pge = pge->frwd) - X_FRAG(pge)->lenback[d] = 0; - gex_dump_contour(ge, clen); - - if(j != 0) { - /* the conflicting fragment is split in two by this line - * fragment, fix up its tail - */ - - fprintf(stderr, " end of %s frag len=%d %p-", - gxf_name[d], j+1, pge->bkwd); - X_FRAG(pge->bkwd)->len[d] = j+1; /* the overlapping */ - for(i = 1; j > 0; j--, i++, pge = pge->frwd) - X_FRAG(pge)->lenback[d] = i; - fprintf(stderr, "%p\n", pge->bkwd); - gex_dump_contour(ge, clen); - } - } - } - /* check if we overlap the beginning of some fragments */ - i = slen-1; /* getntries remaining to consider */ - j = 0; /* gentries remaining in the overlapping fragment */ - for(pge = ge; i > 0; i--, pge = pge->frwd) { - if(j > 0) { - X_FRAG(pge)->lenback[d] = 0; - j--; - } - /* the beginning of one fragment may be the end of another - * fragment, in this case if j-- above results in 0, that will - * cause it to check the same gentry for the beginning - */ - if(j == 0) { - pf = X_FRAG(pge); - j = pf->len[d]; - if(j != 0) { - fprintf(stderr, " removed %s frag at %p len=%d\n", - gxf_name[d], pge, j); - gex_dump_contour(ge, clen); - pf->len[d] = 0; - j--; - } - } - } - /* pge points at the last gentry of the line fragment */ - if(j > 1) { /* we have the tail of a fragment left */ - fprintf(stderr, " end of %s frag len=%d %p-", - gxf_name[d], j, pge); - X_FRAG(pge)->len[d] = j; /* the overlapping */ - for(i = 0; j > 0; j--, i++, pge = pge->frwd) - X_FRAG(pge)->lenback[d] = i; - fprintf(stderr, "%p\n", pge->bkwd); - gex_dump_contour(ge, clen); - } else if(j == 1) { - X_FRAG(pge)->lenback[d] = 0; - } -} - -/* - * Produce an outline from a bitmap. - * scale - factor to scale the sizes - * bmap - array of dots by lines, xsz * ysz - * xoff, yoff - offset of the bitmap's lower left corner - * from the logical position (0,0) - */ - -void -bmp_outline( - GLYPH *g, - int scale, - char *bmap, - int xsz, - int ysz, - int xoff, - int yoff -) -{ - char *hlm, *vlm; /* arrays of the limits of outlines */ - char *amp; /* map of ambiguous points */ - int x, y; - char *ip, *op; - double fscale; - - if(xsz==0 || ysz==0) - return; - -#ifdef USE_AUTOTRACE - if(use_autotrace) { - autotraced_bmp_outline(g, scale, bmap, xsz, ysz, xoff, yoff); - return; - } -#endif /*USE_AUTOTRACE*/ - - fscale = (double)scale; - g->flags &= ~GF_FLOAT; /* build it as int first */ - - if(!warnedhints) { - warnedhints = 1; - if(hints && subhints) { - WARNING_2 fprintf(stderr, - "Use of hint substitution on bitmap fonts is not recommended\n"); - } - } - -#if 0 - printbmap(bmap, xsz, ysz, xoff, yoff); -#endif - - /* now find the outlines */ - hlm=calloc( xsz, ysz+1 ); /* horizontal limits */ - vlm=calloc( xsz+1, ysz ); /* vertical limits */ - amp=calloc( xsz, ysz ); /* ambiguous points */ - - if(hlm==0 || vlm==0 || amp==0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - - /* - * hlm and vlm represent a grid of horisontal and - * vertical lines. Each pixel is surrounded by the grid - * from all the sides. The values of [hv]lm mark the - * parts of grid where the pixel value switches from white - * to black and back. - */ - - /* find the horizontal limits */ - ip=bmap; op=hlm; - /* 1st row */ - for(x=0; x<xsz; x++) { - if(ip[x]) - op[x]=L_ON; - } - ip+=xsz; op+=xsz; - /* internal rows */ - for(y=1; y<ysz; y++) { - for(x=0; x<xsz; x++) { - if(ip[x]) { - if(!ip[x-xsz]) - op[x]=L_ON; - } else { - if(ip[x-xsz]) - op[x]=L_OFF; - } - } - ip+=xsz; op+=xsz; - } - - /* last row */ - ip-=xsz; - for(x=0; x<xsz; x++) { - if(ip[x]) - op[x]=L_OFF; - } - - /* find the vertical limits */ - ip=bmap; op=vlm; - for(y=0; y<ysz; y++) { - if(ip[0]) - op[0]=L_ON; - for(x=1; x<xsz; x++) { - if(ip[x]) { - if(!ip[x-1]) - op[x]=L_ON; - } else { - if(ip[x-1]) - op[x]=L_OFF; - } - } - if(ip[xsz-1]) - op[xsz]=L_OFF; - ip+=xsz; op+=xsz+1; - } - - /* - * Ambiguous points are the nodes of the grids - * that are between two white and two black pixels - * located in a checkerboard style. Actually - * there are only two patterns that may be - * around an ambiguous point: - * - * X|. .|X - * -*- -*- - * .|X X|. - * - * where "|" and "-" represent the grid (respectively members - * of vlm and hlm), "*" represents an ambiguous point - * and "X" and "." represent black and white pixels. - * - * If these sample pattern occur in the lower left corner - * of the bitmap then this ambiguous point will be - * located at amp[1][1] or in other words amp[1*xsz+1]. - * - * These points are named "ambiguous" because it's - * not easy to guess what did the font creator mean - * at these points. So we are going to treat them - * specially, doing no aggressive smoothing. - */ - - /* find the ambiguous points */ - for(y=ysz-1; y>0; y--) - for(x=xsz-1; x>0; x--) { - if(bmap[y*xsz+x]) { - if( !bmap[y*xsz+x-1] && !bmap[y*xsz-xsz+x] && bmap[y*xsz-xsz+x-1] ) - amp[y*xsz+x]=1; - } else { - if( bmap[y*xsz+x-1] && bmap[y*xsz-xsz+x] && !bmap[y*xsz-xsz+x-1] ) - amp[y*xsz+x]=1; - } - } - -#if 0 - printlimits(hlm, vlm, amp, xsz, ysz); -#endif - - /* generate the vectored (stepping) outline */ - - while(1) { - int found = 0; - int outer; /* flag: this is an outer contour */ - int hor, newhor; /* flag: the current contour direction is horizontal */ - int dir; /* previous direction of the coordinate, 1 - L_ON, 0 - L_OFF */ - int startx, starty; /* start of a contour */ - int firstx, firsty; /* start of the current line */ - int newx, newy; /* new coordinates to try */ - char *lm, val; - int maxx, maxy, xor; - - for(y=ysz; !found && y>0; y--) - for(x=0; x<xsz; x++) - if(hlm[y*xsz+x] > L_NONE) - goto foundcontour; - break; /* have no contours left */ - - foundcontour: - ig_rmoveto(g, x+xoff, y+yoff); /* intermediate as int */ - - startx = firstx = x; - starty = firsty = y; - - if(hlm[y*xsz+x] == L_OFF) { - outer = 1; dir = 0; - hlm[y*xsz+x] = -hlm[y*xsz+x]; /* mark as seen */ - hor = 1; x++; - } else { - outer = 0; dir = 0; - hor = 0; y--; - vlm[y*(xsz+1)+x] = -vlm[y*(xsz+1)+x]; /* mark as seen */ - } - - while(x!=startx || y!=starty) { -#if 0 - printf("trace (%d, %d) outer=%d hor=%d dir=%d\n", x, y, outer, hor, dir); -#endif - - /* initialization common for try1 and try2 */ - if(hor) { - lm = vlm; maxx = xsz+1; maxy = ysz; newhor = 0; - } else { - lm = hlm; maxx = xsz; maxy = ysz+1; newhor = 1; - } - xor = (outer ^ hor ^ dir); - - try1: - /* first we try to change axis, to keep the - * contour as long as possible - */ - - newx = x; newy = y; - if(!hor && (!outer ^ dir)) - newx--; - if(hor && (!outer ^ dir)) - newy--; - - if(newx < 0 || newx >= maxx || newy < 0 || newy >= maxy) - goto try2; - - if(!xor) - val = L_ON; - else - val = L_OFF; -#if 0 - printf("try 1, want %d have %d at %c(%d, %d)\n", val, lm[newy*maxx + newx], - (newhor ? 'h':'v'), newx, newy); -#endif - if( lm[newy*maxx + newx] == val ) - goto gotit; - - try2: - /* try to change the axis anyway */ - - newx = x; newy = y; - if(!hor && (outer ^ dir)) - newx--; - if(hor && (outer ^ dir)) - newy--; - - if(newx < 0 || newx >= maxx || newy < 0 || newy >= maxy) - goto try3; - - if(xor) - val = L_ON; - else - val = L_OFF; -#if 0 - printf("try 2, want %d have %d at %c(%d, %d)\n", val, lm[newy*maxx + newx], - (newhor ? 'h':'v'), newx, newy); -#endif - if( lm[newy*maxx + newx] == val ) - goto gotit; - - try3: - /* try to continue in the old direction */ - - if(hor) { - lm = hlm; maxx = xsz; maxy = ysz+1; - } else { - lm = vlm; maxx = xsz+1; maxy = ysz; - } - newhor = hor; - newx = x; newy = y; - if(hor && dir) - newx--; - if(!hor && !dir) - newy--; - - if(newx < 0 || newx >= maxx || newy < 0 || newy >= maxy) - goto badtry; - - if(dir) - val = L_ON; - else - val = L_OFF; -#if 0 - printf("try 3, want %d have %d at %c(%d, %d)\n", val, lm[newy*maxx + newx], - (newhor ? 'h':'v'), newx, newy); -#endif - if( lm[newy*maxx + newx] == val ) - goto gotit; - - badtry: - fprintf(stderr, "**** Internal error in the contour detection code at (%d, %d)\n", x, y); - fprintf(stderr, "glyph='%s' outer=%d hor=%d dir=%d\n", g->name, outer, hor, dir); - fflush(stdout); - exit(1); - - gotit: - if(hor != newhor) { /* changed direction, end the previous line */ - ig_rlineto(g, x+xoff, y+yoff); /* intermediate as int */ - firstx = x; firsty = y; - } - lm[newy*maxx + newx] = -lm[newy*maxx + newx]; - hor = newhor; - dir = (val == L_ON); - if(newhor) - x -= (dir<<1)-1; - else - y += (dir<<1)-1; - } -#if 0 - printf("trace (%d, %d) outer=%d hor=%d dir=%d\n", x, y, outer, hor, dir); -#endif - ig_rlineto(g, x+xoff, y+yoff); /* intermediate as int */ - g_closepath(g); - } - - - /* try to vectorize the curves and sloped lines in the bitmap */ - if(vectorize) { - GENTRY *ge, *pge, *cge, *loopge; - int i; - int skip; - - dumppaths(g, NULL, NULL); - - /* allocate the extensions */ - for(cge=g->entries; cge!=0; cge=cge->next) { - cge->ext = calloc(1, sizeof(GEX_FRAG) ); - if(cge->ext == 0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - } - - for(cge=g->entries; cge!=0; cge=cge->next) { - if(cge->type != GE_MOVE) - continue; - - /* we've found the beginning of a contour */ - { - int d, vert, count, stepmore, delaystop; - int vdir, hdir, fullvdir, fullhdir, len; - int dx, dy, lastdx, lastdy; - int k1, k2, reversal, smooth, good; - int line[2 /*H,V*/], maxlen[2 /*H,V*/], minlen[2 /*H,V*/]; - GENTRY **age; /* array of gentries in a contour */ - int clen; /* contour length, size of ths array */ - int i, j; - GEX_FRAG *f; - - /* we know that all the contours start at the top-left corner, - * so at most it might be before/after the last element of - * the last/first fragment - */ - - ge = cge->next; - pge = ge->bkwd; - if(ge->ix3 == pge->ix3) { /* a vertical line */ - /* we want to start always from a horizontal line because - * then we always start from top and that is quaranteed to be a - * fragment boundary, so move the start point of the contour - */ - pge->prev->next = pge->next; - pge->next->prev = pge->prev; - cge->next = pge; - pge->prev = cge; - pge->next = ge; - ge->prev = pge; - ge = pge; pge = ge->bkwd; - cge->ix3 = pge->ix3; cge->iy3 = pge->iy3; - } - - /* fill the array of gentries */ - clen = 1; - for(ge = cge->next->frwd; ge != cge->next; ge = ge->frwd) - clen++; - age = (GENTRY **)malloc(sizeof(*age) * clen); - ge = cge->next; - count = 0; - do { - age[count] = ge; - X_FRAG(ge)->aidx = count++; - - /* and by the way find the extremums */ - for(i=0; i<2; i++) { - if( isign(ge->frwd->ipoints[i][2] - ge->ipoints[i][2]) - * isign(ge->bkwd->bkwd->ipoints[i][2] - ge->bkwd->ipoints[i][2]) == 1) { - X_FRAG(ge)->flags |= GEXFF_EXTR; - fprintf(stderr, " %s extremum at %p\n", (i?"vert":"hor"), ge); - } - if(abs(ge->ipoints[i][2] - ge->bkwd->ipoints[i][2]) > 1) - X_FRAG(ge)->flags |= GEXFF_LONG; - } - - ge = ge->frwd; - } while(ge != cge->next); - - /* Find the serif fragments, looking as either of: - * -+ | - * | | - * +-+ +-+ - * | | - * +--... +--... - * with the thickness of serifs being 1 pixel. We make no - * difference between serifs on vertical and horizontal stems. - */ - - ge = cge->next; - do { - GENTRY *nge; - int pdx, pdy, ndx, ndy; - - /* two gentries of length 1 mean a potential serif */ - pge = ge->bkwd; - nge = ge->frwd; - - dx = nge->ix3 - pge->ix3; - dy = nge->iy3 - pge->iy3; - - if(abs(dx) != 1 || abs(dy) != 1) /* 2 small ones */ - continue; - - if( - (!(X_FRAG(ge)->flags & GEXFF_EXTR) - || !(X_FRAG(ge->bkwd)->flags & GEXFF_EXTR)) - && (!(X_FRAG(ge->frwd)->flags & GEXFF_EXTR) - || !(X_FRAG(ge->frwd->frwd)->flags & GEXFF_EXTR)) - ) - continue; /* either side must be a couple of extremums */ - - pdx = pge->ix3 - pge->bkwd->ix3; - pdy = pge->iy3 - pge->bkwd->iy3; - ndx = nge->frwd->ix3 - nge->ix3; - ndy = nge->frwd->iy3 - nge->iy3; - - if(pdx*dx + pdy*dy > 0 && ndx*dx + ndy*dy > 0) - continue; /* definitely not a serif but a round corner */ - - if(abs(pdx) + abs(pdy) == 1 || abs(ndx) + abs(ndy) == 1) - continue; - - /* we've found a serif including this and next gentry */ - X_FRAG(ge)->len[GEXFI_SERIF] = 2; - - } while( (ge = ge->frwd) != cge->next ); - - - /* Find the convex and concave fragments, defined as: - * convex (clockwise): dy/dx <= dy0/dx0, - * or a reversal: dy/dx == - dy0/dx0 && abs(dxthis) == 1 && dy/dx > 0 - * concave (counter-clockwise): dy/dx >= dy0/dx0, - * or a reversal: dy/dx == - dy0/dx0 && abs(dxthis) == 1 && dy/dx < 0 - * - * Where dx and dy are measured between the end of this gentry - * and the start of the previous one (dx0 and dy0 are the same - * thing calculated for the previous gentry and its previous one), - * dxthis is between the end and begginning of this gentry. - * - * A reversal is a situation when the curve changes its direction - * along the x axis, so it passes through a momentary vertical - * direction. - */ - for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) { - ge = cge->next; - pge = ge->bkwd; /* the beginning of the fragment */ - count = 1; - lastdx = pge->ix3 - pge->bkwd->bkwd->ix3; - lastdy = pge->iy3 - pge->bkwd->bkwd->iy3; - -#define CHKCURVCONN(ge, msg) do { \ - dx = (ge)->ix3 - (ge)->bkwd->bkwd->ix3; \ - dy = (ge)->iy3 - (ge)->bkwd->bkwd->iy3; \ - if(0 && msg) { \ - fprintf(stderr, " %p: dx=%d dy=%d dx0=%d dy0=%d ", \ - (ge), dx, dy, lastdx, lastdy); \ - } \ - k1 = X_FRAG(ge)->flags; \ - k2 = X_FRAG((ge)->bkwd)->flags; \ - if(0 && msg) { \ - fprintf(stderr, "fl=%c%c%c%c ", \ - (k1 & GEXFF_EXTR) ? 'X' : '-', \ - (k1 & GEXFF_LONG) ? 'L' : '-', \ - (k2 & GEXFF_EXTR) ? 'X' : '-', \ - (k2 & GEXFF_LONG) ? 'L' : '-' \ - ); \ - } \ - if( (k1 & GEXFF_EXTR) && (k2 & GEXFF_LONG) \ - || (k2 & GEXFF_EXTR) && (k1 & GEXFF_LONG) ) { \ - smooth = 0; \ - good = reversal = -1; /* for debugging */ \ - } else { \ - k1 = dy * lastdx; \ - k2 = lastdy * dx; \ - smooth = (abs(dx)==1 || abs(dy)==1); \ - good = (k1 - k2)*gxf_cvk[d] >= 0; \ - if(smooth && !good) { \ - reversal = (k1 == -k2 && abs((ge)->ix3 - (ge)->bkwd->ix3)==1 \ - && dy*dx*gxf_cvk[d] < 0); \ - } else \ - reversal = 0; \ - } \ - if(0 && msg) { \ - fprintf(stderr, "k1=%d k2=%d pge=%p count=%d %s good=%d rev=%d\n", \ - k1, k2, pge, count, gxf_name[d], good, reversal); \ - } \ - } while(0) - - do { - CHKCURVCONN(ge, 1); - - if(smooth && (good || reversal) ) - count++; - else { - /* can't continue */ -#if 0 - if(count >= 4) { /* worth remembering */ - fprintf(stderr, " %s frag %p-%p count=%d\n", gxf_name[d], pge, ge->bkwd, count); - } -#endif - X_FRAG(pge)->len[d] = count; - if(smooth) { - pge = ge->bkwd; - count = 2; - } else { - pge = ge; - count = 1; - } - } - lastdx = dx; lastdy = dy; - ge = ge->frwd; - } while(ge != cge->next); - - /* see if we can connect the last fragment to the first */ - CHKCURVCONN(ge, 1); - - if(smooth && (good || reversal) ) { - /* -1 to avoid ge->bkwd being counted twice */ - if( X_FRAG(ge->bkwd)->len[d] >= 2 ) - count += X_FRAG(ge->bkwd)->len[d] - 1; - else if(count == clen+1) { - /* we are joining a circular (closed) curve, check whether it - * can be joined at any point or whether it has a discontinuity - * at the point where we join it now - */ - lastdx = dx; lastdy = dy; - CHKCURVCONN(ge->frwd, 0); - - if(smooth && (good || reversal) ) { - /* yes, the curve is truly a circular one and can be - * joined at any point - */ - -#if 0 - fprintf(stderr, " found a circular joint point at %p\n", pge); -#endif - /* make sure that in a circular fragment we start from an extremum */ - while( ! (X_FRAG(pge)->flags & GEXFF_EXTR) ) - pge = pge->frwd; - X_FRAG(pge)->flags |= GEXFF_CIRC; - } - } -#if 0 - fprintf(stderr, " %s joined %p to %p count=%d bk_count=%d\n", gxf_name[d], pge, ge->bkwd, - count, X_FRAG(ge->bkwd)->len[d] ); -#endif - X_FRAG(ge->bkwd)->len[d] = 0; - } - X_FRAG(pge)->len[d] = count; -#if 0 - if(count >= 4) { /* worth remembering */ - fprintf(stderr, " %s last frag %p-%p count=%d\n", gxf_name[d], pge, ge->bkwd, count); - } -#endif -#undef CHKCURVCONN - - /* do postprocessing */ - ge = cge->next; - do { - f = X_FRAG(ge); - len = f->len[d]; -#if 0 - fprintf(stderr, " %p %s len=%d clen=%d\n", ge, gxf_name[d], len, clen); -#endif - if(len < 3) /* get rid of the fragments that are too short */ - f->len[d] = 0; - else if(len == 3) { - /* _ - * drop the |_| - shaped fragments, leave alone the _| - shaped - * (and even those only if not too short in pixels), - * those left alone are further filtered later - */ - k1 = (ge->ix3 == ge->bkwd->ix3); /* axis of the start */ - if(isign(ge->ipoints[k1][2] - ge->bkwd->ipoints[k1][2]) - != isign(ge->frwd->ipoints[k1][2] - ge->frwd->frwd->ipoints[k1][2]) - && abs(ge->frwd->frwd->ipoints[k1][2] - ge->bkwd->ipoints[k1][2]) > 2) { -#if 0 - fprintf(stderr, " %s frag %p count=%d good shape\n", - gxf_name[d], ge, count); -#endif - } else - f->len[d] = 0; - } else if(len == clen+1) - break; /* a closed fragment, nothing else interesting */ - else { /* only for open fragments */ - GENTRY *gem, *gex, *gei, *ges; - - ges = ge; /* the start entry */ - gem = age[(f->aidx + f->len[d])%clen]; /* entry past the end of the fragment */ - - gei = ge->frwd; - if( (ge->ix3 == ge->bkwd->ix3) /* vert */ - ^ (isign(ge->bkwd->ix3 - gei->ix3)==isign(ge->bkwd->iy3 - gei->iy3)) - ^ !(d == GEXFI_CONVEX) /* counter-clockwise */ ) { - -#if 0 - fprintf(stderr, " %p: %s potential spurious start\n", ge, gxf_name[d]); -#endif - /* the beginning may be a spurious entry */ - - gex = 0; /* the extremum closest to the beginning - to be found */ - for(gei = ge->frwd; gei != gem; gei = gei->frwd) { - if(X_FRAG(gei)->flags & GEXFF_EXTR) { - gex = gei; - break; - } - } - if(gex == 0) - gex = gem->bkwd; - - /* A special case: ignore the spurious ends on small curves that - * either enclose an 1-pixel-wide extremum or are 1-pixel deep. - * Any 5-or-less-pixel-long curve with extremum 2 steps away - * qualifies for that. - */ - - if(len <= 5 && gex == ge->frwd->frwd) { - good = 0; -#if 0 - fprintf(stderr, " E"); -#endif - } else { - good = 1; /* assume that ge is not spurious */ - - /* gei goes backwards, gex goes forwards from the extremum */ - gei = gex; - /* i is the symmetry axis, j is the other axis (X=0 Y=1) */ - i = (gex->ix3 != gex->bkwd->ix3); - j = !i; - for( ; gei!=ge && gex!=gem; gei=gei->bkwd, gex=gex->frwd) { - if( gei->bkwd->ipoints[i][2] != gex->ipoints[i][2] - || gei->bkwd->ipoints[j][2] - gei->ipoints[j][2] - != gex->bkwd->ipoints[j][2] - gex->ipoints[j][2] - ) { - good = 0; /* no symmetry - must be spurious */ -#if 0 - fprintf(stderr, " M(%p,%p)(%d %d,%d)(%d %d,%d)", - gei, gex, - i, gei->bkwd->ipoints[i][2], gex->ipoints[i][2], - j, gei->bkwd->ipoints[j][2] - gei->ipoints[j][2], - gex->bkwd->ipoints[j][2] - gex->ipoints[j][2] ); -#endif - break; - } - } - if(gex == gem) { /* oops, the other side is too short */ - good = 0; -#if 0 - fprintf(stderr, " X"); -#endif - } - if(good && gei == ge) { - if( isign(gei->bkwd->ipoints[j][2] - gei->ipoints[j][2]) - != isign(gex->bkwd->ipoints[j][2] - gex->ipoints[j][2]) ) { - good = 0; /* oops, goes into another direction */ -#if 0 - fprintf(stderr, " D"); -#endif - } - } - } - if(!good) { /* it is spurious, drop it */ -#if 0 - fprintf(stderr, " %p: %s spurious start\n", ge, gxf_name[d]); -#endif - f->len[d] = 0; - ges = ge->frwd; - len--; - X_FRAG(ges)->len[d] = len; - } - } - - gei = gem->bkwd->bkwd->bkwd; - if( (gem->ix3 != gem->bkwd->ix3) /* gem->bkwd is vert */ - ^ (isign(gem->bkwd->ix3 - gei->ix3)==isign(gem->bkwd->iy3 - gei->iy3)) - ^ (d == GEXFI_CONVEX) /* clockwise */ ) { - -#if 0 - fprintf(stderr, " %p: %s potential spurious end\n", gem->bkwd, gxf_name[d]); -#endif - /* the end may be a spurious entry */ - - gex = 0; /* the extremum closest to the end - to be found */ - for(gei = gem->bkwd->bkwd; gei != ges->bkwd; gei = gei->bkwd) { - if(X_FRAG(gei)->flags & GEXFF_EXTR) { - gex = gei; - break; - } - } - if(gex == 0) - gex = ges; - - good = 1; /* assume that gem->bkwd is not spurious */ - /* gei goes backwards, gex goes forwards from the extremum */ - gei = gex; - /* i is the symmetry axis, j is the other axis (X=0 Y=1) */ - i = (gex->ix3 != gex->bkwd->ix3); - j = !i; - for( ; gei!=ges->bkwd && gex!=gem->bkwd; gei=gei->bkwd, gex=gex->frwd) { - if( gei->bkwd->ipoints[i][2] != gex->ipoints[i][2] - || gei->bkwd->ipoints[j][2] - gei->ipoints[j][2] - != gex->bkwd->ipoints[j][2] - gex->ipoints[j][2] - ) { - good = 0; /* no symmetry - must be spurious */ -#if 0 - fprintf(stderr, " M(%p,%p)(%d %d,%d)(%d %d,%d)", - gei, gex, - i, gei->bkwd->ipoints[i][2], gex->ipoints[i][2], - j, gei->bkwd->ipoints[j][2] - gei->ipoints[j][2], - gex->bkwd->ipoints[j][2] - gex->ipoints[j][2] ); -#endif - break; - } - } - if(gei == ges->bkwd) { /* oops, the other side is too short */ - good = 0; -#if 0 - fprintf(stderr, " X"); -#endif - } - if(good && gex == gem->bkwd) { - if( isign(gei->bkwd->ipoints[j][2] - gei->ipoints[j][2]) - != isign(gex->bkwd->ipoints[j][2] - gex->ipoints[j][2]) ) { - good = 0; /* oops, goes into another direction */ -#if 0 - fprintf(stderr, " D"); -#endif - } - } - if(!good) { /* it is spurious, drop it */ -#if 0 - fprintf(stderr, " %p: %s spurious end\n", gem->bkwd, gxf_name[d]); -#endif - X_FRAG(ges)->len[d] = --len; - } - } - if(len < 4) { - X_FRAG(ges)->len[d] = 0; -#if 0 - fprintf(stderr, " %p: %s frag discarded, too small now\n", ge, gxf_name[d]); -#endif - } - if(ges != ge) { - if(ges == cge->next) - break; /* went around the loop */ - else { - ge = ges->frwd; /* don't look at this fragment twice */ - continue; - } - } - } - - ge = ge->frwd; - } while(ge != cge->next); - } - - /* Find the straight line fragments. - * Even though the lines are sloped, they are called - * "vertical" or "horizontal" according to their longer - * dimension. All the steps in the shother dimension must - * be 1 pixel long, all the steps in the longer dimension - * must be within the difference of 1 pixel. - */ - for(d = GEXFI_LINE; d<= GEXFI_EXACTLINE; d++) { - ge = cge->next; - pge = ge->bkwd; /* the beginning of the fragment */ - count = 1; - delaystop = 0; - do { - int h; - - stepmore = 0; - hdir = isign(ge->ix3 - ge->bkwd->ix3); - vdir = isign(ge->iy3 - ge->bkwd->iy3); - vert = (hdir == 0); - if(count==1) { - /* at this point pge==ge->bkwd */ - /* account for the previous gentry, which was !vert */ - if(!vert) { /* prev was vertical */ - maxlen[0] = minlen[0] = 0; - maxlen[1] = minlen[1] = abs(pge->iy3 - pge->bkwd->iy3); - line[0] = (maxlen[1] == 1); - line[1] = 1; - fullhdir = hdir; - fullvdir = isign(pge->iy3 - pge->bkwd->iy3); - } else { - maxlen[0] = minlen[0] = abs(pge->ix3 - pge->bkwd->ix3); - maxlen[1] = minlen[1] = 0; - line[0] = 1; - line[1] = (maxlen[0] == 1); - fullhdir = isign(pge->ix3 - pge->bkwd->ix3); - fullvdir = vdir; - } - } - h = line[0]; /* remember the prevalent direction */ -#if 0 - fprintf(stderr, " %p: v=%d(%d) h=%d(%d) vl(%d,%d,%d) hl=(%d,%d,%d) %s count=%d ", - ge, vdir, fullvdir, hdir, fullhdir, - line[1], minlen[1], maxlen[1], - line[0], minlen[0], maxlen[0], - gxf_name[d], count); -#endif - if(vert) { - if(vdir != fullvdir) - line[0] = line[1] = 0; - len = abs(ge->iy3 - ge->bkwd->iy3); - } else { - if(hdir != fullhdir) - line[0] = line[1] = 0; - len = abs(ge->ix3 - ge->bkwd->ix3); - } -#if 0 - fprintf(stderr, "len=%d\n", len); -#endif - if(len != 1) /* this is not a continuation in the short dimension */ - line[!vert] = 0; - - /* can it be a continuation in the long dimension ? */ - if( line[vert] ) { - if(maxlen[vert]==0) - maxlen[vert] = minlen[vert] = len; - else if(maxlen[vert]==minlen[vert]) { - if(d == GEXFI_EXACTLINE) { - if(len != maxlen[vert]) - line[vert] = 0; /* it can't */ - } else if(len < maxlen[vert]) { - if(len < minlen[vert]-1) - line[vert] = 0; /* it can't */ - else - minlen[vert] = len; - } else { - if(len > maxlen[vert]+1) - line[vert] = 0; /* it can't */ - else - maxlen[vert] = len; - } - } else if(len < minlen[vert] || len > maxlen[vert]) - line[vert] = 0; /* it can't */ - } - - if(line[0] == 0 && line[1] == 0) { -#if 0 - if(count >= 3) - fprintf(stderr, " %s frag %p-%p count=%d\n", gxf_name[d], pge, ge->bkwd, count); -#endif - X_FRAG(pge)->len[d] = count; - if(d == GEXFI_EXACTLINE && h) { - X_FRAG(pge)->flags |= GEXFF_HLINE; - } - if(count == 1) - pge = ge; - else { - stepmore = 1; /* may reconsider the 1st gentry */ - pge = ge = ge->bkwd; - count = 1; - } - } else - count++; - - ge = ge->frwd; - if(ge == cge->next && !stepmore) - delaystop = 1; /* consider the first gentry again */ - } while(stepmore || ge != cge->next ^ delaystop); - /* see if there is an unfinished line left */ - if(count != 1) { -#if 0 - if(count >= 3) - fprintf(stderr, " %s frag %p-%p count=%d\n", gxf_name[d], pge, ge->bkwd, count); -#endif - X_FRAG(ge->bkwd->bkwd)->len[d] = 0; - X_FRAG(pge)->len[d] = count; - } - } - - /* do postprocessing of the lines */ -#if 0 - fprintf(stderr, "Line postprocessing\n"); - gex_dump_contour(cge->next, clen); -#endif - - /* the non-exact line frags are related to exact line frags sort - * of like to individual gentries: two kinds of exact frags - * must be interleaved, with one kind having the size of 3 - * and the other kind having the size varying within +-2. - */ - - ge = cge->next; - do { - GEX_FRAG *pf, *lastf1, *lastf2; - int len1, len2, fraglen; - - f = X_FRAG(ge); - - fraglen = f->len[GEXFI_LINE]; - if(fraglen >= 4) { - - vert = 0; /* vert is a pseudo-directon */ - line[0] = line[1] = 1; - maxlen[0] = minlen[0] = maxlen[1] = minlen[1] = 0; - lastf2 = lastf1 = f; - len2 = len1 = 0; - for(pge = ge, i = 1; i < fraglen; i++, pge=pge->frwd) { - pf = X_FRAG(pge); - len = pf->len[GEXFI_EXACTLINE]; -#if 0 - fprintf(stderr, " pge=%p i=%d of %d ge=%p exLen=%d\n", pge, i, - f->len[GEXFI_LINE], ge, len); -#endif - len1++; len2++; - if(len==0) { - continue; - } - vert = !vert; /* alternate the pseudo-direction */ - if(len > 3) - line[!vert] = 0; - if(maxlen[vert] == 0) - maxlen[vert] = minlen[vert] = len; - else if(maxlen[vert]-2 >= len && minlen[vert]+2 <= len) { - if(len > maxlen[vert]) - maxlen[vert] = len; - else if(len < minlen[vert]) - minlen[vert] = len; - } else - line[vert] = 0; - if(line[0] == 0 && line[1] == 0) { -#if 0 - fprintf(stderr, " Line breaks at %p %c(%d, %d) %c(%d, %d) len=%d fl=%d l2=%d l1=%d\n", - pge, (!vert)?'*':' ', minlen[0], maxlen[0], - vert?'*':' ', minlen[1], maxlen[1], len, fraglen, len2, len1); -#endif - if(lastf2 != lastf1) { - lastf2->len[GEXFI_LINE] = len2-len1; - } - lastf1->len[GEXFI_LINE] = len1+1; - pf->len[GEXFI_LINE] = fraglen+1 - i; -#if 0 - gex_dump_contour(pge, clen); -#endif - - /* continue with the line */ - vert = 0; /* vert is a pseudo-directon */ - line[0] = line[1] = 1; - maxlen[0] = minlen[0] = maxlen[1] = minlen[1] = 0; - lastf2 = lastf1 = f; - len2 = len1 = 0; - } else { - lastf1 = pf; - len1 = 0; - } - } - } - - ge = ge->frwd; - } while(ge != cge->next); -#if 0 - fprintf(stderr, "Line postprocessing part 2\n"); - gex_dump_contour(cge->next, clen); -#endif - - ge = cge->next; - do { - f = X_FRAG(ge); - - if(f->len[GEXFI_LINE] >= 4) { - len = f->len[GEXFI_EXACTLINE]; - /* if a non-exact line covers precisely two exact lines, - * split it - */ - if(len > 0 && f->len[GEXFI_LINE] >= len+1) { - GEX_FRAG *pf; - pge = age[(f->aidx + len - 1)%clen]; /* last gentry of exact line */ - pf = X_FRAG(pge); - if(f->len[GEXFI_LINE] + 1 == len + pf->len[GEXFI_EXACTLINE]) { - f->len[GEXFI_LINE] = len; - f->flags |= GEXFF_SPLIT; - pf->len[GEXFI_LINE] = pf->len[GEXFI_EXACTLINE]; - pf->flags |= GEXFF_SPLIT; - } - } - } - - ge = ge->frwd; - } while(ge != cge->next); -#if 0 - fprintf(stderr, "Line postprocessing part 2a\n"); - gex_dump_contour(cge->next, clen); -#endif - ge = cge->next; - do { - f = X_FRAG(ge); - - /* too small lines are of no interest */ - if( (f->flags & GEXFF_SPLIT)==0 && f->len[GEXFI_LINE] < 4) - f->len[GEXFI_LINE] = 0; - - len = f->len[GEXFI_EXACTLINE]; - /* too small exact lines are of no interest */ - if(len < 3) /* exact lines may be shorter */ - f->len[GEXFI_EXACTLINE] = 0; - /* get rid of inexact additions to the end of the exact lines */ - else if(f->len[GEXFI_LINE] == len+1) - f->len[GEXFI_LINE] = len; - /* same at the beginning */ - else { - int diff = X_FRAG(ge->bkwd)->len[GEXFI_LINE] - len; - - if(diff == 1 || diff == 2) { - X_FRAG(ge->bkwd)->len[GEXFI_LINE] = 0; - f->len[GEXFI_LINE] = len; - } - } - - ge = ge->frwd; - } while(ge != cge->next); -#if 0 - fprintf(stderr, "Line postprocessing is completed\n"); - gex_dump_contour(cge->next, clen); -#endif - - gex_calc_lenback(cge->next, clen); /* prepare data */ - - /* resolve conflicts between lines and curves */ - - /* - * the short (3-gentry) curve frags must have one of the ends - * coinciding with another curve frag of the same type - */ - - for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) { - ge = cge->next; - do { - f = X_FRAG(ge); - - if(f->len[d] == 3) { - pge = age[(f->aidx + 2)%clen]; /* last gentry of this frag */ - if(f->lenback[d] == 0 && X_FRAG(pge)->len[d] == 0) { - fprintf(stderr, " discarded small %s at %p-%p\n", gxf_name[d], ge, pge); - f->len[d] = 0; - X_FRAG(ge->frwd)->lenback[d] = 0; - X_FRAG(ge->frwd->frwd)->lenback[d] = 0; - } - } - ge = ge->frwd; - } while(ge != cge->next); - } - - /* the serifs take priority over everything else */ - ge = cge->next; - do { - f = X_FRAG(ge); - - len = f->len[GEXFI_SERIF]; - if(len == 0) - continue; - - if(len != 2) { /* this is used in the code below */ - fprintf(stderr, "Internal error at %s line %d: serif frags len is %d\n", - __FILE__, __LINE__, len); - exit(1); - } - - for(d = 0; d < GEXFI_SERIF; d++) { - /* serifs may not have common ends with the other fragments, - * this is expressed as extending them by 1 gentry on each side - */ - frag_subtract(g, age, clen, ge->bkwd, len+2, d); - } - } while( (ge = ge->frwd) != cge->next); - - /* - * longer exact lines take priority over curves; shorter lines - * and inexact lines are resolved with convex/concave conflicts - */ - ge = cge->next; - do { - f = X_FRAG(ge); - - len = f->len[GEXFI_EXACTLINE]; - - if(len < 6) { /* line is short */ - ge = ge->frwd; - continue; - } - - fprintf(stderr, " line at %p len=%d\n", ge, f->len[GEXFI_EXACTLINE]); - for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) { - frag_subtract(g, age, clen, ge, len, d); - } - - ge = ge->frwd; - } while(ge != cge->next); - - /* - * The exact lines take priority over curves that coincide - * with them or extend by only one gentry on either side - * (but not both sides). By this time it applies only to the - * small exact lines. - * - * An interesting general case is when a curve matches more - * than one exact line going diamond-like. - */ - - ge = cge->next; - do { - int done, len2; - int sharpness; - GEX_FRAG *pf; - - f = X_FRAG(ge); - - /* "sharpness" shows how a group of exact line frags is connected: if the gentries - * of some of them overlap, the curve matching requirement is loosened: it may - * extend up to 1 gentry beyond each end of the group of exact line frags - * (sharpness=2); otherwise it may extend to only one end (sharpness=1) - */ - sharpness = 1; - - len = f->len[GEXFI_EXACTLINE]; - if(len >= 4) { - while(len < clen) { - done = 0; - pf = X_FRAG(ge->bkwd); - for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) { - if(f->len[d] == len || f->len[d] == len+1) { - - fprintf(stderr, " removed %s frag at %p len=%d linelen=%d\n", - gxf_name[d], ge, f->len[d], len); - pge = ge->frwd; - for(i = f->len[d]; i > 1; i--, pge = pge->frwd) - X_FRAG(pge)->lenback[d] = 0; - f->len[d] = 0; - gex_dump_contour(ge, clen); - done = 1; - } else if(pf->len[d] == len+1 || pf->len[d] == len+sharpness) { - fprintf(stderr, " removed %s frag at %p len=%d next linelen=%d\n", - gxf_name[d], ge->bkwd, pf->len[d], len); - pge = ge; - for(i = pf->len[d]; i > 1; i--, pge = pge->frwd) - X_FRAG(pge)->lenback[d] = 0; - pf->len[d] = 0; - gex_dump_contour(ge, clen); - done = 1; - } - } - if(done) - break; - - /* is there any chance to match a sequence of exect lines ? */ - if(f->len[GEXFI_CONVEX] < len && f->len[GEXFI_CONCAVE] < len - && pf->len[GEXFI_CONVEX] < len && pf->len[GEXFI_CONCAVE] < len) - break; - - done = 1; - /* check whether the line is connected to another exact line at an extremum */ - pge = age[(f->aidx + len - 1)%clen]; /* last gentry of exact line */ - len2 = X_FRAG(pge)->len[GEXFI_EXACTLINE]; - if(len2 > 0) { - if( len2 >= 4 && (X_FRAG(pge)->flags & GEXFF_EXTR) ) { - len += len2 - 1; - sharpness = 2; - done = 0; - } - } else { - /* see if the extremum is between two exact lines */ - pge = pge->frwd; - if(X_FRAG(pge)->flags & GEXFF_EXTR) { - pge = pge->frwd; - len2 = X_FRAG(pge)->len[GEXFI_EXACTLINE]; - if(len2 >= 4) { - len += len2 + 1; - done = 0; - } - } - } - if(done) - break; - } - } - - ge = ge->frwd; - } while(ge != cge->next); - - /* - * The lines may cover only whole curves (or otherwise empty space), - * so cut them where they overlap parts of the curves. If 2 or less - * gentries are left in the line, remove the line. - * If a line and a curve fully coincide, remove the line. Otherwise - * remove the curves that are completely covered by the lines. - */ - - ge = cge->next; - do { - f = X_FRAG(ge); - - reconsider_line: - len = f->len[GEXFI_LINE]; - - if(len == 0) { - ge = ge->frwd; - continue; - } - - if(f->len[GEXFI_CONVEX] >= len - || f->len[GEXFI_CONCAVE] >= len) { - line_completely_covered: - fprintf(stderr, " removed covered Line frag at %p len=%d\n", - ge, len); - f->len[GEXFI_LINE] = 0; - for(pge = ge->frwd; len > 1; len--, pge = pge->frwd) - X_FRAG(pge)->lenback[GEXFI_LINE] = 0; - gex_dump_contour(ge, clen); - ge = ge->frwd; - continue; - } - - k1 = 0; /* how much to cut at the front */ - for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) { - if(f->lenback[d]) { - pge = age[(f->aidx + clen - f->lenback[d])%clen]; - i = X_FRAG(pge)->len[d] - f->lenback[d] - 1; - if(i > k1) - k1 = i; - } - } - - k2 = 0; /* how much to cut at the end */ - pge = age[(f->aidx + len)%clen]; /* gentry after the end */ - for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) { - i = X_FRAG(pge)->lenback[d] - 1; - if(i > k2) - k2 = i; - } - - if(k1+k2 > 0 && k1+k2 >= len-3) { - fprintf(stderr, " k1=%d k2=%d\n", k1, k2); - goto line_completely_covered; - } - - - if(k2 != 0) { /* cut the end */ - len -= k2; - f->len[GEXFI_LINE] = len; - /* pge still points after the end */ - for(i = k2, pge = pge->bkwd; i > 0; i--, pge = pge->bkwd) - X_FRAG(pge)->lenback[GEXFI_LINE] = 0; - } - if(k1 != 0) { /* cut the beginning */ - len -= k1; - f->len[GEXFI_LINE] = 0; - for(i = 1, pge = ge->frwd; i < k1; i++, pge = pge->frwd) - X_FRAG(pge)->lenback[GEXFI_LINE] = 0; - X_FRAG(pge)->len[GEXFI_LINE] = len; - for(i = 0; i < len; i++, pge = pge->frwd) - X_FRAG(pge)->lenback[GEXFI_LINE] = i; - } - if(k1 != 0 || k2 != 0) { - fprintf(stderr, " cut Line frag at %p by (%d,%d) to len=%d\n", - ge, k1, k2, len); - gex_dump_contour(ge, clen); - - goto reconsider_line; /* the line may have to be cut again */ - } - pge = age[(f->aidx + k1)%clen]; /* new beginning */ - good = 1; /* flag: no need do do a debugging dump */ - for(i=1; i<len; i++, pge = pge->frwd) - for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) { - if(X_FRAG(pge)->len[d]) { - fprintf(stderr, " removed %s frag at %p len=%d covered by line\n", - gxf_name[d], pge, X_FRAG(pge)->len[d], len); - good = 0; - } - X_FRAG(pge)->len[d] = 0; - } - pge = age[(f->aidx + k1 + 1)%clen]; /* next after new beginning */ - for(i=1; i<len; i++, pge = pge->frwd) - for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) - X_FRAG(pge)->lenback[d] = 0; - if(!good) - gex_dump_contour(ge, clen); - - ge = ge->frwd; - } while(ge != cge->next); - - /* Resolve conflicts between curves */ - for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) { - dx = (GEXFI_CONVEX + GEXFI_CONCAVE) - d; /* the other type */ - ge = cge->next; - do { - GENTRY *sge; - - f = X_FRAG(ge); - len = f->len[d]; - if(len < 2) { - ge = ge->frwd; - continue; - } - sge = ge; /* the start of fragment */ - - i = f->len[dx]; - if(i != 0) { /* two curved frags starting here */ - /* should be i!=len because otherwise they would be - * covered by an exact line - */ - if(i > len) { - curve_completely_covered: - /* remove the convex frag */ - fprintf(stderr, " removed %s frag at %p len=%d covered by %s\n", - gxf_name[d], ge, len, gxf_name[dx]); - f->len[d] = 0; - for(pge = ge->frwd, j = 1; j < len; j++, pge = pge->frwd) - X_FRAG(pge)->lenback[d] = 0; - gex_dump_contour(ge, clen); - - ge = ge->frwd; /* the frag is gone, nothing more to do */ - continue; - } else { - /* remove the concave frag */ - fprintf(stderr, " removed %s frag at %p len=%d covered by %s\n", - gxf_name[dx], ge, i, gxf_name[d]); - f->len[dx] = 0; - for(pge = ge->frwd, j = 1; j < i; j++, pge = pge->frwd) - X_FRAG(pge)->lenback[dx] = 0; - gex_dump_contour(ge, clen); - } - } - - - k1 = X_FRAG(ge->frwd)->lenback[dx]; - if(k1 != 0) { /* conflict at the front */ - GENTRY *gels, *gele, *gei; - - pge = age[(f->aidx + clen - (k1-1))%clen]; /* first gentry of concave frag */ - k2 = X_FRAG(pge)->len[dx]; /* its length */ - - i = k2 - (k1-1); /* amount of overlap */ - if(i > len) - i = len; - /* i >= 2 by definition */ - if(i >= k2-1) { /* covers the other frag - maybe with 1 gentry showing */ - fprintf(stderr, " removed %s frag at %p len=%d covered by %s\n", - gxf_name[dx], pge, k2, gxf_name[d]); - X_FRAG(pge)->len[dx] = 0; - for(pge = pge->frwd, j = 1; j < k2; j++, pge = pge->frwd) - X_FRAG(pge)->lenback[dx] = 0; - if(i >= len-1) { /* covers our frag too - maybe with 1 gentry showing */ - /* our frag will be removed as well, prepare a line to replace it */ - gels = ge; - gele = age[(f->aidx + i - 1)%clen]; - fprintf(stderr, " new Line frag at %p-%p len=%d\n", gels, gele, i); - X_FRAG(gels)->len[GEXFI_LINE] = i; - for(gei = gels->frwd, j = 1; j < i; gei = gei->frwd, j++) - X_FRAG(gei)->lenback[GEXFI_LINE] = j; - } else { - gex_dump_contour(ge, clen); - ge = ge->frwd; - continue; - } - } - if(i >= len-1) /* covers our frag - maybe with 1 gentry showing */ - goto curve_completely_covered; - - /* XXX need to do something better for the case when a curve frag - * is actually nothing but an artifact of two other curves of - * the opposite type touching each other, like on the back of "3" - */ - - /* change the overlapping part to a line */ - gels = ge; - gele = age[(f->aidx + i - 1)%clen]; - /* give preference to local extremums */ - if(X_FRAG(gels)->flags & GEXFF_EXTR) { - gels = gels->frwd; - i--; - } - if(X_FRAG(gele)->flags & GEXFF_EXTR) { - gele = gele->bkwd; - i--; - } - if(gels->bkwd == gele) { - /* Oops the line became negative. Probably should - * never happen but I can't think of any formal reasoning - * leading to that, so check just in case. Restore - * the previous state. - */ - gels = gele; gele = gels->frwd; i = 2; - } - - j = X_FRAG(gels)->lenback[dx] + 1; /* new length */ - if(j != k2) { - X_FRAG(pge)->len[dx] = j; - fprintf(stderr, " cut %s frag at %p len=%d to %p len=%d end overlap with %s\n", - gxf_name[dx], pge, k2, gels, j, gxf_name[d]); - for(gei = gels->frwd; j < k2; gei = gei->frwd, j++) - X_FRAG(gei)->lenback[dx] = 0; - } - - if(gele != ge) { - sge = gele; - f->len[d] = 0; - fprintf(stderr, " cut %s frag at %p len=%d ", gxf_name[d], ge, len); - len--; - for(gei = ge->frwd; gei != gele; gei = gei->frwd, len--) - X_FRAG(gei)->lenback[d] = 0; - X_FRAG(gele)->len[d] = len; - X_FRAG(gele)->lenback[d] = 0; - fprintf(stderr, "to %p len=%d start overlap with %s\n", - sge, len, gxf_name[dx]); - for(gei = gei->frwd, j = 1; j < len; gei = gei->frwd, j++) - X_FRAG(gei)->lenback[d] = j; - - } - if(i > 1) { - fprintf(stderr, " new Line frag at %p-%p len=%d\n", gels, gele, i); - X_FRAG(gels)->len[GEXFI_LINE] = i; - for(gei = gels->frwd, j = 1; j < i; gei = gei->frwd, j++) - X_FRAG(gei)->lenback[GEXFI_LINE] = j; - } - gex_dump_contour(ge, clen); - } - - ge = ge->frwd; - } while(ge != cge->next); - } - - /* - * Assert that there are no conflicts any more and - * for each gentry find the fragment types that start - * and continue here. - */ - ge = cge->next; - do { - f = X_FRAG(ge); - dx = GEXFI_NONE; /* type that starts here */ - dy = GEXFI_NONE; /* type that goes through here */ - /* GEXFI_EXACTLINE and GEXFI_SERIF are auxiliary and don't - * generate any actual lines/curves in the result - */ - for(d = GEXFI_CONVEX; d<= GEXFI_LINE; d++) { - if(f->len[d]) { - if(dx >= 0) { - fprintf(stderr, "**** Internal error in vectorization\n"); - fprintf(stderr, "CONFLICT in %s at %p between %s and %s\n", - g->name, ge, gxf_name[dx], gxf_name[d]); - dumppaths(g, cge->next, cge->next->bkwd); - gex_dump_contour(ge, clen); - exit(1); - } - dx = d; - } - if(f->lenback[d]) { - if(dy >= 0) { - fprintf(stderr, "**** Internal error in vectorization\n"); - fprintf(stderr, "CONFLICT in %s at %p between %s and %s\n", - g->name, ge, gxf_name[dy], gxf_name[d]); - dumppaths(g, cge->next, cge->next->bkwd); - gex_dump_contour(ge, clen); - exit(1); - } - dy = d; - } - } - f->ixstart = dx; - f->ixcont = dy; - ge = ge->frwd; - } while(ge != cge->next); - - /* - * make sure that the contour does not start in the - * middle of a fragment - */ - ge = cge->next; /* old start of the contour */ - f = X_FRAG(ge); - if(f->ixstart == GEXFI_NONE && f->ixcont != GEXFI_NONE) { - /* oops, it's mid-fragment, move the start */ - GENTRY *xge; - - xge = ge->bkwd->next; /* entry following the contour */ - - /* find the first gentry of this frag */ - pge = age[(f->aidx + clen - f->lenback[f->ixcont])%clen]; - - ge->prev = ge->bkwd; - ge->bkwd->next = ge; - - cge->next = pge; - pge->prev = cge; - - pge->bkwd->next = xge; - if(xge) - xge->prev = pge->bkwd; - - cge->ix3 = pge->bkwd->ix3; cge->iy3 = pge->bkwd->iy3; - } - - /* vectorize each fragment separately - * make 2 passes: first handle the straight lines, then - * the curves to allow the curver to be connected smoothly - * to the straights - */ - ge = cge->next; - do { /* pass 1 */ - f = X_FRAG(ge); - switch(f->ixstart) { - case GEXFI_LINE: - len = f->len[GEXFI_LINE]; - pge = age[(f->aidx + len - 1)%clen]; /* last gentry */ - - if(ge->iy3 == ge->bkwd->iy3) { /* frag starts and ends horizontally */ - k1 = 1/*Y*/ ; /* across the direction of start */ - k2 = 0/*X*/ ; /* along the direction of start */ - } else { /* frag starts and ends vertically */ - k1 = 0/*X*/ ; /* across the direction of start */ - k2 = 1/*Y*/ ; /* along the direction of start */ - } - - if(len % 2) { - /* odd number of entries in the frag */ - double halfstep, halfend; - - f->vect[0][k1] = fscale * ge->ipoints[k1][2]; - f->vect[3][k1] = fscale * pge->ipoints[k1][2]; - - halfstep = (pge->ipoints[k2][2] - ge->bkwd->ipoints[k2][2]) - * 0.5 / ((len+1)/2); - if(f->ixcont != GEXFI_NONE) { - halfend = (ge->ipoints[k2][2] - ge->bkwd->ipoints[k2][2]) * 0.5; - if(fabs(halfstep) < fabs(halfend)) /* must be at least half gentry away */ - halfstep = halfend; - } - if(X_FRAG(pge)->ixstart != GEXFI_NONE) { - halfend = (pge->ipoints[k2][2] - pge->bkwd->ipoints[k2][2]) * 0.5; - if(fabs(halfstep) < fabs(halfend)) /* must be at least half gentry away */ - halfstep = halfend; - } - f->vect[0][k2] = fscale * (ge->bkwd->ipoints[k2][2] + halfstep); - f->vect[3][k2] = fscale * (pge->ipoints[k2][2] - halfstep); - } else { - /* even number of entries */ - double halfstep, halfend; - - f->vect[0][k1] = fscale * ge->ipoints[k1][2]; - halfstep = (pge->ipoints[k2][2] - ge->bkwd->ipoints[k2][2]) - * 0.5 / (len/2); - if(f->ixcont != GEXFI_NONE) { - halfend = (ge->ipoints[k2][2] - ge->bkwd->ipoints[k2][2]) * 0.5; - if(fabs(halfstep) < fabs(halfend)) /* must be at least half gentry away */ - halfstep = halfend; - } - f->vect[0][k2] = fscale * (ge->bkwd->ipoints[k2][2] + halfstep); - - halfstep = (pge->ipoints[k1][2] - ge->bkwd->ipoints[k1][2]) - * 0.5 / (len/2); - if(X_FRAG(pge)->ixstart != GEXFI_NONE) { - halfend = (pge->ipoints[k1][2] - pge->bkwd->ipoints[k1][2]) * 0.5; - if(fabs(halfstep) < fabs(halfend)) /* must be at least half gentry away */ - halfstep = halfend; - } - f->vect[3][k1] = fscale * (pge->ipoints[k1][2] - halfstep); - f->vect[3][k2] = fscale * pge->ipoints[k2][2]; - } - f->vectlen = len; - f->flags |= GEXFF_DRAWLINE; - break; - } - } while((ge = ge->frwd) != cge->next); - - ge = cge->next; - do { /* pass 2 */ - /* data for curves */ - GENTRY *firstge, *lastge, *gef, *gel, *gei, *gex; - GENTRY *ordhd; /* head of the order list */ - GENTRY **ordlast; - int nsub; /* number of subfrags */ - GEX_FRAG *ff, *lf, *xf; - - f = X_FRAG(ge); - switch(f->ixstart) { - case GEXFI_CONVEX: - case GEXFI_CONCAVE: - len = f->len[f->ixstart]; - firstge = ge; - lastge = age[(f->aidx + len - 1)%clen]; /* last gentry */ - - nsub = 0; - gex = firstge; - xf = X_FRAG(gex); - xf->prevsub = 0; - xf->sublen = 1; - xf->flags &= ~GEXFF_DONE; - for(gei = firstge->frwd; gei != lastge; gei = gei->frwd) { - xf->sublen++; - if(X_FRAG(gei)->flags & GEXFF_EXTR) { - xf->nextsub = gei; - for(i=0; i<2; i++) - xf->bbox[i] = abs(gei->ipoints[i][2] - gex->bkwd->ipoints[i][2]); - nsub++; - xf = X_FRAG(gei); - xf->prevsub = gex; - xf->sublen = 1; - xf->flags &= ~GEXFF_DONE; - gex = gei; - } - } - xf->sublen++; - xf->nextsub = gei; - for(i=0; i<2; i++) - xf->bbox[i] = abs(gei->ipoints[i][2] - gex->bkwd->ipoints[i][2]); - nsub++; - ff = xf; /* remember the beginning of the last subfrag */ - xf = X_FRAG(gei); - xf->prevsub = gex; - if(firstge != lastge) { - xf->nextsub = 0; - xf->sublen = 0; - - /* correct the bounding box of the last and first subfrags for - * intersections with other fragments - */ - if(xf->ixstart != GEXFI_NONE) { - /* ff points to the beginning of the last subfrag */ - for(i=0; i<2; i++) - ff->bbox[i] -= 0.5 * abs(lastge->ipoints[i][2] - lastge->bkwd->ipoints[i][2]); - } - ff = X_FRAG(firstge); - if(ff->ixcont != GEXFI_NONE) { - for(i=0; i<2; i++) - ff->bbox[i] -= 0.5 * abs(firstge->ipoints[i][2] - firstge->bkwd->ipoints[i][2]); - } - } - - fprintf(stderr, " %s frag %p%s nsub=%d\n", gxf_name[f->ixstart], - ge, (f->flags&GEXFF_CIRC)?" circular":"", nsub); - - /* find the symmetry between the subfragments */ - for(gef = firstge, count=0; count < nsub; gef = ff->nextsub, count++) { - ff = X_FRAG(gef); - gex = ff->nextsub; - xf = X_FRAG(gex); - gel = xf->nextsub; - if(gel == 0) { - ff->flags &= ~GEXFF_SYMNEXT; - break; /* not a circular frag */ - } - good = 1; /* assume that we have symmetry */ - /* gei goes backwards, gex goes forwards from the extremum */ - gei = gex; - /* i is the symmetry axis, j is the other axis (X=0 Y=1) */ - ff->symaxis = i = (gex->ix3 != gex->bkwd->ix3); - j = !i; - for( ; gei!=gef && gex!=gel; gei=gei->bkwd, gex=gex->frwd) { - if( gei->bkwd->ipoints[i][2] != gex->ipoints[i][2] - || gei->bkwd->ipoints[j][2] - gei->ipoints[j][2] - != gex->bkwd->ipoints[j][2] - gex->ipoints[j][2] - ) { - good = 0; /* no symmetry */ - break; - } - } - if(good) { - if( isign(gei->bkwd->ipoints[j][2] - gei->ipoints[j][2]) - != isign(gex->bkwd->ipoints[j][2] - gex->ipoints[j][2]) ) { - good = 0; /* oops, goes into another direction */ - } - } - if(good) - ff->flags |= GEXFF_SYMNEXT; - else - ff->flags &= ~GEXFF_SYMNEXT; - } - - for(gef = firstge, count=0; count < nsub; gef = ff->nextsub, count++) { - ff = X_FRAG(gef); - if((ff->flags & GEXFF_SYMNEXT)==0) { - ff->symxlen = 0; - continue; - } - gex = ff->prevsub; - if(gex == 0 || (X_FRAG(gex)->flags & GEXFF_SYMNEXT)==0) { - ff->symxlen = 0; - continue; - } - ff->symxlen = X_FRAG(gex)->sublen; - xf = X_FRAG(ff->nextsub); - if(xf->sublen < ff->symxlen) - ff->symxlen = xf->sublen; - } - - /* find the symmetry inside the subfragments */ - for(gef = firstge, count=0; count < nsub; gef = ff->nextsub, count++) { - ff = X_FRAG(gef); - - if(ff->sublen % 2) { - /* we must have an even number of gentries for diagonal symmetry */ - ff->symge = 0; - continue; - } - - /* gei goes forwards from the front */ - gei = gef->frwd; - /* gex goes backwards from the back */ - gex = ff->nextsub->bkwd; - - /* i is the direction of gei, j is the direction of gex */ - i = (gei->iy3 != gei->bkwd->iy3); - j = !i; - for( ; gei->bkwd != gex; gei=gei->frwd, gex=gex->bkwd) { - if( abs(gei->bkwd->ipoints[i][2] - gei->ipoints[i][2]) - != abs(gex->bkwd->ipoints[j][2] - gex->ipoints[j][2]) ) - break; /* no symmetry */ - i = j; - j = !j; - } - if(gei->bkwd == gex) - ff->symge = gex; - else - ff->symge = 0; /* no symmetry */ - } - - /* find the order of calculation: - * prefer to start from long fragments that have the longest - * neighbours symmetric with them, with all being equal prefer - * the fragments that have smaller physical size - */ - ordhd = 0; - for(gef = firstge, count=0; count < nsub; gef = ff->nextsub, count++) { - ff = X_FRAG(gef); - - for(ordlast = &ordhd; *ordlast != 0; ordlast = &xf->ordersub) { - xf = X_FRAG(*ordlast); - if(ff->sublen > xf->sublen) - break; - if(ff->sublen < xf->sublen) - continue; - if(ff->symxlen > xf->symxlen) - break; - if(ff->symxlen < xf->symxlen) - continue; - if(ff->bbox[0] < xf->bbox[0] || ff->bbox[1] < xf->bbox[1]) - break; - } - - ff->ordersub = *ordlast; - *ordlast = gef; - } - - /* vectorize the subfragments */ - for(gef = ordhd; gef != 0; gef = ff->ordersub) { - - /* debugging stuff */ - ff = X_FRAG(gef); - fprintf(stderr, " %p-%p bbox[%g,%g] sym=%p %s len=%d xlen=%d\n", - gef, ff->nextsub, ff->bbox[0], ff->bbox[1], ff->symge, - (ff->flags & GEXFF_SYMNEXT) ? "symnext" : "", - ff->sublen, ff->symxlen); - - dosubfrag(g, f->ixstart, firstge, gef, fscale); - } - - break; - } - } while((ge = ge->frwd) != cge->next); - - free(age); - - } - - } - - /* all the fragments are found, extract the vectorization */ - pge = g->entries; - g->entries = g->lastentry = 0; - g->flags |= GF_FLOAT; - loopge = 0; - skip = 0; - - for(ge = pge; ge != 0; ge = ge->next) { - GEX_FRAG *f, *pf; - - switch(ge->type) { - case GE_LINE: - f = X_FRAG(ge); - if(skip == 0) { - if(f->flags & (GEXFF_DRAWLINE|GEXFF_DRAWCURVE)) { - /* draw a line to the start point */ - fg_rlineto(g, f->vect[0][0], f->vect[0][1]); - /* draw the fragment */ - if(f->flags & GEXFF_DRAWCURVE) - fg_rrcurveto(g, - f->vect[1][0], f->vect[1][1], - f->vect[2][0], f->vect[2][1], - f->vect[3][0], f->vect[3][1]); - else - fg_rlineto(g, f->vect[3][0], f->vect[3][1]); - skip = f->vectlen - 2; - } else { - fg_rlineto(g, fscale * ge->ix3, fscale * ge->iy3); - } - } else - skip--; - break; - case GE_MOVE: - fg_rmoveto(g, -1e6, -1e6); /* will be fixed by GE_PATH */ - skip = 0; - /* remember the reference to update it later */ - loopge = g->lastentry; - break; - case GE_PATH: - /* update the first MOVE of this contour */ - if(loopge) { - loopge->fx3 = g->lastentry->fx3; - loopge->fy3 = g->lastentry->fy3; - loopge = 0; - } - g_closepath(g); - break; - } - } - for(ge = pge; ge != 0; ge = cge) { - cge = ge->next; - free(ge->ext); - free(ge); - } - dumppaths(g, NULL, NULL); - - /* end of vectorization logic */ - } else { - /* convert the data to float */ - GENTRY *ge; - double x, y; - - for(ge = g->entries; ge != 0; ge = ge->next) { - ge->flags |= GEF_FLOAT; - if(ge->type != GE_MOVE && ge->type != GE_LINE) - continue; - - x = fscale * ge->ix3; - y = fscale * ge->iy3; - - ge->fx3 = x; - ge->fy3 = y; - } - g->flags |= GF_FLOAT; - } - - free(hlm); free(vlm); free(amp); -} - -#if 0 -/* print out the bitmap */ -printbmap(bmap, xsz, ysz, xoff, yoff) - char *bmap; - int xsz, ysz, xoff, yoff; -{ - int x, y; - - for(y=ysz-1; y>=0; y--) { - putchar( (y%10==0) ? y/10+'0' : ' ' ); - putchar( y%10+'0' ); - for(x=0; x<xsz; x++) - putchar( bmap[y*xsz+x] ? 'X' : '.' ); - if(-yoff==y) - putchar('_'); /* mark the baseline */ - putchar('\n'); - } - putchar(' '); putchar(' '); - for(x=0; x<xsz; x++) - putchar( x%10+'0' ); - putchar('\n'); putchar(' '); putchar(' '); - for(x=0; x<xsz; x++) - putchar( (x%10==0) ? x/10+'0' : ' ' ); - putchar('\n'); -} - -/* print out the limits of outlines */ -printlimits(hlm, vlm, amp, xsz, ysz) - char *hlm, *vlm, *amp; - int xsz, ysz; -{ - int x, y; - static char h_char[]={ ' ', '~', '^' }; - static char v_char[]={ ' ', '(', ')' }; - - for(y=ysz-1; y>=0; y--) { - for(x=0; x<xsz; x++) { - if(amp[y*xsz+x]) - putchar('!'); /* ambigouos point is always on a limit */ - else - putchar(v_char[ vlm[y*(xsz+1)+x] & (L_ON|L_OFF) ]); - putchar(h_char[ hlm[(y+1)*xsz+x] & (L_ON|L_OFF) ]); - } - putchar(v_char[ vlm[y*(xsz+1)+x] & (L_ON|L_OFF) ]); - putchar('\n'); - } - /* last line */ - for(x=0; x<xsz; x++) { - putchar(' '); - putchar(h_char[ hlm[x] & (L_ON|L_OFF) ]); - } - putchar(' '); - putchar('\n'); -} -#endif /* 0 */ diff --git a/nx-X11/extras/ttf2pt1/byteorder.h b/nx-X11/extras/ttf2pt1/byteorder.h deleted file mode 100644 index c139817e5..000000000 --- a/nx-X11/extras/ttf2pt1/byteorder.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * see COPYRIGHT - */ - -/* This defines the macroes ntohs and ntohl, which convert short and long - ints from network order (used on 68000 chips, and in TrueType font - files) to whatever order your computer uses. #define _BIG_ENDIAN or not - to control which set of definitions apply. If you don't know, try both. If - you have a peculiar machine you're on your own. -*/ - -#if defined(_BIG_ENDIAN) -#define ntohl(x) (x) -#define ntohs(x) (x) -#else -#define ntohs(x) \ - ((USHORT)((((USHORT)(x) & 0x00ff) << 8) | \ - (((USHORT)(x) & 0xff00) >> 8))) -#define ntohl(x) \ - ((ULONG)((((ULONG)(x) & 0x000000ffU) << 24) | \ - (((ULONG)(x) & 0x0000ff00U) << 8) | \ - (((ULONG)(x) & 0x00ff0000U) >> 8) | \ - (((ULONG)(x) & 0xff000000U) >> 24))) -#endif diff --git a/nx-X11/extras/ttf2pt1/cygbuild.sh b/nx-X11/extras/ttf2pt1/cygbuild.sh deleted file mode 100644 index df109f81e..000000000 --- a/nx-X11/extras/ttf2pt1/cygbuild.sh +++ /dev/null @@ -1,8 +0,0 @@ -: -# this file should be run from Cygnus BASH -# file to build ttf2pt1 with Cygnus GCC on Windows
-# don't forget to copy CYGWIN1.DLL into C:\WINDOWS
-
-gcc -o ttf2pt1 -DWINDOWS ttf2pt1.c pt1.c t1asm.c ttf.c -lm
-gcc -o t1asm -DWINDOWS -DSTANDALONE t1asm.c
-
diff --git a/nx-X11/extras/ttf2pt1/ft.c b/nx-X11/extras/ttf2pt1/ft.c deleted file mode 100644 index 60a429654..000000000 --- a/nx-X11/extras/ttf2pt1/ft.c +++ /dev/null @@ -1,808 +0,0 @@ -/* - * The font parser using the FreeType library version 2. - * - * see COPYRIGHT - * - */ - -#ifdef USE_FREETYPE - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <ctype.h> -#include <sys/types.h> - -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_TRUETYPE_TABLES_H -#include FT_BBOX_H -#include FT_GLYPH_H - -#include FT_CONFIG_CONFIG_H -#include FT_CONFIG_OPTIONS_H -#include FT_ERRORS_H -#include FT_SYSTEM_H -#include FT_IMAGE_H -#include FT_TYPES_H -#include FT_OUTLINE_H -#include FT_MODULE_H -#include FT_RENDER_H -#include FT_TYPE1_TABLES_H -#include FT_TRUETYPE_IDS_H -#include FT_TRUETYPE_TAGS_H -#include FT_MULTIPLE_MASTERS_H -#include FT_SFNT_NAMES_H - -#ifdef XP_PSTEXT -#include "os.h" -#include "Xproto.h" -#include "font.h" -#include "fontstruct.h" -#include "fntfilst.h" -#include "fontutil.h" -#include "fontenc.h" -#include "ft.h" -#define NOT_IN_FTFUNCS -#include "ftfuncs.h" -#endif /* XP_PSTEXT */ - -#include "pt1.h" -#include "global.h" - -/* prototypes of call entries */ -static void openfont(char *fname, char *arg); -static void closefont( void); -static int getnglyphs ( void); -static int glnames( GLYPH *glyph_list); -static void glmetrics( GLYPH *glyph_list); -static int glenc( GLYPH *glyph_list, int *encoding, int *unimap); -static void fnmetrics( struct font_metrics *fm); -static void glpath( int glyphno, GLYPH *glyph_list); -static void kerning( GLYPH *glyph_list); - -/* globals */ - -/* front-end descriptor */ -struct frontsw freetype_sw = { - /*name*/ "ft", - /*descr*/ "based on the FreeType2 library", - /*suffix*/ { "ttf", "ttc", "otf", "otc", "pfa", "pfb" }, - /*open*/ openfont, - /*close*/ closefont, - /*nglyphs*/ getnglyphs, - /*glnames*/ glnames, - /*glmetrics*/ glmetrics, - /*glenc*/ glenc, - /*fnmetrics*/ fnmetrics, - /*glpath*/ glpath, - /*kerning*/ kerning, -}; - -/* statics */ - -static char * dupcnstring( unsigned char *s, int len); - -#ifndef XP_PSTEXT -static FT_Library library; -#endif /* !XP_PSTEXT */ -static FT_Face face; - -static int enc_type, enc_found; - -/* SFNT functions do not seem to be included by default in FT2beta8 */ -#define ENABLE_SFNT - -/* - * Open font and prepare to return information to the main driver. - * May print error and warning messages. - * Exit on error. - */ - -static void -openfont( - char *fname, - char *arg /* unused now */ -) -{ - FT_Error error; - -#ifdef XP_PSTEXT - extern FT_Face xp_pstext_ft_face; - extern FT_Library ftypeLibrary; /* defined in xc/lib/font/FreeType/ftfuncs.c */ - - face = xp_pstext_ft_face; -#else - if( FT_Init_FreeType( &library ) ) { - fprintf(stderr, "** FreeType initialization failed\n"); - exit(1); - } - - if( error = FT_New_Face( library, fname, 0, &face ) ) { - if ( error == FT_Err_Unknown_File_Format ) - fprintf(stderr, "**** %s has format unknown to FreeType\n", fname); - else - fprintf(stderr, "**** Cannot access %s ****\n", fname); - exit(1); - } -#endif /* XP_PSTEXT */ - - if(FT_HAS_FIXED_SIZES(face)) { - WARNING_1 fprintf(stderr, "Font contains bitmaps\n"); - } - if(FT_HAS_MULTIPLE_MASTERS(face)) { - WARNING_1 fprintf(stderr, "Font contains multiple masters, using default\n"); - } - - if(ISDBG(FT)) fprintf(stderr," %d units per EM\n", face->units_per_EM); - - enc_found = 0; -} - -/* - * Close font. - * Exit on error. - */ - -static void -closefont( - void -) -{ -#ifdef XP_PSTEXT - /* NOP */ -#else - if( FT_Done_Face(face) ) { - WARNING_1 fprintf(stderr, "Errors when closing the font file, ignored\n"); - } - if( FT_Done_FreeType(library) ) { - WARNING_1 fprintf(stderr, "Errors when stopping FreeType, ignored\n"); - } -#endif /* XP_PSTEXT */ -} - -/* - * Get the number of glyphs in font. - */ - -static int -getnglyphs ( - void -) -{ - if(ISDBG(FT)) fprintf(stderr, "%d glyphs in font\n", face->num_glyphs); - return (int)face->num_glyphs; -} - -/* - * Get the names of the glyphs. - * Returns 0 if the names were assigned, non-zero if the font - * provides no glyph names. - */ - -static int -glnames( - GLYPH *glyph_list -) -{ -#define MAX_NAMELEN 1024 - -#ifdef XP_PSTEXT - char buf[1024]; - long i; - FT_Error error; - -#ifdef XP_ONLY_BLOCKS - extern unsigned long xp_font_block_offset; - extern FTFontPtr xp_xtf; - int bc; /* block counter */ - - - /* FixMe: This code should use PsOut_Get_FreeType_Glyph_Name() instead of - * duplicating the code - */ - for( bc = xp_font_block_offset ; bc < (xp_font_block_offset+256) ; bc++ ) { - /* Remap X11 font index to FreeType font index */ - i = FTRemap(face, &xp_xtf->mapping, bc); - - if( i >= face->num_glyphs ) - continue; -#else - for(i=0; i < face->num_glyphs; i++) { -#endif /* XP_ONLY_BLOCKS */ - if( FT_Has_PS_Glyph_Names(face) ) { - error = FT_Get_Glyph_Name(face, i, buf, MAX_NAMELEN); - } - else - { - error = -1; - } - - if( error ) { - /* Check for unicode mapping - * See Adobe document "Unicode and Glyph Names" - * (http://partners.adobe.com/asn/tech/type/unicodegn.jsp) - */ - if( (xp_xtf->mapping.mapping->type == FONT_ENCODING_UNICODE) && - (i < 0xFFFE) ) - { - sprintf(buf, "uni%04lx", i); - } - else - { - sprintf(buf, "ch%02lx", i); - } - } - glyph_list[i].name = strdup(buf); - if(ISDBG(FT)) fprintf(stderr, "%d has name %s\n", i, buf); - if (glyph_list[i].name == NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - } - - return 0; -#else - char bf[1024]; - long i; - - if( ! FT_HAS_GLYPH_NAMES(face) ) { - WARNING_1 fprintf(stderr, "Font has no glyph names\n"); - return 1; - } - - for(i=0; i < face->num_glyphs; i++) { - if( FT_Get_Glyph_Name(face, i, bf, MAX_NAMELEN) || bf[0]==0 ) { - sprintf(bf, "_g_%d", i); - WARNING_2 fprintf(stderr, - "Glyph No. %d has no postscript name, becomes %s\n", i, bf); - } - glyph_list[i].name = strdup(bf); - if(ISDBG(FT)) fprintf(stderr, "%d has name %s\n", i, bf); - if (glyph_list[i].name == NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - } - - return 0; -#endif /* XP_PSTEXT */ -} - -/* - * Get the metrics of the glyphs. - */ - -static void -glmetrics( - GLYPH *glyph_list -) -{ - GLYPH *g; - int i; - FT_Glyph_Metrics *met; - FT_BBox bbox; - FT_Glyph gly; - -#ifdef XP_ONLY_BLOCKS - extern unsigned long xp_font_block_offset; - extern FTFontPtr xp_xtf; - int bc; /* block counter */ - - for( bc = xp_font_block_offset ; bc < (xp_font_block_offset+256) ; bc++ ) { - /* Remap X11 font index to FreeType font index */ - i = FTRemap(face, &xp_xtf->mapping, bc); - - if( i >= face->num_glyphs ) - continue; - -#else - for(i=0; i < face->num_glyphs; i++) { -#endif /* XP_ONLY_BLOCKS */ - g = &(glyph_list[i]); - - if( FT_Load_Glyph(face, i, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE) ) { - fprintf(stderr, "Can't load glyph %s, skipped\n", g->name); - continue; - } - - met = &face->glyph->metrics; - - if(FT_HAS_HORIZONTAL(face)) { - g->width = met->horiAdvance; - g->lsb = met->horiBearingX; - } else { - WARNING_2 fprintf(stderr, "Glyph %s has no horizontal metrics, guessed them\n", g->name); - g->width = met->width; - g->lsb = 0; - } - - if( FT_Get_Glyph(face->glyph, &gly) ) { - fprintf(stderr, "Can't access glyph %s bbox, skipped\n", g->name); - continue; - } - - FT_Glyph_Get_CBox(gly, ft_glyph_bbox_unscaled, &bbox); - g->xMin = bbox.xMin; - g->yMin = bbox.yMin; - g->xMax = bbox.xMax; - g->yMax = bbox.yMax; - - g->ttf_pathlen = face->glyph->outline.n_points; - } -} - -/* - * Get the original encoding of the font. - * Returns 1 for if the original encoding is Unicode, 2 if the - * original encoding is other 16-bit, 0 if 8-bit. - */ - -static int -glenc( - GLYPH *glyph_list, - int *encoding, - int *unimap -) -{ -#ifdef XP_PSTEXT - int i, - e; - unsigned code; - extern FTFontPtr xp_xtf; - extern unsigned long xp_font_block_offset; - - enc_found = 1; - enc_type = 0; - - for(i=0; i<ENCTABSZ; i++) { - if(encoding[i] != -1) - continue; - - /* Remap X11 font index to FreeType font index */ - code = FTRemap(face, &xp_xtf->mapping, xp_font_block_offset+i); - - if(code == 0) - continue; /* .notdef */ - - encoding[i] = code; - } - - return enc_type; -#else - int i, e; - unsigned code; - - if(ISDBG(FT)) - for(e=0; e < face->num_charmaps; e++) { - fprintf(stderr, "found encoding pid=%d eid=%d\n", - face->charmaps[e]->platform_id, - face->charmaps[e]->encoding_id); - } - - if(enc_found) - goto populate_map; - - enc_type = 0; - - /* first check for an explicit PID/EID */ - - if(force_pid != -1) { - for(e=0; e < face->num_charmaps; e++) { - if(face->charmaps[e]->platform_id == force_pid - && face->charmaps[e]->encoding_id == force_eid) { - WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n", - force_pid, force_eid); - if( FT_Set_Charmap(face, face->charmaps[e]) ) { - fprintf(stderr, "**** Cannot set charmap in FreeType ****\n"); - exit(1); - } - enc_type = 1; - goto populate_map; - } - } - fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n", - force_pid, force_eid); - exit(1); - } - - /* next check for a direct Adobe mapping */ - - if(!forcemap) { - for(e=0; e < face->num_charmaps; e++) { - if(face->charmaps[e]->encoding == ft_encoding_adobe_custom) { - WARNING_1 fputs("Found Adobe Custom Encoding\n", stderr); - if( FT_Set_Charmap(face, face->charmaps[e]) ) { - fprintf(stderr, "**** Cannot set charmap in FreeType ****\n"); - exit(1); - } - goto populate_map; - } - } - } - - for(e=0; e < face->num_charmaps; e++) { - if(face->charmaps[e]->platform_id == 3) { - switch(face->charmaps[e]->encoding_id) { - case 0: - WARNING_1 fputs("Found Symbol Encoding\n", stderr); - break; - case 1: - WARNING_1 fputs("Found Unicode Encoding\n", stderr); - enc_type = 1; - break; - default: - WARNING_1 { - fprintf(stderr, - "****MS Encoding ID %d not supported****\n", - face->charmaps[e]->encoding_id); - fputs("Treating it like Symbol encoding\n", stderr); - } - break; - } - break; - } - } - if(e >= face->num_charmaps) { - WARNING_1 fputs("No Microsoft encoding, using first encoding available\n", stderr); - e = 0; - } - - if( FT_Set_Charmap(face, face->charmaps[e]) ) { - fprintf(stderr, "**** Cannot set charmap in FreeType ****\n"); - exit(1); - } - -populate_map: - enc_found = 1; - for(i=0; i<ENCTABSZ; i++) { - if(encoding[i] != -1) - continue; - if(enc_type == 1 || forcemap) { - code = unimap[i]; - if(code == (unsigned) -1) - continue; - } else - code = i; - - code = FT_Get_Char_Index(face, code); - if(0 && ISDBG(FT)) fprintf(stderr, "code of %3d is %3d\n", i, code); - if(code == 0) - continue; /* .notdef */ - encoding[i] = code; - } - - return enc_type; -#endif /* XP_PSTEXT */ -} - -/* duplicate a string with counter to a 0-terminated string */ -static char * -dupcnstring( - unsigned char *s, - int len -) -{ - char *res, *out; - int i, c; - static int warned=0; - - if(( res = malloc(len+1) )==NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - - out = res; - for(i=0; i<len; i++) { - if(( c=s[i] )>=' ' && c!=127) - *out++ = c; - else if(!warned) { - warned=1; - WARNING_1 fprintf(stderr, "Some font name strings are in Unicode, may not show properly\n"); - } - } - *out = 0; - return res; -} - -/* - * Get the font metrics - */ -static void -fnmetrics( - struct font_metrics *fm -) -{ - char *str; - static char *fieldstocheck[3]; -#ifdef ENABLE_SFNT - FT_SfntName sn; -#endif /* ENABLE_SFNT */ - int i; - - fm->italic_angle = 0.0; /* FreeType hides the angle */ - fm->underline_position = face->underline_position; - fm->underline_thickness = face->underline_thickness; - fm->is_fixed_pitch = FT_IS_FIXED_WIDTH(face); - - fm->ascender = face->ascender; - fm->descender = face->descender; - - fm->units_per_em = face->units_per_EM; - - fm->bbox[0] = face->bbox.xMin; - fm->bbox[1] = face->bbox.yMin; - fm->bbox[2] = face->bbox.xMax; - fm->bbox[3] = face->bbox.yMax; - -#ifdef ENABLE_SFNT - if( FT_Get_Sfnt_Name(face, TT_NAME_ID_COPYRIGHT, &sn) ) -#endif /* ENABLE_SFNT */ - fm->name_copyright = ""; -#ifdef ENABLE_SFNT - else - fm->name_copyright = dupcnstring(sn.string, sn.string_len); -#endif /* ENABLE_SFNT */ - - fm->name_family = face->family_name; - - fm->name_style = face->style_name; - if(fm->name_style == NULL) - fm->name_style = ""; - -#ifdef ENABLE_SFNT - if( FT_Get_Sfnt_Name(face, TT_NAME_ID_FULL_NAME, &sn) ) -#endif /* ENABLE_SFNT */ - { - int len; - - len = strlen(fm->name_family) + strlen(fm->name_style) + 2; - if(( fm->name_full = malloc(len) )==NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - strcpy(fm->name_full, fm->name_family); - if(strlen(fm->name_style) != 0) { - strcat(fm->name_full, " "); - strcat(fm->name_full, fm->name_style); - } - } -#ifdef ENABLE_SFNT - else - fm->name_full = dupcnstring(sn.string, sn.string_len); -#endif /* ENABLE_SFNT */ - -#ifdef ENABLE_SFNT - if( FT_Get_Sfnt_Name(face, TT_NAME_ID_VERSION_STRING, &sn) ) -#endif /* ENABLE_SFNT */ - fm->name_version = "1.0"; -#ifdef ENABLE_SFNT - else - fm->name_version = dupcnstring(sn.string, sn.string_len); -#endif /* ENABLE_SFNT */ - -#ifdef XP_PSTEXT - { - extern const char *xp_psfontname; - - fm->name_ps = strdup(xp_psfontname); - - /* Handle the rare case if a family name was not provided by the TTF - * font (like Solaris TTF fonts in /usr/openwin/lib/locale/ko.UTF-8/X11/fonts/TrueType, - * /usr/openwin/lib/locale/ko/X11/fonts/TrueType) - in this case we - * have to generate a family name somehow... */ - if(fm->name_family == NULL) - fm->name_family = fm->name_ps; - } -#else - -#ifdef ENABLE_SFNT - if( FT_Get_Sfnt_Name(face, TT_NAME_ID_PS_NAME , &sn) ) { -#endif /* ENABLE_SFNT */ - if(( fm->name_ps = strdup(fm->name_full) )==NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } -#ifdef ENABLE_SFNT - } else - fm->name_ps = dupcnstring(sn.string, sn.string_len); -#endif /* ENABLE_SFNT */ - -#endif /* XP_PSTEXT */ - - for(i=0; fm->name_ps[i]!=0; i++) - if(fm->name_ps[i] == ' ') - fm->name_ps[i] = '_'; /* no spaces in the Postscript name *m */ - - /* guess the boldness from the font names */ - fm->force_bold=0; - - fieldstocheck[0] = fm->name_style; - fieldstocheck[1] = fm->name_full; - fieldstocheck[2] = fm->name_ps; - - for(i=0; !fm->force_bold && i<sizeof fieldstocheck /sizeof(fieldstocheck[0]); i++) { - str=fieldstocheck[i]; - for(i=0; str[i]!=0; i++) { - if( (str[i]=='B' - || str[i]=='b' - && ( i==0 || !isalpha(str[i-1]) ) - ) - && !strncmp("old",&str[i+1],3) - && !islower(str[i+4]) - ) { - fm->force_bold=1; - break; - } - } - } -} - -/* - * Functions to decompose the outlines - */ - -static GLYPH *curg; -static double lastx, lasty; - -static int -outl_moveto( - FT_Vector *to, - void *unused -) -{ - double tox, toy; - - tox = fscale((double)to->x); toy = fscale((double)to->y); - - /* FreeType does not do explicit closepath() */ - if(curg->lastentry) { - g_closepath(curg); - } - fg_rmoveto(curg, tox, toy); - lastx = tox; lasty = toy; - - return 0; -} - -static int -outl_lineto( - FT_Vector *to, - void *unused -) -{ - double tox, toy; - - tox = fscale((double)to->x); toy = fscale((double)to->y); - - fg_rlineto(curg, tox, toy); - lastx = tox; lasty = toy; - - return 0; -} - -static int -outl_conicto( - FT_Vector *control1, - FT_Vector *to, - void *unused -) -{ - double c1x, c1y, tox, toy; - - c1x = fscale((double)control1->x); c1y = fscale((double)control1->y); - tox = fscale((double)to->x); toy = fscale((double)to->y); - - fg_rrcurveto(curg, - (lastx + 2.0 * c1x) / 3.0, (lasty + 2.0 * c1y) / 3.0, - (2.0 * c1x + tox) / 3.0, (2.0 * c1y + toy) / 3.0, - tox, toy ); - lastx = tox; lasty = toy; - - return 0; -} - -static int -outl_cubicto( - FT_Vector *control1, - FT_Vector *control2, - FT_Vector *to, - void *unused -) -{ - double c1x, c1y, c2x, c2y, tox, toy; - - c1x = fscale((double)control1->x); c1y = fscale((double)control1->y); - c2x = fscale((double)control2->x); c2y = fscale((double)control2->y); - tox = fscale((double)to->x); toy = fscale((double)to->y); - - fg_rrcurveto(curg, c1x, c1y, c2x, c2y, tox, toy); - lastx = tox; lasty = toy; - - return 0; -} - -static FT_Outline_Funcs ft_outl_funcs = { - outl_moveto, - outl_lineto, - outl_conicto, - outl_cubicto, - 0, - 0 -}; - -/* - * Get the path of contrours for a glyph. - */ - -static void -glpath( - int glyphno, - GLYPH *glyf_list -) -{ - FT_Outline *ol; - - curg = &glyf_list[glyphno]; - - if( FT_Load_Glyph(face, glyphno, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE|FT_LOAD_NO_HINTING) - || face->glyph->format != ft_glyph_format_outline ) { - fprintf(stderr, "Can't load glyph %s, skipped\n", curg->name); - return; - } - - ol = &face->glyph->outline; - lastx = 0.0; lasty = 0.0; - - if( FT_Outline_Decompose(ol, &ft_outl_funcs, NULL) ) { - fprintf(stderr, "Can't decompose outline of glyph %s, skipped\n", curg->name); - return; - } - - /* FreeType does not do explicit closepath() */ - if(curg->lastentry) { - g_closepath(curg); - } - - if(ol->flags & ft_outline_reverse_fill) { - assertpath(curg->entries, __FILE__, __LINE__, curg->name); - reversepaths(curg); - } -} - -/* - * Get the kerning data. - */ - -static void -kerning( - GLYPH *glyph_list -) -{ - int i, j, n; - int nglyphs = face->num_glyphs; - FT_Vector k; - GLYPH *gl; - - if( nglyphs == 0 || !FT_HAS_KERNING(face) ) { - WARNING_1 fputs("No Kerning data\n", stderr); - return; - } - - for(i=0; i<nglyphs; i++) { - if( (glyph_list[i].flags & GF_USED) ==0) - continue; - for(j=0; j<nglyphs; j++) { - if( (glyph_list[j].flags & GF_USED) ==0) - continue; - if( FT_Get_Kerning(face, i, j, ft_kerning_unscaled, &k) ) - continue; - if( k.x == 0 ) - continue; - - addkernpair(i, j, k.x); - } - } -} - -#endif diff --git a/nx-X11/extras/ttf2pt1/global.h b/nx-X11/extras/ttf2pt1/global.h deleted file mode 100644 index 4d53878f7..000000000 --- a/nx-X11/extras/ttf2pt1/global.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * see COPYRIGHT - */ - - -/* options */ - -extern int encode; /* encode the resulting file */ -extern int pfbflag; /* produce compressed file */ -extern int wantafm; /* want to see .afm instead of .t1a on stdout */ -extern int correctvsize; /* try to correct the vertical size of characters */ -extern int wantuid; /* user wants UniqueID entry in the font */ -extern int allglyphs; /* convert all glyphs, not only 256 of them */ -extern int warnlevel; /* the level of permitted warnings */ -extern int forcemap; /* do mapping even on non-Unicode fonts */ -/* options - maximal limits */ -extern int max_stemdepth; /* maximal depth of stem stack in interpreter */ -/* options - debugging */ -extern int absolute; /* print out in absolute values */ -extern int reverse; /* reverse font to Type1 path directions */ -/* options - suboptions of Outline Processing */ -extern int optimize; /* enables space optimization */ -extern int smooth; /* enable smoothing of outlines */ -extern int transform; /* enables transformation to 1000x1000 matrix */ -extern int hints; /* enables autogeneration of hints */ -extern int subhints; /* enables autogeneration of substituted hints */ -extern int trybold; /* try to guess whether the font is bold */ -extern int correctwidth; /* try to correct the character width */ -extern int vectorize; /* vectorize the bitmaps */ -extern int use_autotrace; /* use the autotrace library on bitmap */ -/* options - suboptions of File Generation */ -extern int gen_pfa; /* generate the font file */ -extern int gen_afm; /* generate the metrics file */ -extern int gen_dvienc; /* generate the dvips encoding file */ - -/* not quite options to select a particular source encoding */ -extern int force_pid; /* specific platform id */ -extern int force_eid; /* specific encoding id */ - -/* other globals */ -extern FILE *null_file, *pfa_file, *afm_file, *dvienc_file; -extern int numglyphs; - -/* warnings */ - -#define WARNING_1 if(warnlevel >= 1) -#define WARNING_2 if(warnlevel >= 2) -#define WARNING_3 if(warnlevel >= 3) -#define WARNING_4 if(warnlevel >= 4) - -/* - * Bitmap control macros - */ - -#define BITMAP_BYTES(size) (((size)+7)>>3) -#define DEF_BITMAP(name, size) unsigned char name[BITMAP_BYTES(size)] -#define SET_BITMAP(name, bit) ( name[(bit)>>3] |= (1<<((bit)&7)) ) -#define CLR_BITMAP(name, bit) ( name[(bit)>>3] &= ~(1<<((bit)&7)) ) -#define IS_BITMAP(name, bit) ( name[(bit)>>3] & (1<<((bit)&7)) ) - -/* debugging */ - -/* debug flags */ -#define DEBUG_UNICODE 0x00000001 /* unicode to 8-bit code conversion */ -#define DEBUG_MAINSTEMS 0x00000002 /* glyph-wide main stem generation */ -#define DEBUG_SUBSTEMS 0x00000004 /* substituted stem generation */ -#define DEBUG_STEMS (DEBUG_MAINSTEMS|DEBUG_SUBSTEMS) -#define DEBUG_REVERSAL 0x00000008 /* reversal of the paths */ -#define DEBUG_FIXCVDIR 0x00000010 /* fixcvdir() */ -#define DEBUG_STEMOVERLAP 0x00000020 /* stemoverlap() */ -#define DEBUG_BLUESTEMS 0x00000040 /* markbluestems() */ -#define DEBUG_STRAIGHTEN 0x00000080 /* markbluestems() */ -#define DEBUG_EXTMAP 0x00000100 /* parsing of external map */ -#define DEBUG_TOINT 0x00000200 /* conversion of path to integer */ -#define DEBUG_BUILDG 0x00000400 /* building of glyph path */ -#define DEBUG_QUAD 0x00000800 /* splitting curves by quadrants */ -#define DEBUG_SQEQ 0x00001000 /* square equation solver */ -#define DEBUG_COMPOSITE 0x00002000 /* handling of composite glyphs */ -#define DEBUG_FCONCISE 0x00004000 /* normalization of curves */ -#define DEBUG_FT 0x00008000 /* FreeType front-end */ -#define DEBUG_BITMAP 0x00010000 /* conversion from bitmap */ -#define DEBUG_DISABLED 0x80000000 /* special flag: temporary disable debugging */ - -#if 0 -/* at what we want to look now */ -#ifndef DEBUG -# define DEBUG (DEBUG_BITMAP) -#endif - -/* uncomment the next line if debugging data is wanted for one glyph only */ -#define DBG_GLYPH "C118" /* */ -#endif - -#if 1 -# define ISDBG(name) (0) -# define ENABLEDBG(condition) (0) -# define DISABLEDBG(condition) (0) -#else - extern int debug; /* collection of the flags */ -/* this ISDBG will only work on ANSI C, not K&R */ -# define ISDBG(name) ( (debug & DEBUG_DISABLED) ? 0 : (debug & (DEBUG_##name)) ) -# define ENABLEDBG(condition) ( (condition) ? (debug&=~DEBUG_DISABLED) : 0 ) -# define DISABLEDBG(condition) ( (condition) ? (debug|=DEBUG_DISABLED) : 0 ) -#endif - -#ifdef DBG_GLYPH -# define DBG_TO_GLYPH(g) DISABLEDBG( strcmp( (g)->name, DBG_GLYPH ) ) -# define DBG_FROM_GLYPH(g) ENABLEDBG(1) -#else -# define DBG_TO_GLYPH(g) (0) -# define DBG_FROM_GLYPH(g) (0) -#endif - -/* prototypes */ -int iscale( int val); -double fscale( double val); -int unicode_rev_lookup( int unival); -void bmp_outline( GLYPH *g, int scale, char *bmap, - int xsz, int ysz, int xoff, int yoff); -int isign( int x); -int fsign( double x); - -/* global metrics for a font */ - -struct font_metrics { - /* post */ - double italic_angle; - short underline_position; - short underline_thickness; - short is_fixed_pitch; - - /* hhea */ - short ascender; - short descender; - - /* head */ - unsigned short units_per_em; - short bbox[4]; - - /* name */ - char *name_copyright; - char *name_family; - char *name_style; - char *name_full; - char *name_version; - char *name_ps; - - /* other */ - int force_bold; -}; - -/* size of the encoding table - glyphs beyond 255 are actually unnumbered */ - -#define ENCTABSZ 1024 - -/* switch table structure for front-ends */ - -#define MAXSUFFIX 10 - -struct frontsw { - char *name; /* name of the front end */ - char *descr; /* description of the front end */ - char *suffix[MAXSUFFIX]; /* possible file name suffixes */ - - void (*open)(char *fname, char *arg); /* open font file */ - void (*close)(void); /* close font file */ - int (*nglyphs)(void); /* get the number of glyphs */ - int (*glnames)(GLYPH *glyphs); /* get the names of glyphs */ - void (*glmetrics)(GLYPH *glyphs); /* get the metrics of glyphs */ - int (*glenc)(GLYPH *glyphs, int *enc, int *unimap); /* get the encoding */ - void (*fnmetrics)(struct font_metrics *fm); /* get the font metrics */ - void (*glpath)(int glyphno, GLYPH *glyphs); /* get the glyph path */ - void (*kerning)(GLYPH *glyph_list); /* extract the kerning data */ -}; diff --git a/nx-X11/extras/ttf2pt1/pt1.c b/nx-X11/extras/ttf2pt1/pt1.c deleted file mode 100644 index b1c46d57a..000000000 --- a/nx-X11/extras/ttf2pt1/pt1.c +++ /dev/null @@ -1,7374 +0,0 @@ -/* - * see COPYRIGHT - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <time.h> -#include <ctype.h> -#include <math.h> - -#ifndef WINDOWS -# include <netinet/in.h> -# include <unistd.h> -#else -# include "windows.h" -#endif - -#include "ttf.h" -#include "pt1.h" -#include "global.h" - -/* big and small values for comparisons */ -#define FBIGVAL (1e20) -#define FEPS (100000./FBIGVAL) - -/* names of the axes */ -#define X 0 -#define Y 1 - -/* the GENTRY extension structure used in fforceconcise() */ - -struct gex_con { - double d[2 /*X, Y*/]; /* sizes of curve */ - double sin2; /* squared sinus of the angle to the next gentry */ - double len2; /* squared distance between the endpoints */ - -/* number of reference dots taken from each curve */ -#define NREFDOTS 3 - - double dots[NREFDOTS][2]; /* reference dots */ - - int flags; /* flags for gentry and tits joint to the next gentry */ -/* a vertical or horizontal line may be in 2 quadrants at once */ -#define GEXF_QUL 0x00000001 /* in up-left quadrant */ -#define GEXF_QUR 0x00000002 /* in up-right quadrant */ -#define GEXF_QDR 0x00000004 /* in down-right quadrant */ -#define GEXF_QDL 0x00000008 /* in down-left quadrant */ -#define GEXF_QMASK 0x0000000F /* quadrant mask */ - -/* if a line is nearly vertical or horizontal, we remember that idealized quartant too */ -#define GEXF_QTO_IDEAL(f) (((f)&0xF)<<4) -#define GEXF_QFROM_IDEAL(f) (((f)&0xF0)>>4) -#define GEXF_IDQ_L 0x00000090 /* left */ -#define GEXF_IDQ_R 0x00000060 /* right */ -#define GEXF_IDQ_U 0x00000030 /* up */ -#define GEXF_IDQ_D 0x000000C0 /* down */ - -/* possibly can be joined with conditions: - * (in order of increasing preference, the numeric order is important) - */ -#define GEXF_JLINE 0x00000100 /* into one line */ -#define GEXF_JIGN 0x00000200 /* if one entry's tangent angle is ignored */ -#define GEXF_JID 0x00000400 /* if one entry is idealized to hor/vert */ -#define GEXF_JFLAT 0x00000800 /* if one entry is flattened */ -#define GEXF_JGOOD 0x00001000 /* perfectly, no additional maodifications */ - -#define GEXF_JMASK 0x00001F00 /* the mask of all above */ -#define GEXF_JCVMASK 0x00001E00 /* the mask of all above except JLINE */ - -/* which entry needs to be modified for conditional joining */ -#define GEXF_JIGN1 0x00002000 -#define GEXF_JIGN2 0x00004000 -#define GEXF_JIGNDIR(dir) (GEXF_JIGN1<<(dir)) -#define GEXF_JID1 0x00008000 -#define GEXF_JID2 0x00010000 -#define GEXF_JIDDIR(dir) (GEXF_JID1<<(dir)) -#define GEXF_JFLAT1 0x00020000 -#define GEXF_JFLAT2 0x00040000 -#define GEXF_JFLATDIR(dir) (GEXF_JFLAT1<<(dir)) - -#define GEXF_VERT 0x00100000 /* is nearly vertical */ -#define GEXF_HOR 0x00200000 /* is nearly horizontal */ -#define GEXF_FLAT 0x00400000 /* is nearly flat */ - -#define GEXF_VDOTS 0x01000000 /* the dots are valid */ - - signed char isd[2 /*X,Y*/]; /* signs of the sizes */ -}; -typedef struct gex_con GEX_CON; - -/* convenience macros */ -#define X_CON(ge) ((GEX_CON *)((ge)->ext)) -#define X_CON_D(ge) (X_CON(ge)->d) -#define X_CON_DX(ge) (X_CON(ge)->d[0]) -#define X_CON_DY(ge) (X_CON(ge)->d[1]) -#define X_CON_ISD(ge) (X_CON(ge)->isd) -#define X_CON_ISDX(ge) (X_CON(ge)->isd[0]) -#define X_CON_ISDY(ge) (X_CON(ge)->isd[1]) -#define X_CON_SIN2(ge) (X_CON(ge)->sin2) -#define X_CON_LEN2(ge) (X_CON(ge)->len2) -#define X_CON_F(ge) (X_CON(ge)->flags) - -/* performance statistics about guessing the concise curves */ -static int ggoodcv=0, ggoodcvdots=0, gbadcv=0, gbadcvdots=0; - -int stdhw, stdvw; /* dominant stems widths */ -int stemsnaph[12], stemsnapv[12]; /* most typical stem width */ - -int bluevalues[14]; -int nblues; -int otherblues[10]; -int notherb; -int bbox[4]; /* the FontBBox array */ -double italic_angle; - -GLYPH *glyph_list; -int encoding[ENCTABSZ]; /* inverse of glyph[].char_no */ -int kerning_pairs = 0; - -/* prototypes */ -static void fixcvdir( GENTRY * ge, int dir); -static void fixcvends( GENTRY * ge); -static int fgetcvdir( GENTRY * ge); -static int igetcvdir( GENTRY * ge); -static int fiszigzag( GENTRY *ge); -static int iiszigzag( GENTRY *ge); -static GENTRY * freethisge( GENTRY *ge); -static void addgeafter( GENTRY *oge, GENTRY *nge ); -static GENTRY * newgentry( int flags); -static void debugstems( char *name, STEM * hstems, int nhs, STEM * vstems, int nvs); -static int addbluestems( STEM *s, int n); -static void sortstems( STEM * s, int n); -static int stemoverlap( STEM * s1, STEM * s2); -static int steminblue( STEM *s); -static void markbluestems( STEM *s, int nold); -static int joinmainstems( STEM * s, int nold, int useblues); -static void joinsubstems( STEM * s, short *pairs, int nold, int useblues); -static void fixendpath( GENTRY *ge); -static void fdelsmall( GLYPH *g, double minlen); -static void alloc_gex_con( GENTRY *ge); -static double fjointsin2( GENTRY *ge1, GENTRY *ge2); -#if 0 -static double fcvarea( GENTRY *ge); -#endif -static double fcvval( GENTRY *ge, int axis, double t); -static void fsampledots( GENTRY *ge, double dots[][2], int ndots); -static void fnormalizege( GENTRY *ge); -static void fanalyzege( GENTRY *ge); -static void fanalyzejoint( GENTRY *ge); -static void fconcisecontour( GLYPH *g, GENTRY *ge); -static double fclosegap( GENTRY *from, GENTRY *to, int axis, - double gap, double *ret); - -int -isign( - int x -) -{ - if (x > 0) - return 1; - else if (x < 0) - return -1; - else - return 0; -} - -int -fsign( - double x -) -{ - if (x > 0.0) - return 1; - else if (x < 0.0) - return -1; - else - return 0; -} - -static GENTRY * -newgentry( - int flags -) -{ - GENTRY *ge; - - ge = calloc(1, sizeof(GENTRY)); - - if (ge == 0) { - fprintf(stderr, "***** Memory allocation error *****\n"); - exit(255); - } - ge->stemid = -1; - ge->flags = flags; - /* the rest is set to 0 by calloc() */ - return ge; -} - -/* - * Routines to print out Postscript functions with optimization - */ - -void -rmoveto( - int dx, - int dy -) -{ - if (optimize && dx == 0) - fprintf(pfa_file, "%d vmoveto\n", dy); - else if (optimize && dy == 0) - fprintf(pfa_file, "%d hmoveto\n", dx); - else - fprintf(pfa_file, "%d %d rmoveto\n", dx, dy); -} - -void -rlineto( - int dx, - int dy -) -{ - if (optimize && dx == 0 && dy == 0) /* for special pathologic - * case */ - return; - else if (optimize && dx == 0) - fprintf(pfa_file, "%d vlineto\n", dy); - else if (optimize && dy == 0) - fprintf(pfa_file, "%d hlineto\n", dx); - else - fprintf(pfa_file, "%d %d rlineto\n", dx, dy); -} - -void -rrcurveto( - int dx1, - int dy1, - int dx2, - int dy2, - int dx3, - int dy3 -) -{ - /* first two ifs are for crazy cases that occur surprisingly often */ - if (optimize && dx1 == 0 && dx2 == 0 && dx3 == 0) - rlineto(0, dy1 + dy2 + dy3); - else if (optimize && dy1 == 0 && dy2 == 0 && dy3 == 0) - rlineto(dx1 + dx2 + dx3, 0); - else if (optimize && dy1 == 0 && dx3 == 0) - fprintf(pfa_file, "%d %d %d %d hvcurveto\n", - dx1, dx2, dy2, dy3); - else if (optimize && dx1 == 0 && dy3 == 0) - fprintf(pfa_file, "%d %d %d %d vhcurveto\n", - dy1, dx2, dy2, dx3); - else - fprintf(pfa_file, "%d %d %d %d %d %d rrcurveto\n", - dx1, dy1, dx2, dy2, dx3, dy3); -} - -void -closepath(void) -{ - fprintf(pfa_file, "closepath\n"); -} - -/* - * Many of the path processing routines exist (or will exist) in - * both floating-point and integer version. Fimally most of the - * processing will go in floating point and the integer processing - * will become legacy. - * The names of floating routines start with f, names of integer - * routines start with i, and those old routines existing in one - * version only have no such prefix at all. - */ - -/* -** Routine that checks integrity of the path, for debugging -*/ - -void -assertpath( - GENTRY * from, - char *file, - int line, - char *name -) -{ - GENTRY *first, *pe, *ge; - int isfloat; - - if(from==0) - return; - isfloat = (from->flags & GEF_FLOAT); - pe = from->prev; - for (ge = from; ge != 0; pe = ge, ge = ge->next) { - if( (ge->flags & GEF_FLOAT) ^ isfloat ) { - fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name); - fprintf(stderr, "float flag changes from %s to %s at 0x%p (type %c, prev type %c)\n", - (isfloat ? "TRUE" : "FALSE"), (isfloat ? "FALSE" : "TRUE"), ge, ge->type, pe->type); - abort(); - } - if (pe != ge->prev) { - fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name); - fprintf(stderr, "unidirectional chain 0x%x -next-> 0x%x -prev-> 0x%x \n", - pe, ge, ge->prev); - abort(); - } - - switch(ge->type) { - case GE_MOVE: - break; - case GE_PATH: - if (ge->prev == 0) { - fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name); - fprintf(stderr, "empty path at 0x%x \n", ge); - abort(); - } - break; - case GE_LINE: - case GE_CURVE: - if(ge->frwd->bkwd != ge) { - fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name); - fprintf(stderr, "unidirectional chain 0x%x -frwd-> 0x%x -bkwd-> 0x%x \n", - ge, ge->frwd, ge->frwd->bkwd); - abort(); - } - if(ge->prev->type == GE_MOVE) { - first = ge; - if(ge->bkwd->next->type != GE_PATH) { - fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name); - fprintf(stderr, "broken first backlink 0x%x -bkwd-> 0x%x -next-> 0x%x \n", - ge, ge->bkwd, ge->bkwd->next); - abort(); - } - } - if(ge->next->type == GE_PATH) { - if(ge->frwd != first) { - fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name); - fprintf(stderr, "broken loop 0x%x -...-> 0x%x -frwd-> 0x%x \n", - first, ge, ge->frwd); - abort(); - } - } - break; - } - - } -} - -void -assertisfloat( - GLYPH *g, - char *msg -) -{ - if( !(g->flags & GF_FLOAT) ) { - fprintf(stderr, "**! Glyph %s is not float: %s\n", g->name, msg); - abort(); - } - if(g->lastentry) { - if( !(g->lastentry->flags & GEF_FLOAT) ) { - fprintf(stderr, "**! Glyphs %s last entry is int: %s\n", g->name, msg); - abort(); - } - } -} - -void -assertisint( - GLYPH *g, - char *msg -) -{ - if( (g->flags & GF_FLOAT) ) { - fprintf(stderr, "**! Glyph %s is not int: %s\n", g->name, msg); - abort(); - } - if(g->lastentry) { - if( (g->lastentry->flags & GEF_FLOAT) ) { - fprintf(stderr, "**! Glyphs %s last entry is float: %s\n", g->name, msg); - abort(); - } - } -} - - -/* - * Routines to save the generated data about glyph - */ - -void -fg_rmoveto( - GLYPH * g, - double x, - double y) -{ - GENTRY *oge; - - if (ISDBG(BUILDG)) - fprintf(stderr, "%s: f rmoveto(%g, %g)\n", g->name, x, y); - - assertisfloat(g, "adding float MOVE"); - - if ((oge = g->lastentry) != 0) { - if (oge->type == GE_MOVE) { /* just eat up the first move */ - oge->fx3 = x; - oge->fy3 = y; - } else if (oge->type == GE_LINE || oge->type == GE_CURVE) { - fprintf(stderr, "Glyph %s: MOVE in middle of path\n", g->name); - } else { - GENTRY *nge; - - nge = newgentry(GEF_FLOAT); - nge->type = GE_MOVE; - nge->fx3 = x; - nge->fy3 = y; - - oge->next = nge; - nge->prev = oge; - g->lastentry = nge; - } - } else { - GENTRY *nge; - - nge = newgentry(GEF_FLOAT); - nge->type = GE_MOVE; - nge->fx3 = x; - nge->fy3 = y; - nge->bkwd = (GENTRY*)&g->entries; - g->entries = g->lastentry = nge; - } - - if (0 && ISDBG(BUILDG)) - dumppaths(g, NULL, NULL); -} - -void -ig_rmoveto( - GLYPH * g, - int x, - int y) -{ - GENTRY *oge; - - if (ISDBG(BUILDG)) - fprintf(stderr, "%s: i rmoveto(%d, %d)\n", g->name, x, y); - - assertisint(g, "adding int MOVE"); - - if ((oge = g->lastentry) != 0) { - if (oge->type == GE_MOVE) { /* just eat up the first move */ - oge->ix3 = x; - oge->iy3 = y; - } else if (oge->type == GE_LINE || oge->type == GE_CURVE) { - fprintf(stderr, "Glyph %s: MOVE in middle of path, ignored\n", g->name); - } else { - GENTRY *nge; - - nge = newgentry(0); - nge->type = GE_MOVE; - nge->ix3 = x; - nge->iy3 = y; - - oge->next = nge; - nge->prev = oge; - g->lastentry = nge; - } - } else { - GENTRY *nge; - - nge = newgentry(0); - nge->type = GE_MOVE; - nge->ix3 = x; - nge->iy3 = y; - nge->bkwd = (GENTRY*)&g->entries; - g->entries = g->lastentry = nge; - } - -} - -void -fg_rlineto( - GLYPH * g, - double x, - double y) -{ - GENTRY *oge, *nge; - - if (ISDBG(BUILDG)) - fprintf(stderr, "%s: f rlineto(%g, %g)\n", g->name, x, y); - - assertisfloat(g, "adding float LINE"); - - nge = newgentry(GEF_FLOAT); - nge->type = GE_LINE; - nge->fx3 = x; - nge->fy3 = y; - - if ((oge = g->lastentry) != 0) { - if (x == oge->fx3 && y == oge->fy3) { /* empty line */ - /* ignore it or we will get in troubles later */ - free(nge); - return; - } - if (g->path == 0) { - g->path = nge; - nge->bkwd = nge->frwd = nge; - } else { - oge->frwd = nge; - nge->bkwd = oge; - g->path->bkwd = nge; - nge->frwd = g->path; - } - - oge->next = nge; - nge->prev = oge; - g->lastentry = nge; - } else { - WARNING_1 fprintf(stderr, "Glyph %s: LINE outside of path\n", g->name); - free(nge); - } - - if (0 && ISDBG(BUILDG)) - dumppaths(g, NULL, NULL); -} - -void -ig_rlineto( - GLYPH * g, - int x, - int y) -{ - GENTRY *oge, *nge; - - if (ISDBG(BUILDG)) - fprintf(stderr, "%s: i rlineto(%d, %d)\n", g->name, x, y); - - assertisint(g, "adding int LINE"); - - nge = newgentry(0); - nge->type = GE_LINE; - nge->ix3 = x; - nge->iy3 = y; - - if ((oge = g->lastentry) != 0) { - if (x == oge->ix3 && y == oge->iy3) { /* empty line */ - /* ignore it or we will get in troubles later */ - free(nge); - return; - } - if (g->path == 0) { - g->path = nge; - nge->bkwd = nge->frwd = nge; - } else { - oge->frwd = nge; - nge->bkwd = oge; - g->path->bkwd = nge; - nge->frwd = g->path; - } - - oge->next = nge; - nge->prev = oge; - g->lastentry = nge; - } else { - WARNING_1 fprintf(stderr, "Glyph %s: LINE outside of path\n", g->name); - free(nge); - } - -} - -void -fg_rrcurveto( - GLYPH * g, - double x1, - double y1, - double x2, - double y2, - double x3, - double y3) -{ - GENTRY *oge, *nge; - - oge = g->lastentry; - - if (ISDBG(BUILDG)) - fprintf(stderr, "%s: f rrcurveto(%g, %g, %g, %g, %g, %g)\n" - ,g->name, x1, y1, x2, y2, x3, y3); - - assertisfloat(g, "adding float CURVE"); - - if (oge && oge->fx3 == x1 && x1 == x2 && x2 == x3) /* check if it's - * actually a line */ - fg_rlineto(g, x1, y3); - else if (oge && oge->fy3 == y1 && y1 == y2 && y2 == y3) - fg_rlineto(g, x3, y1); - else { - nge = newgentry(GEF_FLOAT); - nge->type = GE_CURVE; - nge->fx1 = x1; - nge->fy1 = y1; - nge->fx2 = x2; - nge->fy2 = y2; - nge->fx3 = x3; - nge->fy3 = y3; - - if (oge != 0) { - if (x3 == oge->fx3 && y3 == oge->fy3) { - free(nge); /* consider this curve empty */ - /* ignore it or we will get in troubles later */ - return; - } - if (g->path == 0) { - g->path = nge; - nge->bkwd = nge->frwd = nge; - } else { - oge->frwd = nge; - nge->bkwd = oge; - g->path->bkwd = nge; - nge->frwd = g->path; - } - - oge->next = nge; - nge->prev = oge; - g->lastentry = nge; - } else { - WARNING_1 fprintf(stderr, "Glyph %s: CURVE outside of path\n", g->name); - free(nge); - } - } - - if (0 && ISDBG(BUILDG)) - dumppaths(g, NULL, NULL); -} - -void -ig_rrcurveto( - GLYPH * g, - int x1, - int y1, - int x2, - int y2, - int x3, - int y3) -{ - GENTRY *oge, *nge; - - oge = g->lastentry; - - if (ISDBG(BUILDG)) - fprintf(stderr, "%s: i rrcurveto(%d, %d, %d, %d, %d, %d)\n" - ,g->name, x1, y1, x2, y2, x3, y3); - - assertisint(g, "adding int CURVE"); - - if (oge && oge->ix3 == x1 && x1 == x2 && x2 == x3) /* check if it's - * actually a line */ - ig_rlineto(g, x1, y3); - else if (oge && oge->iy3 == y1 && y1 == y2 && y2 == y3) - ig_rlineto(g, x3, y1); - else { - nge = newgentry(0); - nge->type = GE_CURVE; - nge->ix1 = x1; - nge->iy1 = y1; - nge->ix2 = x2; - nge->iy2 = y2; - nge->ix3 = x3; - nge->iy3 = y3; - - if (oge != 0) { - if (x3 == oge->ix3 && y3 == oge->iy3) { - free(nge); /* consider this curve empty */ - /* ignore it or we will get in troubles later */ - return; - } - if (g->path == 0) { - g->path = nge; - nge->bkwd = nge->frwd = nge; - } else { - oge->frwd = nge; - nge->bkwd = oge; - g->path->bkwd = nge; - nge->frwd = g->path; - } - - oge->next = nge; - nge->prev = oge; - g->lastentry = nge; - } else { - WARNING_1 fprintf(stderr, "Glyph %s: CURVE outside of path\n", g->name); - free(nge); - } - } -} - -void -g_closepath( - GLYPH * g -) -{ - GENTRY *oge, *nge; - - if (ISDBG(BUILDG)) - fprintf(stderr, "%s: closepath\n", g->name); - - oge = g->lastentry; - - if (g->path == 0) { - WARNING_1 fprintf(stderr, "Warning: **** closepath on empty path in glyph \"%s\" ****\n", - g->name); - if (oge == 0) { - WARNING_1 fprintf(stderr, "No previois entry\n"); - } else { - WARNING_1 fprintf(stderr, "Previous entry type: %c\n", oge->type); - if (oge->type == GE_MOVE) { - g->lastentry = oge->prev; - if (oge->prev == 0) - g->entries = 0; - else - g->lastentry->next = 0; - free(oge); - } - } - return; - } - - nge = newgentry(oge->flags & GEF_FLOAT); /* keep the same type */ - nge->type = GE_PATH; - - g->path = 0; - - oge->next = nge; - nge->prev = oge; - g->lastentry = nge; - - if (0 && ISDBG(BUILDG)) - dumppaths(g, NULL, NULL); -} - -/* - * * SB * Routines to smooth and fix the glyphs - */ - -/* -** we don't want to see the curves with coinciding middle and -** outer points -*/ - -static void -fixcvends( - GENTRY * ge -) -{ - int dx, dy; - int x0, y0, x1, y1, x2, y2, x3, y3; - - if (ge->type != GE_CURVE) - return; - - if(ge->flags & GEF_FLOAT) { - fprintf(stderr, "**! fixcvends(0x%x) on floating entry, ABORT\n", ge); - abort(); /* dump core */ - } - - x0 = ge->prev->ix3; - y0 = ge->prev->iy3; - x1 = ge->ix1; - y1 = ge->iy1; - x2 = ge->ix2; - y2 = ge->iy2; - x3 = ge->ix3; - y3 = ge->iy3; - - - /* look at the start of the curve */ - if (x1 == x0 && y1 == y0) { - dx = x2 - x1; - dy = y2 - y1; - - if ((dx == 0 && dy == 0) - || (x2 == x3 && y2 == y3)) { - /* Oops, we actually have a straight line */ - /* - * if it's small, we hope that it will get optimized - * later - */ - if (abs(x3 - x0) <= 2 || abs(y3 - y0) <= 2) { - ge->ix1 = x3; - ge->iy1 = y3; - ge->ix2 = x0; - ge->iy2 = y0; - } else {/* just make it a line */ - ge->type = GE_LINE; - } - } else { - if (abs(dx) < 4 && abs(dy) < 4) { /* consider it very - * small */ - ge->ix1 = x2; - ge->iy1 = y2; - } else if (abs(dx) < 8 && abs(dy) < 8) { /* consider it small */ - ge->ix1 += dx / 2; - ge->iy1 += dy / 2; - } else { - ge->ix1 += dx / 4; - ge->iy1 += dy / 4; - } - /* make sure that it's still on the same side */ - if (abs(x3 - x0) * abs(dy) < abs(y3 - y0) * abs(dx)) { - if (abs(x3 - x0) * abs(ge->iy1 - y0) > abs(y3 - y0) * abs(ge->ix1 - x0)) - ge->ix1 += isign(dx); - } else { - if (abs(x3 - x0) * abs(ge->iy1 - y0) < abs(y3 - y0) * abs(ge->ix1 - x0)) - ge->iy1 += isign(dy); - } - - ge->ix2 += (x3 - x2) / 8; - ge->iy2 += (y3 - y2) / 8; - /* make sure that it's still on the same side */ - if (abs(x3 - x0) * abs(y3 - y2) < abs(y3 - y0) * abs(x3 - x2)) { - if (abs(x3 - x0) * abs(y3 - ge->iy2) > abs(y3 - y0) * abs(x3 - ge->ix2)) - ge->iy1 -= isign(y3 - y2); - } else { - if (abs(x3 - x0) * abs(y3 - ge->iy2) < abs(y3 - y0) * abs(x3 - ge->ix2)) - ge->ix1 -= isign(x3 - x2); - } - - } - } else if (x2 == x3 && y2 == y3) { - dx = x1 - x2; - dy = y1 - y2; - - if (dx == 0 && dy == 0) { - /* Oops, we actually have a straight line */ - /* - * if it's small, we hope that it will get optimized - * later - */ - if (abs(x3 - x0) <= 2 || abs(y3 - y0) <= 2) { - ge->ix1 = x3; - ge->iy1 = y3; - ge->ix2 = x0; - ge->iy2 = y0; - } else {/* just make it a line */ - ge->type = GE_LINE; - } - } else { - if (abs(dx) < 4 && abs(dy) < 4) { /* consider it very - * small */ - ge->ix2 = x1; - ge->iy2 = y1; - } else if (abs(dx) < 8 && abs(dy) < 8) { /* consider it small */ - ge->ix2 += dx / 2; - ge->iy2 += dy / 2; - } else { - ge->ix2 += dx / 4; - ge->iy2 += dy / 4; - } - /* make sure that it's still on the same side */ - if (abs(x3 - x0) * abs(dy) < abs(y3 - y0) * abs(dx)) { - if (abs(x3 - x0) * abs(ge->iy2 - y3) > abs(y3 - y0) * abs(ge->ix2 - x3)) - ge->ix2 += isign(dx); - } else { - if (abs(x3 - x0) * abs(ge->iy2 - y3) < abs(y3 - y0) * abs(ge->ix2 - x3)) - ge->iy2 += isign(dy); - } - - ge->ix1 += (x0 - x1) / 8; - ge->iy1 += (y0 - y1) / 8; - /* make sure that it's still on the same side */ - if (abs(x3 - x0) * abs(y0 - y1) < abs(y3 - y0) * abs(x0 - x1)) { - if (abs(x3 - x0) * abs(y0 - ge->iy1) > abs(y3 - y0) * abs(x0 - ge->ix1)) - ge->iy1 -= isign(y0 - y1); - } else { - if (abs(x3 - x0) * abs(y0 - ge->iy1) < abs(y3 - y0) * abs(x0 - ge->ix1)) - ge->ix1 -= isign(x0 - x1); - } - - } - } -} - -/* -** After transformations we want to make sure that the resulting -** curve is going in the same quadrant as the original one, -** because rounding errors introduced during transformations -** may make the result completeley wrong. -** -** `dir' argument describes the direction of the original curve, -** it is the superposition of two values for the front and -** rear ends of curve: -** -** >EQUAL - goes over the line connecting the ends -** =EQUAL - coincides with the line connecting the ends -** <EQUAL - goes under the line connecting the ends -** -** See CVDIR_* for exact definitions. -*/ - -static void -fixcvdir( - GENTRY * ge, - int dir -) -{ - int a, b, c, d; - double kk, kk1, kk2; - int changed; - int fdir, rdir; - - if(ge->flags & GEF_FLOAT) { - fprintf(stderr, "**! fixcvdir(0x%x) on floating entry, ABORT\n", ge); - abort(); /* dump core */ - } - - fdir = (dir & CVDIR_FRONT) - CVDIR_FEQUAL; - if ((dir & CVDIR_REAR) == CVDIR_RSAME) - rdir = fdir; /* we need only isign, exact value doesn't matter */ - else - rdir = (dir & CVDIR_REAR) - CVDIR_REQUAL; - - fixcvends(ge); - - c = isign(ge->ix3 - ge->prev->ix3); /* note the direction of - * curve */ - d = isign(ge->iy3 - ge->prev->iy3); - - a = ge->iy3 - ge->prev->iy3; - b = ge->ix3 - ge->prev->ix3; - kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - a = ge->iy1 - ge->prev->iy3; - b = ge->ix1 - ge->prev->ix3; - kk1 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - a = ge->iy3 - ge->iy2; - b = ge->ix3 - ge->ix2; - kk2 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - - changed = 1; - while (changed) { - if (ISDBG(FIXCVDIR)) { - /* for debugging */ - fprintf(stderr, "fixcvdir %d %d (%d %d %d %d %d %d) %f %f %f\n", - fdir, rdir, - ge->ix1 - ge->prev->ix3, - ge->iy1 - ge->prev->iy3, - ge->ix2 - ge->ix1, - ge->iy2 - ge->iy1, - ge->ix3 - ge->ix2, - ge->iy3 - ge->iy2, - kk1, kk, kk2); - } - changed = 0; - - if (fdir > 0) { - if (kk1 > kk) { /* the front end has problems */ - if (c * (ge->ix1 - ge->prev->ix3) > 0) { - ge->ix1 -= c; - changed = 1; - } if (d * (ge->iy2 - ge->iy1) > 0) { - ge->iy1 += d; - changed = 1; - } - /* recalculate the coefficients */ - a = ge->iy3 - ge->prev->iy3; - b = ge->ix3 - ge->prev->ix3; - kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - a = ge->iy1 - ge->prev->iy3; - b = ge->ix1 - ge->prev->ix3; - kk1 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - } - } else if (fdir < 0) { - if (kk1 < kk) { /* the front end has problems */ - if (c * (ge->ix2 - ge->ix1) > 0) { - ge->ix1 += c; - changed = 1; - } if (d * (ge->iy1 - ge->prev->iy3) > 0) { - ge->iy1 -= d; - changed = 1; - } - /* recalculate the coefficients */ - a = ge->iy1 - ge->prev->iy3; - b = ge->ix1 - ge->prev->ix3; - kk1 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - a = ge->iy3 - ge->prev->iy3; - b = ge->ix3 - ge->prev->ix3; - kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - } - } - if (rdir > 0) { - if (kk2 < kk) { /* the rear end has problems */ - if (c * (ge->ix2 - ge->ix1) > 0) { - ge->ix2 -= c; - changed = 1; - } if (d * (ge->iy3 - ge->iy2) > 0) { - ge->iy2 += d; - changed = 1; - } - /* recalculate the coefficients */ - a = ge->iy3 - ge->prev->iy3; - b = ge->ix3 - ge->prev->ix3; - kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - a = ge->iy3 - ge->iy2; - b = ge->ix3 - ge->ix2; - kk2 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - } - } else if (rdir < 0) { - if (kk2 > kk) { /* the rear end has problems */ - if (c * (ge->ix3 - ge->ix2) > 0) { - ge->ix2 += c; - changed = 1; - } if (d * (ge->iy2 - ge->iy1) > 0) { - ge->iy2 -= d; - changed = 1; - } - /* recalculate the coefficients */ - a = ge->iy3 - ge->prev->iy3; - b = ge->ix3 - ge->prev->ix3; - kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - a = ge->iy3 - ge->iy2; - b = ge->ix3 - ge->ix2; - kk2 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - } - } - } - fixcvends(ge); -} - -/* Get the directions of ends of curve for further usage */ - -/* expects that the previous element is also float */ - -static int -fgetcvdir( - GENTRY * ge -) -{ - double a, b; - double k, k1, k2; - int dir = 0; - - if( !(ge->flags & GEF_FLOAT) ) { - fprintf(stderr, "**! fgetcvdir(0x%x) on int entry, ABORT\n", ge); - abort(); /* dump core */ - } - - a = fabs(ge->fy3 - ge->prev->fy3); - b = fabs(ge->fx3 - ge->prev->fx3); - k = a < FEPS ? (b < FEPS ? 1. : 100000.) : ( b / a); - - a = fabs(ge->fy1 - ge->prev->fy3); - b = fabs(ge->fx1 - ge->prev->fx3); - if(a < FEPS) { - if(b < FEPS) { - a = fabs(ge->fy2 - ge->prev->fy3); - b = fabs(ge->fx2 - ge->prev->fx3); - k1 = a < FEPS ? (b < FEPS ? k : 100000.) : ( b / a); - } else - k1 = FBIGVAL; - } else - k1 = b / a; - - a = fabs(ge->fy3 - ge->fy2); - b = fabs(ge->fx3 - ge->fx2); - if(a < FEPS) { - if(b < FEPS) { - a = fabs(ge->fy3 - ge->fy1); - b = fabs(ge->fx3 - ge->fx1); - k2 = a < FEPS ? (b < FEPS ? k : 100000.) : ( b / a); - } else - k2 = FBIGVAL; - } else - k2 = b / a; - - if(fabs(k1-k) < 0.0001) - dir |= CVDIR_FEQUAL; - else if (k1 < k) - dir |= CVDIR_FUP; - else - dir |= CVDIR_FDOWN; - - if(fabs(k2-k) < 0.0001) - dir |= CVDIR_REQUAL; - else if (k2 > k) - dir |= CVDIR_RUP; - else - dir |= CVDIR_RDOWN; - - return dir; -} - - -/* expects that the previous element is also int */ - -static int -igetcvdir( - GENTRY * ge -) -{ - int a, b; - double k, k1, k2; - int dir = 0; - - if(ge->flags & GEF_FLOAT) { - fprintf(stderr, "**! igetcvdir(0x%x) on floating entry, ABORT\n", ge); - abort(); /* dump core */ - } - - a = ge->iy3 - ge->prev->iy3; - b = ge->ix3 - ge->prev->ix3; - k = (a == 0) ? (b == 0 ? 1. : 100000.) : fabs((double) b / (double) a); - - a = ge->iy1 - ge->prev->iy3; - b = ge->ix1 - ge->prev->ix3; - if(a == 0) { - if(b == 0) { - a = ge->iy2 - ge->prev->iy3; - b = ge->ix2 - ge->prev->ix3; - k1 = (a == 0) ? (b == 0 ? k : 100000.) : fabs((double) b / (double) a); - } else - k1 = FBIGVAL; - } else - k1 = fabs((double) b / (double) a); - - a = ge->iy3 - ge->iy2; - b = ge->ix3 - ge->ix2; - if(a == 0) { - if(b == 0) { - a = ge->iy3 - ge->iy1; - b = ge->ix3 - ge->ix1; - k2 = (a == 0) ? (b == 0 ? k : 100000.) : fabs((double) b / (double) a); - } else - k2 = FBIGVAL; - } else - k2 = fabs((double) b / (double) a); - - if(fabs(k1-k) < 0.0001) - dir |= CVDIR_FEQUAL; - else if (k1 < k) - dir |= CVDIR_FUP; - else - dir |= CVDIR_FDOWN; - - if(fabs(k2-k) < 0.0001) - dir |= CVDIR_REQUAL; - else if (k2 > k) - dir |= CVDIR_RUP; - else - dir |= CVDIR_RDOWN; - - return dir; -} - -#if 0 -/* a function just to test the work of fixcvdir() */ -static void -testfixcvdir( - GLYPH * g -) -{ - GENTRY *ge; - int dir; - - for (ge = g->entries; ge != 0; ge = ge->next) { - if (ge->type == GE_CURVE) { - dir = igetcvdir(ge); - fixcvdir(ge, dir); - } - } -} -#endif - -static int -iround( - double val -) -{ - return (int) (val > 0 ? val + 0.5 : val - 0.5); -} - -/* for debugging - dump the glyph - * mark with a star the entries from start to end inclusive - * (start == NULL means don't mark any, end == NULL means to the last) - */ - -void -dumppaths( - GLYPH *g, - GENTRY *start, - GENTRY *end -) -{ - GENTRY *ge; - int i; - char mark=' '; - - fprintf(stderr, "Glyph %s:\n", g->name); - - /* now do the conversion */ - for(ge = g->entries; ge != 0; ge = ge->next) { - if(ge == start) - mark = '*'; - fprintf(stderr, " %c %8x", mark, ge); - switch(ge->type) { - case GE_MOVE: - case GE_LINE: - if(ge->flags & GEF_FLOAT) - fprintf(stderr," %c float (%g, %g)\n", ge->type, ge->fx3, ge->fy3); - else - fprintf(stderr," %c int (%d, %d)\n", ge->type, ge->ix3, ge->iy3); - break; - case GE_CURVE: - if(ge->flags & GEF_FLOAT) { - fprintf(stderr," C float "); - for(i=0; i<3; i++) - fprintf(stderr,"(%g, %g) ", ge->fxn[i], ge->fyn[i]); - fprintf(stderr,"\n"); - } else { - fprintf(stderr," C int "); - for(i=0; i<3; i++) - fprintf(stderr,"(%d, %d) ", ge->ixn[i], ge->iyn[i]); - fprintf(stderr,"\n"); - } - break; - default: - fprintf(stderr, " %c\n", ge->type); - break; - } - if(ge == end) - mark = ' '; - } -} - -/* - * Routine that converts all entries in the path from float to int - */ - -void -pathtoint( - GLYPH *g -) -{ - GENTRY *ge; - int x[3], y[3]; - int i; - - - if(ISDBG(TOINT)) - fprintf(stderr, "TOINT: glyph %s\n", g->name); - assertisfloat(g, "converting path to int\n"); - - fdelsmall(g, 1.0); /* get rid of sub-pixel contours */ - assertpath(g->entries, __FILE__, __LINE__, g->name); - - /* 1st pass, collect the directions of the curves: have - * to do that in advance, while everyting is float - */ - for(ge = g->entries; ge != 0; ge = ge->next) { - if( !(ge->flags & GEF_FLOAT) ) { - fprintf(stderr, "**! glyphs %s has int entry, found in conversion to int\n", - g->name); - exit(1); - } - if(ge->type == GE_CURVE) { - ge->dir = fgetcvdir(ge); - } - } - - /* now do the conversion */ - for(ge = g->entries; ge != 0; ge = ge->next) { - switch(ge->type) { - case GE_MOVE: - case GE_LINE: - if(ISDBG(TOINT)) - fprintf(stderr," %c float x=%g y=%g\n", ge->type, ge->fx3, ge->fy3); - x[0] = iround(ge->fx3); - y[0] = iround(ge->fy3); - for(i=0; i<3; i++) { /* put some valid values everywhere, for convenience */ - ge->ixn[i] = x[0]; - ge->iyn[i] = y[0]; - } - if(ISDBG(TOINT)) - fprintf(stderr," int x=%d y=%d\n", ge->ix3, ge->iy3); - break; - case GE_CURVE: - if(ISDBG(TOINT)) - fprintf(stderr," %c float ", ge->type); - - for(i=0; i<3; i++) { - if(ISDBG(TOINT)) - fprintf(stderr,"(%g, %g) ", ge->fxn[i], ge->fyn[i]); - x[i] = iround(ge->fxn[i]); - y[i] = iround(ge->fyn[i]); - } - - if(ISDBG(TOINT)) - fprintf(stderr,"\n int "); - - for(i=0; i<3; i++) { - ge->ixn[i] = x[i]; - ge->iyn[i] = y[i]; - if(ISDBG(TOINT)) - fprintf(stderr,"(%d, %d) ", ge->ixn[i], ge->iyn[i]); - } - ge->flags &= ~GEF_FLOAT; /* for fixcvdir */ - fixcvdir(ge, ge->dir); - - if(ISDBG(TOINT)) { - fprintf(stderr,"\n fixed "); - for(i=0; i<3; i++) - fprintf(stderr,"(%d, %d) ", ge->ixn[i], ge->iyn[i]); - fprintf(stderr,"\n"); - } - - break; - } - ge->flags &= ~GEF_FLOAT; - } - g->flags &= ~GF_FLOAT; -} - - -/* check whether we can fix up the curve to change its size by (dx,dy) */ -/* 0 means NO, 1 means YES */ - -/* for float: if scaling would be under 10% */ - -int -fcheckcv( - GENTRY * ge, - double dx, - double dy -) -{ - if( !(ge->flags & GEF_FLOAT) ) { - fprintf(stderr, "**! fcheckcv(0x%x) on int entry, ABORT\n", ge); - abort(); /* dump core */ - } - - if (ge->type != GE_CURVE) - return 0; - - if( fabs(ge->fx3 - ge->prev->fx3) < fabs(dx) * 10 ) - return 0; - - if( fabs(ge->fy3 - ge->prev->fy3) < fabs(dy) * 10 ) - return 0; - - return 1; -} - -/* for int: if won't create new zigzags at the ends */ - -int -icheckcv( - GENTRY * ge, - int dx, - int dy -) -{ - int xdep, ydep; - - if(ge->flags & GEF_FLOAT) { - fprintf(stderr, "**! icheckcv(0x%x) on floating entry, ABORT\n", ge); - abort(); /* dump core */ - } - - if (ge->type != GE_CURVE) - return 0; - - xdep = ge->ix3 - ge->prev->ix3; - ydep = ge->iy3 - ge->prev->iy3; - - if (ge->type == GE_CURVE - && (xdep * (xdep + dx)) > 0 - && (ydep * (ydep + dy)) > 0) { - return 1; - } else - return 0; -} - -/* float connect the ends of open contours */ - -void -fclosepaths( - GLYPH * g -) -{ - GENTRY *ge, *fge, *xge, *nge; - int i; - - assertisfloat(g, "fclosepaths float\n"); - - for (xge = g->entries; xge != 0; xge = xge->next) { - if( xge->type != GE_PATH ) - continue; - - ge = xge->prev; - if(ge == 0 || (ge->type != GE_LINE && ge->type!= GE_CURVE)) { - fprintf(stderr, "**! Glyph %s got empty path\n", - g->name); - exit(1); - } - - fge = ge->frwd; - if (fge->prev == 0 || fge->prev->type != GE_MOVE) { - fprintf(stderr, "**! Glyph %s got strange beginning of path\n", - g->name); - exit(1); - } - fge = fge->prev; - if (fge->fx3 != ge->fx3 || fge->fy3 != ge->fy3) { - /* we have to fix this open path */ - - WARNING_4 fprintf(stderr, "Glyph %s got path open by dx=%g dy=%g\n", - g->name, fge->fx3 - ge->fx3, fge->fy3 - ge->fy3); - - - /* add a new line */ - nge = newgentry(GEF_FLOAT); - (*nge) = (*ge); - nge->fx3 = fge->fx3; - nge->fy3 = fge->fy3; - nge->type = GE_LINE; - - addgeafter(ge, nge); - - if (fabs(ge->fx3 - fge->fx3) <= 2 && fabs(ge->fy3 - fge->fy3) <= 2) { - /* - * small change, try to get rid of the new entry - */ - - double df[2]; - - for(i=0; i<2; i++) { - df[i] = ge->fpoints[i][2] - fge->fpoints[i][2]; - df[i] = fclosegap(nge, nge, i, df[i], NULL); - } - - if(df[0] == 0. && df[1] == 0.) { - /* closed gap successfully, remove the added entry */ - freethisge(nge); - } - } - } - } -} - -void -smoothjoints( - GLYPH * g -) -{ - GENTRY *ge, *ne; - int dx1, dy1, dx2, dy2, k; - int dir; - - return; /* this stuff seems to create problems */ - - assertisint(g, "smoothjoints int"); - - if (g->entries == 0) /* nothing to do */ - return; - - for (ge = g->entries->next; ge != 0; ge = ge->next) { - ne = ge->frwd; - - /* - * although there should be no one-line path * and any path - * must end with CLOSEPATH, * nobody can say for sure - */ - - if (ge == ne || ne == 0) - continue; - - /* now handle various joints */ - - if (ge->type == GE_LINE && ne->type == GE_LINE) { - dx1 = ge->ix3 - ge->prev->ix3; - dy1 = ge->iy3 - ge->prev->iy3; - dx2 = ne->ix3 - ge->ix3; - dy2 = ne->iy3 - ge->iy3; - - /* check whether they have the same direction */ - /* and the same slope */ - /* then we can join them into one line */ - - if (dx1 * dx2 >= 0 && dy1 * dy2 >= 0 && dx1 * dy2 == dy1 * dx2) { - /* extend the previous line */ - ge->ix3 = ne->ix3; - ge->iy3 = ne->iy3; - - /* and get rid of the next line */ - freethisge(ne); - } - } else if (ge->type == GE_LINE && ne->type == GE_CURVE) { - fixcvends(ne); - - dx1 = ge->ix3 - ge->prev->ix3; - dy1 = ge->iy3 - ge->prev->iy3; - dx2 = ne->ix1 - ge->ix3; - dy2 = ne->iy1 - ge->iy3; - - /* if the line is nearly horizontal and we can fix it */ - if (dx1 != 0 && 5 * abs(dy1) / abs(dx1) == 0 - && icheckcv(ne, 0, -dy1) - && abs(dy1) <= 4) { - dir = igetcvdir(ne); - ge->iy3 -= dy1; - ne->iy1 -= dy1; - fixcvdir(ne, dir); - if (ge->next != ne) - ne->prev->iy3 -= dy1; - dy1 = 0; - } else if (dy1 != 0 && 5 * abs(dx1) / abs(dy1) == 0 - && icheckcv(ne, -dx1, 0) - && abs(dx1) <= 4) { - /* the same but vertical */ - dir = igetcvdir(ne); - ge->ix3 -= dx1; - ne->ix1 -= dx1; - fixcvdir(ne, dir); - if (ge->next != ne) - ne->prev->ix3 -= dx1; - dx1 = 0; - } - /* - * if line is horizontal and curve begins nearly - * horizontally - */ - if (dy1 == 0 && dx2 != 0 && 5 * abs(dy2) / abs(dx2) == 0) { - dir = igetcvdir(ne); - ne->iy1 -= dy2; - fixcvdir(ne, dir); - dy2 = 0; - } else if (dx1 == 0 && dy2 != 0 && 5 * abs(dx2) / abs(dy2) == 0) { - /* the same but vertical */ - dir = igetcvdir(ne); - ne->ix1 -= dx2; - fixcvdir(ne, dir); - dx2 = 0; - } - } else if (ge->type == GE_CURVE && ne->type == GE_LINE) { - fixcvends(ge); - - dx1 = ge->ix3 - ge->ix2; - dy1 = ge->iy3 - ge->iy2; - dx2 = ne->ix3 - ge->ix3; - dy2 = ne->iy3 - ge->iy3; - - /* if the line is nearly horizontal and we can fix it */ - if (dx2 != 0 && 5 * abs(dy2) / abs(dx2) == 0 - && icheckcv(ge, 0, dy2) - && abs(dy2) <= 4) { - dir = igetcvdir(ge); - ge->iy3 += dy2; - ge->iy2 += dy2; - fixcvdir(ge, dir); - if (ge->next != ne) - ne->prev->iy3 += dy2; - dy2 = 0; - } else if (dy2 != 0 && 5 * abs(dx2) / abs(dy2) == 0 - && icheckcv(ge, dx2, 0) - && abs(dx2) <= 4) { - /* the same but vertical */ - dir = igetcvdir(ge); - ge->ix3 += dx2; - ge->ix2 += dx2; - fixcvdir(ge, dir); - if (ge->next != ne) - ne->prev->ix3 += dx2; - dx2 = 0; - } - /* - * if line is horizontal and curve ends nearly - * horizontally - */ - if (dy2 == 0 && dx1 != 0 && 5 * abs(dy1) / abs(dx1) == 0) { - dir = igetcvdir(ge); - ge->iy2 += dy1; - fixcvdir(ge, dir); - dy1 = 0; - } else if (dx2 == 0 && dy1 != 0 && 5 * abs(dx1) / abs(dy1) == 0) { - /* the same but vertical */ - dir = igetcvdir(ge); - ge->ix2 += dx1; - fixcvdir(ge, dir); - dx1 = 0; - } - } else if (ge->type == GE_CURVE && ne->type == GE_CURVE) { - fixcvends(ge); - fixcvends(ne); - - dx1 = ge->ix3 - ge->ix2; - dy1 = ge->iy3 - ge->iy2; - dx2 = ne->ix1 - ge->ix3; - dy2 = ne->iy1 - ge->iy3; - - /* - * check if we have a rather smooth joint at extremal - * point - */ - /* left or right extremal point */ - if (abs(dx1) <= 4 && abs(dx2) <= 4 - && dy1 != 0 && 5 * abs(dx1) / abs(dy1) == 0 - && dy2 != 0 && 5 * abs(dx2) / abs(dy2) == 0 - && ((ge->iy3 < ge->prev->iy3 && ne->iy3 < ge->iy3) - || (ge->iy3 > ge->prev->iy3 && ne->iy3 > ge->iy3)) - && (ge->ix3 - ge->prev->ix3) * (ne->ix3 - ge->ix3) < 0 - ) { - dir = igetcvdir(ge); - ge->ix2 += dx1; - dx1 = 0; - fixcvdir(ge, dir); - dir = igetcvdir(ne); - ne->ix1 -= dx2; - dx2 = 0; - fixcvdir(ne, dir); - } - /* top or down extremal point */ - else if (abs(dy1) <= 4 && abs(dy2) <= 4 - && dx1 != 0 && 5 * abs(dy1) / abs(dx1) == 0 - && dx2 != 0 && 5 * abs(dy2) / abs(dx2) == 0 - && ((ge->ix3 < ge->prev->ix3 && ne->ix3 < ge->ix3) - || (ge->ix3 > ge->prev->ix3 && ne->ix3 > ge->ix3)) - && (ge->iy3 - ge->prev->iy3) * (ne->iy3 - ge->iy3) < 0 - ) { - dir = igetcvdir(ge); - ge->iy2 += dy1; - dy1 = 0; - fixcvdir(ge, dir); - dir = igetcvdir(ne); - ne->iy1 -= dy2; - dy2 = 0; - fixcvdir(ne, dir); - } - /* or may be we just have a smooth junction */ - else if (dx1 * dx2 >= 0 && dy1 * dy2 >= 0 - && 10 * abs(k = abs(dx1 * dy2) - abs(dy1 * dx2)) < (abs(dx1 * dy2) + abs(dy1 * dx2))) { - int tries[6][4]; - int results[6]; - int i, b; - - /* build array of changes we are going to try */ - /* uninitalized entries are 0 */ - if (k > 0) { - static int t1[6][4] = { - {0, 0, 0, 0}, - {-1, 0, 1, 0}, - {-1, 0, 0, 1}, - {0, -1, 1, 0}, - {0, -1, 0, 1}, - {-1, -1, 1, 1}}; - memcpy(tries, t1, sizeof tries); - } else { - static int t1[6][4] = { - {0, 0, 0, 0}, - {1, 0, -1, 0}, - {1, 0, 0, -1}, - {0, 1, -1, 0}, - {0, 1, 0, -1}, - {1, 1, -1, -1}}; - memcpy(tries, t1, sizeof tries); - } - - /* now try the changes */ - results[0] = abs(k); - for (i = 1; i < 6; i++) { - results[i] = abs((abs(dx1) + tries[i][0]) * (abs(dy2) + tries[i][1]) - - (abs(dy1) + tries[i][2]) * (abs(dx2) + tries[i][3])); - } - - /* and find the best try */ - k = abs(k); - b = 0; - for (i = 1; i < 6; i++) - if (results[i] < k) { - k = results[i]; - b = i; - } - /* and finally apply it */ - if (dx1 < 0) - tries[b][0] = -tries[b][0]; - if (dy2 < 0) - tries[b][1] = -tries[b][1]; - if (dy1 < 0) - tries[b][2] = -tries[b][2]; - if (dx2 < 0) - tries[b][3] = -tries[b][3]; - - dir = igetcvdir(ge); - ge->ix2 -= tries[b][0]; - ge->iy2 -= tries[b][2]; - fixcvdir(ge, dir); - dir = igetcvdir(ne); - ne->ix1 += tries[b][3]; - ne->iy1 += tries[b][1]; - fixcvdir(ne, dir); - } - } - } -} - -/* debugging: print out stems of a glyph */ -static void -debugstems( - char *name, - STEM * hstems, - int nhs, - STEM * vstems, - int nvs -) -{ - int i; - - fprintf(pfa_file, "%% %s\n", name); - fprintf(pfa_file, "%% %d horizontal stems:\n", nhs); - for (i = 0; i < nhs; i++) - fprintf(pfa_file, "%% %3d %d (%d...%d) %c %c%c%c%c\n", i, hstems[i].value, - hstems[i].from, hstems[i].to, - ((hstems[i].flags & ST_UP) ? 'U' : 'D'), - ((hstems[i].flags & ST_END) ? 'E' : '-'), - ((hstems[i].flags & ST_FLAT) ? 'F' : '-'), - ((hstems[i].flags & ST_ZONE) ? 'Z' : ' '), - ((hstems[i].flags & ST_TOPZONE) ? 'T' : ' ')); - fprintf(pfa_file, "%% %d vertical stems:\n", nvs); - for (i = 0; i < nvs; i++) - fprintf(pfa_file, "%% %3d %d (%d...%d) %c %c%c\n", i, vstems[i].value, - vstems[i].from, vstems[i].to, - ((vstems[i].flags & ST_UP) ? 'U' : 'D'), - ((vstems[i].flags & ST_END) ? 'E' : '-'), - ((vstems[i].flags & ST_FLAT) ? 'F' : '-')); -} - -/* add pseudo-stems for the limits of the Blue zones to the stem array */ -static int -addbluestems( - STEM *s, - int n -) -{ - int i; - - for(i=0; i<nblues && i<2; i+=2) { /* baseline */ - s[n].value=bluevalues[i]; - s[n].flags=ST_UP|ST_ZONE; - /* don't overlap with anything */ - s[n].origin=s[n].from=s[n].to= -10000+i; - n++; - s[n].value=bluevalues[i+1]; - s[n].flags=ST_ZONE; - /* don't overlap with anything */ - s[n].origin=s[n].from=s[n].to= -10000+i+1; - n++; - } - for(i=2; i<nblues; i+=2) { /* top zones */ - s[n].value=bluevalues[i]; - s[n].flags=ST_UP|ST_ZONE|ST_TOPZONE; - /* don't overlap with anything */ - s[n].origin=s[n].from=s[n].to= -10000+i; - n++; - s[n].value=bluevalues[i+1]; - s[n].flags=ST_ZONE|ST_TOPZONE; - /* don't overlap with anything */ - s[n].origin=s[n].from=s[n].to= -10000+i+1; - n++; - } - for(i=0; i<notherb; i+=2) { /* bottom zones */ - s[n].value=otherblues[i]; - s[n].flags=ST_UP|ST_ZONE; - /* don't overlap with anything */ - s[n].origin=s[n].from=s[n].to= -10000+i+nblues; - n++; - s[n].value=otherblues[i+1]; - s[n].flags=ST_ZONE; - /* don't overlap with anything */ - s[n].origin=s[n].from=s[n].to= -10000+i+1+nblues; - n++; - } - return n; -} - -/* sort stems in array */ -static void -sortstems( - STEM * s, - int n -) -{ - int i, j; - STEM x; - - - /* a simple sorting */ - /* hm, the ordering criteria are not quite simple :-) - * if the values are tied - * ST_UP always goes under not ST_UP - * ST_ZONE goes on the most outer side - * ST_END goes towards inner side after ST_ZONE - * ST_FLAT goes on the inner side - */ - - for (i = 0; i < n; i++) - for (j = i + 1; j < n; j++) { - if(s[i].value < s[j].value) - continue; - if(s[i].value == s[j].value) { - if( (s[i].flags & ST_UP) < (s[j].flags & ST_UP) ) - continue; - if( (s[i].flags & ST_UP) == (s[j].flags & ST_UP) ) { - if( s[i].flags & ST_UP ) { - if( - ((s[i].flags & (ST_ZONE|ST_FLAT|ST_END)) ^ ST_FLAT) - > - ((s[j].flags & (ST_ZONE|ST_FLAT|ST_END)) ^ ST_FLAT) - ) - continue; - } else { - if( - ((s[i].flags & (ST_ZONE|ST_FLAT|ST_END)) ^ ST_FLAT) - < - ((s[j].flags & (ST_ZONE|ST_FLAT|ST_END)) ^ ST_FLAT) - ) - continue; - } - } - } - x = s[j]; - s[j] = s[i]; - s[i] = x; - } -} - -/* check whether two stem borders overlap */ - -static int -stemoverlap( - STEM * s1, - STEM * s2 -) -{ - int result; - - if ((s1->from <= s2->from && s1->to >= s2->from) - || (s2->from <= s1->from && s2->to >= s1->from)) - result = 1; - else - result = 0; - - if (ISDBG(STEMOVERLAP)) - fprintf(pfa_file, "%% overlap %d(%d..%d)x%d(%d..%d)=%d\n", - s1->value, s1->from, s1->to, s2->value, s2->from, s2->to, result); - return result; -} - -/* - * check if the stem [border] is in an appropriate blue zone - * (currently not used) - */ - -static int -steminblue( - STEM *s -) -{ - int i, val; - - val=s->value; - if(s->flags & ST_UP) { - /* painted size up, look at lower zones */ - if(nblues>=2 && val>=bluevalues[0] && val<=bluevalues[1] ) - return 1; - for(i=0; i<notherb; i++) { - if( val>=otherblues[i] && val<=otherblues[i+1] ) - return 1; - } - } else { - /* painted side down, look at upper zones */ - for(i=2; i<nblues; i++) { - if( val>=bluevalues[i] && val<=bluevalues[i+1] ) - return 1; - } - } - - return 0; -} - -/* mark the outermost stem [borders] in the blue zones */ - -static void -markbluestems( - STEM *s, - int nold -) -{ - int i, j, a, b, c; - /* - * traverse the list of Blue Values, mark the lowest upper - * stem in each bottom zone and the topmost lower stem in - * each top zone with ST_BLUE - */ - - /* top zones */ - for(i=2; i<nblues; i+=2) { - a=bluevalues[i]; b=bluevalues[i+1]; - if(ISDBG(BLUESTEMS)) - fprintf(pfa_file, "%% looking at blue zone %d...%d\n", a, b); - for(j=nold-1; j>=0; j--) { - if( s[j].flags & (ST_ZONE|ST_UP|ST_END) ) - continue; - c=s[j].value; - if(c<a) /* too low */ - break; - if(c<=b) { /* found the topmost stem border */ - /* mark all the stems with the same value */ - if(ISDBG(BLUESTEMS)) - fprintf(pfa_file, "%% found D BLUE at %d\n", s[j].value); - /* include ST_END values */ - while( s[j+1].value==c && (s[j+1].flags & ST_ZONE)==0 ) - j++; - s[j].flags |= ST_BLUE; - for(j--; j>=0 && s[j].value==c - && (s[j].flags & (ST_UP|ST_ZONE))==0 ; j--) - s[j].flags |= ST_BLUE; - break; - } - } - } - /* baseline */ - if(nblues>=2) { - a=bluevalues[0]; b=bluevalues[1]; - for(j=0; j<nold; j++) { - if( (s[j].flags & (ST_ZONE|ST_UP|ST_END))!=ST_UP ) - continue; - c=s[j].value; - if(c>b) /* too high */ - break; - if(c>=a) { /* found the lowest stem border */ - /* mark all the stems with the same value */ - if(ISDBG(BLUESTEMS)) - fprintf(pfa_file, "%% found U BLUE at %d\n", s[j].value); - /* include ST_END values */ - while( s[j-1].value==c && (s[j-1].flags & ST_ZONE)==0 ) - j--; - s[j].flags |= ST_BLUE; - for(j++; j<nold && s[j].value==c - && (s[j].flags & (ST_UP|ST_ZONE))==ST_UP ; j++) - s[j].flags |= ST_BLUE; - break; - } - } - } - /* bottom zones: the logic is the same as for baseline */ - for(i=0; i<notherb; i+=2) { - a=otherblues[i]; b=otherblues[i+1]; - for(j=0; j<nold; j++) { - if( (s[j].flags & (ST_UP|ST_ZONE|ST_END))!=ST_UP ) - continue; - c=s[j].value; - if(c>b) /* too high */ - break; - if(c>=a) { /* found the lowest stem border */ - /* mark all the stems with the same value */ - if(ISDBG(BLUESTEMS)) - fprintf(pfa_file, "%% found U BLUE at %d\n", s[j].value); - /* include ST_END values */ - while( s[j-1].value==c && (s[j-1].flags & ST_ZONE)==0 ) - j--; - s[j].flags |= ST_BLUE; - for(j++; j<nold && s[j].value==c - && (s[j].flags & (ST_UP|ST_ZONE))==ST_UP ; j++) - s[j].flags |= ST_BLUE; - break; - } - } - } -} - -/* Eliminate invalid stems, join equivalent lines and remove nested stems - * to build the main (non-substituted) set of stems. - * XXX add consideration of the italic angle - */ -static int -joinmainstems( - STEM * s, - int nold, - int useblues /* do we use the blue values ? */ -) -{ -#define MAX_STACK 1000 - STEM stack[MAX_STACK]; - int nstack = 0; - int sbottom = 0; - int nnew; - int i, j, k; - int a, b, c, w1, w2, w3; - int fw, fd; - /* - * priority of the last found stem: - * 0 - nothing found yet - * 1 - has ST_END in it (one or more) - * 2 - has no ST_END and no ST_FLAT, can override only one stem - * with priority 1 - * 3 - has no ST_END and at least one ST_FLAT, can override one - * stem with priority 2 or any number of stems with priority 1 - * 4 (handled separately) - has ST_BLUE, can override anything - */ - int readystem = 0; - int pri; - int nlps = 0; /* number of non-committed - * lowest-priority stems */ - - - for (i = 0, nnew = 0; i < nold; i++) { - if (s[i].flags & (ST_UP|ST_ZONE)) { - if(s[i].flags & ST_BLUE) { - /* we just HAVE to use this value */ - if (readystem) - nnew += 2; - readystem=0; - - /* remember the list of Blue zone stems with the same value */ - for(a=i, i++; i<nold && s[a].value==s[i].value - && (s[i].flags & ST_BLUE); i++) - {} - b=i; /* our range is a <= i < b */ - c= -1; /* index of our best guess up to now */ - pri=0; - /* try to find a match, don't cross blue zones */ - for(; i<nold && (s[i].flags & ST_BLUE)==0; i++) { - if(s[i].flags & ST_UP) { - if(s[i].flags & ST_TOPZONE) - break; - else - continue; - } - for(j=a; j<b; j++) { - if(!stemoverlap(&s[j], &s[i]) ) - continue; - /* consider priorities */ - if( ( (s[j].flags|s[i].flags) & (ST_FLAT|ST_END) )==ST_FLAT ) { - c=i; - goto bluematch; - } - if( ((s[j].flags|s[i].flags) & ST_END)==0 ) { - if(pri < 2) { - c=i; pri=2; - } - } else { - if(pri == 0) { - c=i; pri=1; - } - } - } - } - bluematch: - /* clean up the stack */ - nstack=sbottom=0; - readystem=0; - /* add this stem */ - s[nnew++]=s[a]; - if(c<0) { /* make one-dot-wide stem */ - if(nnew>=b) { /* have no free space */ - for(j=nold; j>=b; j--) /* make free space */ - s[j]=s[j-1]; - b++; - nold++; - } - s[nnew]=s[a]; - s[nnew].flags &= ~(ST_UP|ST_BLUE); - nnew++; - i=b-1; - } else { - s[nnew++]=s[c]; - i=c; /* skip up to this point */ - } - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% +stem %d...%d U BLUE\n", - s[nnew-2].value, s[nnew-1].value); - } else { - if (nstack >= MAX_STACK) { - WARNING_1 fprintf(stderr, "Warning: **** converter's stem stack overflow ****\n"); - nstack = 0; - } - stack[nstack++] = s[i]; - } - } else if(s[i].flags & ST_BLUE) { - /* again, we just HAVE to use this value */ - if (readystem) - nnew += 2; - readystem=0; - - /* remember the list of Blue zone stems with the same value */ - for(a=i, i++; i<nold && s[a].value==s[i].value - && (s[i].flags & ST_BLUE); i++) - {} - b=i; /* our range is a <= i < b */ - c= -1; /* index of our best guess up to now */ - pri=0; - /* try to find a match */ - for (i = nstack - 1; i >= 0; i--) { - if( (stack[i].flags & ST_UP)==0 ) { - if( (stack[i].flags & (ST_ZONE|ST_TOPZONE))==ST_ZONE ) - break; - else - continue; - } - for(j=a; j<b; j++) { - if(!stemoverlap(&s[j], &stack[i]) ) - continue; - /* consider priorities */ - if( ( (s[j].flags|stack[i].flags) & (ST_FLAT|ST_END) )==ST_FLAT ) { - c=i; - goto bluedownmatch; - } - if( ((s[j].flags|stack[i].flags) & ST_END)==0 ) { - if(pri < 2) { - c=i; pri=2; - } - } else { - if(pri == 0) { - c=i; pri=1; - } - } - } - } - bluedownmatch: - /* if found no match make a one-dot-wide stem */ - if(c<0) { - c=0; - stack[0]=s[b-1]; - stack[0].flags |= ST_UP; - stack[0].flags &= ~ST_BLUE; - } - /* remove all the stems conflicting with this one */ - readystem=0; - for(j=nnew-2; j>=0; j-=2) { - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% ?stem %d...%d -- %d\n", - s[j].value, s[j+1].value, stack[c].value); - if(s[j+1].value < stack[c].value) /* no conflict */ - break; - if(s[j].flags & ST_BLUE) { - /* oops, we don't want to spoil other blue zones */ - stack[c].value=s[j+1].value+1; - break; - } - if( (s[j].flags|s[j+1].flags) & ST_END ) { - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% -stem %d...%d p=1\n", - s[j].value, s[j+1].value); - continue; /* pri==1, silently discard it */ - } - /* we want to discard no nore than 2 stems of pri>=2 */ - if( ++readystem > 2 ) { - /* change our stem to not conflict */ - stack[c].value=s[j+1].value+1; - break; - } else { - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% -stem %d...%d p>=2\n", - s[j].value, s[j+1].value); - continue; - } - } - nnew=j+2; - /* add this stem */ - if(nnew>=b-1) { /* have no free space */ - for(j=nold; j>=b-1; j--) /* make free space */ - s[j]=s[j-1]; - b++; - nold++; - } - s[nnew++]=stack[c]; - s[nnew++]=s[b-1]; - /* clean up the stack */ - nstack=sbottom=0; - readystem=0; - /* set the next position to search */ - i=b-1; - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% +stem %d...%d D BLUE\n", - s[nnew-2].value, s[nnew-1].value); - } else if (nstack > 0) { - - /* - * check whether our stem overlaps with anything in - * stack - */ - for (j = nstack - 1; j >= sbottom; j--) { - if (s[i].value <= stack[j].value) - break; - if (stack[j].flags & ST_ZONE) - continue; - - if ((s[i].flags & ST_END) - || (stack[j].flags & ST_END)) - pri = 1; - else if ((s[i].flags & ST_FLAT) - || (stack[j].flags & ST_FLAT)) - pri = 3; - else - pri = 2; - - if ((pri < readystem && s[nnew + 1].value >= stack[j].value) - || !stemoverlap(&stack[j], &s[i])) - continue; - - if (readystem > 1 && s[nnew + 1].value < stack[j].value) { - nnew += 2; - readystem = 0; - nlps = 0; - } - /* - * width of the previous stem (if it's - * present) - */ - w1 = s[nnew + 1].value - s[nnew].value; - - /* width of this stem */ - w2 = s[i].value - stack[j].value; - - if (readystem == 0) { - /* nothing yet, just add a new stem */ - s[nnew] = stack[j]; - s[nnew + 1] = s[i]; - readystem = pri; - if (pri == 1) - nlps = 1; - else if (pri == 2) - sbottom = j; - else { - sbottom = j + 1; - while (sbottom < nstack - && stack[sbottom].value <= stack[j].value) - sbottom++; - } - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% +stem %d...%d p=%d n=%d\n", - stack[j].value, s[i].value, pri, nlps); - } else if (pri == 1) { - if (stack[j].value > s[nnew + 1].value) { - /* - * doesn't overlap with the - * previous one - */ - nnew += 2; - nlps++; - s[nnew] = stack[j]; - s[nnew + 1] = s[i]; - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% +stem %d...%d p=%d n=%d\n", - stack[j].value, s[i].value, pri, nlps); - } else if (w2 < w1) { - /* is narrower */ - s[nnew] = stack[j]; - s[nnew + 1] = s[i]; - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% /stem %d...%d p=%d n=%d %d->%d\n", - stack[j].value, s[i].value, pri, nlps, w1, w2); - } - } else if (pri == 2) { - if (readystem == 2) { - /* choose the narrower stem */ - if (w1 > w2) { - s[nnew] = stack[j]; - s[nnew + 1] = s[i]; - sbottom = j; - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% /stem %d...%d p=%d n=%d\n", - stack[j].value, s[i].value, pri, nlps); - } - /* else readystem==1 */ - } else if (stack[j].value > s[nnew + 1].value) { - /* - * value doesn't overlap with - * the previous one - */ - nnew += 2; - nlps = 0; - s[nnew] = stack[j]; - s[nnew + 1] = s[i]; - sbottom = j; - readystem = pri; - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% +stem %d...%d p=%d n=%d\n", - stack[j].value, s[i].value, pri, nlps); - } else if (nlps == 1 - || stack[j].value > s[nnew - 1].value) { - /* - * we can replace the top - * stem - */ - nlps = 0; - s[nnew] = stack[j]; - s[nnew + 1] = s[i]; - readystem = pri; - sbottom = j; - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% /stem %d...%d p=%d n=%d\n", - stack[j].value, s[i].value, pri, nlps); - } - } else if (readystem == 3) { /* that means also - * pri==3 */ - /* choose the narrower stem */ - if (w1 > w2) { - s[nnew] = stack[j]; - s[nnew + 1] = s[i]; - sbottom = j + 1; - while (sbottom < nstack - && stack[sbottom].value <= stack[j].value) - sbottom++; - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% /stem %d...%d p=%d n=%d\n", - stack[j].value, s[i].value, pri, nlps); - } - } else if (pri == 3) { - /* - * we can replace as many stems as - * neccessary - */ - nnew += 2; - while (nnew > 0 && s[nnew - 1].value >= stack[j].value) { - nnew -= 2; - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% -stem %d..%d\n", - s[nnew].value, s[nnew + 1].value); - } - nlps = 0; - s[nnew] = stack[j]; - s[nnew + 1] = s[i]; - readystem = pri; - sbottom = j + 1; - while (sbottom < nstack - && stack[sbottom].value <= stack[j].value) - sbottom++; - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% +stem %d...%d p=%d n=%d\n", - stack[j].value, s[i].value, pri, nlps); - } - } - } - } - if (readystem) - nnew += 2; - - /* change the 1-pixel-wide stems to 20-pixel-wide stems if possible - * the constant 20 is recommended in the Type1 manual - */ - if(useblues) { - for(i=0; i<nnew; i+=2) { - if(s[i].value != s[i+1].value) - continue; - if( ((s[i].flags ^ s[i+1].flags) & ST_BLUE)==0 ) - continue; - if( s[i].flags & ST_BLUE ) { - if(nnew>i+2 && s[i+2].value<s[i].value+22) - s[i+1].value=s[i+2].value-2; /* compensate for fuzziness */ - else - s[i+1].value+=20; - } else { - if(i>0 && s[i-1].value>s[i].value-22) - s[i].value=s[i-1].value+2; /* compensate for fuzziness */ - else - s[i].value-=20; - } - } - } - /* make sure that no stem it stretched between - * a top zone and a bottom zone - */ - if(useblues) { - for(i=0; i<nnew; i+=2) { - a=10000; /* lowest border of top zone crosing the stem */ - b= -10000; /* highest border of bottom zone crossing the stem */ - - for(j=2; j<nblues; j++) { - c=bluevalues[j]; - if( c>=s[i].value && c<=s[i+1].value && c<a ) - a=c; - } - if(nblues>=2) { - c=bluevalues[1]; - if( c>=s[i].value && c<=s[i+1].value && c>b ) - b=c; - } - for(j=1; j<notherb; j++) { - c=otherblues[j]; - if( c>=s[i].value && c<=s[i+1].value && c>b ) - b=c; - } - if( a!=10000 && b!= -10000 ) { /* it is stretched */ - /* split the stem into 2 ghost stems */ - for(j=nnew+1; j>i+1; j--) /* make free space */ - s[j]=s[j-2]; - nnew+=2; - - if(s[i].value+22 >= a) - s[i+1].value=a-2; /* leave space for fuzziness */ - else - s[i+1].value=s[i].value+20; - - if(s[i+3].value-22 <= b) - s[i+2].value=b+2; /* leave space for fuzziness */ - else - s[i+2].value=s[i+3].value-20; - - i+=2; - } - } - } - /* look for triple stems */ - for (i = 0; i < nnew; i += 2) { - if (nnew - i >= 6) { - a = s[i].value + s[i + 1].value; - b = s[i + 2].value + s[i + 3].value; - c = s[i + 4].value + s[i + 5].value; - - w1 = s[i + 1].value - s[i].value; - w2 = s[i + 3].value - s[i + 2].value; - w3 = s[i + 5].value - s[i + 4].value; - - fw = w3 - w1; /* fuzz in width */ - fd = ((c - b) - (b - a)); /* fuzz in distance - * (doubled) */ - - /* we are able to handle some fuzz */ - /* - * it doesn't hurt if the declared stem is a bit - * narrower than actual unless it's an edge in - * a blue zone - */ - if (abs(abs(fd) - abs(fw)) * 5 < w2 - && abs(fw) * 20 < (w1 + w3)) { /* width dirrerence <10% */ - - if(useblues) { /* check that we don't disturb any blue stems */ - j=c; k=a; - if (fw > 0) { - if (fd > 0) { - if( s[i+5].flags & ST_BLUE ) - continue; - j -= fw; - } else { - if( s[i+4].flags & ST_BLUE ) - continue; - j += fw; - } - } else if(fw < 0) { - if (fd > 0) { - if( s[i+1].flags & ST_BLUE ) - continue; - k -= fw; - } else { - if( s[i].flags & ST_BLUE ) - continue; - k += fw; - } - } - pri = ((j - b) - (b - k)); - - if (pri > 0) { - if( s[i+2].flags & ST_BLUE ) - continue; - } else if(pri < 0) { - if( s[i+3].flags & ST_BLUE ) - continue; - } - } - - /* - * first fix up the width of 1st and 3rd - * stems - */ - if (fw > 0) { - if (fd > 0) { - s[i + 5].value -= fw; - c -= fw; - } else { - s[i + 4].value += fw; - c += fw; - } - } else { - if (fd > 0) { - s[i + 1].value -= fw; - a -= fw; - } else { - s[i].value += fw; - a += fw; - } - } - fd = ((c - b) - (b - a)); - - if (fd > 0) { - s[i + 2].value += abs(fd) / 2; - } else { - s[i + 3].value -= abs(fd) / 2; - } - - s[i].flags |= ST_3; - i += 4; - } - } - } - - return (nnew & ~1); /* number of lines must be always even */ -} - -/* - * these macros and function allow to set the base stem, - * check that it's not empty and subtract another stem - * from the base stem (possibly dividing it into multiple parts) - */ - -/* pairs for pieces of the base stem */ -static short xbstem[MAX_STEMS*2]; -/* index of the last point */ -static int xblast= -1; - -#define setbasestem(from, to) \ - (xbstem[0]=from, xbstem[1]=to, xblast=1) -#define isbaseempty() (xblast<=0) - -/* returns 1 if was overlapping, 0 otherwise */ -static int -subfrombase( - int from, - int to -) -{ - int a, b; - int i, j; - - if(isbaseempty()) - return 0; - - /* handle the simple case simply */ - if(from > xbstem[xblast] || to < xbstem[0]) - return 0; - - /* the binary search may be more efficient */ - /* but for now the linear search is OK */ - for(b=1; from > xbstem[b]; b+=2) {} /* result: from <= xbstem[b] */ - for(a=xblast-1; to < xbstem[a]; a-=2) {} /* result: to >= xbstem[a] */ - - /* now the interesting examples are: - * (it was hard for me to understand, so I looked at the examples) - * 1 - * a|-----| |-----|b |-----| |-----| - * f|-----|t - * 2 - * a|-----|b |-----| |-----| |-----| - * f|--|t - * 3 - * a|-----|b |-----| |-----| |-----| - * f|-----|t - * 4 - * |-----|b a|-----| |-----| |-----| - * f|------------|t - * 5 - * |-----| |-----|b |-----| a|-----| - * f|-----------------------------|t - * 6 - * |-----|b |-----| |-----| a|-----| - * f|--------------------------------------------------|t - * 7 - * |-----|b |-----| a|-----| |-----| - * f|--------------------------|t - */ - - if(a < b-1) /* hits a gap - example 1 */ - return 0; - - /* now the subtraction itself */ - - if(a==b-1 && from > xbstem[a] && to < xbstem[b]) { - /* overlaps with only one subrange and splits it - example 2 */ - j=xblast; i=(xblast+=2); - while(j>=b) - xbstem[i--]=xbstem[j--]; - xbstem[b]=from-1; - xbstem[b+1]=to+1; - return 1; - /* becomes - * 2a - * a|b || |-----| |-----| |-----| - * f|--|t - */ - } - - if(xbstem[b-1] < from) { - /* cuts the back of this subrange - examples 3, 4, 7 */ - xbstem[b] = from-1; - b+=2; - /* becomes - * 3a - * a|----| |-----|b |-----| |-----| - * f|-----|t - * 4a - * |---| a|-----|b |-----| |-----| - * f|------------|t - * 7a - * |---| |-----|b a|-----| |-----| - * f|--------------------------|t - */ - } - - if(xbstem[a+1] > to) { - /* cuts the front of this subrange - examples 4a, 5, 7a */ - xbstem[a] = to+1; - a-=2; - /* becomes - * 4b - * a|---| |---|b |-----| |-----| - * f|------------|t - * 5b - * |-----| |-----|b a|-----| || - * f|-----------------------------|t - * 7b - * |---| a|-----|b || |-----| - * f|--------------------------|t - */ - } - - if(a < b-1) /* now after modification it hits a gap - examples 3a, 4b */ - return 1; /* because we have removed something */ - - /* now remove the subranges completely covered by the new stem */ - /* examples 5b, 6, 7b */ - i=b-1; j=a+2; - /* positioned as: - * 5b i j - * |-----| |-----|b a|-----| || - * f|-----------------------------|t - * 6 i xblast j - * |-----|b |-----| |-----| a|-----| - * f|--------------------------------------------------|t - * 7b i j - * |---| a|-----|b || |-----| - * f|--------------------------|t - */ - while(j <= xblast) - xbstem[i++]=xbstem[j++]; - xblast=i-1; - return 1; -} - -/* for debugging */ -static void -printbasestem(void) -{ - int i; - - printf("( "); - for(i=0; i<xblast; i+=2) - printf("%d-%d ", xbstem[i], xbstem[i+1]); - printf(") %d\n", xblast); -} - -/* - * Join the stem borders to build the sets of substituted stems - * XXX add consideration of the italic angle - */ -static void -joinsubstems( - STEM * s, - short *pairs, - int nold, - int useblues /* do we use the blue values ? */ -) -{ - int i, j, x; - static unsigned char mx[MAX_STEMS][MAX_STEMS]; - - /* we do the substituted groups of stems first - * and it looks like it's going to be REALLY SLOW - * AND PAINFUL but let's bother about it later - */ - - /* for the substituted stems we don't bother about [hv]stem3 - - * anyway the X11R6 rasterizer does not bother about hstem3 - * at all and is able to handle only one global vstem3 - * per glyph - */ - - /* clean the used part of matrix */ - for(i=0; i<nold; i++) - for(j=0; j<nold; j++) - mx[i][j]=0; - - /* build the matrix of stem pairs */ - for(i=0; i<nold; i++) { - if( s[i].flags & ST_ZONE ) - continue; - if(s[i].flags & ST_BLUE) - mx[i][i]=1; /* allow to pair with itself if no better pair */ - if(s[i].flags & ST_UP) { /* the down-stems are already matched */ - setbasestem(s[i].from, s[i].to); - for(j=i+1; j<nold; j++) { - if(s[i].value==s[j].value - || s[j].flags & ST_ZONE ) { - continue; - } - x=subfrombase(s[j].from, s[j].to); - - if(s[j].flags & ST_UP) /* match only up+down pairs */ - continue; - - mx[i][j]=mx[j][i]=x; - - if(isbaseempty()) /* nothing else to do */ - break; - } - } - } - - if(ISDBG(SUBSTEMS)) { - fprintf(pfa_file, "%% "); - for(j=0; j<nold; j++) - putc( j%10==0 ? '0'+(j/10)%10 : ' ', pfa_file); - fprintf(pfa_file, "\n%% "); - for(j=0; j<nold; j++) - putc('0'+j%10, pfa_file); - putc('\n', pfa_file); - for(i=0; i<nold; i++) { - fprintf(pfa_file, "%% %3d ",i); - for(j=0; j<nold; j++) - putc( mx[i][j] ? 'X' : '.', pfa_file); - putc('\n', pfa_file); - } - } - - /* now use the matrix to find the best pair for each stem */ - for(i=0; i<nold; i++) { - int pri, lastpri, v, f; - - x= -1; /* best pair: none */ - lastpri=0; - - v=s[i].value; - f=s[i].flags; - - if(f & ST_ZONE) { - pairs[i]= -1; - continue; - } - - if(f & ST_UP) { - for(j=i+1; j<nold; j++) { - if(mx[i][j]==0) - continue; - - if( (f | s[j].flags) & ST_END ) - pri=1; - else if( (f | s[j].flags) & ST_FLAT ) - pri=3; - else - pri=2; - - if(lastpri==0 - || ( pri > lastpri - && ( lastpri==1 || s[j].value-v<20 || (s[x].value-v)*2 >= s[j].value-v ) ) ) { - lastpri=pri; - x=j; - } - } - } else { - for(j=i-1; j>=0; j--) { - if(mx[i][j]==0) - continue; - - if( (f | s[j].flags) & ST_END ) - pri=1; - else if( (f | s[j].flags) & ST_FLAT ) - pri=3; - else - pri=2; - - if(lastpri==0 - || ( pri > lastpri - && ( lastpri==1 || v-s[j].value<20 || (v-s[x].value)*2 >= v-s[j].value ) ) ) { - lastpri=pri; - x=j; - } - } - } - if(x== -1 && mx[i][i]) - pairs[i]=i; /* a special case */ - else - pairs[i]=x; - } - - if(ISDBG(SUBSTEMS)) { - for(i=0; i<nold; i++) { - j=pairs[i]; - if(j>0) - fprintf(pfa_file, "%% %d...%d (%d x %d)\n", s[i].value, s[j].value, i, j); - } - } -} - -/* - * Make all the stems originating at the same value get the - * same width. Without this the rasterizer may move the dots - * randomly up or down by one pixel, and that looks bad. - * The prioritisation is the same as in findstemat(). - */ -static void -uniformstems( - STEM * s, - short *pairs, - int ns -) -{ - int i, j, from, to, val, dir; - int pri, prevpri[2], wd, prevwd[2], prevbest[2]; - - for(from=0; from<ns; from=to) { - prevpri[0] = prevpri[1] = 0; - prevwd[0] = prevwd[1] = 0; - prevbest[0] = prevbest[1] = -1; - val = s[from].value; - - for(to = from; to<ns && s[to].value == val; to++) { - dir = ((s[to].flags & ST_UP)!=0); - - i=pairs[to]; /* the other side of this stem */ - if(i<0 || i==to) - continue; /* oops, no other side */ - wd=abs(s[i].value-val); - if(wd == 0) - continue; - pri=1; - if( (s[to].flags | s[i].flags) & ST_END ) - pri=0; - if( prevbest[dir] == -1 || pri > prevpri[dir] || wd<prevwd[dir] ) { - prevbest[dir]=i; - prevpri[dir]=pri; - prevwd[dir]=wd; - } - } - - for(i=from; i<to; i++) { - dir = ((s[i].flags & ST_UP)!=0); - if(prevbest[dir] >= 0) { - if(ISDBG(SUBSTEMS)) { - fprintf(stderr, "at %d (%s %d) pair %d->%d(%d)\n", i, - (dir ? "UP":"DOWN"), s[i].value, pairs[i], prevbest[dir], - s[prevbest[dir]].value); - } - pairs[i] = prevbest[dir]; - } - } - } -} - -/* - * Find the best stem in the array at the specified (value, origin), - * related to the entry ge. - * Returns its index in the array sp, -1 means "none". - * prevbest is the result for the other end of the line, we must - * find something better than it or leave it as it is. - */ -static int -findstemat( - int value, - int origin, - GENTRY *ge, - STEM *sp, - short *pairs, - int ns, - int prevbest /* -1 means "none" */ -) -{ - int i, min, max; - int v, si; - int pri, prevpri; /* priority, 0 = has ST_END, 1 = no ST_END */ - int wd, prevwd; /* stem width */ - - si= -1; /* nothing yet */ - - /* stems are ordered by value, binary search */ - min=0; max=ns; /* min <= i < max */ - while( min < max ) { - i=(min+max)/2; - v=sp[i].value; - if(v<value) - min=i+1; - else if(v>value) - max=i; - else { - si=i; /* temporary value */ - break; - } - } - - if( si < 0 ) /* found nothing this time */ - return prevbest; - - /* find the priority of the prevbest */ - /* we expect that prevbest has a pair */ - if(prevbest>=0) { - i=pairs[prevbest]; - prevpri=1; - if( (sp[prevbest].flags | sp[i].flags) & ST_END ) - prevpri=0; - prevwd=abs(sp[i].value-value); - } - - /* stems are not ordered by origin, so now do the linear search */ - - while( si>0 && sp[si-1].value==value ) /* find the first one */ - si--; - - for(; si<ns && sp[si].value==value; si++) { - if(sp[si].origin != origin) - continue; - if(sp[si].ge != ge) { - if(ISDBG(SUBSTEMS)) { - fprintf(stderr, - "dbg: possible self-intersection at v=%d o=%d exp_ge=0x%x ge=0x%x\n", - value, origin, ge, sp[si].ge); - } - continue; - } - i=pairs[si]; /* the other side of this stem */ - if(i<0) - continue; /* oops, no other side */ - pri=1; - if( (sp[si].flags | sp[i].flags) & ST_END ) - pri=0; - wd=abs(sp[i].value-value); - if( prevbest == -1 || pri >prevpri - || (pri==prevpri && prevwd==0) || (wd!=0 && wd<prevwd) ) { - prevbest=si; - prevpri=pri; - prevwd=wd; - continue; - } - } - - return prevbest; -} - -/* add the substems for one glyph entry - * (called from groupsubstems()) - * returns 0 if all OK, 1 if too many groups - */ - -static int gssentry_lastgrp=0; /* reset to 0 for each new glyph */ - -static int -gssentry( /* crazy number of parameters */ - GENTRY *ge, - STEM *hs, /* horizontal stems, sorted by value */ - short *hpairs, - int nhs, - STEM *vs, /* vertical stems, sorted by value */ - short *vpairs, - int nvs, - STEMBOUNDS *s, - short *egp, - int *nextvsi, - int *nexthsi /* -2 means "check by yourself" */ -) { - enum { - SI_VP, /* vertical primary */ - SI_HP, /* horizontal primary */ - SI_SIZE /* size of the array */ - }; - int si[SI_SIZE]; /* indexes of relevant stems */ - - /* the bounds of the existing relevant stems */ - STEMBOUNDS r[ sizeof(si) / sizeof(si[0]) * 2 ]; - char rexpand; /* by how much we need to expand the group */ - int nr; /* and the number of them */ - - /* yet more temporary storage */ - short lb, hb, isvert; - int conflict, grp; - int i, j, x, y; - - - /* for each line or curve we try to find a horizontal and - * a vertical stem corresponding to its first point - * (corresponding to the last point of the previous - * glyph entry), because the directions of the lines - * will be eventually reversed and it will then become the last - * point. And the T1 rasterizer applies the hints to - * the last point. - * - */ - - /* start with the common part, the first point */ - x=ge->prev->ix3; - y=ge->prev->iy3; - - if(*nextvsi == -2) - si[SI_VP]=findstemat(x, y, ge, vs, vpairs, nvs, -1); - else { - si[SI_VP]= *nextvsi; *nextvsi= -2; - } - if(*nexthsi == -2) - si[SI_HP]=findstemat(y, x, ge, hs, hpairs, nhs, -1); - else { - si[SI_HP]= *nexthsi; *nexthsi= -2; - } - - /* - * For the horizontal lines we make sure that both - * ends of the line have the same horizontal stem, - * and the same thing for vertical lines and stems. - * In both cases we enforce the stem for the next entry. - * Otherwise unpleasant effects may arise. - */ - - if(ge->type==GE_LINE) { - if(ge->ix3==x) { /* vertical line */ - *nextvsi=si[SI_VP]=findstemat(x, ge->iy3, ge->frwd, vs, vpairs, nvs, si[SI_VP]); - } else if(ge->iy3==y) { /* horizontal line */ - *nexthsi=si[SI_HP]=findstemat(y, ge->ix3, ge->frwd, hs, hpairs, nhs, si[SI_HP]); - } - } - - if(si[SI_VP]+si[SI_HP] == -2) /* no stems, leave it alone */ - return 0; - - /* build the array of relevant bounds */ - nr=0; - for(i=0; i< sizeof(si) / sizeof(si[0]); i++) { - STEM *sp; - short *pairs; - int step; - int f; - int nzones, firstzone, binzone, einzone; - int btype, etype; - - if(si[i] < 0) - continue; - - if(i<SI_HP) { - r[nr].isvert=1; sp=vs; pairs=vpairs; - } else { - r[nr].isvert=0; sp=hs; pairs=hpairs; - } - - r[nr].low=sp[ si[i] ].value; - r[nr].high=sp[ pairs[ si[i] ] ].value; - - if(r[nr].low > r[nr].high) { - j=r[nr].low; r[nr].low=r[nr].high; r[nr].high=j; - step= -1; - } else { - step=1; - } - - /* handle the interaction with Blue Zones */ - - if(i>=SI_HP) { /* only for horizontal stems */ - if(si[i]==pairs[si[i]]) { - /* special case, the outermost stem in the - * Blue Zone without a pair, simulate it to 20-pixel - */ - if(sp[ si[i] ].flags & ST_UP) { - r[nr].high+=20; - for(j=si[i]+1; j<nhs; j++) - if( (sp[j].flags & (ST_ZONE|ST_TOPZONE)) - == (ST_ZONE|ST_TOPZONE) ) { - if(r[nr].high > sp[j].value-2) - r[nr].high=sp[j].value-2; - break; - } - } else { - r[nr].low-=20; - for(j=si[i]-1; j>=0; j--) - if( (sp[j].flags & (ST_ZONE|ST_TOPZONE)) - == (ST_ZONE) ) { - if(r[nr].low < sp[j].value+2) - r[nr].low=sp[j].value+2; - break; - } - } - } - - /* check that the stem borders don't end up in - * different Blue Zones */ - f=sp[ si[i] ].flags; - nzones=0; einzone=binzone=0; - for(j=si[i]; j!=pairs[ si[i] ]; j+=step) { - if( (sp[j].flags & ST_ZONE)==0 ) - continue; - /* if see a zone border going in the same direction */ - if( ((f ^ sp[j].flags) & ST_UP)==0 ) { - if( ++nzones == 1 ) { - firstzone=sp[j].value; /* remember the first one */ - etype=sp[j].flags & ST_TOPZONE; - } - einzone=1; - - } else { /* the opposite direction */ - if(nzones==0) { /* beginning is in a blue zone */ - binzone=1; - btype=sp[j].flags & ST_TOPZONE; - } - einzone=0; - } - } - - /* beginning and end are in Blue Zones of different types */ - if( binzone && einzone && (btype ^ etype)!=0 ) { - if( sp[si[i]].flags & ST_UP ) { - if(firstzone > r[nr].low+22) - r[nr].high=r[nr].low+20; - else - r[nr].high=firstzone-2; - } else { - if(firstzone < r[nr].high-22) - r[nr].low=r[nr].high-20; - else - r[nr].low=firstzone+2; - } - } - } - - if(ISDBG(SUBSTEMS)) - fprintf(pfa_file, "%% at(%d,%d)[%d,%d] %d..%d %c (%d x %d)\n", x, y, i, nr, - r[nr].low, r[nr].high, r[nr].isvert ? 'v' : 'h', - si[i], pairs[si[i]]); - - nr++; - } - - /* now try to find a group */ - conflict=0; /* no conflicts found yet */ - for(j=0; j<nr; j++) - r[j].already=0; - - /* check if it fits into the last group */ - grp = gssentry_lastgrp; - i = (grp==0)? 0 : egp[grp-1]; - for(; i<egp[grp]; i++) { - lb=s[i].low; hb=s[i].high; isvert=s[i].isvert; - for(j=0; j<nr; j++) - if( r[j].isvert==isvert /* intersects */ - && r[j].low <= hb && r[j].high >= lb ) { - if( r[j].low == lb && r[j].high == hb ) /* coincides */ - r[j].already=1; - else - conflict=1; - } - - if(conflict) - break; - } - - if(conflict) { /* nope, check all the groups */ - for(j=0; j<nr; j++) - r[j].already=0; - - for(i=0, grp=0; i<egp[NSTEMGRP-1]; i++) { - if(i == egp[grp]) { /* checked all stems in a group */ - if(conflict) { - grp++; conflict=0; /* check the next group */ - for(j=0; j<nr; j++) - r[j].already=0; - } else - break; /* insert into this group */ - } - - lb=s[i].low; hb=s[i].high; isvert=s[i].isvert; - for(j=0; j<nr; j++) - if( r[j].isvert==isvert /* intersects */ - && r[j].low <= hb && r[j].high >= lb ) { - if( r[j].low == lb && r[j].high == hb ) /* coincides */ - r[j].already=1; - else - conflict=1; - } - - if(conflict) - i=egp[grp]-1; /* fast forward to the next group */ - } - } - - /* do we have any empty group ? */ - if(conflict && grp < NSTEMGRP-1) { - grp++; conflict=0; - for(j=0; j<nr; j++) - r[j].already=0; - } - - if(conflict) { /* oops, can't find any group to fit */ - return 1; - } - - /* OK, add stems to this group */ - - rexpand = nr; - for(j=0; j<nr; j++) - rexpand -= r[j].already; - - if(rexpand > 0) { - for(i=egp[NSTEMGRP-1]-1; i>=egp[grp]; i--) - s[i+rexpand]=s[i]; - for(i=0; i<nr; i++) - if(!r[i].already) - s[egp[grp]++]=r[i]; - for(i=grp+1; i<NSTEMGRP; i++) - egp[i]+=rexpand; - } - - ge->stemid = gssentry_lastgrp = grp; - return 0; -} - -/* - * Create the groups of substituted stems from the list. - * Each group will be represented by a subroutine in the Subs - * array. - */ - -static void -groupsubstems( - GLYPH *g, - STEM *hs, /* horizontal stems, sorted by value */ - short *hpairs, - int nhs, - STEM *vs, /* vertical stems, sorted by value */ - short *vpairs, - int nvs -) -{ - GENTRY *ge; - int i, j; - - /* temporary storage */ - STEMBOUNDS s[MAX_STEMS*2]; - /* indexes in there, pointing past the end each stem group */ - short egp[NSTEMGRP]; - - int nextvsi, nexthsi; /* -2 means "check by yourself" */ - - for(i=0; i<NSTEMGRP; i++) - egp[i]=0; - - nextvsi=nexthsi= -2; /* processed no horiz/vert line */ - - gssentry_lastgrp = 0; /* reset the last group for new glyph */ - - for (ge = g->entries; ge != 0; ge = ge->next) { - if(ge->type!=GE_LINE && ge->type!=GE_CURVE) { - nextvsi=nexthsi= -2; /* next path is independent */ - continue; - } - - if( gssentry(ge, hs, hpairs, nhs, vs, vpairs, nvs, s, egp, &nextvsi, &nexthsi) ) { - WARNING_2 fprintf(stderr, "*** glyph %s requires over %d hint subroutines, ignored them\n", - g->name, NSTEMGRP); - /* it's better to have no substituted hints at all than have only part */ - for (ge = g->entries; ge != 0; ge = ge->next) - ge->stemid= -1; - g->nsg=0; /* just to be safe, already is 0 by initialization */ - return; - } - - /* - * handle the last vert/horiz line of the path specially, - * correct the hint for the first entry of the path - */ - if(ge->frwd != ge->next && (nextvsi != -2 || nexthsi != -2) ) { - if( gssentry(ge->frwd, hs, hpairs, nhs, vs, vpairs, nvs, s, egp, &nextvsi, &nexthsi) ) { - WARNING_2 fprintf(stderr, "*** glyph %s requires over %d hint subroutines, ignored them\n", - g->name, NSTEMGRP); - /* it's better to have no substituted hints at all than have only part */ - for (ge = g->entries; ge != 0; ge = ge->next) - ge->stemid= -1; - g->nsg=0; /* just to be safe, already is 0 by initialization */ - return; - } - } - - } - - /* find the index of the first empty group - same as the number of groups */ - if(egp[0]>0) { - for(i=1; i<NSTEMGRP && egp[i]!=egp[i-1]; i++) - {} - g->nsg=i; - } else - g->nsg=0; - - if(ISDBG(SUBSTEMS)) { - fprintf(pfa_file, "%% %d substem groups (%d %d %d)\n", g->nsg, - g->nsg>1 ? egp[g->nsg-2] : -1, - g->nsg>0 ? egp[g->nsg-1] : -1, - g->nsg<NSTEMGRP ? egp[g->nsg] : -1 ); - j=0; - for(i=0; i<g->nsg; i++) { - fprintf(pfa_file, "%% grp %3d: ", i); - for(; j<egp[i]; j++) { - fprintf(pfa_file, " %4d...%-4d %c ", s[j].low, s[j].high, - s[j].isvert ? 'v' : 'h'); - } - fprintf(pfa_file, "\n"); - } - } - - if(g->nsg==1) { /* it would be the same as the main stems */ - /* so erase it */ - for (ge = g->entries; ge != 0; ge = ge->next) - ge->stemid= -1; - g->nsg=0; - } - - if(g->nsg>0) { - if( (g->nsbs=malloc(g->nsg * sizeof (egp[0]))) == 0 ) { - fprintf(stderr, "**** not enough memory for substituted hints ****\n"); - exit(255); - } - memmove(g->nsbs, egp, g->nsg * sizeof(short)); - if( (g->sbstems=malloc(egp[g->nsg-1] * sizeof (s[0]))) == 0 ) { - fprintf(stderr, "**** not enough memory for substituted hints ****\n"); - exit(255); - } - memmove(g->sbstems, s, egp[g->nsg-1] * sizeof(s[0])); - } -} - -void -buildstems( - GLYPH * g -) -{ - STEM hs[MAX_STEMS], vs[MAX_STEMS]; /* temporary working - * storage */ - short hs_pairs[MAX_STEMS], vs_pairs[MAX_STEMS]; /* best pairs for these stems */ - STEM *sp; - GENTRY *ge, *nge, *pge; - int nx, ny; - int ovalue; - int totals, grp, lastgrp; - - assertisint(g, "buildstems int"); - - g->nhs = g->nvs = 0; - memset(hs, 0, sizeof hs); - memset(vs, 0, sizeof vs); - - /* first search the whole character for possible stem points */ - - for (ge = g->entries; ge != 0; ge = ge->next) { - if (ge->type == GE_CURVE) { - - /* - * SURPRISE! - * We consider the stems bound by the - * H/V ends of the curves as flat ones. - * - * But we don't include the point on the - * other end into the range. - */ - - /* first check the beginning of curve */ - /* if it is horizontal, add a hstem */ - if (ge->iy1 == ge->prev->iy3) { - hs[g->nhs].value = ge->iy1; - - if (ge->ix1 < ge->prev->ix3) - hs[g->nhs].flags = ST_FLAT | ST_UP; - else - hs[g->nhs].flags = ST_FLAT; - - hs[g->nhs].origin = ge->prev->ix3; - hs[g->nhs].ge = ge; - - if (ge->ix1 < ge->prev->ix3) { - hs[g->nhs].from = ge->ix1+1; - hs[g->nhs].to = ge->prev->ix3; - if(hs[g->nhs].from > hs[g->nhs].to) - hs[g->nhs].from--; - } else { - hs[g->nhs].from = ge->prev->ix3; - hs[g->nhs].to = ge->ix1-1; - if(hs[g->nhs].from > hs[g->nhs].to) - hs[g->nhs].to++; - } - if (ge->ix1 != ge->prev->ix3) - g->nhs++; - } - /* if it is vertical, add a vstem */ - else if (ge->ix1 == ge->prev->ix3) { - vs[g->nvs].value = ge->ix1; - - if (ge->iy1 > ge->prev->iy3) - vs[g->nvs].flags = ST_FLAT | ST_UP; - else - vs[g->nvs].flags = ST_FLAT; - - vs[g->nvs].origin = ge->prev->iy3; - vs[g->nvs].ge = ge; - - if (ge->iy1 < ge->prev->iy3) { - vs[g->nvs].from = ge->iy1+1; - vs[g->nvs].to = ge->prev->iy3; - if(vs[g->nvs].from > vs[g->nvs].to) - vs[g->nvs].from--; - } else { - vs[g->nvs].from = ge->prev->iy3; - vs[g->nvs].to = ge->iy1-1; - if(vs[g->nvs].from > vs[g->nvs].to) - vs[g->nvs].to++; - } - - if (ge->iy1 != ge->prev->iy3) - g->nvs++; - } - /* then check the end of curve */ - /* if it is horizontal, add a hstem */ - if (ge->iy3 == ge->iy2) { - hs[g->nhs].value = ge->iy3; - - if (ge->ix3 < ge->ix2) - hs[g->nhs].flags = ST_FLAT | ST_UP; - else - hs[g->nhs].flags = ST_FLAT; - - hs[g->nhs].origin = ge->ix3; - hs[g->nhs].ge = ge->frwd; - - if (ge->ix3 < ge->ix2) { - hs[g->nhs].from = ge->ix3; - hs[g->nhs].to = ge->ix2-1; - if( hs[g->nhs].from > hs[g->nhs].to ) - hs[g->nhs].to++; - } else { - hs[g->nhs].from = ge->ix2+1; - hs[g->nhs].to = ge->ix3; - if( hs[g->nhs].from > hs[g->nhs].to ) - hs[g->nhs].from--; - } - - if (ge->ix3 != ge->ix2) - g->nhs++; - } - /* if it is vertical, add a vstem */ - else if (ge->ix3 == ge->ix2) { - vs[g->nvs].value = ge->ix3; - - if (ge->iy3 > ge->iy2) - vs[g->nvs].flags = ST_FLAT | ST_UP; - else - vs[g->nvs].flags = ST_FLAT; - - vs[g->nvs].origin = ge->iy3; - vs[g->nvs].ge = ge->frwd; - - if (ge->iy3 < ge->iy2) { - vs[g->nvs].from = ge->iy3; - vs[g->nvs].to = ge->iy2-1; - if( vs[g->nvs].from > vs[g->nvs].to ) - vs[g->nvs].to++; - } else { - vs[g->nvs].from = ge->iy2+1; - vs[g->nvs].to = ge->iy3; - if( vs[g->nvs].from > vs[g->nvs].to ) - vs[g->nvs].from--; - } - - if (ge->iy3 != ge->iy2) - g->nvs++; - } else { - - /* - * check the end of curve for a not smooth - * local extremum - */ - nge = ge->frwd; - - if (nge == 0) - continue; - else if (nge->type == GE_LINE) { - nx = nge->ix3; - ny = nge->iy3; - } else if (nge->type == GE_CURVE) { - nx = nge->ix1; - ny = nge->iy1; - } else - continue; - - /* check for vertical extremums */ - if ((ge->iy3 > ge->iy2 && ge->iy3 > ny) - || (ge->iy3 < ge->iy2 && ge->iy3 < ny)) { - hs[g->nhs].value = ge->iy3; - hs[g->nhs].from - = hs[g->nhs].to - = hs[g->nhs].origin = ge->ix3; - hs[g->nhs].ge = ge->frwd; - - if (ge->ix3 < ge->ix2 - || nx < ge->ix3) - hs[g->nhs].flags = ST_UP; - else - hs[g->nhs].flags = 0; - - if (ge->ix3 != ge->ix2 || nx != ge->ix3) - g->nhs++; - } - /* - * the same point may be both horizontal and - * vertical extremum - */ - /* check for horizontal extremums */ - if ((ge->ix3 > ge->ix2 && ge->ix3 > nx) - || (ge->ix3 < ge->ix2 && ge->ix3 < nx)) { - vs[g->nvs].value = ge->ix3; - vs[g->nvs].from - = vs[g->nvs].to - = vs[g->nvs].origin = ge->iy3; - vs[g->nvs].ge = ge->frwd; - - if (ge->iy3 > ge->iy2 - || ny > ge->iy3) - vs[g->nvs].flags = ST_UP; - else - vs[g->nvs].flags = 0; - - if (ge->iy3 != ge->iy2 || ny != ge->iy3) - g->nvs++; - } - } - - } else if (ge->type == GE_LINE) { - nge = ge->frwd; - - /* if it is horizontal, add a hstem */ - /* and the ends as vstems if they brace the line */ - if (ge->iy3 == ge->prev->iy3 - && ge->ix3 != ge->prev->ix3) { - hs[g->nhs].value = ge->iy3; - if (ge->ix3 < ge->prev->ix3) { - hs[g->nhs].flags = ST_FLAT | ST_UP; - hs[g->nhs].from = ge->ix3; - hs[g->nhs].to = ge->prev->ix3; - } else { - hs[g->nhs].flags = ST_FLAT; - hs[g->nhs].from = ge->prev->ix3; - hs[g->nhs].to = ge->ix3; - } - hs[g->nhs].origin = ge->ix3; - hs[g->nhs].ge = ge->frwd; - - pge = ge->bkwd; - - /* add beginning as vstem */ - vs[g->nvs].value = pge->ix3; - vs[g->nvs].origin - = vs[g->nvs].from - = vs[g->nvs].to = pge->iy3; - vs[g->nvs].ge = ge; - - if(pge->type==GE_CURVE) - ovalue=pge->iy2; - else - ovalue=pge->prev->iy3; - - if (pge->iy3 > ovalue) - vs[g->nvs].flags = ST_UP | ST_END; - else if (pge->iy3 < ovalue) - vs[g->nvs].flags = ST_END; - else - vs[g->nvs].flags = 0; - - if( vs[g->nvs].flags != 0 ) - g->nvs++; - - /* add end as vstem */ - vs[g->nvs].value = ge->ix3; - vs[g->nvs].origin - = vs[g->nvs].from - = vs[g->nvs].to = ge->iy3; - vs[g->nvs].ge = ge->frwd; - - if(nge->type==GE_CURVE) - ovalue=nge->iy1; - else - ovalue=nge->iy3; - - if (ovalue > ge->iy3) - vs[g->nvs].flags = ST_UP | ST_END; - else if (ovalue < ge->iy3) - vs[g->nvs].flags = ST_END; - else - vs[g->nvs].flags = 0; - - if( vs[g->nvs].flags != 0 ) - g->nvs++; - - g->nhs++; - } - /* if it is vertical, add a vstem */ - /* and the ends as hstems if they brace the line */ - else if (ge->ix3 == ge->prev->ix3 - && ge->iy3 != ge->prev->iy3) { - vs[g->nvs].value = ge->ix3; - if (ge->iy3 > ge->prev->iy3) { - vs[g->nvs].flags = ST_FLAT | ST_UP; - vs[g->nvs].from = ge->prev->iy3; - vs[g->nvs].to = ge->iy3; - } else { - vs[g->nvs].flags = ST_FLAT; - vs[g->nvs].from = ge->iy3; - vs[g->nvs].to = ge->prev->iy3; - } - vs[g->nvs].origin = ge->iy3; - vs[g->nvs].ge = ge->frwd; - - pge = ge->bkwd; - - /* add beginning as hstem */ - hs[g->nhs].value = pge->iy3; - hs[g->nhs].origin - = hs[g->nhs].from - = hs[g->nhs].to = pge->ix3; - hs[g->nhs].ge = ge; - - if(pge->type==GE_CURVE) - ovalue=pge->ix2; - else - ovalue=pge->prev->ix3; - - if (pge->ix3 < ovalue) - hs[g->nhs].flags = ST_UP | ST_END; - else if (pge->ix3 > ovalue) - hs[g->nhs].flags = ST_END; - else - hs[g->nhs].flags = 0; - - if( hs[g->nhs].flags != 0 ) - g->nhs++; - - /* add end as hstem */ - hs[g->nhs].value = ge->iy3; - hs[g->nhs].origin - = hs[g->nhs].from - = hs[g->nhs].to = ge->ix3; - hs[g->nhs].ge = ge->frwd; - - if(nge->type==GE_CURVE) - ovalue=nge->ix1; - else - ovalue=nge->ix3; - - if (ovalue < ge->ix3) - hs[g->nhs].flags = ST_UP | ST_END; - else if (ovalue > ge->ix3) - hs[g->nhs].flags = ST_END; - else - hs[g->nhs].flags = 0; - - if( hs[g->nhs].flags != 0 ) - g->nhs++; - - g->nvs++; - } - /* - * check the end of line for a not smooth local - * extremum - */ - nge = ge->frwd; - - if (nge == 0) - continue; - else if (nge->type == GE_LINE) { - nx = nge->ix3; - ny = nge->iy3; - } else if (nge->type == GE_CURVE) { - nx = nge->ix1; - ny = nge->iy1; - } else - continue; - - /* check for vertical extremums */ - if ((ge->iy3 > ge->prev->iy3 && ge->iy3 > ny) - || (ge->iy3 < ge->prev->iy3 && ge->iy3 < ny)) { - hs[g->nhs].value = ge->iy3; - hs[g->nhs].from - = hs[g->nhs].to - = hs[g->nhs].origin = ge->ix3; - hs[g->nhs].ge = ge->frwd; - - if (ge->ix3 < ge->prev->ix3 - || nx < ge->ix3) - hs[g->nhs].flags = ST_UP; - else - hs[g->nhs].flags = 0; - - if (ge->ix3 != ge->prev->ix3 || nx != ge->ix3) - g->nhs++; - } - /* - * the same point may be both horizontal and vertical - * extremum - */ - /* check for horizontal extremums */ - if ((ge->ix3 > ge->prev->ix3 && ge->ix3 > nx) - || (ge->ix3 < ge->prev->ix3 && ge->ix3 < nx)) { - vs[g->nvs].value = ge->ix3; - vs[g->nvs].from - = vs[g->nvs].to - = vs[g->nvs].origin = ge->iy3; - vs[g->nvs].ge = ge->frwd; - - if (ge->iy3 > ge->prev->iy3 - || ny > ge->iy3) - vs[g->nvs].flags = ST_UP; - else - vs[g->nvs].flags = 0; - - if (ge->iy3 != ge->prev->iy3 || ny != ge->iy3) - g->nvs++; - } - } - } - - g->nhs=addbluestems(hs, g->nhs); - sortstems(hs, g->nhs); - sortstems(vs, g->nvs); - - if (ISDBG(STEMS)) - debugstems(g->name, hs, g->nhs, vs, g->nvs); - - /* find the stems interacting with the Blue Zones */ - markbluestems(hs, g->nhs); - - if(subhints) { - if (ISDBG(SUBSTEMS)) - fprintf(pfa_file, "%% %s: joining subst horizontal stems\n", g->name); - joinsubstems(hs, hs_pairs, g->nhs, 1); - uniformstems(hs, hs_pairs, g->nhs); - - if (ISDBG(SUBSTEMS)) - fprintf(pfa_file, "%% %s: joining subst vertical stems\n", g->name); - joinsubstems(vs, vs_pairs, g->nvs, 0); - - groupsubstems(g, hs, hs_pairs, g->nhs, vs, vs_pairs, g->nvs); - } - - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% %s: joining main horizontal stems\n", g->name); - g->nhs = joinmainstems(hs, g->nhs, 1); - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% %s: joining main vertical stems\n", g->name); - g->nvs = joinmainstems(vs, g->nvs, 0); - - if (ISDBG(MAINSTEMS)) - debugstems(g->name, hs, g->nhs, vs, g->nvs); - - if(g->nhs > 0) { - if ((sp = malloc(sizeof(STEM) * g->nhs)) == 0) { - fprintf(stderr, "**** not enough memory for hints ****\n"); - exit(255); - } - g->hstems = sp; - memcpy(sp, hs, sizeof(STEM) * g->nhs); - } else - g->hstems = 0; - - if(g->nvs > 0) { - if ((sp = malloc(sizeof(STEM) * g->nvs)) == 0) { - fprintf(stderr, "**** not enough memory for hints ****\n"); - exit(255); - } - g->vstems = sp; - memcpy(sp, vs, sizeof(STEM) * g->nvs); - } else - g->vstems = 0; - - /* now check that the stems won't overflow the interpreter's stem stack: - * some interpreters (like X11) push the stems on each change into - * stack and pop them only after the whole glyphs is completed. - */ - - totals = (g->nhs+g->nvs) / 2; /* we count whole stems, not halves */ - lastgrp = -1; - - for (ge = g->entries; ge != 0; ge = ge->next) { - grp=ge->stemid; - if(grp >= 0 && grp != lastgrp) { - if(grp==0) - totals += g->nsbs[0]; - else - totals += g->nsbs[grp] - g->nsbs[grp-1]; - - lastgrp = grp; - } - } - - /* be on the safe side, check for >= , not > */ - if(totals >= max_stemdepth) { /* oops, too deep */ - WARNING_2 { - fprintf(stderr, "Warning: glyph %s needs hint stack depth %d\n", g->name, totals); - fprintf(stderr, " (limit %d): removed the substituted hints from it\n", max_stemdepth); - } - if(g->nsg > 0) { - for (ge = g->entries; ge != 0; ge = ge->next) - ge->stemid = -1; - free(g->sbstems); g->sbstems = 0; - free(g->nsbs); g->nsbs = 0; - g->nsg = 0; - } - } - - /* now check if there are too many main stems */ - totals = (g->nhs+g->nvs) / 2; /* we count whole stems, not halves */ - if(totals >= max_stemdepth) { - /* even worse, too much of non-substituted stems */ - WARNING_2 { - fprintf(stderr, "Warning: glyph %s has %d main hints\n", g->name, totals); - fprintf(stderr, " (limit %d): removed the hints from it\n", max_stemdepth); - } - if(g->vstems) { - free(g->vstems); g->vstems = 0; g->nvs = 0; - } - if(g->hstems) { - free(g->hstems); g->hstems = 0; g->nhs = 0; - } - } -} - -/* convert weird curves that are close to lines into lines. -*/ - -void -fstraighten( - GLYPH * g -) -{ - GENTRY *ge, *pge, *nge, *ige; - double df; - int dir; - double iln, oln; - int svdir, i, o; - - for (ige = g->entries; ige != 0; ige = ige->next) { - if (ige->type != GE_CURVE) - continue; - - ge = ige; - pge = ge->bkwd; - nge = ge->frwd; - - df = 0.; - - /* look for vertical then horizontal */ - for(i=0; i<2; i++) { - o = !i; /* other axis */ - - iln = fabs(ge->fpoints[i][2] - pge->fpoints[i][2]); - oln = fabs(ge->fpoints[o][2] - pge->fpoints[o][2]); - /* - * if current curve is almost a vertical line, and it - * doesn't begin or end horizontally (and the prev/next - * line doesn't join smoothly ?) - */ - if( oln < 1. - || ge->fpoints[o][2] == ge->fpoints[o][1] - || ge->fpoints[o][0] == pge->fpoints[o][2] - || iln > 2. - || (iln > 1. && iln/oln > 0.1) ) - continue; - - - if(ISDBG(STRAIGHTEN)) - fprintf(stderr,"** straighten almost %s\n", (i? "horizontal":"vertical")); - - df = ge->fpoints[i][2] - pge->fpoints[i][2]; - dir = fsign(ge->fpoints[o][2] - pge->fpoints[o][2]); - ge->type = GE_LINE; - - /* - * suck in all the sequence of such almost lines - * going in the same direction but not deviating - * too far from vertical - */ - iln = fabs(nge->fpoints[i][2] - ge->fpoints[i][2]); - oln = nge->fpoints[o][2] - ge->fpoints[o][2]; - - while (fabs(df) <= 5 && nge->type == GE_CURVE - && dir == fsign(oln) /* that also gives oln != 0 */ - && iln <= 2. - && ( iln <= 1. || iln/fabs(oln) <= 0.1 ) ) { - ge->fx3 = nge->fx3; - ge->fy3 = nge->fy3; - - if(ISDBG(STRAIGHTEN)) - fprintf(stderr,"** straighten collapsing %s\n", (i? "horizontal":"vertical")); - freethisge(nge); - fixendpath(ge); - pge = ge->bkwd; - nge = ge->frwd; - - df = ge->fpoints[i][2] - pge->fpoints[i][2]; - - iln = fabs(nge->fpoints[i][2] - ge->fpoints[i][2]); - oln = nge->fpoints[o][2] - ge->fpoints[o][2]; - } - - /* now check what do we have as previous/next line */ - - if(ge != pge) { - if( pge->type == GE_LINE && pge->fpoints[i][2] == pge->prev->fpoints[i][2] - && fabs(pge->fpoints[o][2] != pge->prev->fpoints[o][2]) ) { - if(ISDBG(STRAIGHTEN)) fprintf(stderr,"** straighten join with previous 0x%x 0x%x\n", pge, ge); - /* join the previous line with current */ - pge->fx3 = ge->fx3; - pge->fy3 = ge->fy3; - - ige = freethisge(ge)->prev; /* keep the iterator valid */ - ge = pge; - fixendpath(ge); - pge = ge->bkwd; - } - } - - if(ge != nge) { - if (nge->type == GE_LINE && nge->fpoints[i][2] == ge->fpoints[i][2] - && fabs(nge->fpoints[o][2] != ge->fpoints[o][2]) ) { - if(ISDBG(STRAIGHTEN)) fprintf(stderr,"** straighten join with next 0x%x 0x%x\n", ge, nge); - /* join the next line with current */ - ge->fx3 = nge->fx3; - ge->fy3 = nge->fy3; - - freethisge(nge); - fixendpath(ge); - pge = ge->bkwd; - nge = ge->frwd; - - } - } - - if(ge != pge) { - /* try to align the lines if neccessary */ - if(df != 0.) - fclosegap(ge, ge, i, df, NULL); - } else { - /* contour consists of only one line, get rid of it */ - ige = freethisge(ge); /* keep the iterator valid */ - if(ige == 0) /* this was the last contour */ - return; - ige = ige->prev; - } - - break; /* don't bother looking at the other axis */ - } - } -} - -/* solve a square equation, - * returns the number of solutions found, the solutions - * are stored in res which should point to array of two doubles. - * min and max limit the area for solutions - */ - -static int -fsqequation( - double a, - double b, - double c, - double *res, - double min, - double max -) -{ - double D; - int n; - - if(ISDBG(SQEQ)) fprintf(stderr, "sqeq(%g,%g,%g) [%g;%g]\n", a, b, c, min, max); - - if(fabs(a) < 0.000001) { /* if a linear equation */ - n=0; - if(fabs(b) < 0.000001) /* not an equation at all */ - return 0; - res[0] = -c/b; - if(ISDBG(SQEQ)) fprintf(stderr, "sqeq: linear t=%g\n", res[0]); - if(res[0] >= min && res[0] <= max) - n++; - return n; - } - - D = b*b - 4.0*a*c; - if(ISDBG(SQEQ)) fprintf(stderr, "sqeq: D=%g\n", D); - if(D<0) - return 0; - - D = sqrt(D); - - n=0; - res[0] = (-b+D) / (2*a); - if(ISDBG(SQEQ)) fprintf(stderr, "sqeq: t1=%g\n", res[0]); - if(res[0] >= min && res[0] <= max) - n++; - - res[n] = (-b-D) / (2*a); - if(ISDBG(SQEQ)) fprintf(stderr, "sqeq: t2=%g\n", res[n]); - if(res[n] >= min && res[n] <= max) - n++; - - /* return 2nd solution only if it's different enough */ - if(n==2 && fabs(res[0]-res[1])<0.000001) - n=1; - - return n; -} - -/* check that the curves don't cross quadrant boundary */ -/* (float) */ - -/* - Here we make sure that the curve does not continue past - horizontal or vertical extremums. The horizontal points are - explained, vertical points are by analogy. - - The horizontal points are where the derivative - dy/dx is equal to 0. But the Bezier curves are defined by - parametric formulas - x=fx(t) - y=fy(t) - so finding this derivative is complicated. - Also even if we find some point (x,y) splitting at this point - is far not obvious. Fortunately we can use dy/dt = 0 instead, - this gets to a rather simple square equation and splitting - at a known value of t is simple. - - The formulas are: - - y = A*(1-t)^3 + 3*B*(1-t)^2*t + 3*C*(1-t)*t^2 + D*t^3 - y = (-A+3*B-3*C+D)*t^3 + (3*A-6*B+3*C)*t^2 + (-3*A+3*B)*t + A - dy/dt = 3*(-A+3*B-3*C+D)*t^2 + 2*(3*A-6*B+3*C)*t + (-3*A+3*B) - */ - -void -ffixquadrants( - GLYPH *g -) -{ - GENTRY *ge, *nge; - int i, j, np, oldnp; - double sp[5]; /* split points, last one empty */ - char dir[5]; /* for debugging, direction by which split happened */ - double a, b, *pts; /* points of a curve */ - - for (ge = g->entries; ge != 0; ge = ge->next) { - if (ge->type != GE_CURVE) - continue; - - doagain: - np = 0; /* no split points yet */ - if(ISDBG(QUAD)) { - fprintf(stderr, "%s: trying 0x%x (%g %g) (%g %g) (%g %g) (%g %g)\n ", g->name, - ge, ge->prev->fx3, ge->prev->fy3, ge->fx1, ge->fy1, ge->fx2, ge->fy2, - ge->fx3, ge->fy3); - } - for(i=0; i<2; i++) { /* first for x then for y */ - /* find the cooridnates of control points */ - a = ge->prev->fpoints[i][2]; - pts = &ge->fpoints[i][0]; - - oldnp = np; - np += fsqequation( - 3.0*(-a + 3.0*pts[0] - 3.0*pts[1] + pts[2]), - 6.0*(a - 2.0*pts[0] + pts[1]), - 3.0*(-a + pts[0]), - &sp[np], - 0.0, 1.0); /* XXX range is [0;1] */ - - if(np == oldnp) - continue; - - if(ISDBG(QUAD)) - fprintf(stderr, "%s: 0x%x: %d pts(%c): ", - g->name, ge, np-oldnp, i? 'y':'x'); - - /* remove points that are too close to the ends - * because hor/vert ends are permitted, also - * if the split point is VERY close to the ends - * but not exactly then just flatten it and check again. - */ - for(j = oldnp; j<np; j++) { - dir[j] = i; - if(ISDBG(QUAD)) - fprintf(stderr, "%g ", sp[j]); - if(sp[j] < 0.03) { /* front end of curve */ - if(ge->fpoints[i][0] != ge->prev->fpoints[i][2]) { - ge->fpoints[i][0] = ge->prev->fpoints[i][2]; - if(ISDBG(QUAD)) fprintf(stderr, "flattened at front\n"); - goto doagain; - } - if( ge->fpoints[i][1] != ge->fpoints[i][0] - && fsign(ge->fpoints[i][2] - ge->fpoints[i][1]) - != fsign(ge->fpoints[i][1] - ge->fpoints[i][0]) ) { - ge->fpoints[i][1] = ge->fpoints[i][0]; - if(ISDBG(QUAD)) fprintf(stderr, "flattened zigzag at front\n"); - goto doagain; - } - sp[j] = sp[j+1]; np--; j--; - if(ISDBG(QUAD)) fprintf(stderr, "(front flat) "); - } else if(sp[j] > 0.97) { /* rear end of curve */ - if(ge->fpoints[i][1] != ge->fpoints[i][2]) { - ge->fpoints[i][1] = ge->fpoints[i][2]; - if(ISDBG(QUAD)) fprintf(stderr, "flattened at rear\n"); - goto doagain; - } - if( ge->fpoints[i][0] != ge->fpoints[i][1] - && fsign(ge->prev->fpoints[i][2] - ge->fpoints[i][0]) - != fsign(ge->fpoints[i][0] - ge->fpoints[i][1]) ) { - ge->fpoints[i][0] = ge->fpoints[i][1]; - if(ISDBG(QUAD)) fprintf(stderr, "flattened zigzag at rear\n"); - goto doagain; - } - sp[j] = sp[j+1]; np--; j--; - if(ISDBG(QUAD)) fprintf(stderr, "(rear flat) "); - } - } - if(ISDBG(QUAD)) fprintf(stderr, "\n"); - } - - if(np==0) /* no split points, leave it alone */ - continue; - - if(ISDBG(QUAD)) { - fprintf(stderr, "%s: splitting 0x%x (%g %g) (%g %g) (%g %g) (%g %g) at %d points\n ", g->name, - ge, ge->prev->fx3, ge->prev->fy3, ge->fx1, ge->fy1, ge->fx2, ge->fy2, - ge->fx3, ge->fy3, np); - for(i=0; i<np; i++) - fprintf(stderr, "%g(%c) ", sp[i], dir[i] ? 'y':'x'); - fprintf(stderr, "\n"); - } - - /* sort the points ascending */ - for(i=0; i<np; i++) - for(j=i+1; j<np; j++) - if(sp[i] > sp[j]) { - a = sp[i]; sp[i] = sp[j]; sp[j] = a; - } - - /* now finally do the split on each point */ - for(j=0; j<np; j++) { - double k1, k2, c; - - k1 = sp[j]; - k2 = 1 - k1; - - if(ISDBG(QUAD)) fprintf(stderr, " 0x%x %g/%g\n", ge, k1, k2); - - nge = newgentry(GEF_FLOAT); - (*nge) = (*ge); - -#define SPLIT(pt1, pt2) ( (pt1) + k1*((pt2)-(pt1)) ) /* order is important! */ - for(i=0; i<2; i++) { /* for x and y */ - a = ge->fpoints[i][0]; /* get the middle points */ - b = ge->fpoints[i][1]; - - /* calculate new internal points */ - c = SPLIT(a, b); - - ge->fpoints[i][0] = SPLIT(ge->prev->fpoints[i][2], a); - ge->fpoints[i][1] = SPLIT(ge->fpoints[i][0], c); - - nge->fpoints[i][1] = SPLIT(b, nge->fpoints[i][2]); - nge->fpoints[i][0] = SPLIT(c, nge->fpoints[i][1]); - - ge->fpoints[i][2] = SPLIT(ge->fpoints[i][1], - + nge->fpoints[i][0]); - } -#undef SPLIT - - addgeafter(ge, nge); - - /* go to the next part, adjust remaining points */ - ge = nge; - for(i=j+1; i<np; i++) - sp[i] = (sp[i]-k1) / k2; - } - } - -} - -/* check if a curve is a zigzag */ - -static int -iiszigzag( - GENTRY *ge -) -{ - double k, k1, k2; - int a, b; - - if (ge->type != GE_CURVE) - return 0; - - a = ge->iy2 - ge->iy1; - b = ge->ix2 - ge->ix1; - if(a == 0) { - if(b == 0) { - return 0; - } else - k = FBIGVAL; - } else - k = fabs((double) b / (double) a); - - a = ge->iy1 - ge->prev->iy3; - b = ge->ix1 - ge->prev->ix3; - if(a == 0) { - if(b == 0) { - return 0; - } else - k1 = FBIGVAL; - } else - k1 = fabs((double) b / (double) a); - - a = ge->iy3 - ge->iy2; - b = ge->ix3 - ge->ix2; - if(a == 0) { - if(b == 0) { - return 0; - } else - k2 = FBIGVAL; - } else - k2 = fabs((double) b / (double) a); - - /* if the curve is not a zigzag */ - if ((k1+0.0001 >= k && k2 <= k+0.0001) || (k1 <= k+0.0001 && k2+0.0001 >= k)) - return 0; - else - return 1; -} - -/* check if a curve is a zigzag - floating */ - -static int -fiszigzag( - GENTRY *ge -) -{ - double k, k1, k2; - double a, b; - - if (ge->type != GE_CURVE) - return 0; - - a = fabs(ge->fy2 - ge->fy1); - b = fabs(ge->fx2 - ge->fx1); - if(a < FEPS) { - if(b < FEPS) { - return 0; - } else - k = FBIGVAL; - } else - k = b / a; - - a = fabs(ge->fy1 - ge->prev->fy3); - b = fabs(ge->fx1 - ge->prev->fx3); - if(a < FEPS) { - if(b < FEPS) { - return 0; - } else - k1 = FBIGVAL; - } else - k1 = b / a; - - a = fabs(ge->fy3 - ge->fy2); - b = fabs(ge->fx3 - ge->fx2); - if(a < FEPS) { - if(b < FEPS) { - return 0; - } else - k2 = FBIGVAL; - } else - k2 = b / a; - - /* if the curve is not a zigzag */ - if ((k1+0.0001 >= k && k2 <= k+0.0001) || (k1 <= k+0.0001 && k2+0.0001 >= k)) - return 0; - else - return 1; -} - -/* split the zigzag-like curves into two parts */ - -void -fsplitzigzags( - GLYPH * g -) -{ - GENTRY *ge, *nge; - double a, b, c, d; - - assertisfloat(g, "splitting zigzags"); - for (ge = g->entries; ge != 0; ge = ge->next) { - if (ge->type != GE_CURVE) - continue; - - /* if the curve is not a zigzag */ - if ( !fiszigzag(ge) ) { - continue; - } - - if(ISDBG(FCONCISE)) { - double maxsc1, maxsc2; - fprintf(stderr, "split a zigzag "); - fnormalizege(ge); - if( fcrossraysge(ge, ge, &maxsc1, &maxsc2, NULL) ) { - fprintf(stderr, "sc1=%g sc2=%g\n", maxsc1, maxsc2); - } else { - fprintf(stderr, "(rays don't cross)\n"); - } - } - /* split the curve by t=0.5 */ - nge = newgentry(GEF_FLOAT); - (*nge) = (*ge); - nge->type = GE_CURVE; - - a = ge->prev->fx3; - b = ge->fx1; - c = ge->fx2; - d = ge->fx3; - nge->fx3 = d; - nge->fx2 = (c + d) / 2.; - nge->fx1 = (b + 2. * c + d) / 4.; - ge->fx3 = (a + b * 3. + c * 3. + d) / 8.; - ge->fx2 = (a + 2. * b + c) / 4.; - ge->fx1 = (a + b) / 2.; - - a = ge->prev->fy3; - b = ge->fy1; - c = ge->fy2; - d = ge->fy3; - nge->fy3 = d; - nge->fy2 = (c + d) / 2.; - nge->fy1 = (b + 2. * c + d) / 4.; - ge->fy3 = (a + b * 3. + c * 3. + d) / 8.; - ge->fy2 = (a + 2. * b + c) / 4.; - ge->fy1 = (a + b) / 2.; - - addgeafter(ge, nge); - - if(ISDBG(FCONCISE)) { - dumppaths(g, ge, nge); - } - } -} - -/* free this GENTRY, returns what was ge->next - * (ge must be of type GE_LINE or GE_CURVE) - * works on both float and int entries - */ - -static GENTRY * -freethisge( - GENTRY *ge -) -{ - GENTRY *xge; - - if (ge->bkwd != ge->prev) { - /* at beginning of the contour */ - - xge = ge->bkwd; - if(xge == ge) { /* was the only line in contour */ - /* remove the contour completely */ - /* prev is GE_MOVE, next is GE_PATH, remove them all */ - - /* may be the first contour, then ->bkwd points to ge->entries */ - if(ge->prev->prev == 0) - *(GENTRY **)(ge->prev->bkwd) = ge->next->next; - else - ge->prev->prev->next = ge->next->next; - - if(ge->next->next) { - ge->next->next->prev = ge->prev->prev; - ge->next->next->bkwd = ge->prev->bkwd; - } - - xge = ge->next->next; - free(ge->prev); free(ge->next); free(ge); - return xge; - } - - /* move the start point of the contour */ - if(ge->flags & GEF_FLOAT) { - ge->prev->fx3 = xge->fx3; - ge->prev->fy3 = xge->fy3; - } else { - ge->prev->ix3 = xge->ix3; - ge->prev->iy3 = xge->iy3; - } - } else if(ge->frwd != ge->next) { - /* at end of the contour */ - - xge = ge->frwd->prev; - /* move the start point of the contour */ - if(ge->flags & GEF_FLOAT) { - xge->fx3 = ge->bkwd->fx3; - xge->fy3 = ge->bkwd->fy3; - } else { - xge->ix3 = ge->bkwd->ix3; - xge->iy3 = ge->bkwd->iy3; - } - } - - ge->prev->next = ge->next; - ge->next->prev = ge->prev; - ge->bkwd->frwd = ge->frwd; - ge->frwd->bkwd = ge->bkwd; - - xge = ge->next; - free(ge); - return xge; -} - -/* inserts a new gentry (LINE or CURVE) after another (MOVE - * or LINE or CURVE) - * corrects the first GE_MOVE if neccessary - */ - -static void -addgeafter( - GENTRY *oge, /* after this */ - GENTRY *nge /* insert this */ -) -{ - if(oge->type == GE_MOVE) { - /* insert before next */ - if(oge->next->type == GE_PATH) { - /* first and only GENTRY in path */ - nge->frwd = nge->bkwd = nge; - } else { - nge->frwd = oge->next; - nge->bkwd = oge->next->bkwd; - oge->next->bkwd->frwd = nge; - oge->next->bkwd = nge; - } - } else { - nge->frwd = oge->frwd; - nge->bkwd = oge; - oge->frwd->bkwd = nge; - oge->frwd = nge; - } - - nge->next = oge->next; - nge->prev = oge; - oge->next->prev = nge; - oge->next = nge; - - if(nge->frwd->prev->type == GE_MOVE) { - /* fix up the GE_MOVE entry */ - if(nge->flags & GEF_FLOAT) { - nge->frwd->prev->fx3 = nge->fx3; - nge->frwd->prev->fy3 = nge->fy3; - } else { - nge->frwd->prev->ix3 = nge->ix3; - nge->frwd->prev->iy3 = nge->iy3; - } - } -} - -/* - * Check if this GENTRY happens to be at the end of path - * and fix the first MOVETO accordingly - * handles both int and float - */ - -static void -fixendpath( - GENTRY *ge -) -{ - GENTRY *mge; - - mge = ge->frwd->prev; - if(mge->type == GE_MOVE) { - if(ge->flags & GEF_FLOAT) { - mge->fx3 = ge->fx3; - mge->fy3 = ge->fy3; - } else { - mge->ix3 = ge->ix3; - mge->iy3 = ge->iy3; - } - } -} - -/* - * This function adjusts the rest of path (the part from...to is NOT changed) - * to cover the specified gap by the specified axis (0 - X, 1 - Y). - * Gap is counted in direction (end_of_to - beginning_of_from). - * Returns by how much the gap was not closed (0.0 if it was fully closed). - * Ret contains by how much the first and last points of [from...to] - * were moved to bring them in consistence to the rest of the path. - * If ret==NULL then this info is not returned. - */ - -static double -fclosegap( - GENTRY *from, - GENTRY *to, - int axis, - double gap, - double *ret -) -{ -#define TIMESLARGER 10. /* how many times larger must be a curve to not change too much */ - double rm[2]; - double oldpos[2]; - double times, limit, df, dx; - int j, k; - GENTRY *xge, *pge, *nge, *bge[2]; - - /* remember the old points to calculate ret */ - oldpos[0] = from->prev->fpoints[axis][2]; - oldpos[1] = to->fpoints[axis][2]; - - rm[0] = rm[1] = gap / 2. ; - - bge[0] = from; /* this is convenient for iterations */ - bge[1] = to; - - /* first try to modify large curves but if have none then settle for small */ - for(times = (TIMESLARGER-1); times > 0.1; times /= 2. ) { - - if(rm[0]+rm[1] == 0.) - break; - - /* iterate in both directions, backwards then forwards */ - for(j = 0; j<2; j++) { - - if(rm[j] == 0.) /* if this direction is exhausted */ - continue; - - limit = fabs(rm[j]) * (1.+times); - - for(xge = bge[j]->cntr[j]; xge != bge[!j]; xge = xge->cntr[j]) { - dx = xge->fpoints[axis][2] - xge->prev->fpoints[axis][2]; - df = fabs(dx) - limit; - if( df <= FEPS ) /* curve is too small to change */ - continue; - - if( df >= fabs(rm[j]) ) - df = rm[j]; - else - df *= fsign(rm[j]); /* we may cover this part of rm */ - - rm[j] -= df; - limit = fabs(rm[j]) * (1.+times); - - if(xge->type == GE_CURVE) { /* correct internal points */ - double scale = ((dx+df) / dx) - 1.; - double base; - - if(j) - base = xge->fpoints[axis][2]; - else - base = xge->prev->fpoints[axis][2]; - - for(k = 0; k<2; k++) - xge->fpoints[axis][k] += scale * - (xge->fpoints[axis][k] - base); - } - - /* move all the intermediate lines */ - if(j) { - df = -df; /* absolute direction */ - pge = bge[1]->bkwd; - nge = xge->bkwd; - } else { - xge->fpoints[axis][2] += df; - pge = bge[0]; - nge = xge->frwd; - } - while(nge != pge) { - if(nge->type == GE_CURVE) { - nge->fpoints[axis][0] +=df; - nge->fpoints[axis][1] +=df; - } - nge->fpoints[axis][2] += df; - if(nge->next != nge->frwd) { /* last entry of contour */ - nge->frwd->prev->fpoints[axis][2] += df; - } - nge = nge->cntr[!j]; - } - - if(rm[j] == 0.) - break; - } - } - } - - /* find the difference */ - oldpos[0] -= from->prev->fpoints[axis][2]; - oldpos[1] -= to->fpoints[axis][2]; - - if(ret) { - ret[0] = oldpos[0] - from->prev->fpoints[axis][2]; - ret[1] = oldpos[1] - to->fpoints[axis][2]; - } - -#if 0 - if( rm[0]+rm[1] != gap - oldpos[1] + oldpos[0]) { - fprintf(stderr, "** gap=%g rm[0]=%g rm[1]=%g o[0]=%g o[1]=%g rg=%g og=%g\n", - gap, rm[0], rm[1], oldpos[0], oldpos[1], rm[0]+rm[1], - gap - oldpos[1] + oldpos[0]); - } -#endif - - return rm[0]+rm[1]; -#undef TIMESLARGER -} - -/* remove the lines or curves smaller or equal to the size limit */ - -static void -fdelsmall( - GLYPH *g, - double minlen -) -{ - GENTRY *ge, *nge, *pge, *xge, *next; - int i, k; - double dx, dy, d2, d2m; - double minlen2; -#define TIMESLARGER 10. /* how much larger must be a curve to not change too much */ - - minlen2 = minlen*minlen; - - for (ge = g->entries; ge != 0; ge = next) { - next = ge->next; - - if (ge->type != GE_CURVE && ge->type != GE_LINE) - continue; - - d2m = 0; - for(i= (ge->type==GE_CURVE? 0: 2); i<3; i++) { - dx = ge->fxn[i] - ge->prev->fx3; - dy = ge->fyn[i] - ge->prev->fy3; - d2 = dx*dx + dy*dy; - if(d2m < d2) - d2m = d2; - } - - if( d2m > minlen2 ) { /* line is not too small */ - /* XXX add more normalization here */ - continue; - } - - /* if the line is too small */ - - /* check forwards if we have a whole sequence of them */ - nge = ge; - for(xge = ge->frwd; xge != ge; xge = xge->frwd) { - d2m = 0; - for(i= (xge->type==GE_CURVE? 0: 2); i<3; i++) { - dx = xge->fxn[i] - xge->prev->fx3; - dy = xge->fyn[i] - xge->prev->fy3; - d2 = dx*dx + dy*dy; - if(d2m < d2) - d2m = d2; - } - if( d2m > minlen2 ) /* line is not too small */ - break; - nge = xge; - if(next == nge) /* move the next step past this sequence */ - next = next->next; - } - - /* check backwards if we have a whole sequence of them */ - pge = ge; - for(xge = ge->bkwd; xge != ge; xge = xge->bkwd) { - d2m = 0; - for(i= (xge->type==GE_CURVE? 0: 2); i<3; i++) { - dx = xge->fxn[i] - xge->prev->fx3; - dy = xge->fyn[i] - xge->prev->fy3; - d2 = dx*dx + dy*dy; - if(d2m < d2) - d2m = d2; - } - if( d2m > minlen2 ) /* line is not too small */ - break; - pge = xge; - } - - /* now we have a sequence of small fragments in pge...nge (inclusive) */ - - if(ISDBG(FCONCISE)) { - fprintf(stderr, "glyph %s has very small fragments(%x..%x..%x)\n", - g->name, pge, ge, nge); - dumppaths(g, pge, nge); - } - - /* reduce whole sequence to one part and remember the middle point */ - if(pge != nge) { - while(1) { - xge = pge->frwd; - if(xge == nge) { - pge->fx1 = pge->fx2 = pge->fx3; - pge->fx3 = nge->fx3; - pge->fy1 = pge->fy2 = pge->fy3; - pge->fy3 = nge->fy3; - pge->type = GE_CURVE; - freethisge(nge); - break; - } - if(xge == nge->bkwd) { - pge->fx1 = pge->fx2 = (pge->fx3+xge->fx3)/2.; - pge->fx3 = nge->fx3; - pge->fy1 = pge->fy2 = (pge->fy3+xge->fy3)/2.; - pge->fy3 = nge->fy3; - pge->type = GE_CURVE; - freethisge(nge); - freethisge(xge); - break; - } - freethisge(pge); pge = xge; - xge = nge->bkwd; freethisge(nge); nge = xge; - } - } - ge = pge; - - /* check if the whole sequence is small */ - dx = ge->fx3 - ge->prev->fx3; - dy = ge->fy3 - ge->prev->fy3; - d2 = dx*dx + dy*dy; - - if( d2 > minlen2 ) { /* no, it is not */ - double b, d; - - WARNING_3 fprintf(stderr, "glyph %s had a sequence of fragments < %g points each, reduced to one curve\n", - g->name, minlen); - - /* check that we did not create a monstrosity spanning quadrants */ - if(fsign(ge->fx1 - ge->prev->fx1) * fsign(ge->fx3 - ge->fx1) < 0 - || fsign(ge->fy1 - ge->prev->fy1) * fsign(ge->fy3 - ge->fy1) < 0 ) { - /* yes, we did; are both parts of this thing big enough ? */ - dx = ge->fx1 - ge->prev->fx3; - dy = ge->fy1 - ge->prev->fy3; - d2 = dx*dx + dy*dy; - - dx = ge->fx3 - ge->fx1; - dy = ge->fy3 - ge->fy1; - d2m = dx*dx + dy*dy; - - if(d2 > minlen2 && d2m > minlen2) { /* make two straights */ - nge = newgentry(GEF_FLOAT); - *nge = *ge; - - for(i=0; i<2; i++) { - ge->fpoints[i][2] = ge->fpoints[i][0]; - b = nge->fpoints[i][0]; - d = nge->fpoints[i][2] - b; - nge->fpoints[i][0] = b + 0.1*d; - nge->fpoints[i][1] = b + 0.9*d; - } - } - for(i=0; i<2; i++) { /* make one straight or first of two straights */ - b = ge->prev->fpoints[i][2]; - d = ge->fpoints[i][2] - b; - ge->fpoints[i][0] = b + 0.1*d; - ge->fpoints[i][1] = b + 0.9*d; - } - } - continue; - } - - if(ge->frwd == ge) { /* points to itself, just remove the path completely */ - WARNING_3 fprintf(stderr, "glyph %s had a path made of fragments < %g points each, removed\n", - g->name, minlen); - - next = freethisge(ge); - continue; - } - - /* now close the gap by x and y */ - for(i=0; i<2; i++) { - double gap; - - gap = ge->fpoints[i][2] - ge->prev->fpoints[i][2]; - if( fclosegap(ge, ge, i, gap, NULL) != 0.0 ) { - double scale, base; - - /* not good, as the last resort just scale the next line */ - gap = ge->fpoints[i][2] - ge->prev->fpoints[i][2]; - - if(ISDBG(FCONCISE)) - fprintf(stderr, " last resort on %c: closing next by %g\n", - (i==0 ? 'x' : 'y'), gap); - - nge = ge->frwd; - base = nge->fpoints[i][2]; - dx = ge->fpoints[i][2] - base; - if(fabs(dx) < FEPS) - continue; - - scale = ((dx-gap) / dx); - - if(nge->type == GE_CURVE) - for(k = 0; k<2; k++) - nge->fpoints[i][k] = base + - scale * (nge->fpoints[i][k] - base); - - ge->fpoints[i][2] -= gap; - } - } - - /* OK, the gap is closed - remove this useless GENTRY */ - freethisge(ge); - } -#undef TIMESLARGER -} - -/* find the point where two rays continuing vectors cross - * returns 1 if they cross, 0 if they don't - * If they cross optionally (if the pointers are not NULL) returns - * the maximal scales for both vectors and also optionally the point - * where the rays cross (twice). - * Expects that the curves are normalized. - * - * For convenience there are 2 front-end functions taking - * arguments in different formats - */ - -struct ray { - double x1, y1, x2, y2; - int isvert; - double k, b; /* lines are represented as y = k*x + b */ - double *maxp; -}; -static struct ray ray[3]; - -/* the back-end doing the actual work - * the rays are defined in the static array ray[] - */ - -static int -fcrossraysxx( - double crossdot[2][2] -) -{ - double x, y, max; - int i; - - for(i=0; i<2; i++) { - if(ray[i].x1 == ray[i].x2) - ray[i].isvert = 1; - else { - ray[i].isvert = 0; - ray[i].k = (ray[i].y2 - ray[i].y1) / (ray[i].x2 - ray[i].x1); - ray[i].b = ray[i].y2 - ray[i].k * ray[i].x2; - } - } - - if(ray[0].isvert && ray[1].isvert) { - if(ISDBG(FCONCISE)) fprintf(stderr, "crossrays: both vertical\n"); - return 0; /* both vertical, don't cross */ - } - - if(ray[1].isvert) { - ray[2] = ray[0]; /* exchange them */ - ray[0] = ray[1]; - ray[1] = ray[2]; - } - - if(ray[0].isvert) { - x = ray[0].x1; - } else { - if( fabs(ray[0].k - ray[1].k) < FEPS) { - if(ISDBG(FCONCISE)) fprintf(stderr, "crossrays: parallel lines, k = %g, %g\n", - ray[0].k, ray[1].k); - return 0; /* parallel lines */ - } - x = (ray[1].b - ray[0].b) / (ray[0].k - ray[1].k) ; - } - y = ray[1].k * x + ray[1].b; - - for(i=0; i<2; i++) { - if(ray[i].isvert) - max = (y - ray[i].y1) / (ray[i].y2 - ray[i].y1); - else - max = (x - ray[i].x1) / (ray[i].x2 - ray[i].x1); - /* check if wrong sides of rays cross */ - if( max < 0 ) { - if(ISDBG(FCONCISE)) fprintf(stderr, "crossrays: %c scale=%g @(%g,%g) (%g,%g)<-(%g,%g)\n", - (i?'Y':'X'), max, x, y, ray[i].x2, ray[i].y2, ray[i].x1, ray[i].y1); - return 0; - } - if(ray[i].maxp) - *ray[i].maxp = max; - } - if(crossdot != 0) { - crossdot[0][0] = crossdot[1][0] = x; - crossdot[0][1] = crossdot[1][1] = y; - } - return 1; -} - -/* the front-end getting the arguments from 4 dots defining - * a curve in the same format as for fapproxcurve(): - * rays are defined as beginning and end of the curve, - * the crossdot is inserted as the two middle dots of the curve - */ - -int -fcrossrayscv( - double curve[4][2 /*X,Y*/], - double *max1, - double *max2 -) -{ - ray[0].x1 = curve[0][X]; - ray[0].y1 = curve[0][Y]; - ray[0].x2 = curve[1][X]; - ray[0].y2 = curve[1][Y]; - ray[0].maxp = max1; - - ray[1].x1 = curve[2][X]; - ray[1].y1 = curve[2][Y]; - ray[1].x2 = curve[3][X]; - ray[1].y2 = curve[3][Y]; - ray[1].maxp = max2; - - return fcrossraysxx(&curve[1]); -} - -/* the front-end getting the arguments from gentries: - * rays are defined as beginning of curve1 and end of curve 2 - */ - -int -fcrossraysge( - GENTRY *ge1, - GENTRY *ge2, - double *max1, - double *max2, - double crossdot[2][2] -) -{ - ray[0].x1 = ge1->prev->fx3; - ray[0].y1 = ge1->prev->fy3; - ray[0].x2 = ge1->fpoints[X][ge1->ftg]; - ray[0].y2 = ge1->fpoints[Y][ge1->ftg]; - ray[0].maxp = max1; - - ray[1].x1 = ge2->fx3; - ray[1].y1 = ge2->fy3; - if(ge2->rtg < 0) { - ray[1].x2 = ge2->prev->fx3; - ray[1].y2 = ge2->prev->fy3; - } else { - ray[1].x2 = ge2->fpoints[X][ge2->rtg]; - ray[1].y2 = ge2->fpoints[Y][ge2->rtg]; - } - ray[1].maxp = max2; - - return fcrossraysxx(crossdot); -} - -/* debugging printout functions */ - -#if defined(DEBUG_DOTSEG) || defined(DEBUG_DOTCURVE) || defined(DEBUG_APPROXCV) - -/* for debugging */ -static -printdot( - double dot[2] -) -{ - fprintf(stderr, "(%g,%g)", dot[0], dot[1]); -} - -static -printseg( - double seg[2][2] -) -{ - putc('[', stderr); - printdot(seg[0]); - putc(' ', stderr); - printdot(seg[1]); - putc(']', stderr); -} - -#endif /* DEBUG_* */ - -/* - * Find squared distance from a dot to a line segment - */ - -double -fdotsegdist2( - double seg[2][2 /*X,Y*/], - double dot[2 /*X,Y*/] -) -{ -#define x1 seg[0][X] -#define y1 seg[0][Y] -#define x2 seg[1][X] -#define y2 seg[1][Y] -#define xdot dot[X] -#define ydot dot[Y] - - double dx, dy; /* segment dimensions */ - double kline, bline; /* segment line formula is y=k*x+b */ - double kperp, bperp; /* perpendicular from the dot to the line */ - double xcross, ycross; /* where the perpendicular crosses the segment */ - -/* handle the situation where the nearest point of the segment is its end */ -#define HANDLE_LIMITS(less12, lesscr1, lesscr2) \ - if( less12 ) { \ - if( lesscr1 ) { \ - xcross = x1; \ - ycross = y1; \ - } else if( !(lesscr2) ) { \ - xcross = x2; \ - ycross = y2; \ - } \ - } else { \ - if( !(lesscr1) ) { \ - xcross = x1; \ - ycross = y1; \ - } else if( lesscr2 ) { \ - xcross = x2; \ - ycross = y2; \ - } \ - } \ - /* end of macro */ - - - dx = x2 - x1; - dy = y2 - y1; - - if(fabs(dx) < FEPS) { - /* special case - vertical line */ -#ifdef DEBUG_DOTSEG - printf("vertical line!\n"); -#endif - xcross = x1; - ycross = ydot; - HANDLE_LIMITS( y1 < y2, ycross < y1, ycross < y2); - } else if(fabs(dy) < FEPS) { - /* special case - horizontal line */ -#ifdef DEBUG_DOTSEG - printf("horizontal line!\n"); -#endif - xcross = xdot; - ycross = y1; - HANDLE_LIMITS( x1 < x2, xcross < x1, xcross < x2) - } else { - kline = dy/dx; - bline = y1 - x1*kline; - kperp = -1./kline; - bperp = ydot - xdot*kperp; - - xcross = (bline-bperp) / (kperp-kline); - ycross = kline*xcross + bline; - - HANDLE_LIMITS( x1 < x2, xcross < x1, xcross < x2) - } -#ifdef DEBUG_DOTSEG - printf("crossover at (%g,%g)\n", xcross, ycross); -#endif - - dx = xdot-xcross; - dy = ydot-ycross; - return dx*dx+dy*dy; -#undef x1 -#undef y1 -#undef x2 -#undef y2 -#undef xdot -#undef ydot -#undef HANDLE_LIMITS -} - -/* find the weighted quadratic average for the distance of a set - * of dots from the curve; also fills out the individual distances - * for each dot; if maxp!=NULL then returns the maximal squared - * distance in there - */ - -double -fdotcurvdist2( - double curve[4][2 /*X,Y*/ ], - struct dot_dist *dots, - int ndots, /* number of entries in dots */ - double *maxp -) -{ - /* a curve is approximated by this many straight segments */ -#define NAPSECT 16 - /* a curve is divided into this many sections with equal weight each */ -#define NWSECT 4 - /* table of coefficients for finding the dots on the curve */ - /* tt[0] is left unused */ - static double tt[NAPSECT][4]; - static int havett = 0; /* flag: tt is initialized */ - /* dots on the curve */ - double cvd[NAPSECT+1][2 /*X,Y*/]; - /* sums by sections */ - double sum[NWSECT]; - /* counts by sections */ - double count[NWSECT]; - int d, i, j; - int id1, id2; - double dist1, dist2, dist3, dx, dy, x, y; - double max = 0.; - - if(!havett) { - double t, nt, t2, nt2, step; - - havett++; - step = 1. / NAPSECT; - t = 0; - for(i=1; i<NAPSECT; i++) { - t += step; - nt = 1 - t; - t2 = t*t; - nt2 = nt*nt; - tt[i][0] = nt2*nt; /* (1-t)^3 */ - tt[i][1] = 3*nt2*t; /* 3*(1-t)^2*t */ - tt[i][2] = 3*nt*t2; /* 3*(1-t)*t^2 */ - tt[i][3] = t2*t; /* t^3 */ - } - } - - for(i=0; i<NWSECT; i++) { - sum[i] = 0.; - count[i] = 0; - } - - /* split the curve into segments */ - for(d=0; d<2; d++) { /* X and Y */ - cvd[0][d] = curve[0][d]; /* endpoints */ - cvd[NAPSECT][d] = curve[3][d]; - for(i=1; i<NAPSECT; i++) { - cvd[i][d] = curve[0][d] * tt[i][0] - + curve[1][d] * tt[i][1] - + curve[2][d] * tt[i][2] - + curve[3][d] * tt[i][3]; - } - } - - for(d=0; d<ndots; d++) { -#ifdef DEBUG_DOTCURVE - printf("dot %d ", d); printdot(dots[d].p); printf(":\n"); - - /* for debugging */ - for(i=0; i< NAPSECT; i++) { - dist1 = fdotsegdist2(&cvd[i], dots[d].p); - printf(" seg %d ",i); printseg(&cvd[i]); printf(" dist=%g\n", sqrt(dist1)); - } -#endif - - x = dots[d].p[X]; - y = dots[d].p[Y]; - - /* find the nearest dot on the curve - * there may be up to 2 local minimums - so we start from the - * ends of curve and go to the center - */ - - id1 = 0; - dx = x - cvd[0][X]; - dy = y - cvd[0][Y]; - dist1 = dx*dx + dy*dy; -#ifdef DEBUG_DOTCURVE - printf(" dot 0 "); printdot(cvd[id1]); printf(" dist=%g\n", sqrt(dist1)); -#endif - for(i = 1; i<=NAPSECT; i++) { - dx = x - cvd[i][X]; - dy = y - cvd[i][Y]; - dist3 = dx*dx + dy*dy; -#ifdef DEBUG_DOTCURVE - printf(" dot %d ",i); printdot(cvd[i]); printf(" dist=%g\n", sqrt(dist3)); -#endif - if(dist3 < dist1) { - dist1 = dist3; - id1 = i; - } else - break; - } - - if(id1 < NAPSECT-1) { - id2 = NAPSECT; - dx = x - cvd[NAPSECT][X]; - dy = y - cvd[NAPSECT][Y]; - dist2 = dx*dx + dy*dy; -#ifdef DEBUG_DOTCURVE - printf(" +dot %d ", id2); printdot(cvd[id2]); printf(" dist=%g\n", sqrt(dist2)); -#endif - for(i = NAPSECT-1; i>id1+1; i--) { - dx = x - cvd[i][X]; - dy = y - cvd[i][Y]; - dist3 = dx*dx + dy*dy; -#ifdef DEBUG_DOTCURVE - printf(" dot %d ",i); printdot(cvd[i]); printf(" dist=%g\n", sqrt(dist3)); -#endif - if(dist3 < dist2) { - dist2 = dist3; - id2 = i; - } else - break; - } - - /* now find which of the local minimums is smaller */ - if(dist2 < dist1) { - id1 = id2; - } - } - - /* the nearest segment must include the nearest dot */ - if(id1==0) { - dots[d].seg = 0; - dots[d].dist2 = fdotsegdist2(&cvd[0], dots[d].p); - } else if(id1==NAPSECT) { - dots[d].seg = NAPSECT-1; - dots[d].dist2 = fdotsegdist2(&cvd[NAPSECT-1], dots[d].p); - } else { - dist1 = fdotsegdist2(&cvd[id1], dots[d].p); - dist2 = fdotsegdist2(&cvd[id1-1], dots[d].p); - if(dist2 < dist1) { - dots[d].seg = id1-1; - dots[d].dist2 = dist2; - } else { - dots[d].seg = id1; - dots[d].dist2 = dist1; - } - } - - i = dots[d].seg % NWSECT; - sum[i] += dots[d].dist2; - if(dots[d].dist2 > max) - max = dots[d].dist2; - count[i]++; -#ifdef DEBUG_DOTCURVE - printf(" best seg %d sect %d dist=%g\n", dots[d].seg, i, sqrt(dots[d].dist2)); -#endif - } - - /* calculate the weighted average */ - id1=0; - dist1=0.; - for(i=0; i<NWSECT; i++) { - if(count[i]==0) - continue; - id1++; - dist1 += sum[i]/count[i]; - } - if(maxp) - *maxp = max; - if(id1==0) /* no dots, strange */ - return 0.; - else - return dist1/id1; /* to get the average distance apply sqrt() */ -} - -/* - * Approximate a curve matching the giving set of points and with - * middle reference points going along the given segments (and no farther - * than these segments). - */ - -void -fapproxcurve( - double cv[4][2 /*X,Y*/ ], /* points 0-3 are passed in, points 1,2 - out */ - struct dot_dist *dots, /* the dots to approximate - distances returned - * there may be invalid */ - int ndots -) -{ - /* b and c are the middle control points */ -#define B 0 -#define C 1 - /* maximal number of sections on each axis - used for the first step */ -#define MAXSECT 2 - /* number of sections used for the other steps */ -#define NORMSECT 2 - /* when the steps become less than this many points, it's time to stop */ -#define STEPEPS 1. - double from[2 /*B,C*/], to[2 /*B,C*/]; - double middf[2 /*B,C*/][2 /*X,Y*/], df; - double coef[2 /*B,C*/][MAXSECT]; - double res[MAXSECT][MAXSECT], thisres, bestres, goodres; - int ncoef[2 /*B,C*/], best[2 /*B,C*/], good[2 /*B,C*/]; - int i, j, k, keepsym; - char bc[]="BC"; - char xy[]="XY"; - -#ifdef DEBUG_APPROXCV - fprintf(stderr, "Curve points:"); - for(i=0; i<4; i++) { - fprintf(stderr, " "); - printdot(cv[i]); - } - fprintf(stderr, "\nDots:"); - for(i=0; i<ndots; i++) { - fprintf(stderr, " "); - printdot(dots[i].p); - } - fprintf(stderr, "\n"); -#endif - - /* load the endpoints and calculate differences */ - for(i=0; i<2; i++) { - /* i is X, Y */ - middf[B][i] = cv[1][i]-cv[0][i]; - middf[C][i] = cv[2][i]-cv[3][i]; - - /* i is B, C */ - from[i] = 0.; - to[i] = 1.; - ncoef[i] = MAXSECT; - } - - while(ncoef[B] != 1 || ncoef[C] != 1) { - /* prepare the values of coefficients */ - for(i=0; i<2; i++) { /*B,C*/ -#ifdef DEBUG_APPROXCV - fprintf(stderr, "Coefficients by %c(%g,%g):", bc[i], from[i], to[i]); -#endif - df = (to[i]-from[i]) / (ncoef[i]*2); - for(j=0; j<ncoef[i]; j++) { - coef[i][j] = from[i] + df*(2*j+1); -#ifdef DEBUG_APPROXCV - fprintf(stderr, " %g", coef[i][j]); -#endif - } -#ifdef DEBUG_APPROXCV - fprintf(stderr, "\n"); -#endif - } - bestres = FBIGVAL; - /* i iterates by ncoef[B], j iterates by ncoef[C] */ - for(i=0; i<ncoef[B]; i++) { - for(j=0; j<ncoef[C]; j++) { - for(k=0; k<2; k++) { /*X, Y*/ - cv[1][k] = cv[0][k] + middf[B][k]*coef[B][i]; - cv[2][k] = cv[3][k] + middf[C][k]*coef[C][j]; - } - res[i][j] = thisres = fdotcurvdist2(cv, dots, ndots, NULL); - if(thisres < bestres) { - goodres = bestres; - good[B] = best[B]; - good[C] = best[C]; - bestres = thisres; - best[B] = i; - best[C] = j; - } else if(thisres < goodres) { - goodres = thisres; - good[B] = i; - good[C] = j; - } -#ifdef DEBUG_APPROXCV - fprintf(stderr, " at (%g,%g) dist=%g %s\n", coef[B][i], coef[C][j], sqrt(thisres), - (best[B]==i && best[C]==j)? "(BEST)":""); -#endif - } - } -#ifdef DEBUG_APPROXCV - fprintf(stderr, " best: at (%g, %g) dist=%g\n", - coef[B][best[B]], coef[C][best[C]], sqrt(bestres)); - fprintf(stderr, " B:%d,%d C:%d,%d -- 2nd best: at (%g, %g) dist=%g\n", - best[B], good[B], best[C], good[C], coef[B][good[B]], coef[C][good[C]], sqrt(goodres)); -#endif - - if(bestres < (0.1*0.1)) { /* consider it close enough */ - /* calculate the coordinates to return */ - for(k=0; k<2; k++) { /*X, Y*/ - cv[1][k] = cv[0][k] + middf[B][k]*coef[B][best[B]]; - cv[2][k] = cv[3][k] + middf[C][k]*coef[C][best[C]]; - } -#ifdef DEBUG_APPROXCV - fprintf(stderr, "quick approximated middle points "); printdot(cv[1]); - fprintf(stderr, " "); printdot(cv[2]); fprintf(stderr, "\n"); -#endif - return; - } - keepsym = 0; - if(best[B] != best[C] && best[B]-best[C] == good[C]-good[B]) { - keepsym = 1; -#ifdef DEBUG_APPROXCV - fprintf(stderr, "keeping symmetry!\n"); -#endif - } - for(i=0; i<2; i++) { /*B,C*/ - if(ncoef[i]==1) - continue; - if(keepsym) { - /* try to keep the symmetry */ - if(best[i] < good[i]) { - from[i] = coef[i][best[i]]; - to[i] = coef[i][good[i]]; - } else { - from[i] = coef[i][good[i]]; - to[i] = coef[i][best[i]]; - } - } else { - df = (to[i]-from[i]) / ncoef[i]; - from[i] += df*best[i]; - to[i] = from[i] + df; - } - if( fabs(df*middf[i][0]) < STEPEPS && fabs(df*middf[i][1]) < STEPEPS) { - /* this side has converged */ - from[i] = to[i] = (from[i]+to[i]) / 2.; - ncoef[i] = 1; - } else - ncoef[i] = NORMSECT; - } - - } - /* calculate the coordinates to return */ - for(k=0; k<2; k++) { /*X, Y*/ - cv[1][k] = cv[0][k] + middf[B][k]*from[B]; - cv[2][k] = cv[3][k] + middf[C][k]*from[C]; - } -#ifdef DEBUG_APPROXCV - fprintf(stderr, "approximated middle points "); printdot(cv[1]); - fprintf(stderr, " "); printdot(cv[2]); fprintf(stderr, "\n"); -#endif -#undef B -#undef C -#undef MAXSECT -#undef NORMSECT -#undef STEPEPS -} - -/* - * Find the squared value of the sinus of the angle between the - * end of ge1 and the beginning of ge2 - * The curve must be normalized. - */ - -static double -fjointsin2( - GENTRY *ge1, - GENTRY *ge2 -) -{ - double d[3][2 /*X,Y*/]; - double scale1, scale2, len1, len2; - int axis; - - if(ge1->rtg < 0) { - d[1][X] = ge1->fx3 - ge1->prev->fx3; - d[1][Y] = ge1->fy3 - ge1->prev->fy3; - } else { - d[1][X] = ge1->fx3 - ge1->fpoints[X][ge1->rtg]; - d[1][Y] = ge1->fy3 - ge1->fpoints[Y][ge1->rtg]; - } - d[2][X] = ge2->fpoints[X][ge2->ftg] - ge2->prev->fx3; - d[2][Y] = ge2->fpoints[Y][ge2->ftg] - ge2->prev->fy3; - - len1 = sqrt( d[1][X]*d[1][X] + d[1][Y]*d[1][Y] ); - len2 = sqrt( d[2][X]*d[2][X] + d[2][Y]*d[2][Y] ); - /* scale the 2nd segment to the length of 1 - * and to make sure that the 1st segment is longer scale it to - * the length of 2 and extend to the same distance backwards - */ - scale1 = 2./len1; - scale2 = 1./len2; - - for(axis=0; axis <2; axis++) { - d[0][axis] = -( d[1][axis] *= scale1 ); - d[2][axis] *= scale2; - } - return fdotsegdist2(d, d[2]); -} - -#if 0 -/* find the area covered by the curve - * (limited by the projections to the X axis) - */ - -static double -fcvarea( - GENTRY *ge -) -{ - double Ly, My, Ny, Py, Qx, Rx, Sx; - double area; - - /* y = Ly*t^3 + My*t^2 + Ny*t + Py */ - Ly = -ge->prev->fy3 + 3*(ge->fy1 - ge->fy2) + ge->fy3; - My = 3*ge->prev->fy3 - 6*ge->fy1 + 3*ge->fy2; - Ny = 3*(-ge->prev->fy3 + ge->fy1); - Py = ge->prev->fy3; - - /* dx/dt = Qx*t^2 + Rx*t + Sx */ - Qx = 3*(-ge->prev->fx3 + 3*(ge->fx1 - ge->fx2) + ge->fx3); - Rx = 6*(ge->prev->fx3 - 2*ge->fx1 + ge->fx2); - Sx = 3*(-ge->prev->fx3 + ge->fx1); - - /* area is integral[from 0 to 1]( y(t) * dx(t)/dt *dt) */ - area = 1./6.*(Ly*Qx) + 1./5.*(Ly*Rx + My*Qx) - + 1./4.*(Ly*Sx + My*Rx + Ny*Qx) + 1./3.*(My*Sx + Ny*Rx + Py*Qx) - + 1./2.*(Ny*Sx + Py*Rx) + Py*Sx; - - return area; -} -#endif - -/* find the value of point on the curve at the given parameter t, - * along the given axis (0 - X, 1 - Y). - */ - -static double -fcvval( - GENTRY *ge, - int axis, - double t -) -{ - double t2, mt, mt2; - - /* val = A*(1-t)^3 + 3*B*(1-t)^2*t + 3*C*(1-t)*t^2 + D*t^3 */ - t2 = t*t; - mt = 1-t; - mt2 = mt*mt; - - return ge->prev->fpoints[axis][2]*mt2*mt - + 3*(ge->fpoints[axis][0]*mt2*t + ge->fpoints[axis][1]*mt*t2) - + ge->fpoints[axis][2]*t*t2; -} - -/* - * Find ndots equally spaced dots on a curve or line and fill - * their coordinates into the dots array - */ - -static void -fsampledots( - GENTRY *ge, - double dots[][2], /* the dots to fill */ - int ndots -) -{ - int i, axis; - double t, nf, dx, d[2]; - - nf = ndots+1; - if(ge->type == GE_CURVE) { - for(i=0; i<ndots; i++) { - t = (i+1)/nf; - for(axis=0; axis<2; axis++) - dots[i][axis] = fcvval(ge, axis, t); - } - } else { /* line */ - d[0] = ge->fx3 - ge->prev->fx3; - d[1] = ge->fy3 - ge->prev->fy3; - for(i=0; i<ndots; i++) { - t = (i+1)/nf; - for(axis=0; axis<2; axis++) - dots[i][axis] = ge->prev->fpoints[axis][2] - + t*d[axis]; - } - } -} - -/* - * Allocate a structure gex_con - */ - -static void -alloc_gex_con( - GENTRY *ge -) -{ - ge->ext = (void*)calloc(1, sizeof(GEX_CON)); - if(ge->ext == 0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } -} - -/* - * Normalize a gentry for fforceconcise() : find the points that - * can be used to calculate the tangents. - */ - -static void -fnormalizege( - GENTRY *ge -) -{ - int midsame, frontsame, rearsame; - - if(ge->type == GE_LINE) { - ge->ftg = 2; - ge->rtg = -1; - } else { /* assume it's a curve */ - midsame = (fabs(ge->fx1-ge->fx2)<FEPS && fabs(ge->fy1-ge->fy2)<FEPS); - frontsame = (fabs(ge->fx1-ge->prev->fx3)<FEPS && fabs(ge->fy1-ge->prev->fy3)<FEPS); - rearsame = (fabs(ge->fx3-ge->fx2)<FEPS && fabs(ge->fy3-ge->fy2)<FEPS); - - if(midsame && (frontsame || rearsame) ) { - /* essentially a line */ - ge->ftg = 2; - ge->rtg = -1; - } else { - if(frontsame) { - ge->ftg = 1; - } else { - ge->ftg = 0; - } - if(rearsame) { - ge->rtg = 0; - } else { - ge->rtg = 1; - } - } - } -} - -/* various definition for the processing of outlines */ - -/* maximal average quadratic distance from the original curve - * (in dots) to consider the joined curve good - */ -#define CVEPS 1.5 -#define CVEPS2 (CVEPS*CVEPS) -/* squared sinus of the maximal angle that we consider a smooth joint */ -#define SMOOTHSIN2 0.25 /* 0.25==sin(30 degrees)^2 */ -/* squared line length that we consider small */ -#define SMALL_LINE2 (15.*15.) -/* how many times a curve must be bigger than a line to join, squared */ -#define TIMES_LINE2 (3.*3.) - -/* - * Normalize and analyse a gentry for fforceconcise() and fill out the gex_con - * structure - */ - -static void -fanalyzege( - GENTRY *ge -) -{ - int i, ix, iy; - double avsd2, dots[3][2 /*X,Y*/]; - GEX_CON *gex; - - gex = X_CON(ge); - memset(gex, 0, sizeof *gex); - - gex->len2 = 0; - for(i=0; i<2; i++) { - avsd2 = gex->d[i] = ge->fpoints[i][2] - ge->prev->fpoints[i][2]; - gex->len2 += avsd2*avsd2; - } - gex->sin2 = fjointsin2(ge, ge->frwd); - if(ge->type == GE_CURVE) { - ge->dir = fgetcvdir(ge); - for(i=0; i<2; i++) { - dots[0][i] = ge->prev->fpoints[i][2]; - dots[1][i] = ge->fpoints[i][2]; - dots[2][i] = fcvval(ge, i, 0.5); - } - avsd2 = fdotsegdist2(dots, dots[2]); - if(avsd2 <= CVEPS2) { - gex->flags |= GEXF_FLAT; - } - } else { - ge->dir = CVDIR_FEQUAL|CVDIR_REQUAL; - gex->flags |= GEXF_FLAT; - } - if(gex->flags & GEXF_FLAT) { - if( fabs(gex->d[X]) > FEPS && fabs(gex->d[Y]) < 5. - && fabs(gex->d[Y] / gex->d[X]) < 0.2) - gex->flags |= GEXF_HOR; - else if( fabs(gex->d[Y]) > FEPS && fabs(gex->d[X]) < 5. - && fabs(gex->d[X] / gex->d[Y]) < 0.2) - gex->flags |= GEXF_VERT; - } - ix = gex->isd[X] = fsign(gex->d[X]); - iy = gex->isd[Y] = fsign(gex->d[Y]); - if(ix <= 0) { - if(iy <= 0) - gex->flags |= GEXF_QDL; - if(iy >= 0) - gex->flags |= GEXF_QUL; - if(gex->flags & GEXF_HOR) - gex->flags |= GEXF_IDQ_L; - } - if(ix >= 0) { - if(iy <= 0) - gex->flags |= GEXF_QDR; - if(iy >= 0) - gex->flags |= GEXF_QUR; - if(gex->flags & GEXF_HOR) - gex->flags |= GEXF_IDQ_R; - } - if(gex->flags & GEXF_VERT) { - if(iy <= 0) { - gex->flags |= GEXF_IDQ_U; - } else { /* supposedly there is no 0-sized entry */ - gex->flags |= GEXF_IDQ_D; - } - } -} - -/* - * Analyse a joint between this and following gentry for fforceconcise() - * and fill out the corresponding parts of the gex_con structure - * Bothe entries must be analyzed first. - */ - -static void -fanalyzejoint( - GENTRY *ge -) -{ - GENTRY *nge = ge->frwd; - GENTRY tge; - GEX_CON *gex, *ngex; - double avsd2, dots[3][2 /*X,Y*/]; - int i; - - gex = X_CON(ge); ngex = X_CON(nge); - - /* look if they can be joined honestly */ - - /* if any is flat, they should join smoothly */ - if( (gex->flags & GEXF_FLAT || ngex->flags & GEXF_FLAT) - && gex->sin2 > SMOOTHSIN2) - goto try_flatboth; - - if(ge->type == GE_LINE) { - if(nge->type == GE_LINE) { - if(gex->len2 > SMALL_LINE2 || ngex->len2 > SMALL_LINE2) - goto try_flatboth; - } else { - if(gex->len2*TIMES_LINE2 > ngex->len2) - goto try_flatboth; - } - } else if(nge->type == GE_LINE) { - if(ngex->len2*TIMES_LINE2 > gex->len2) - goto try_flatboth; - } - - /* if curve changes direction */ - if( gex->isd[X]*ngex->isd[X]<0 || gex->isd[Y]*ngex->isd[Y]<0) - goto try_idealone; - - /* if would create a zigzag */ - if( ((ge->dir&CVDIR_FRONT)-CVDIR_FEQUAL) * ((nge->dir&CVDIR_REAR)-CVDIR_REQUAL) < 0 ) - goto try_flatone; - - if( fcrossraysge(ge, nge, NULL, NULL, NULL) ) - gex->flags |= GEXF_JGOOD; - -try_flatone: - /* look if they can be joined by flatting out one of the entries */ - - /* at this point we know that the general direction of the - * gentries is OK - */ - - if( gex->flags & GEXF_FLAT ) { - tge = *ge; - tge.fx1 = tge.fx3; - tge.fy1 = tge.fy3; - fnormalizege(&tge); - if( fcrossraysge(&tge, nge, NULL, NULL, NULL) ) - gex->flags |= GEXF_JFLAT|GEXF_JFLAT1; - } - if( ngex->flags & GEXF_FLAT ) { - tge = *nge; - tge.fx2 = ge->fx3; - tge.fy2 = ge->fy3; - fnormalizege(&tge); - if( fcrossraysge(ge, &tge, NULL, NULL, NULL) ) - gex->flags |= GEXF_JFLAT|GEXF_JFLAT2; - } - -try_idealone: - /* look if one of the entries can be brought to an idealized - * horizontal or vertical position and then joined - */ - if( gex->flags & GEXF_HOR && gex->isd[X]*ngex->isd[X]>=0 ) { - tge = *ge; - tge.fx1 = tge.fx3; - tge.fy1 = ge->prev->fy3; /* force horizontal */ - fnormalizege(&tge); - if( fcrossraysge(&tge, nge, NULL, NULL, NULL) ) - gex->flags |= GEXF_JID|GEXF_JID1; - } else if( gex->flags & GEXF_VERT && gex->isd[Y]*ngex->isd[Y]>=0 ) { - tge = *ge; - tge.fx1 = ge->prev->fx3; /* force vertical */ - tge.fy1 = tge.fy3; - fnormalizege(&tge); - if( fcrossraysge(&tge, nge, NULL, NULL, NULL) ) - gex->flags |= GEXF_JID|GEXF_JID1; - } - if( ngex->flags & GEXF_HOR && gex->isd[X]*ngex->isd[X]>=0 ) { - tge = *nge; - tge.fx2 = ge->fx3; - tge.fy2 = nge->fy3; /* force horizontal */ - fnormalizege(&tge); - if( fcrossraysge(ge, &tge, NULL, NULL, NULL) ) - gex->flags |= GEXF_JID|GEXF_JID2; - } else if( ngex->flags & GEXF_VERT && gex->isd[Y]*ngex->isd[Y]>=0 ) { - tge = *nge; - tge.fx2 = nge->fx3; /* force vertical */ - tge.fy2 = ge->fy3; - fnormalizege(&tge); - if( fcrossraysge(ge, &tge, NULL, NULL, NULL) ) - gex->flags |= GEXF_JID|GEXF_JID2; - } - -try_flatboth: - /* look if we can change them to one line */ - if(gex->flags & GEXF_FLAT && ngex->flags & GEXF_FLAT) { - for(i=0; i<2; i++) { - dots[0][i] = ge->prev->fpoints[i][2]; - dots[1][i] = nge->fpoints[i][2]; - dots[2][i] = ge->fpoints[i][2]; - } - if( fdotsegdist2(dots, dots[2]) <= CVEPS2) - gex->flags |= GEXF_JLINE; - } -} - -/* - * Force conciseness of one contour in the glyph, - * the contour is indicated by one entry from it. - */ - -static void -fconcisecontour( - GLYPH *g, - GENTRY *startge -) -{ -/* initial maximal number of dots to be used as reference */ -#define MAXDOTS ((NREFDOTS+1)*12) - - GENTRY *ge, *pge, *nge, *ige; - GEX_CON *gex, *pgex, *ngex, *nngex; - GENTRY tpge, tnge; - int quad, qq, i, j, ndots, maxdots; - int found[2]; - int joinmask, pflag, nflag; - struct dot_dist *dots; - double avsd2, maxd2, eps2; - double apcv[4][2]; - - if(startge == 0) { - fprintf(stderr, "WARNING: assertion in %s line %d, please report it to the ttf2pt1 project\n", - __FILE__, __LINE__); - fprintf(stderr, "Strange contour in glyph %s\n", g->name); - dumppaths(g, NULL, NULL); - return; - } - - if(startge->type != GE_CURVE && startge->type != GE_LINE) - return; /* probably a degenerate contour */ - - if(ISDBG(FCONCISE)) - fprintf(stderr, "processing contour 0x%p of glyph %s\n", startge, g->name); - - maxdots = MAXDOTS; - dots = (struct dot_dist *)malloc(sizeof(*dots)*maxdots); - if(dots == NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - - ge = startge; - joinmask = GEXF_JGOOD; - while(1) { - restart: - gex = X_CON(ge); - if((gex->flags & GEXF_JMASK) > ((joinmask<<1)-1)) { - if(ISDBG(FCONCISE)) - fprintf(stderr, "found higher flag (%x>%x) at 0x%p\n", - gex->flags & GEXF_JMASK, ((joinmask<<1)-1), ge); - joinmask <<= 1; - startge = ge; /* have to redo the pass */ - continue; - } - if(( gex->flags & joinmask )==0) - goto next; - - /* if we happen to be in the middle of a string of - * joinable entries, find its beginning - */ - if( gex->flags & (GEXF_JCVMASK^GEXF_JID) ) - quad = gex->flags & X_CON_F(ge->frwd) & GEXF_QMASK; - else if( gex->flags & GEXF_JID2 ) - quad = gex->flags & GEXF_QFROM_IDEAL(X_CON_F(ge->frwd)) & GEXF_QMASK; - else /* must be GEXF_JID1 */ - quad = GEXF_QFROM_IDEAL(gex->flags) & X_CON_F(ge->frwd) & GEXF_QMASK; - - pge = ge; - pgex = X_CON(pge->bkwd); - - if(ISDBG(FCONCISE)) - fprintf(stderr, "ge %p prev -> 0x%p ", ge, pge); - - while(pgex->flags & GEXF_JCVMASK) { - if( !(pgex->flags & ((GEXF_JCVMASK^GEXF_JID)|GEXF_JID2)) ) - qq = GEXF_QFROM_IDEAL(pgex->flags); - else - qq = pgex->flags & GEXF_QMASK; - - if(ISDBG(FCONCISE)) - fprintf(stderr, "(%x?%x)", quad, qq); - - if( !(quad & qq) ) { - if( !(X_CON_F(pge) & (GEXF_JCVMASK^GEXF_JID)) - && pgex->flags & (GEXF_JCVMASK^GEXF_JID) ) { - /* the previos entry is definitely a better match */ - if(pge == ge) { - if(ISDBG(FCONCISE)) - fprintf(stderr, "\nprev is a better match at %p\n", pge); - startge = ge; - goto next; - } else - pge = pge->frwd; - } - break; - } - - quad &= qq; - pge = pge->bkwd; - pgex = X_CON(pge->bkwd); - if(ISDBG(FCONCISE)) - fprintf(stderr, "0x%p ", pge); - } - - /* collect as many entries for joining as possible */ - nge = ge->frwd; - ngex = X_CON(nge); - nngex = X_CON(nge->frwd); - - if(ISDBG(FCONCISE)) - fprintf(stderr, ": 0x%x\nnext -> 0x%p ", pge, nge); - - while(ngex->flags & GEXF_JCVMASK) { - if( !(ngex->flags & ((GEXF_JCVMASK^GEXF_JID)|GEXF_JID1)) ) - qq = GEXF_QFROM_IDEAL(nngex->flags); - else - qq = nngex->flags & GEXF_QMASK; - - if(ISDBG(FCONCISE)) - fprintf(stderr, "(%x?%x)", quad, qq); - if( !(quad & qq) ) { - if( !(X_CON_F(nge->bkwd) & (GEXF_JCVMASK^GEXF_JID)) - && ngex->flags & (GEXF_JCVMASK^GEXF_JID) ) { - /* the next-next entry is definitely a better match */ - if(nge == ge->frwd) { - if(ISDBG(FCONCISE)) - fprintf(stderr, "\nnext %x is a better match than %x at %p (jmask %x)\n", - ngex->flags & GEXF_JCVMASK, gex->flags & GEXF_JCVMASK, nge, joinmask); - goto next; - } else - nge = nge->bkwd; - } - break; - } - - quad &= qq; - nge = nge->frwd; - ngex = nngex; - nngex = X_CON(nge->frwd); - if(ISDBG(FCONCISE)) - fprintf(stderr, "0x%p ", nge); - } - - if(ISDBG(FCONCISE)) - fprintf(stderr, ": 0x%x\n", nge); - - /* XXX add splitting of last entries if neccessary */ - - /* make sure that all the reference dots are valid */ - for(ige = pge; ige != nge->frwd; ige = ige->frwd) { - nngex = X_CON(ige); - if( !(nngex->flags & GEXF_VDOTS) ) { - fsampledots(ige, nngex->dots, NREFDOTS); - nngex->flags |= GEXF_VDOTS; - } - } - - /* do the actual joining */ - while(1) { - pgex = X_CON(pge); - ngex = X_CON(nge->bkwd); - /* now the segments to be joined are pge...nge */ - - ndots = 0; - for(ige = pge; ige != nge->frwd; ige = ige->frwd) { - if(maxdots < ndots+(NREFDOTS+1)) { - maxdots += MAXDOTS; - dots = (struct dot_dist *)realloc((void *)dots, sizeof(*dots)*maxdots); - if(dots == NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - } - nngex = X_CON(ige); - for(i=0; i<NREFDOTS; i++) { - for(j=0; j<2; j++) - dots[ndots].p[j] = nngex->dots[i][j]; - ndots++; - } - for(j=0; j<2; j++) - dots[ndots].p[j] = ige->fpoints[j][2]; - ndots++; - } - ndots--; /* the last point is not interesting */ - - tpge = *pge; - pflag = pgex->flags; - if(pflag & (GEXF_JGOOD|GEXF_JFLAT2|GEXF_JID2)) { - /* nothing */ - } else if(pflag & GEXF_JFLAT) { - tpge.fx1 = tpge.fx3; - tpge.fy1 = tpge.fy3; - } else if(pflag & GEXF_JID) { - if(pflag & GEXF_HOR) - tpge.fy1 = tpge.bkwd->fy3; - else - tpge.fx1 = tpge.bkwd->fx3; - } - - tnge = *nge; - nflag = ngex->flags; - if(nflag & (GEXF_JGOOD|GEXF_JFLAT1|GEXF_JID) - && !(nflag & GEXF_JID2)) { - /* nothing */ - } else if(nflag & GEXF_JFLAT) { - tnge.fx2 = tnge.bkwd->fx3; - tnge.fy2 = tnge.bkwd->fy3; - } else if(nflag & GEXF_JID) { - if(X_CON_F(nge) & GEXF_HOR) - tnge.fy2 = tnge.fy3; - else - tnge.fx2 = tnge.fx3; - } - - fnormalizege(&tpge); - fnormalizege(&tnge); - if( fcrossraysge(&tpge, &tnge, NULL, NULL, &apcv[1]) ) { - apcv[0][X] = tpge.bkwd->fx3; - apcv[0][Y] = tpge.bkwd->fy3; - /* apcv[1] and apcv[2] were filled by fcrossraysge() */ - apcv[3][X] = tnge.fx3; - apcv[3][Y] = tnge.fy3; - - /* calculate the precision depending on the smaller dimension of the curve */ - maxd2 = apcv[3][X]-apcv[0][X]; - maxd2 *= maxd2; - eps2 = apcv[3][Y]-apcv[0][Y]; - eps2 *= eps2; - if(maxd2 < eps2) - eps2 = maxd2; - eps2 *= (CVEPS2*4.) / (400.*400.); - if(eps2 < CVEPS2) - eps2 = CVEPS2; - else if(eps2 > CVEPS2*4.) - eps2 = CVEPS2*4.; - - fapproxcurve(apcv, dots, ndots); - - avsd2 = fdotcurvdist2(apcv, dots, ndots, &maxd2); - if(ISDBG(FCONCISE)) - fprintf(stderr, "avsd = %g, maxd = %g, ", sqrt(avsd2), sqrt(maxd2)); - if(avsd2 <= eps2 && maxd2 <= eps2*2.) { - /* we've guessed a curve that is close enough */ - ggoodcv++; ggoodcvdots += ndots; - - if(ISDBG(FCONCISE)) { - fprintf(stderr, "in %s joined %p-%p to ", g->name, pge, nge); - for(i=0; i<4; i++) { - fprintf(stderr, " (%g, %g)", apcv[i][X], apcv[i][Y]); - } - fprintf(stderr, " from\n"); - dumppaths(g, pge, nge); - } - for(i=0; i<3; i++) { - pge->fxn[i] = apcv[i+1][X]; - pge->fyn[i] = apcv[i+1][Y]; - } - pge->type = GE_CURVE; - ge = pge; - for(ige = pge->frwd; ; ige = pge->frwd) { - if(ige == pge) { - fprintf(stderr, "WARNING: assertion in %s line %d, please report it to the ttf2pt1 project\n", - __FILE__, __LINE__); - free(dots); - return; - } - if(startge == ige) - startge = pge; - free(ige->ext); - freethisge(ige); - if(ige == nge) - break; - } - fnormalizege(ge); - if(ISDBG(FCONCISE)) { - fprintf(stderr, "normalized "); - for(i=0; i<3; i++) { - fprintf(stderr, " (%g, %g)", ge->fpoints[X][i], ge->fpoints[Y][i]); - } - fprintf(stderr, "\n"); - } - fanalyzege(ge); - fanalyzejoint(ge); - fanalyzege(ge->bkwd); - fanalyzejoint(ge->bkwd); - - /* the results of this join will have to be reconsidered */ - startge = ge = ge->frwd; - goto restart; - } else { - gbadcv++; gbadcvdots += ndots; - } - } - - /* if we're down to 2 entries then the join has failed */ - if(pge->frwd == nge) { - pgex->flags &= ~joinmask; - if(ISDBG(FCONCISE)) - fprintf(stderr, "no match\n"); - goto next; - } - - /* reduce the number of entries by dropping one at some end, - * should never drop the original ge from the range - */ - - if(nge->bkwd == ge - || (pge != ge && (pgex->flags & GEXF_JCVMASK) <= (ngex->flags & GEXF_JCVMASK)) ) { - pge = pge->frwd; - } else { - nge = nge->bkwd; - } - if(ISDBG(FCONCISE)) - fprintf(stderr, "next try: %p to %p\n", pge, nge); - } - -next: - ge = ge->frwd; - if(ge == startge) { - joinmask = (joinmask >> 1) & GEXF_JCVMASK; - if(joinmask == 0) - break; - } - } - - /* join flat segments into lines */ - /* here ge==startge */ - while(1) { - gex = X_CON(ge); - if( !(gex->flags & GEXF_JLINE) ) - goto next2; - - ndots = 0; - dots[ndots].p[X] = ge->fx3; - dots[ndots].p[Y] = ge->fy3; - ndots++; - - pge = ge->bkwd; - nge = ge->frwd; - - if(ISDBG(FCONCISE)) - fprintf(stderr, "joining LINE from %p-%p\n", ge, nge); - - while(pge!=nge) { - pgex = X_CON(pge); - ngex = X_CON(nge); - if(ISDBG(FCONCISE)) - fprintf(stderr, "(p=%p/%x n=0x%x/%x) ", pge, pgex->flags & GEXF_JLINE, - nge, ngex->flags & GEXF_JLINE); - if( !((pgex->flags | ngex->flags) & GEXF_JLINE) ) { - if(ISDBG(FCONCISE)) - fprintf(stderr, "(end p=%p n=%p) ", pge, nge); - break; - } - - if(maxdots < ndots+2) { - maxdots += MAXDOTS; - dots = (struct dot_dist *)realloc((void *)dots, sizeof(*dots)*maxdots); - if(dots == NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - } - if( pgex->flags & GEXF_JLINE ) { - for(i=0; i<2; i++) { - apcv[0][i] = pge->bkwd->fpoints[i][2]; - apcv[1][i] = nge->fpoints[i][2]; - dots[ndots].p[i] = pge->fpoints[i][2]; - } - ndots++; - for(i=0; i<ndots; i++) { - avsd2 = fdotsegdist2(apcv, dots[i].p); - if(avsd2 > CVEPS2) - break; - } - if(i<ndots) { /* failed to join */ - if(ISDBG(FCONCISE)) - fprintf(stderr, "failed to join prev %p ", pge); - ndots--; - pgex->flags &= ~GEXF_JLINE; - } else { - pge = pge->bkwd; - if(pge == nge) { - if(ISDBG(FCONCISE)) - fprintf(stderr, "intersected at prev %p ", pge); - break; /* oops, tried to self-intersect */ - } - } - } else if(ISDBG(FCONCISE)) - fprintf(stderr, "(p=%p) ", pge); - - if( ngex->flags & GEXF_JLINE ) { - for(i=0; i<2; i++) { - apcv[0][i] = pge->fpoints[i][2]; /* pge points before the 1st segment */ - apcv[1][i] = nge->frwd->fpoints[i][2]; - dots[ndots].p[i] = nge->fpoints[i][2]; - } - ndots++; - for(i=0; i<ndots; i++) { - avsd2 = fdotsegdist2(apcv, dots[i].p); - if(avsd2 > CVEPS2) - break; - } - if(i<ndots) { /* failed to join */ - if(ISDBG(FCONCISE)) - fprintf(stderr, "failed to join next %p ", nge->frwd); - ndots--; - ngex->flags &= ~GEXF_JLINE; - } else { - nge = nge->frwd; - } - } else if(ISDBG(FCONCISE)) - fprintf(stderr, "(n=%p) ", nge); - } - - pge = pge->frwd; /* now the limits are pge...nge inclusive */ - if(pge == nge) /* a deeply perversive contour */ - break; - - if(ISDBG(FCONCISE)) { - fprintf(stderr, "\nin %s joined LINE %p-%p from\n", g->name, pge, nge); - dumppaths(g, pge, nge); - } - pge->type = GE_LINE; - for(i=0; i<2; i++) { - pge->fpoints[i][2] = nge->fpoints[i][2]; - } - fnormalizege(pge); - X_CON_F(pge) &= ~GEXF_JLINE; - - ge = pge; - for(ige = pge->frwd; ; ige = pge->frwd) { - if(ige == pge) { - fprintf(stderr, "WARNING: assertion in %s line %d, please report it to the ttf2pt1 project\n", - __FILE__, __LINE__); - free(dots); - return; - } - if(startge == ige) - startge = pge; - free(ige->ext); - freethisge(ige); - if(ige == nge) - break; - } -next2: - ge = ge->frwd; - if(ge == startge) - break; - } - - free(dots); -} - -/* force conciseness: substitute 2 or more curves going in the -** same quadrant with one curve -** in floating point -*/ - -void -fforceconcise( - GLYPH * g -) -{ - - GENTRY *ge, *nge, *endge, *xge; - - assertisfloat(g, "enforcing conciseness"); - - fdelsmall(g, 0.05); - assertpath(g->entries, __FILE__, __LINE__, g->name); - - if(ISDBG(FCONCISE)) - dumppaths(g, NULL, NULL); - - /* collect more information about each gentry and their joints */ - for (ge = g->entries; ge != 0; ge = ge->next) - if (ge->type == GE_CURVE || ge->type == GE_LINE) - fnormalizege(ge); - - for (ge = g->entries; ge != 0; ge = ge->next) - if (ge->type == GE_CURVE || ge->type == GE_LINE) { - alloc_gex_con(ge); - fanalyzege(ge); - } - - /* see what we can do about joining */ - for (ge = g->entries; ge != 0; ge = ge->next) - if (ge->type == GE_CURVE || ge->type == GE_LINE) - fanalyzejoint(ge); - - /* now do the joining */ - for (ge = g->entries; ge != 0; ge = ge->next) - if(ge->type == GE_MOVE) - fconcisecontour(g, ge->next); - - for (ge = g->entries; ge != 0; ge = ge->next) - if (ge->type == GE_CURVE || ge->type == GE_LINE) - free(ge->ext); -} - -void -print_glyph( - int glyphno -) -{ - GLYPH *g; - GENTRY *ge; - int x = 0, y = 0; - int i; - int grp, lastgrp= -1; - - if(ISDBG(FCONCISE) && glyphno == 0) { - fprintf(stderr, "Guessed curves: bad %d/%d good %d/%d\n", - gbadcv, gbadcvdots, ggoodcv, ggoodcvdots); - } - - g = &glyph_list[glyphno]; - - fprintf(pfa_file, "/%s { \n", g->name); - - /* consider widths >MAXLEGALWIDTH as bugs */ - if( g->scaledwidth <= MAXLEGALWIDTH ) { - fprintf(pfa_file, "0 %d hsbw\n", g->scaledwidth); - } else { - fprintf(pfa_file, "0 1000 hsbw\n"); - WARNING_2 fprintf(stderr, "glyph %s: width %d seems to be buggy, set to 1000\n", - g->name, g->scaledwidth); - } - -#if 0 - fprintf(pfa_file, "%% contours: "); - for (i = 0; i < g->ncontours; i++) - fprintf(pfa_file, "%s(%d,%d) ", (g->contours[i].direction == DIR_OUTER ? "out" : "in"), - g->contours[i].xofmin, g->contours[i].ymin); - fprintf(pfa_file, "\n"); - - if (g->rymin < 5000) - fprintf(pfa_file, "%d lower%s\n", g->rymin, (g->flatymin ? "flat" : "curve")); - if (g->rymax > -5000) - fprintf(pfa_file, "%d upper%s\n", g->rymax, (g->flatymax ? "flat" : "curve")); -#endif - - if (g->hstems) - for (i = 0; i < g->nhs; i += 2) { - if (g->hstems[i].flags & ST_3) { - fprintf(pfa_file, "%d %d %d %d %d %d hstem3\n", - g->hstems[i].value, - g->hstems[i + 1].value - g->hstems[i].value, - g->hstems[i + 2].value, - g->hstems[i + 3].value - g->hstems[i + 2].value, - g->hstems[i + 4].value, - g->hstems[i + 5].value - g->hstems[i + 4].value - ); - i += 4; - } else { - fprintf(pfa_file, "%d %d hstem\n", g->hstems[i].value, - g->hstems[i + 1].value - g->hstems[i].value); - } - } - - if (g->vstems) - for (i = 0; i < g->nvs; i += 2) { - if (g->vstems[i].flags & ST_3) { - fprintf(pfa_file, "%d %d %d %d %d %d vstem3\n", - g->vstems[i].value, - g->vstems[i + 1].value - g->vstems[i].value, - g->vstems[i + 2].value, - g->vstems[i + 3].value - g->vstems[i + 2].value, - g->vstems[i + 4].value, - g->vstems[i + 5].value - g->vstems[i + 4].value - ); - i += 4; - } else { - fprintf(pfa_file, "%d %d vstem\n", g->vstems[i].value, - g->vstems[i + 1].value - g->vstems[i].value); - } - } - - for (ge = g->entries; ge != 0; ge = ge->next) { - if(g->nsg>0) { - grp=ge->stemid; - if(grp >= 0 && grp != lastgrp) { - fprintf(pfa_file, "%d 4 callsubr\n", grp+g->firstsubr); - lastgrp=grp; - } - } - - switch (ge->type) { - case GE_MOVE: - if (absolute) - fprintf(pfa_file, "%d %d amoveto\n", ge->ix3, ge->iy3); - else - rmoveto(ge->ix3 - x, ge->iy3 - y); - if (0) - fprintf(stderr, "Glyph %s: print moveto(%d, %d)\n", - g->name, ge->ix3, ge->iy3); - x = ge->ix3; - y = ge->iy3; - break; - case GE_LINE: - if (absolute) - fprintf(pfa_file, "%d %d alineto\n", ge->ix3, ge->iy3); - else - rlineto(ge->ix3 - x, ge->iy3 - y); - x = ge->ix3; - y = ge->iy3; - break; - case GE_CURVE: - if (absolute) - fprintf(pfa_file, "%d %d %d %d %d %d arcurveto\n", - ge->ix1, ge->iy1, ge->ix2, ge->iy2, ge->ix3, ge->iy3); - else - rrcurveto(ge->ix1 - x, ge->iy1 - y, - ge->ix2 - ge->ix1, ge->iy2 - ge->iy1, - ge->ix3 - ge->ix2, ge->iy3 - ge->iy2); - x = ge->ix3; - y = ge->iy3; - break; - case GE_PATH: - closepath(); - break; - default: - WARNING_1 fprintf(stderr, "**** Glyph %s: unknown entry type '%c'\n", - g->name, ge->type); - break; - } - } - - fprintf(pfa_file, "endchar } ND\n"); -} - -/* print the subroutines for this glyph, returns the number of them */ -int -print_glyph_subs( - int glyphno, - int startid /* start numbering subroutines from this id */ -) -{ - GLYPH *g; - int i, grp; - - g = &glyph_list[glyphno]; - - if(!hints || !subhints || g->nsg<1) - return 0; - - g->firstsubr=startid; - -#if 0 - fprintf(pfa_file, "%% %s %d\n", g->name, g->nsg); -#endif - for(grp=0; grp<g->nsg; grp++) { - fprintf(pfa_file, "dup %d {\n", startid++); - for(i= (grp==0)? 0 : g->nsbs[grp-1]; i<g->nsbs[grp]; i++) - fprintf(pfa_file, "\t%d %d %cstem\n", g->sbstems[i].low, - g->sbstems[i].high-g->sbstems[i].low, - g->sbstems[i].isvert ? 'v' : 'h'); - fprintf(pfa_file, "\treturn\n\t} NP\n"); - } - - return g->nsg; -} - -void -print_glyph_metrics( - int code, - int glyphno -) -{ - GLYPH *g; - - g = &glyph_list[glyphno]; - - if(transform) - fprintf(afm_file, "C %d ; WX %d ; N %s ; B %d %d %d %d ;\n", - code, g->scaledwidth, g->name, - iscale(g->xMin), iscale(g->yMin), iscale(g->xMax), iscale(g->yMax)); - else - fprintf(afm_file, "C %d ; WX %d ; N %s ; B %d %d %d %d ;\n", - code, g->scaledwidth, g->name, - g->xMin, g->yMin, g->xMax, g->yMax); -} - -/* - SB: - An important note about the BlueValues. - - The Adobe documentation says that the maximal width of a Blue zone - is connected to the value of BlueScale, which is by default 0.039625. - The BlueScale value defines, at which point size the overshoot - suppression be disabled. - - The formula for it that is given in the manual is: - - BlueScale=point_size/240, for a 300dpi device - - that makes us wonder what is this 240 standing for. Incidentally - 240=72*1000/300, where 72 is the relation between inches and points, - 1000 is the size of the glyph matrix, and 300dpi is the resolution of - the output device. Knowing that we can recalculate the formula for - the font size in pixels rather than points: - - BlueScale=pixel_size/1000 - - That looks a lot simpler than the original formula, does not it ? - And the limitation about the maximal width of zone also looks - a lot simpler after the transformation: - - max_width < 1000/pixel_size - - that ensures that even at the maximal pixel size when the overshoot - suppression is disabled the zone width will be less than one pixel. - This is important, failure to comply to this limit will result in - really ugly fonts (been there, done that). But knowing the formula - for the pixel width, we see that in fact we can use the maximal width - of 24, not 23 as specified in the manual. - -*/ - -#define MAXBLUEWIDTH (24) - -/* - * Find the indexes of the most frequent values - * in the hystogram, sort them in ascending order, and save which one - * was the best one (if asked). - * Returns the number of values found (may be less than maximal because - * we ignore the zero values) - */ - -#define MAXHYST (2000) /* size of the hystogram */ -#define HYSTBASE 500 - -static int -besthyst( - int *hyst, /* the hystogram */ - int base, /* the base point of the hystogram */ - int *best, /* the array for indexes of best values */ - int nbest, /* its allocated size */ - int width, /* minimal difference between indexes */ - int *bestindp /* returned top point */ -) -{ - unsigned char hused[MAXHYST / 8 + 1]; - int i, max, j, w, last = 0; - int nf = 0; - - width--; - - memset(hused, 0 , sizeof hused); - - max = 1; - for (i = 0; i < nbest && max != 0; i++) { - best[i] = 0; - max = 0; - for (j = 1; j < MAXHYST - 1; j++) { - w = hyst[j]; - - if (w > max && (hused[j>>3] & (1 << (j & 0x07))) == 0) { - best[i] = j; - max = w; - } - } - if (max != 0) { - if (max < last/2) { - /* do not pick the too low values */ - break; - } - for (j = best[i] - width; j <= best[i] + width; j++) { - if (j >= 0 && j < MAXHYST) - hused[j >> 3] |= (1 << (j & 0x07)); - } - last = max; - best[i] -= base; - nf = i + 1; - } - } - - if (bestindp) - *bestindp = best[0]; - - /* sort the indexes in ascending order */ - for (i = 0; i < nf; i++) { - for (j = i + 1; j < nf; j++) - if (best[j] < best[i]) { - w = best[i]; - best[i] = best[j]; - best[j] = w; - } - } - - return nf; -} - -/* - * Find the next best Blue zone in the hystogram. - * Return the weight of the found zone. - */ - -static int -bestblue( - short *zhyst, /* the zones hystogram */ - short *physt, /* the points hystogram */ - short *ozhyst, /* the other zones hystogram */ - int *bluetab /* where to put the found zone */ -) -{ - int i, j, w, max, ind, first, last; - - /* find the highest point in the zones hystogram */ - /* if we have a plateau, take its center */ - /* if we have multiple peaks, take the first one */ - - max = -1; - first = last = -10; - for (i = 0; i <= MAXHYST - MAXBLUEWIDTH; i++) { - w = zhyst[i]; - if (w > max) { - first = last = i; - max = w; - } else if (w == max) { - if (last == i - 1) - last = i; - } - } - ind = (first + last) / 2; - - if (max == 0) /* no zones left */ - return 0; - - /* now we reuse `first' and `last' as inclusive borders of the zone */ - first = ind; - last = ind + (MAXBLUEWIDTH - 1); - - /* our maximal width is far too big, so we try to make it narrower */ - w = max; - j = (w & 1); /* a pseudo-random bit */ - while (1) { - while (physt[first] == 0) - first++; - while (physt[last] == 0) - last--; - if (last - first < (MAXBLUEWIDTH * 2 / 3) || (max - w) * 10 > max) - break; - - if (physt[first] < physt[last] - || (physt[first] == physt[last] && j)) { - if (physt[first] * 20 > w) /* if weight is >5%, - * stop */ - break; - w -= physt[first]; - first++; - j = 0; - } else { - if (physt[last] * 20 > w) /* if weight is >5%, - * stop */ - break; - w -= physt[last]; - last--; - j = 1; - } - } - - /* save our zone */ - bluetab[0] = first - HYSTBASE; - bluetab[1] = last - HYSTBASE; - - /* invalidate all the zones overlapping with this one */ - /* the constant of 2 is determined by the default value of BlueFuzz */ - for (i = first - (MAXBLUEWIDTH - 1) - 2; i <= last + 2; i++) - if (i >= 0 && i < MAXHYST) { - zhyst[i] = 0; - ozhyst[i] = 0; - } - return w; -} - -/* - * Try to find the Blue Values, bounding box and italic angle - */ - -void -findblues(void) -{ - /* hystograms for upper and lower zones */ - short hystl[MAXHYST]; - short hystu[MAXHYST]; - short zuhyst[MAXHYST]; - short zlhyst[MAXHYST]; - int nchars; - int i, j, k, w, max; - GENTRY *ge; - GLYPH *g; - double ang; - - /* find the lowest and highest points of glyphs */ - /* and by the way build the values for FontBBox */ - /* and build the hystogram for the ItalicAngle */ - - /* re-use hystl for the hystogram of italic angle */ - - bbox[0] = bbox[1] = 5000; - bbox[2] = bbox[3] = -5000; - - for (i = 0; i < MAXHYST; i++) - hystl[i] = 0; - - nchars = 0; - - for (i = 0, g = glyph_list; i < numglyphs; i++, g++) { - if (g->flags & GF_USED) { - nchars++; - - g->rymin = 5000; - g->rymax = -5000; - for (ge = g->entries; ge != 0; ge = ge->next) { - if (ge->type == GE_LINE) { - - j = ge->iy3 - ge->prev->iy3; - k = ge->ix3 - ge->prev->ix3; - if (j > 0) - ang = atan2(-k, j) * 180.0 / M_PI; - else - ang = atan2(k, -j) * 180.0 / M_PI; - - k /= 100; - j /= 100; - if (ang > -45.0 && ang < 45.0) { - /* - * be careful to not overflow - * the counter - */ - hystl[HYSTBASE + (int) (ang * 10.0)] += (k * k + j * j) / 4; - } - if (ge->iy3 == ge->prev->iy3) { - if (ge->iy3 <= g->rymin) { - g->rymin = ge->iy3; - g->flatymin = 1; - } - if (ge->iy3 >= g->rymax) { - g->rymax = ge->iy3; - g->flatymax = 1; - } - } else { - if (ge->iy3 < g->rymin) { - g->rymin = ge->iy3; - g->flatymin = 0; - } - if (ge->iy3 > g->rymax) { - g->rymax = ge->iy3; - g->flatymax = 0; - } - } - } else if (ge->type == GE_CURVE) { - if (ge->iy3 < g->rymin) { - g->rymin = ge->iy3; - g->flatymin = 0; - } - if (ge->iy3 > g->rymax) { - g->rymax = ge->iy3; - g->flatymax = 0; - } - } - if (ge->type == GE_LINE || ge->type == GE_CURVE) { - if (ge->ix3 < bbox[0]) - bbox[0] = ge->ix3; - if (ge->ix3 > bbox[2]) - bbox[2] = ge->ix3; - if (ge->iy3 < bbox[1]) - bbox[1] = ge->iy3; - if (ge->iy3 > bbox[3]) - bbox[3] = ge->iy3; - } - } - } - } - - /* get the most popular angle */ - max = 0; - w = 0; - for (i = 0; i < MAXHYST; i++) { - if (hystl[i] > w) { - w = hystl[i]; - max = i; - } - } - ang = (double) (max - HYSTBASE) / 10.0; - WARNING_2 fprintf(stderr, "Guessed italic angle: %f\n", ang); - if (italic_angle == 0.0) - italic_angle = ang; - - /* build the hystogram of the lower points */ - for (i = 0; i < MAXHYST; i++) - hystl[i] = 0; - - for (i = 0, g = glyph_list; i < numglyphs; i++, g++) { - if ((g->flags & GF_USED) - && g->rymin + HYSTBASE >= 0 && g->rymin < MAXHYST - HYSTBASE) { - hystl[g->rymin + HYSTBASE]++; - } - } - - /* build the hystogram of the upper points */ - for (i = 0; i < MAXHYST; i++) - hystu[i] = 0; - - for (i = 0, g = glyph_list; i < numglyphs; i++, g++) { - if ((g->flags & GF_USED) - && g->rymax + HYSTBASE >= 0 && g->rymax < MAXHYST - HYSTBASE) { - hystu[g->rymax + HYSTBASE]++; - } - } - - /* build the hystogram of all the possible lower zones with max width */ - for (i = 0; i < MAXHYST; i++) - zlhyst[i] = 0; - - for (i = 0; i <= MAXHYST - MAXBLUEWIDTH; i++) { - for (j = 0; j < MAXBLUEWIDTH; j++) - zlhyst[i] += hystl[i + j]; - } - - /* build the hystogram of all the possible upper zones with max width */ - for (i = 0; i < MAXHYST; i++) - zuhyst[i] = 0; - - for (i = 0; i <= MAXHYST - MAXBLUEWIDTH; i++) { - for (j = 0; j < MAXBLUEWIDTH; j++) - zuhyst[i] += hystu[i + j]; - } - - /* find the baseline */ - w = bestblue(zlhyst, hystl, zuhyst, &bluevalues[0]); - if (0) - fprintf(stderr, "BaselineBlue zone %d%% %d...%d\n", w * 100 / nchars, - bluevalues[0], bluevalues[1]); - - if (w == 0) /* no baseline, something weird */ - return; - - /* find the upper zones */ - for (nblues = 2; nblues < 14; nblues += 2) { - w = bestblue(zuhyst, hystu, zlhyst, &bluevalues[nblues]); - - if (0) - fprintf(stderr, "Blue zone %d%% %d...%d\n", w * 100 / nchars, - bluevalues[nblues], bluevalues[nblues+1]); - - if (w * 20 < nchars) - break; /* don't save this zone */ - } - - /* find the lower zones */ - for (notherb = 0; notherb < 10; notherb += 2) { - w = bestblue(zlhyst, hystl, zuhyst, &otherblues[notherb]); - - if (0) - fprintf(stderr, "OtherBlue zone %d%% %d...%d\n", w * 100 / nchars, - otherblues[notherb], otherblues[notherb+1]); - - - if (w * 20 < nchars) - break; /* don't save this zone */ - } - -} - -/* - * Find the actual width of the glyph and modify the - * description to reflect it. Not guaranteed to do - * any good, may make character spacing too wide. - */ - -void -docorrectwidth(void) -{ - int i; - GENTRY *ge; - GLYPH *g; - int xmin, xmax; - int maxwidth, minsp; - - /* enforce this minimal spacing, - * we limit the amount of the enforced spacing to avoid - * spacing the bold wonts too widely - */ - minsp = (stdhw>60 || stdhw<10)? 60 : stdhw; - - for (i = 0, g = glyph_list; i < numglyphs; i++, g++) { - g->oldwidth=g->scaledwidth; /* save the old width, will need for AFM */ - - if (correctwidth && g->flags & GF_USED) { - xmin = 5000; - xmax = -5000; - for (ge = g->entries; ge != 0; ge = ge->next) { - if (ge->type != GE_LINE && ge->type != GE_CURVE) - continue; - - if (ge->ix3 <= xmin) { - xmin = ge->ix3; - } - if (ge->ix3 >= xmax) { - xmax = ge->ix3; - } - } - - maxwidth=xmax+minsp; - if( g->scaledwidth < maxwidth ) { - g->scaledwidth = maxwidth; - WARNING_3 fprintf(stderr, "glyph %s: extended from %d to %d\n", - g->name, g->oldwidth, g->scaledwidth ); - } - } - } - -} - -/* - * Try to find the typical stem widths - */ - -void -stemstatistics(void) -{ -#define MINDIST 10 /* minimal distance between the widths */ - int hyst[MAXHYST+MINDIST*2]; - int best[12]; - int i, j, k, w; - int nchars; - int ns; - STEM *s; - GLYPH *g; - - /* start with typical stem width */ - - nchars=0; - - /* build the hystogram of horizontal stem widths */ - memset(hyst, 0, sizeof hyst); - - for (i = 0, g = glyph_list; i < numglyphs; i++, g++) { - if (g->flags & GF_USED) { - nchars++; - s = g->hstems; - for (j = 0; j < g->nhs; j += 2) { - if ((s[j].flags | s[j + 1].flags) & ST_END) - continue; - w = s[j + 1].value - s[j].value+1; - if(w==20) /* split stems should not be counted */ - continue; - if (w > 0 && w < MAXHYST - 1) { - /* - * handle some fuzz present in - * converted fonts - */ - hyst[w+MINDIST] += MINDIST-1; - for(k=1; k<MINDIST-1; k++) { - hyst[w+MINDIST + k] += MINDIST-1-k; - hyst[w+MINDIST - k] += MINDIST-1-k; - } - } - } - } - } - - /* find 12 most frequent values */ - ns = besthyst(hyst+MINDIST, 0, best, 12, MINDIST, &stdhw); - - /* store data in stemsnaph */ - for (i = 0; i < ns; i++) - stemsnaph[i] = best[i]; - if (ns < 12) - stemsnaph[ns] = 0; - - /* build the hystogram of vertical stem widths */ - memset(hyst, 0, sizeof hyst); - - for (i = 0, g = glyph_list; i < numglyphs; i++, g++) { - if (g->flags & GF_USED) { - s = g->vstems; - for (j = 0; j < g->nvs; j += 2) { - if ((s[j].flags | s[j + 1].flags) & ST_END) - continue; - w = s[j + 1].value - s[j].value+1; - if (w > 0 && w < MAXHYST - 1) { - /* - * handle some fuzz present in - * converted fonts - */ - hyst[w+MINDIST] += MINDIST-1; - for(k=1; k<MINDIST-1; k++) { - hyst[w+MINDIST + k] += MINDIST-1-k; - hyst[w+MINDIST - k] += MINDIST-1-k; - } - } - } - } - } - - /* find 12 most frequent values */ - ns = besthyst(hyst+MINDIST, 0, best, 12, MINDIST, &stdvw); - - /* store data in stemsnaph */ - for (i = 0; i < ns; i++) - stemsnapv[i] = best[i]; - if (ns < 12) - stemsnapv[ns] = 0; - -#undef MINDIST -} - -/* - * SB - * A funny thing: TTF paths are going in reverse direction compared - * to Type1. So after all (because the rest of logic uses TTF - * path directions) we have to reverse the paths. - * - * It was a big headache to discover that. - */ - -/* works on both int and float paths */ - -void -reversepathsfromto( - GENTRY * from, - GENTRY * to -) -{ - GENTRY *ge, *nge, *pge; - GENTRY *cur, *next; - int i, n, ilast[2]; - double flast[2], f; - - for (ge = from; ge != 0 && ge != to; ge = ge->next) { - if(ge->type == GE_LINE || ge->type == GE_CURVE) { - if (ISDBG(REVERSAL)) - fprintf(stderr, "reverse path 0x%x <- 0x%x, 0x%x\n", ge, ge->prev, ge->bkwd); - - /* cut out the path itself */ - pge = ge->prev; /* GE_MOVE */ - if (pge == 0) { - fprintf(stderr, "**! No MOVE before line !!! Fatal. ****\n"); - exit(1); - } - nge = ge->bkwd->next; /* GE_PATH */ - pge->next = nge; - nge->prev = pge; - ge->bkwd->next = 0; /* mark end of chain */ - - /* remember the starting point */ - if(ge->flags & GEF_FLOAT) { - flast[0] = pge->fx3; - flast[1] = pge->fy3; - } else { - ilast[0] = pge->ix3; - ilast[1] = pge->iy3; - } - - /* then reinsert them in backwards order */ - for(cur = ge; cur != 0; cur = next ) { - next = cur->next; /* or addgeafter() will screw it up */ - if(cur->flags & GEF_FLOAT) { - for(i=0; i<2; i++) { - /* reverse the direction of path element */ - f = cur->fpoints[i][0]; - cur->fpoints[i][0] = cur->fpoints[i][1]; - cur->fpoints[i][1] = f; - f = flast[i]; - flast[i] = cur->fpoints[i][2]; - cur->fpoints[i][2] = f; - } - } else { - for(i=0; i<2; i++) { - /* reverse the direction of path element */ - n = cur->ipoints[i][0]; - cur->ipoints[i][0] = cur->ipoints[i][1]; - cur->ipoints[i][1] = n; - n = ilast[i]; - ilast[i] = cur->ipoints[i][2]; - cur->ipoints[i][2] = n; - } - } - addgeafter(pge, cur); - } - - /* restore the starting point */ - if(ge->flags & GEF_FLOAT) { - pge->fx3 = flast[0]; - pge->fy3 = flast[1]; - } else { - pge->ix3 = ilast[0]; - pge->iy3 = ilast[1]; - } - - ge = nge; - } - - } -} - -void -reversepaths( - GLYPH * g -) -{ - reversepathsfromto(g->entries, NULL); -} - -/* add a kerning pair information, scales the value */ - -void -addkernpair( - unsigned id1, - unsigned id2, - int unscval -) -{ - static unsigned char *bits = 0; - static int lastid; - GLYPH *g = &glyph_list[id1]; - int i, n; - struct kern *p; - - if(unscval == 0 || id1 >= numglyphs || id2 >= numglyphs) - return; - - if( (glyph_list[id1].flags & GF_USED)==0 - || (glyph_list[id2].flags & GF_USED)==0 ) - return; - - if(bits == 0) { - bits = calloc( BITMAP_BYTES(numglyphs), 1); - if (bits == NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - lastid = id1; - } - - if(lastid != id1) { - /* refill the bitmap cache */ - memset(bits, 0,BITMAP_BYTES(numglyphs)); - p = g->kern; - for(i=g->kerncount; i>0; i--) { - n = (p++)->id; - SET_BITMAP(bits, n); - } - lastid = id1; - } - - if(IS_BITMAP(bits, id2)) - return; /* duplicate */ - - if(g->kerncount <= g->kernalloc) { - g->kernalloc += 8; - p = realloc(g->kern, sizeof(struct kern) * g->kernalloc); - if(p == 0) { - fprintf (stderr, "** realloc failed, kerning data will be incomplete\n"); - } - g->kern = p; - } - - SET_BITMAP(bits, id2); - p = &g->kern[g->kerncount]; - p->id = id2; - p->val = iscale(unscval) - (g->scaledwidth - g->oldwidth); - g->kerncount++; - kerning_pairs++; -} - -/* print out the kerning information */ - -void -print_kerning( - FILE *afm_file -) -{ - int i, j, n; - GLYPH *g; - struct kern *p; - - if( kerning_pairs == 0 ) - return; - - fprintf(afm_file, "StartKernData\n"); - fprintf(afm_file, "StartKernPairs %hd\n", kerning_pairs); - - for(i=0; i<numglyphs; i++) { - g = &glyph_list[i]; - if( (g->flags & GF_USED) ==0) - continue; - p = g->kern; - for(j=g->kerncount; j>0; j--, p++) { - fprintf(afm_file, "KPX %s %s %d\n", g->name, - glyph_list[ p->id ].name, p->val ); - } - } - - fprintf(afm_file, "EndKernPairs\n"); - fprintf(afm_file, "EndKernData\n"); -} - - -#if 0 - -/* -** This function is commented out because the information -** collected by it is not used anywhere else yet. Now -** it only collects the directions of contours. And the -** direction of contours gets fixed already in draw_glyf(). -** -*********************************************** -** -** Here we expect that the paths are already closed. -** We also expect that the contours do not intersect -** and that curves doesn't cross any border of quadrant. -** -** Find which contours go inside which and what is -** their proper direction. Then fix the direction -** to make it right. -** -*/ - -#define MAXCONT 1000 - -void -fixcontours( - GLYPH * g -) -{ - CONTOUR cont[MAXCONT]; - short ymax[MAXCONT]; /* the highest point */ - short xofmax[MAXCONT]; /* X-coordinate of any point - * at ymax */ - short ymin[MAXCONT]; /* the lowest point */ - short xofmin[MAXCONT]; /* X-coordinate of any point - * at ymin */ - short count[MAXCONT]; /* count of lines */ - char dir[MAXCONT]; /* in which direction they must go */ - GENTRY *start[MAXCONT], *minptr[MAXCONT], *maxptr[MAXCONT]; - int ncont; - int i; - int dx1, dy1, dx2, dy2; - GENTRY *ge, *nge; - - /* find the contours and their most upper/lower points */ - ncont = 0; - ymax[0] = -5000; - ymin[0] = 5000; - for (ge = g->entries; ge != 0; ge = ge->next) { - if (ge->type == GE_LINE || ge->type == GE_CURVE) { - if (ge->iy3 > ymax[ncont]) { - ymax[ncont] = ge->iy3; - xofmax[ncont] = ge->ix3; - maxptr[ncont] = ge; - } - if (ge->iy3 < ymin[ncont]) { - ymin[ncont] = ge->iy3; - xofmin[ncont] = ge->ix3; - minptr[ncont] = ge; - } - } - if (ge->frwd != ge->next) { - start[ncont++] = ge->frwd; - ymax[ncont] = -5000; - ymin[ncont] = 5000; - } - } - - /* determine the directions of contours */ - for (i = 0; i < ncont; i++) { - ge = minptr[i]; - nge = ge->frwd; - - if (ge->type == GE_CURVE) { - dx1 = ge->ix3 - ge->ix2; - dy1 = ge->iy3 - ge->iy2; - - if (dx1 == 0 && dy1 == 0) { /* a pathological case */ - dx1 = ge->ix3 - ge->ix1; - dy1 = ge->iy3 - ge->iy1; - } - if (dx1 == 0 && dy1 == 0) { /* a more pathological - * case */ - dx1 = ge->ix3 - ge->prev->ix3; - dy1 = ge->iy3 - ge->prev->iy3; - } - } else { - dx1 = ge->ix3 - ge->prev->ix3; - dy1 = ge->iy3 - ge->prev->iy3; - } - if (nge->type == GE_CURVE) { - dx2 = ge->ix3 - nge->ix1; - dy2 = ge->iy3 - nge->iy1; - if (dx1 == 0 && dy1 == 0) { /* a pathological case */ - dx2 = ge->ix3 - nge->ix2; - dy2 = ge->iy3 - nge->iy2; - } - if (dx1 == 0 && dy1 == 0) { /* a more pathological - * case */ - dx2 = ge->ix3 - nge->ix3; - dy2 = ge->iy3 - nge->iy3; - } - } else { - dx2 = ge->ix3 - nge->ix3; - dy2 = ge->iy3 - nge->iy3; - } - - /* compare angles */ - cont[i].direction = DIR_INNER; - if (dy1 == 0) { - if (dx1 < 0) - cont[i].direction = DIR_OUTER; - } else if (dy2 == 0) { - if (dx2 > 0) - cont[i].direction = DIR_OUTER; - } else if (dx2 * dy1 < dx1 * dy2) - cont[i].direction = DIR_OUTER; - - cont[i].ymin = ymin[i]; - cont[i].xofmin = xofmin[i]; - } - - /* save the information that may be needed further */ - g->ncontours = ncont; - if (ncont > 0) { - g->contours = malloc(sizeof(CONTOUR) * ncont); - if (g->contours == 0) { - fprintf(stderr, "***** Memory allocation error *****\n"); - exit(255); - } - memcpy(g->contours, cont, sizeof(CONTOUR) * ncont); - } -} - -#endif - -/* - * - */ - diff --git a/nx-X11/extras/ttf2pt1/pt1.h b/nx-X11/extras/ttf2pt1/pt1.h deleted file mode 100644 index 4f65f8847..000000000 --- a/nx-X11/extras/ttf2pt1/pt1.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - * see COPYRIGHT - */ - - -/* glyph entry, one drawing command */ -typedef struct gentry { - /* this list links all GENTRYs of a GLYPH sequentially */ - struct gentry *next; /* double linked list */ - struct gentry *prev; - - /* this list links all GENTRYs of one contour - - * of types GE_LINE and GE_CURVE only - * bkwd is also reused: in the very first entry (normally - * of type GE_MOVE) it points to g->entries - */ - struct gentry *cntr[2]; /* double-linked circular list */ -/* convenience handles */ -#define bkwd cntr[0] -#define frwd cntr[1] - - /* various extended structures used at some stage of transformation */ - void *ext; - - union { - struct { - int val[2][3]; /* integer values */ - } i; - struct { - double val[2][3]; /* floating values */ - } f; - } points; /* absolute values, NOT deltas */ -/* convenience handles */ -#define ipoints points.i.val -#define fpoints points.f.val -#define ixn ipoints[0] -#define iyn ipoints[1] -#define fxn fpoints[0] -#define fyn fpoints[1] -#define ix1 ixn[0] -#define ix2 ixn[1] -#define ix3 ixn[2] -#define iy1 iyn[0] -#define iy2 iyn[1] -#define iy3 iyn[2] -#define fx1 fxn[0] -#define fx2 fxn[1] -#define fx3 fxn[2] -#define fy1 fyn[0] -#define fy2 fyn[1] -#define fy3 fyn[2] - - char flags; -#define GEF_FLOAT 0x02 /* entry contains floating point data */ -#define GEF_LINE 0x04 /* entry looks like a line even if it's a curve */ - - unsigned char dir; /* used to temporarily store the values for - * the directions of the ends of curves */ -/* front end */ -#define CVDIR_FUP 0x02 /* goes over the line connecting the ends */ -#define CVDIR_FEQUAL 0x01 /* coincides with the line connecting the - * ends */ -#define CVDIR_FDOWN 0x00 /* goes under the line connecting the ends */ -#define CVDIR_FRONT 0x0F /* mask of all front directions */ -/* rear end */ -#define CVDIR_RSAME 0x30 /* is the same as for the front end */ -#define CVDIR_RUP 0x20 /* goes over the line connecting the ends */ -#define CVDIR_REQUAL 0x10 /* coincides with the line connecting the - * ends */ -#define CVDIR_RDOWN 0x00 /* goes under the line connecting the ends */ -#define CVDIR_REAR 0xF0 /* mask of all rear directions */ - - signed char stemid; /* connection to the substituted stem group */ - char type; -#define GE_HSBW 'B' -#define GE_MOVE 'M' -#define GE_LINE 'L' -#define GE_CURVE 'C' -#define GE_PATH 'P' - - /* indexes of the points to be used for calculation of the tangents */ - signed char ftg; /* front tangent */ - signed char rtg; /* rear tangent, -1 means "idx 2 of the previous entry" */ -} GENTRY; - -/* stem structure, describes one [hv]stem */ -/* acually, it describes one border of a stem */ -/* the whole stem is a pair of these structures */ - -typedef struct stem { - short value; /* value of X or Y coordinate */ - short origin; /* point of origin for curve stems */ - GENTRY *ge; /* entry that has (value, origin) as its first dot */ - /* also for all the stems the couple (value, origin) - * is used to determine whether a stem is relevant for a - * line, it's considered revelant if this tuple is - * equal to any of the ends of the line. - * ge is also used to resolve ambiguity if there is more than - * one line going through certain pointi, it is used to - * distinguish these lines. - */ - - short from, to; /* values of other coordinate between - * which this stem is valid */ - - short flags; - /* ordering of ST_END, ST_FLAT, ST_ZONE is IMPORTANT for sorting */ -#define ST_END 0x01 /* end of line, lowest priority */ -#define ST_FLAT 0x02 /* stem is defined by a flat line, not a - * curve */ -#define ST_ZONE 0x04 /* pseudo-stem, the limit of a blue zone */ -#define ST_UP 0x08 /* the black area is to up or right from - * value */ -#define ST_3 0x20 /* first stem of [hv]stem3 */ -#define ST_BLUE 0x40 /* stem is in blue zone */ -#define ST_TOPZONE 0x80 /* 1 - top zone, 0 - bottom zone */ -#define ST_VERT 0x100 /* vertical stem (used in substitutions) */ -} STEM; - -#define MAX_STEMS 2000 /* we can't have more stems than path - * elements (or hope so) */ -#define NSTEMGRP 50 /* maximal number of the substituted stem groups */ - -/* structure for economical representation of the - * substituted stems - */ - -typedef struct stembounds { - short low; /* low bound */ - short high; /* high bound */ - char isvert; /* 1 - vertical, 0 - horizontal */ - char already; /* temp. flag: is aleready included */ -} STEMBOUNDS; - -struct kern { - unsigned id; /* ID of the second glyph */ - int val; /* kerning value */ -}; - -typedef struct contour { - short ymin, xofmin; - short inside; /* inside which contour */ - char direction; -#define DIR_OUTER 1 -#define DIR_INNER 0 -} CONTOUR; - -typedef struct glyph { - int char_no;/* Encoding of glyph */ - int orig_code;/* code of glyph in the font's original encoding */ - char *name; /* Postscript name of glyph */ - int xMin, yMin, xMax, yMax; /* values from TTF dictionary */ - int lsb; /* left sidebearing */ - int ttf_pathlen; /* total length of TTF paths */ - short width; - short flags; -#define GF_USED 0x0001 /* whether is this glyph used in T1 font */ -#define GF_FLOAT 0x0002 /* thys glyph contains floating point entries */ - - GENTRY *entries;/* doube linked list of entries */ - GENTRY *lastentry; /* the last inserted entry */ - GENTRY *path; /* beggining of the last path */ - int oldwidth; /* actually also scaled */ - int scaledwidth; -#define MAXLEGALWIDTH 10000 - - struct kern *kern; /* kerning data */ - int kerncount; /* number of kerning pairs */ - int kernalloc; /* for how many pairs we have space */ - - STEM *hstems; /* global horiz. and vert. stems */ - STEM *vstems; - int nhs, nvs; /* numbers of stems */ - - STEMBOUNDS *sbstems; /* substituted stems for all the groups */ - short *nsbs; /* indexes of the group ends in the common array */ - int nsg; /* actual number of the stem groups */ - int firstsubr; /* first substistuted stems subroutine number */ - - CONTOUR *contours; /* it is not used now */ - int ncontours; - - int rymin, rymax; /* real values */ - /* do we have flat surfaces on top/bottom */ - char flatymin, flatymax; - -} GLYPH; - -/* description of a dot for calculation of its distance to a curve */ - -struct dot_dist { - double p[2 /*X,Y*/]; /* coordinates of a dot */ - double dist2; /* squared distance from the dot to the curve */ - short seg; /* the closest segment of the curve */ -}; - -extern int stdhw, stdvw; /* dominant stems widths */ -extern int stemsnaph[12], stemsnapv[12]; /* most typical stem width */ - -extern int bluevalues[14]; -extern int nblues; -extern int otherblues[10]; -extern int notherb; -extern int bbox[4]; /* the FontBBox array */ -extern double italic_angle; - -extern GLYPH *glyph_list; -extern int encoding[]; /* inverse of glyph[].char_no */ - -/* prototypes of functions */ -void rmoveto( int dx, int dy); -void rlineto( int dx, int dy); -void rrcurveto( int dx1, int dy1, int dx2, int dy2, int dx3, int dy3); -void assertpath( GENTRY * from, char *file, int line, char *name); - -void fg_rmoveto( GLYPH * g, double x, double y); -void ig_rmoveto( GLYPH * g, int x, int y); -void fg_rlineto( GLYPH * g, double x, double y); -void ig_rlineto( GLYPH * g, int x, int y); -void fg_rrcurveto( GLYPH * g, double x1, double y1, - double x2, double y2, double x3, double y3); -void ig_rrcurveto( GLYPH * g, int x1, int y1, - int x2, int y2, int x3, int y3); -void g_closepath( GLYPH * g); - -void pathtoint( GLYPH *g); -void ffixquadrants( GLYPH *g); -void flattencurves( GLYPH * g); -int checkcv( GENTRY * ge, int dx, int dy); -void iclosepaths( GLYPH * g); -void fclosepaths( GLYPH * g); -void smoothjoints( GLYPH * g); -void buildstems( GLYPH * g); -void fstraighten( GLYPH * g); -void istraighten( GLYPH * g, int zigonly); -void isplitzigzags( GLYPH * g); -void fsplitzigzags( GLYPH * g); -void fforceconcise( GLYPH * g); -void iforceconcise( GLYPH * g); -void reversepathsfromto( GENTRY * from, GENTRY * to); -void reversepaths( GLYPH * g); -void dumppaths( GLYPH * g, GENTRY *start, GENTRY *end); -void print_glyph( int glyphno); -int print_glyph_subs( int glyphno, int startid); -void print_glyph_metrics( int code, int glyphno); -void findblues(void); -void stemstatistics(void); -void docorrectwidth(void); -void addkernpair( unsigned id1, unsigned id2, int unscval); -void print_kerning( FILE *afm_file); - -int fcrossrayscv( double curve[4][2], double *max1, double *max2); -int fcrossraysge( GENTRY *ge1, GENTRY *ge2, double *max1, double *max2, - double crossdot[2][2]); -double fdotsegdist2( double seg[2][2], double dot[2]); -double fdotcurvdist2( double curve[4][2], struct dot_dist *dots, int ndots, double *maxp); -void fapproxcurve( double cv[4][2], struct dot_dist *dots, int ndots); diff --git a/nx-X11/extras/ttf2pt1/runt1asm.c b/nx-X11/extras/ttf2pt1/runt1asm.c deleted file mode 100644 index 58c4cad8c..000000000 --- a/nx-X11/extras/ttf2pt1/runt1asm.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Wrap-around code to either compile in t1asm or call it externally - * - * Copyright (C) 2000 by Sergey Babkin - * Copyright (C) 2000 by The TTF2PT1 Project - * - * See COPYRIGHT for full license - */ - -#ifdef EXTERNAL_T1ASM - -#include <stdio.h> -#include <errno.h> - -FILE *ifp; -FILE *ofp; - -int -runt1asm( - int pfbflag -) -{ - char *cmd; - int id, od; - int error; - - /* first make a copy in case some of then is already stdin/stdout */ - if(( id = dup(fileno(ifp)) )<0) { - perror("** Re-opening input file for t1asm"); - exit(1); - } - if(( od = dup(fileno(ofp)) )<0) { - perror("** Re-opening output file for t1asm"); - exit(1); - } - fclose(ifp); fclose(ofp); - close(0); - if(( dup(id) )!=0) { - perror("** Re-directing input file for t1asm"); - exit(1); - } - close(1); - if(( dup(od) )!=1) { - perror("** Re-directing output file for t1asm"); - exit(1); - } - close(id); close(od); - - if(pfbflag) - error = execlp("t1asm", "t1asm", "-b", NULL); - else - error = execlp("t1asm", "t1asm", NULL); - - perror("** Calling t1asm"); - - exit(1); -} - -#else -# include "t1asm.c" -#endif diff --git a/nx-X11/extras/ttf2pt1/t1asm.c b/nx-X11/extras/ttf2pt1/t1asm.c deleted file mode 100644 index cf13f2005..000000000 --- a/nx-X11/extras/ttf2pt1/t1asm.c +++ /dev/null @@ -1,606 +0,0 @@ -/* t1asm - * - * This program `assembles' Adobe Type-1 font programs in pseudo-PostScript - * form into either PFB or PFA format. The human readable/editable input is - * charstring- and eexec-encrypted as specified in the `Adobe Type 1 Font - * Format' version 1.1 (the `black book'). There is a companion program, - * t1disasm, which `disassembles' PFB and PFA files into a pseudo-PostScript - * file. - * - * Copyright (c) 1992 by I. Lee Hetherington, all rights reserved. - * - * Permission is hereby granted to use, modify, and distribute this program - * for any purpose provided this copyright notice and the one below remain - * intact. - * - * I. Lee Hetherington (ilh@lcs.mit.edu) - * - * Revision 1.2 92/05/22 11:54:45 ilh - * Fixed bug where integers larger than 32000 could not be encoded in - * charstrings. Now integer range is correct for four-byte - * twos-complement integers: -(1<<31) <= i <= (1<<31)-1. Bug detected by - * Piet Tutelaers (rcpt@urc.tue.nl). - * - * Revision 1.1 92/05/22 11:48:46 ilh - * initial version - * - * Ported to Microsoft C/C++ Compiler and MS-DOS operating system by - * Kai-Uwe Herbing (herbing@netmbx.netmbx.de) on June 12, 1992. Code - * specific to the MS-DOS version is encapsulated with #ifdef _MSDOS - * ... #endif, where _MSDOS is an identifier, which is automatically - * defined, if you compile with the Microsoft C/C++ Compiler. - * - */ - -#ifndef lint -static char copyright[] = - "@(#) Copyright (c) 1992 by I. Lee Hetherington, all rights reserved."; -#ifdef _MSDOS -static char portnotice[] = - "@(#) Ported to MS-DOS by Kai-Uwe Herbing (herbing@netmbx.netmbx.de)."; -#endif -#endif - -/* Note: this is ANSI C. */ - -#ifdef _MSDOS - #include <fcntl.h> - #include <getopt.h> - #include <io.h> -#endif -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <limits.h> - -#ifdef WINDOWS -# ifdef STANDALONE -# define WINDOWS_FUNCTIONS -# include "windows.h" -# endif -#endif - -/* int32 must be at least 32-bit and uint16 must be at least 16-bit */ -#ifndef AIXV3 -#if INT_MAX >= 0x7FFFFFFFUL -typedef int int32; -#else -typedef long int32; -#endif -#endif /* !AIXV3 */ -#if USHRT_MAX >= 0xFFFFUL -typedef unsigned short uint16; -#else -typedef unsigned int uint16; -#endif - -#define LINESIZE 256 - -#define MAXBLOCKLEN ((1L<<17)-6) -#define MINBLOCKLEN ((1L<<8)-6) - -#define MARKER 128 -#define ASCII 1 -#define BINARY 2 -#define DONE 3 - -typedef unsigned char byte; - -/* must be visible from outside */ -FILE *ifp; -FILE *ofp; - -/* flags */ -static int pfb = 0; -static int active = 0; -static int start_charstring = 0; -static int in_eexec = 0; - -static char line[LINESIZE]; - -/* lenIV and charstring start command */ -static int lenIV = 4; -static char cs_start[10]; - -/* for charstring buffering */ -static byte charstring_buf[65535]; -static byte *charstring_bp; - -/* for PFB block buffering */ -static byte blockbuf[MAXBLOCKLEN]; -static int32 blocklen = MAXBLOCKLEN; -static int32 blockpos = -1; -static int blocktyp = ASCII; - -/* decryption stuff */ -static uint16 er, cr; -static uint16 c1 = 52845, c2 = 22719; - -/* table of charstring commands */ -static struct command { - char *name; - int one, two; -} command_table[] = { - { "callothersubr", 12, 16 }, - { "callsubr", 10, -1 }, - { "closepath", 9, -1 }, - { "div", 12, 12 }, - { "dotsection", 12, 0 }, - { "endchar", 14, -1 }, - { "hlineto", 6, -1 }, - { "hmoveto", 22, -1 }, - { "hsbw", 13, -1 }, - { "hstem", 1, -1 }, - { "hstem3", 12, 2 }, - { "hvcurveto", 31, -1 }, - { "pop", 12, 17 }, - { "return", 11, -1 }, - { "rlineto", 5, -1 }, - { "rmoveto", 21, -1 }, - { "rrcurveto", 8, -1 }, - { "sbw", 12, 7 }, - { "seac", 12, 6 }, - { "setcurrentpoint", 12, 33 }, - { "vhcurveto", 30, -1 }, - { "vlineto", 7, -1 }, - { "vmoveto", 4, -1 }, - { "vstem", 3, -1 }, - { "vstem3", 12, 1 }, -}; /* alphabetical */ - -/* Two separate encryption functions because eexec and charstring encryption - must proceed in parallel. */ - -static byte eencrypt(byte plain) -{ - byte cipher; - - cipher = (byte) (plain ^ (er >> 8)); - er = (uint16) ((cipher + er) * c1 + c2); - return cipher; -} - -static byte cencrypt(byte plain) -{ - byte cipher; - - cipher = (byte) (plain ^ (cr >> 8)); - cr = (uint16) ((cipher + cr) * c1 + c2); - return cipher; -} - -/* This function flushes a buffered PFB block. */ - -static void output_block() -{ - int32 i; - - /* output four-byte block length */ - fputc((int) (blockpos & 0xff), ofp); - fputc((int) ((blockpos >> 8) & 0xff), ofp); - fputc((int) ((blockpos >> 16) & 0xff), ofp); - fputc((int) ((blockpos >> 24) & 0xff), ofp); - - /* output block data */ - for (i = 0; i < blockpos; i++) - fputc(blockbuf[i], ofp); - - /* mark block buffer empty and uninitialized */ - blockpos = -1; -} - -/* This function outputs a single byte. If output is in PFB format then output - is buffered through blockbuf[]. If output is in PFA format, then output - will be hexadecimal if in_eexec is set, ASCII otherwise. */ - -static void output_byte(byte b) -{ - static char *hexchar = "0123456789ABCDEF"; - static int hexcol = 0; - - if (pfb) { - /* PFB */ - if (blockpos < 0) { - fputc(MARKER, ofp); - fputc(blocktyp, ofp); - blockpos = 0; - } - blockbuf[blockpos++] = b; - if (blockpos == blocklen) - output_block(); - } else { - /* PFA */ - if (in_eexec) { - /* trim hexadecimal lines to 64 columns */ - if (hexcol >= 64) { - fputc('\n', ofp); - hexcol = 0; - } - fputc(hexchar[(b >> 4) & 0xf], ofp); - fputc(hexchar[b & 0xf], ofp); - hexcol += 2; - } else { - fputc(b, ofp); - } - } -} - -/* This function outputs a byte through possible eexec encryption. */ - -static void eexec_byte(byte b) -{ - if (in_eexec) - output_byte(eencrypt(b)); - else - output_byte(b); -} - -/* This function outputs a null-terminated string through possible eexec - encryption. */ - -static void eexec_string(char *string) -{ - while (*string) - eexec_byte((byte) *string++); -} - -/* This function gets ready for the eexec-encrypted data. If output is in - PFB format then flush current ASCII block and get ready for binary block. - We start encryption with four random (zero) bytes. */ - -static void eexec_start() -{ - eexec_string(line); - if (pfb) { - output_block(); - blocktyp = BINARY; - } - - in_eexec = 1; - er = 55665; - eexec_byte(0); - eexec_byte(0); - eexec_byte(0); - eexec_byte(0); -} - -/* This function wraps-up the eexec-encrypted data. - If output is in PFB format then this entails flushing binary block and - starting an ASCII block. */ - -static void eexec_end() -{ - int i, j; - - if (pfb) { - output_block(); - blocktyp = ASCII; - } else { - fputc('\n', ofp); - } - in_eexec = 0; - for (i = 0; i < 8; i++) { - for (j = 0; j < 64; j++) - eexec_byte('0'); - eexec_byte('\n'); - } -#if 0 - eexec_string("cleartomark\n"); -#endif -} - -/* This function writes ASCII trailer. - If output is in PFB format then this entails flushing binary block and - starting an ASCII block. */ - -static void file_end() -{ - if (pfb) { - output_block(); - fputc(MARKER, ofp); - fputc(DONE, ofp); - } -} -/* This function returns an input line of characters. A line is terminated by - length (including terminating null) greater than LINESIZE, a newline \n, or - when active (looking for charstrings) by '{'. When terminated by a newline - the newline is put into line[]. When terminated by '{', the '{' is not put - into line[], and the flag start_charstring is set to 1. */ - -static void t1asm_getline() -{ - int c; - char *p = line; - int comment = 0; - - start_charstring = 0; - while (p < line + LINESIZE) { - c = fgetc(ifp); - if (c == EOF) - break; - if (c == '%') - comment = 1; - if (active && !comment && c == '{') { - start_charstring = 1; - break; - } - *p++ = (char) c; - if (c == '\n') - break; - } - *p = '\0'; -} - -/* This function is used by the binary search, bsearch(), for command names in - the command table. */ - -static int command_compare(const void *key, const void *item) -{ - return strcmp((char *) key, ((struct command *) item)->name); -} - -/* This function returns 1 if the string is an integer and 0 otherwise. */ - -static int is_integer(char *string) -{ - if (isdigit(string[0]) || string[0] == '-' || string[0] == '+') { - while (*++string && isdigit(*string)) - ; /* deliberately empty */ - if (!*string) - return 1; - } - return 0; -} - -/* This function initializes charstring encryption. Note that this is called - at the beginning of every charstring. */ - -static void charstring_start() -{ - int i; - - charstring_bp = charstring_buf; - cr = 4330; - for (i = 0; i < lenIV; i++) - *charstring_bp++ = cencrypt((byte) 0); -} - -/* This function encrypts and buffers a single byte of charstring data. */ - -static void charstring_byte(int v) -{ - byte b = (byte) (v & 0xff); - - if (charstring_bp - charstring_buf > sizeof(charstring_buf)) { - fprintf(stderr, "error: charstring_buf full (%d bytes)\n", - sizeof(charstring_buf)); - exit(1); - } - *charstring_bp++ = cencrypt(b); -} - -/* This function outputs buffered, encrypted charstring data through possible - eexec encryption. */ - -static void charstring_end() -{ - byte *bp; - - sprintf(line, "%d ", charstring_bp - charstring_buf); - eexec_string(line); - sprintf(line, "%s ", cs_start); - eexec_string(line); - for (bp = charstring_buf; bp < charstring_bp; bp++) - eexec_byte(*bp); -} - -/* This function generates the charstring representation of an integer. */ - -static void charstring_int(int num) -{ - int x; - - if (num >= -107 && num <= 107) { - charstring_byte(num + 139); - } else if (num >= 108 && num <= 1131) { - x = num - 108; - charstring_byte(x / 256 + 247); - charstring_byte(x % 256); - } else if (num >= -1131 && num <= -108) { - x = abs(num) - 108; - charstring_byte(x / 256 + 251); - charstring_byte(x % 256); - } else if (num >= (-2147483647-1) && num <= 2147483647) { - charstring_byte(255); - charstring_byte(num >> 24); - charstring_byte(num >> 16); - charstring_byte(num >> 8); - charstring_byte(num); - } else { - fprintf(stderr, - "error: cannot format the integer %d, too large\n", num); - exit(1); - } -} - -/* This function parses an entire charstring into integers and commands, - outputting bytes through the charstring buffer. */ - -static void parse_charstring() -{ - struct command *cp; - - charstring_start(); - while (fscanf(ifp, "%s", line) == 1) { - if (line[0] == '%') { - /* eat comment to end of line */ - while (fgetc(ifp) != '\n' && !feof(ifp)) - ; /* deliberately empty */ - continue; - } - if (line[0] == '}') - break; - if (is_integer(line)) { - charstring_int(atoi(line)); - } else { - cp = (struct command *) - bsearch((void *) line, (void *) command_table, - sizeof(command_table) / sizeof(struct command), - sizeof(struct command), - command_compare); - if (cp) { - charstring_byte(cp->one); - if (cp->two >= 0) - charstring_byte(cp->two); - } else { - fprintf(stderr, "error: cannot use `%s' in charstring\n",line); - exit(1); - } - } - } - charstring_end(); -} - -static void usage() -{ - fprintf(stderr, - "usage: t1asm [-b] [-l block-length] [input [output]]\n"); - fprintf(stderr, - "\n-b means output in PFB format, otherwise PFA format.\n"); - fprintf(stderr, - "The block length applies to the length of blocks in the\n"); - fprintf(stderr, - "PFB output file; the default is to use the largest possible.\n"); - exit(1); -} - -static void print_banner() -{ - static char rcs_revision[] = ""; /* removed RCS */ - static char revision[20]; - - if (sscanf(rcs_revision, "$Revision: %19s", revision) != 1) - revision[0] = '\0'; - fprintf(stderr, "This is t1asm %s.\n", revision); -} - -#ifdef STANDALONE -int main(int argc, char **argv) -{ - char *p, *q, *r; - int c; - - extern char *optarg; - extern int optind; - - ifp = stdin; - ofp = stdout; - - print_banner(); - - /* interpret command line arguments using getopt */ - while ((c = getopt(argc, argv, "bl:")) != -1) - switch (c) { - case 'b': - pfb = 1; - break; - case 'l': - blocklen = atoi(optarg); - if (blocklen < MINBLOCKLEN) { - blocklen = MINBLOCKLEN; - fprintf(stderr, - "warning: using minimum block length of %d\n", - blocklen); - } else if (blocklen > MAXBLOCKLEN) { - blocklen = MAXBLOCKLEN; - fprintf(stderr, - "warning: using maximum block length of %d\n", - blocklen); - } - break; - default: - usage(); - break; - } - if (argc - optind > 2) - usage(); - - /* possibly open input & output files */ - if (argc - optind >= 1) { - ifp = fopen(argv[optind], "r"); - if (!ifp) { - fprintf(stderr, "error: cannot open %s for reading\n", argv[1]); - exit(1); - } - } - if (argc - optind >= 2) { - ofp = fopen(argv[optind + 1], "w"); - if (!ofp) { - fprintf(stderr, "error: cannot open %s for writing\n", argv[2]); - exit(1); - } - } - -#else -int runt1asm(int pfbflag) -{ - char *p, *q, *r; - - pfb = pfbflag; -#endif - - #ifdef _MSDOS - /* If we are processing a PFB (binary) output */ - /* file, we must set its file mode to binary. */ - if (pfb) - _setmode(_fileno(ofp), _O_BINARY); - #endif - - /* Finally, we loop until no more input. Some special things to look for - are the `currentfile eexec' line, the beginning of the `/Subrs' - definition, the definition of `/lenIV', and the definition of the - charstring start command which has `...string currentfile...' in it. */ - - while (!feof(ifp) && !ferror(ifp)) { - t1asm_getline(); - if (strcmp(line, "currentfile eexec\n") == 0) { - eexec_start(); - continue; - } else if (strstr(line, "/Subrs") && isspace(line[6])) { - active = 1; - } else if ((p = strstr(line, "/lenIV"))) { - sscanf(p, "%*s %d", &lenIV); - } else if ((p = strstr(line, "string currentfile"))) { - /* locate the name of the charstring start command */ - *p = '\0'; /* damage line[] */ - q = strrchr(line, '/'); - if (q) { - r = cs_start; - ++q; - while (!isspace(*q) && *q != '{') - *r++ = *q++; - *r = '\0'; - } - *p = 's'; /* repair line[] */ - } - /* output line data */ - eexec_string(line); - if ((p = strstr(line, "currentfile closefile"))) { - eexec_end(); - } - if (start_charstring) { - if (!cs_start[0]) { - fprintf(stderr, "error: couldn't find charstring start command\n"); - exit(1); - } - parse_charstring(); - } - } - file_end(); - - fclose(ifp); - fclose(ofp); - - return 0; -} diff --git a/nx-X11/extras/ttf2pt1/ttf.c b/nx-X11/extras/ttf2pt1/ttf.c deleted file mode 100644 index b5cc5bdf8..000000000 --- a/nx-X11/extras/ttf2pt1/ttf.c +++ /dev/null @@ -1,1480 +0,0 @@ -/* - * True Type Font to Adobe Type 1 font converter - * By Mark Heath <mheath@netspace.net.au> - * Based on ttf2pfa by Andrew Weeks <ccsaw@bath.ac.uk> - * With help from Frank M. Siegert <fms@this.net> - * - * see COPYRIGHT - * - */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <time.h> -#include <ctype.h> -#include <math.h> - -#ifndef WINDOWS -# include <unistd.h> -# include <netinet/in.h> -#else -# include "windows.h" -#endif - -#include "ttf.h" -#include "pt1.h" -#include "global.h" - -/* prototypes of call entries */ -static void openfont(char *fname, char *arg); -static void closefont( void); -static int getnglyphs ( void); -static int glnames( GLYPH *glyph_list); -static void glmetrics( GLYPH *glyph_list); -static int glenc( GLYPH *glyph_list, int *encoding, int *unimap); -static void fnmetrics( struct font_metrics *fm); -static void glpath( int glyphno, GLYPH *glyph_list); -static void kerning( GLYPH *glyph_list); - -/* globals */ - -/* front-end descriptor */ -struct frontsw ttf_sw = { - /*name*/ "ttf", - /*descr*/ "built-in TTF support", - /*suffix*/ { "ttf" }, - /*open*/ openfont, - /*close*/ closefont, - /*nglyphs*/ getnglyphs, - /*glnames*/ glnames, - /*glmetrics*/ glmetrics, - /*glenc*/ glenc, - /*fnmetrics*/ fnmetrics, - /*glpath*/ glpath, - /*kerning*/ kerning, -}; - -/* statics */ - -static FILE *ttf_file; -static int ttf_nglyphs, long_offsets; - -static TTF_DIRECTORY *directory; -static TTF_DIR_ENTRY *dir_entry; -static char *filebuffer; -static char *filebuffer_end; -static TTF_NAME *name_table = NULL; -static TTF_NAME_REC *name_record; -static TTF_HEAD *head_table = NULL; -static TTF_HHEA *hhea_table = NULL; -static TTF_KERN *kern_table = NULL; -static TTF_CMAP *cmap_table = NULL; -static LONGHORMETRIC *hmtx_table = NULL; -static TTF_GLYF *glyf_table; -static BYTE *glyf_start = NULL; -static TTF_MAXP *maxp_table = NULL; -static TTF_POST_HEAD *post_table = NULL; -static union { - USHORT *sp; - ULONG *lp; -} loca_table; -#define short_loca_table loca_table.sp -#define long_loca_table loca_table.lp - -static short cmap_n_segs; -static USHORT *cmap_seg_start, *cmap_seg_end; -static short *cmap_idDelta, *cmap_idRangeOffset; -static TTF_CMAP_FMT0 *encoding0; -static int enc_type; - -static char name_buffer[2000]; -static char *name_fields[8]; - -static int enc_found_ms, enc_found_mac; - -static char *mac_glyph_names[258] = { - ".notdef", ".null", "CR", - "space", "exclam", "quotedbl", "numbersign", - "dollar", "percent", "ampersand", "quotesingle", - "parenleft", "parenright", "asterisk", "plus", - "comma", "hyphen", "period", "slash", - "zero", "one", "two", "three", - "four", "five", "six", "seven", - "eight", "nine", "colon", "semicolon", - "less", "equal", "greater", "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", - "backslash", "bracketright", "asciicircum", "underscore", - "grave", "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", "braceleft", - "bar", "braceright", "asciitilde", "Adieresis", - "Aring", "Ccedilla", "Eacute", "Ntilde", - "Odieresis", "Udieresis", "aacute", "agrave", - "acircumflex", "adieresis", "atilde", "aring", - "ccedilla", "eacute", "egrave", "ecircumflex", - "edieresis", "iacute", "igrave", "icircumflex", - "idieresis", "ntilde", "oacute", "ograve", - "ocircumflex", "odieresis", "otilde", "uacute", - "ugrave", "ucircumflex", "udieresis", "dagger", - "degree", "cent", "sterling", "section", - "bullet", "paragraph", "germandbls", "registered", - "copyright", "trademark", "acute", "dieresis", - "notequal", "AE", "Oslash", "infinity", - "plusminus", "lessequal", "greaterequal", "yen", - "mu", "partialdiff", "summation", "product", - "pi", "integral", "ordfeminine", "ordmasculine", - "Omega", "ae", "oslash", "questiondown", - "exclamdown", "logicalnot", "radical", "florin", - "approxequal", "increment", "guillemotleft", "guillemotright", - "ellipsis", "nbspace", "Agrave", "Atilde", - "Otilde", "OE", "oe", "endash", - "emdash", "quotedblleft", "quotedblright", "quoteleft", - "quoteright", "divide", "lozenge", "ydieresis", - "Ydieresis", "fraction", "currency", "guilsinglleft", - "guilsinglright", "fi", "fl", "daggerdbl", - "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", - "Acircumflex", "Ecircumflex", "Aacute", "Edieresis", - "Egrave", "Iacute", "Icircumflex", "Idieresis", - "Igrave", "Oacute", "Ocircumflex", "applelogo", - "Ograve", "Uacute", "Ucircumflex", "Ugrave", - "dotlessi", "circumflex", "tilde", "macron", - "breve", "dotaccent", "ring", "cedilla", - "hungarumlaut", "ogonek", "caron", "Lslash", - "lslash", "Scaron", "scaron", "Zcaron", - "zcaron", "brokenbar", "Eth", "eth", - "Yacute", "yacute", "Thorn", "thorn", - "minus", "multiply", "onesuperior", "twosuperior", - "threesuperior", "onehalf", "onequarter", "threequarters", - "franc", "Gbreve", "gbreve", "Idot", - "Scedilla", "scedilla", "Cacute", "cacute", - "Ccaron", "ccaron", "dmacron" -}; - -/* other prototypes */ -static void draw_composite_glyf( GLYPH *g, GLYPH *glyph_list, int glyphno, - double *matrix, int level); -static void draw_simple_glyf( GLYPH *g, GLYPH *glyph_list, int glyphno, - double *matrix); -static double f2dot14( short x); - -/* get the TTF description table address and length for this index */ - -static void -get_glyf_table( - int glyphno, - TTF_GLYF **tab, - int *len -) -{ - if(tab!=NULL) { - if (long_offsets) { - *tab = (TTF_GLYF *) (glyf_start + ntohl(long_loca_table[glyphno])); - } else { - *tab = (TTF_GLYF *) (glyf_start + (ntohs(short_loca_table[glyphno]) << 1)); - } - } - if(len!=NULL) { - if (long_offsets) { - *len = ntohl(long_loca_table[glyphno + 1]) - ntohl(long_loca_table[glyphno]); - } else { - *len = (ntohs(short_loca_table[glyphno + 1]) - ntohs(short_loca_table[glyphno])) << 1; - } - } -} - -static void -handle_name(void) -{ - int j, k, lang, len, platform; - char *p, *string_area; - char *nbp = name_buffer; - int found3 = 0; - - string_area = (char *) name_table + ntohs(name_table->offset); - name_record = &(name_table->nameRecords); - - for (j = 0; j < 8; j++) { - name_fields[j] = ""; - } - - for (j = 0; j < ntohs(name_table->numberOfNameRecords); j++) { - - platform = ntohs(name_record->platformID); - - if (platform == 3) { - - found3 = 1; - lang = ntohs(name_record->languageID) & 0xff; - len = ntohs(name_record->stringLength); - if (lang == 0 || lang == 9) { - k = ntohs(name_record->nameID); - if (k < 8) { - name_fields[k] = nbp; - - p = string_area + ntohs(name_record->stringOffset); - for (k = 0; k < len; k++) { - if (p[k] != '\0') { - if (p[k] == '(') { - *nbp = '['; - } else if (p[k] == ')') { - *nbp = ']'; - } else { - *nbp = p[k]; - } - nbp++; - } - } - *nbp = '\0'; - nbp++; - } - } - } - name_record++; - } - - string_area = (char *) name_table + ntohs(name_table->offset); - name_record = &(name_table->nameRecords); - - if (!found3) { - for (j = 0; j < ntohs(name_table->numberOfNameRecords); j++) { - - platform = ntohs(name_record->platformID); - - if (platform == 1) { - - found3 = 1; - lang = ntohs(name_record->languageID) & 0xff; - len = ntohs(name_record->stringLength); - if (lang == 0 || lang == 9) { - k = ntohs(name_record->nameID); - if (k < 8) { - name_fields[k] = nbp; - - p = string_area + ntohs(name_record->stringOffset); - for (k = 0; k < len; k++) { - if (p[k] != '\0') { - if (p[k] == '(') { - *nbp = '['; - } else if (p[k] == ')') { - *nbp = ']'; - } else { - *nbp = p[k]; - } - nbp++; - } - } - *nbp = '\0'; - nbp++; - } - } - } - name_record++; - } - } - if (!found3) { - fprintf(stderr, "**** Cannot decode font name fields ****\n"); - exit(1); - } - if (name_fields[4][0] == 0) { /* Full Name empty, use Family Name */ - name_fields[4] = name_fields[1]; - } - if (name_fields[6][0] == 0) { /* Font Name empty, use Full Name */ - name_fields[6] = name_fields[4]; - if (name_fields[6][0] == 0) { /* oops, empty again */ - WARNING_1 fprintf(stderr, "Font name is unknown, setting to \"Unknown\"\n"); - name_fields[6] = "Unknown"; - } - } - p = name_fields[6]; - /* must not start with a digit */ - if(isdigit(*p)) - *p+= 'A'-'0'; /* change to a letter */ - while (*p != '\0') { - if (!isalnum(*p) || *p=='_') { - *p = '-'; - } - p++; - } -} - -static void -handle_head(void) -{ - long_offsets = ntohs(head_table->indexToLocFormat); - if (long_offsets != 0 && long_offsets != 1) { - fprintf(stderr, "**** indexToLocFormat wrong ****\n"); - exit(1); - } -} - -/* limit the recursion level to avoid cycles */ -#define MAX_COMPOSITE_LEVEL 20 - -static void -draw_composite_glyf( - GLYPH *g, - GLYPH *glyph_list, - int glyphno, - double *orgmatrix, - int level -) -{ - int len; - short ncontours; - USHORT flagbyte, glyphindex; - double arg1, arg2; - BYTE *ptr; - char *bptr; - SHORT *sptr; - double matrix[6], newmatrix[6]; - - get_glyf_table(glyphno, &glyf_table, &len); - - if(len<=0) /* nothing to do */ - return; - - ncontours = ntohs(glyf_table->numberOfContours); - if (ncontours >= 0) { /* simple case */ - draw_simple_glyf(g, glyph_list, glyphno, orgmatrix); - return; - } - - if(ISDBG(COMPOSITE) && level ==0) - fprintf(stderr, "* %s [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n", g->name, - orgmatrix[0], orgmatrix[1], orgmatrix[2], orgmatrix[3], - orgmatrix[4], orgmatrix[5]); - - /* complex case */ - if(level >= MAX_COMPOSITE_LEVEL) { - WARNING_1 fprintf(stderr, - "*** Glyph %s: stopped (possibly infinite) recursion at depth %d\n", - g->name, level); - return; - } - - ptr = ((BYTE *) glyf_table + sizeof(TTF_GLYF)); - sptr = (SHORT *) ptr; - do { - flagbyte = ntohs(*sptr); - sptr++; - glyphindex = ntohs(*sptr); - sptr++; - - if (flagbyte & ARG_1_AND_2_ARE_WORDS) { - arg1 = (short)ntohs(*sptr); - sptr++; - arg2 = (short)ntohs(*sptr); - sptr++; - } else { - bptr = (char *) sptr; - arg1 = (signed char) bptr[0]; - arg2 = (signed char) bptr[1]; - sptr++; - } - matrix[1] = matrix[2] = 0.0; - - if (flagbyte & WE_HAVE_A_SCALE) { - matrix[0] = matrix[3] = f2dot14(*sptr); - sptr++; - } else if (flagbyte & WE_HAVE_AN_X_AND_Y_SCALE) { - matrix[0] = f2dot14(*sptr); - sptr++; - matrix[3] = f2dot14(*sptr); - sptr++; - } else if (flagbyte & WE_HAVE_A_TWO_BY_TWO) { - matrix[0] = f2dot14(*sptr); - sptr++; - matrix[2] = f2dot14(*sptr); - sptr++; - matrix[1] = f2dot14(*sptr); - sptr++; - matrix[3] = f2dot14(*sptr); - sptr++; - } else { - matrix[0] = matrix[3] = 1.0; - } - - /* - * See * - * http://fonts.apple.com/TTRefMan/RM06/Chap6g - * lyf.html * matrix[0,1,2,3,4,5]=a,b,c,d,m,n - */ - - if (fabs(matrix[0]) > fabs(matrix[1])) - matrix[4] = fabs(matrix[0]); - else - matrix[4] = fabs(matrix[1]); - if (fabs(fabs(matrix[0]) - fabs(matrix[2])) <= 33. / 65536.) - matrix[4] *= 2.0; - - if (fabs(matrix[2]) > fabs(matrix[3])) - matrix[5] = fabs(matrix[2]); - else - matrix[5] = fabs(matrix[3]); - if (fabs(fabs(matrix[2]) - fabs(matrix[3])) <= 33. / 65536.) - matrix[5] *= 2.0; - - /* - * fprintf (stderr,"Matrix Opp %hd - * %hd\n",arg1,arg2); - */ -#if 0 - fprintf(stderr, "Matrix: %f %f %f %f %f %f\n", - matrix[0], matrix[1], matrix[2], matrix[3], - matrix[4], matrix[5]); - fprintf(stderr, "Offset: %f %f (%s)\n", - arg1, arg2, - ((flagbyte & ARGS_ARE_XY_VALUES) ? "XY" : "index")); -#endif - - if (flagbyte & ARGS_ARE_XY_VALUES) { - matrix[4] *= arg1; - matrix[5] *= arg2; - } else { - WARNING_1 fprintf(stderr, - "*** Glyph %s: reusing scale from another glyph is unsupported\n", - g->name); - /* - * must extract values from a glyph - * but it seems to be too much pain - * and it's not clear now that it - * would be really used in any - * interesting font - */ - } - - /* at this point arg1,arg2 contain what logically should be matrix[4,5] */ - - /* combine matrices */ - - newmatrix[0] = orgmatrix[0]*matrix[0] + orgmatrix[2]*matrix[1]; - newmatrix[1] = orgmatrix[0]*matrix[2] + orgmatrix[2]*matrix[3]; - - newmatrix[2] = orgmatrix[1]*matrix[0] + orgmatrix[3]*matrix[1]; - newmatrix[3] = orgmatrix[1]*matrix[2] + orgmatrix[3]*matrix[3]; - - newmatrix[4] = orgmatrix[0]*matrix[4] + orgmatrix[2]*matrix[5] + orgmatrix[4]; - newmatrix[5] = orgmatrix[1]*matrix[4] + orgmatrix[3]*matrix[5] + orgmatrix[5]; - - if(ISDBG(COMPOSITE)) { - fprintf(stderr, "%*c+-> %2d %s [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n", - level+1, ' ', level, glyph_list[glyphindex].name, - matrix[0], matrix[1], matrix[2], matrix[3], - matrix[4], matrix[5]); - fprintf(stderr, "%*c = [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n", - level+1, ' ', - newmatrix[0], newmatrix[1], newmatrix[2], newmatrix[3], - newmatrix[4], newmatrix[5]); - } - draw_composite_glyf(g, glyph_list, glyphindex, newmatrix, level+1); - - } while (flagbyte & MORE_COMPONENTS); -} - -static void -draw_simple_glyf( - GLYPH *g, - GLYPH *glyph_list, - int glyphno, - double *matrix -) -{ - int i, j, k, k1, len, first, cs, ce; - /* We assume that hsbw always sets to(0, 0) */ - double xlast = 0, ylast = 0; - int finished, nguide, contour_start, contour_end; - short ncontours, n_inst, last_point; - USHORT *contour_end_pt; - BYTE *ptr; -#define GLYFSZ 2000 - short xabs[GLYFSZ], yabs[GLYFSZ], xrel[GLYFSZ], yrel[GLYFSZ]; - double xcoord[GLYFSZ], ycoord[GLYFSZ]; - BYTE flags[GLYFSZ]; - double tx, ty; - int needreverse = 0; /* transformation may require - * that */ - GENTRY *lge; - - lge = g->lastentry; - - get_glyf_table(glyphno, &glyf_table, &len); - - if (len <= 0) { - WARNING_1 fprintf(stderr, - "**** Composite glyph %s refers to non-existent glyph %s, ignored\n", - g->name, - glyph_list[glyphno].name); - return; - } - ncontours = ntohs(glyf_table->numberOfContours); - if (ncontours < 0) { - WARNING_1 fprintf(stderr, - "**** Composite glyph %s refers to composite glyph %s, ignored\n", - g->name, - glyph_list[glyphno].name); - return; - } - contour_end_pt = (USHORT *) ((char *) glyf_table + sizeof(TTF_GLYF)); - - last_point = ntohs(contour_end_pt[ncontours - 1]); - n_inst = ntohs(contour_end_pt[ncontours]); - - ptr = ((BYTE *) contour_end_pt) + (ncontours << 1) + n_inst + 2; - j = k = 0; - while (k <= last_point) { - flags[k] = ptr[j]; - - if (ptr[j] & REPEAT) { - for (k1 = 0; k1 < ptr[j + 1]; k1++) { - k++; - flags[k] = ptr[j]; - } - j++; - } - j++; - k++; - } - - for (k = 0; k <= last_point; k++) { - if (flags[k] & XSHORT) { - if (flags[k] & XSAME) { - xrel[k] = ptr[j]; - } else { - xrel[k] = -ptr[j]; - } - j++; - } else if (flags[k] & XSAME) { - xrel[k] = 0.0; - } else { - xrel[k] = (short)( ptr[j] * 256 + ptr[j + 1] ); - j += 2; - } - if (k == 0) { - xabs[k] = xrel[k]; - } else { - xabs[k] = xrel[k] + xabs[k - 1]; - } - - } - - for (k = 0; k <= last_point; k++) { - if (flags[k] & YSHORT) { - if (flags[k] & YSAME) { - yrel[k] = ptr[j]; - } else { - yrel[k] = -ptr[j]; - } - j++; - } else if (flags[k] & YSAME) { - yrel[k] = 0; - } else { - yrel[k] = ptr[j] * 256 + ptr[j + 1]; - j += 2; - } - if (k == 0) { - yabs[k] = yrel[k]; - } else { - yabs[k] = yrel[k] + yabs[k - 1]; - } - } - - if (matrix) { - for (i = 0; i <= last_point; i++) { - tx = xabs[i]; - ty = yabs[i]; - xcoord[i] = fscale(matrix[0] * tx + matrix[2] * ty + matrix[4]); - ycoord[i] = fscale(matrix[1] * tx + matrix[3] * ty + matrix[5]); - } - } else { - for (i = 0; i <= last_point; i++) { - xcoord[i] = fscale(xabs[i]); - ycoord[i] = fscale(yabs[i]); - } - } - - i = j = 0; - first = 1; - - while (i <= ntohs(contour_end_pt[ncontours - 1])) { - contour_end = ntohs(contour_end_pt[j]); - - if (first) { - fg_rmoveto(g, xcoord[i], ycoord[i]); - xlast = xcoord[i]; - ylast = ycoord[i]; - contour_start = i; - first = 0; - } else if (flags[i] & ONOROFF) { - fg_rlineto(g, xcoord[i], ycoord[i]); - xlast = xcoord[i]; - ylast = ycoord[i]; - } else { - cs = i - 1; - finished = nguide = 0; - while (!finished) { - if (i == contour_end + 1) { - ce = contour_start; - finished = 1; - } else if (flags[i] & ONOROFF) { - ce = i; - finished = 1; - } else { - i++; - nguide++; - } - } - - switch (nguide) { - case 0: - fg_rlineto(g, xcoord[ce], ycoord[ce]); - xlast = xcoord[ce]; - ylast = ycoord[ce]; - break; - - case 1: - fg_rrcurveto(g, - (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0, - (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0, - (2.0 * xcoord[cs + 1] + xcoord[ce]) / 3.0, - (2.0 * ycoord[cs + 1] + ycoord[ce]) / 3.0, - xcoord[ce], - ycoord[ce] - ); - xlast = xcoord[ce]; - ylast = ycoord[ce]; - - break; - - case 2: - fg_rrcurveto(g, - (-xcoord[cs] + 4.0 * xcoord[cs + 1]) / 3.0, - (-ycoord[cs] + 4.0 * ycoord[cs + 1]) / 3.0, - (4.0 * xcoord[cs + 2] - xcoord[ce]) / 3.0, - (4.0 * ycoord[cs + 2] - ycoord[ce]) / 3.0, - xcoord[ce], - ycoord[ce] - ); - xlast = xcoord[ce]; - ylast = ycoord[ce]; - break; - - case 3: - fg_rrcurveto(g, - (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0, - (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0, - (5.0 * xcoord[cs + 1] + xcoord[cs + 2]) / 6.0, - (5.0 * ycoord[cs + 1] + ycoord[cs + 2]) / 6.0, - (xcoord[cs + 1] + xcoord[cs + 2]) / 2.0, - (ycoord[cs + 1] + ycoord[cs + 2]) / 2.0 - ); - - fg_rrcurveto(g, - (xcoord[cs + 1] + 5.0 * xcoord[cs + 2]) / 6.0, - (ycoord[cs + 1] + 5.0 * ycoord[cs + 2]) / 6.0, - (5.0 * xcoord[cs + 2] + xcoord[cs + 3]) / 6.0, - (5.0 * ycoord[cs + 2] + ycoord[cs + 3]) / 6.0, - (xcoord[cs + 3] + xcoord[cs + 2]) / 2.0, - (ycoord[cs + 3] + ycoord[cs + 2]) / 2.0 - ); - - fg_rrcurveto(g, - (xcoord[cs + 2] + 5.0 * xcoord[cs + 3]) / 6.0, - (ycoord[cs + 2] + 5.0 * ycoord[cs + 3]) / 6.0, - (2.0 * xcoord[cs + 3] + xcoord[ce]) / 3.0, - (2.0 * ycoord[cs + 3] + ycoord[ce]) / 3.0, - xcoord[ce], - ycoord[ce] - ); - ylast = ycoord[ce]; - xlast = xcoord[ce]; - - break; - - default: - k1 = cs + nguide; - fg_rrcurveto(g, - (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0, - (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0, - (5.0 * xcoord[cs + 1] + xcoord[cs + 2]) / 6.0, - (5.0 * ycoord[cs + 1] + ycoord[cs + 2]) / 6.0, - (xcoord[cs + 1] + xcoord[cs + 2]) / 2.0, - (ycoord[cs + 1] + ycoord[cs + 2]) / 2.0 - ); - - for (k = cs + 2; k <= k1 - 1; k++) { - fg_rrcurveto(g, - (xcoord[k - 1] + 5.0 * xcoord[k]) / 6.0, - (ycoord[k - 1] + 5.0 * ycoord[k]) / 6.0, - (5.0 * xcoord[k] + xcoord[k + 1]) / 6.0, - (5.0 * ycoord[k] + ycoord[k + 1]) / 6.0, - (xcoord[k] + xcoord[k + 1]) / 2.0, - (ycoord[k] + ycoord[k + 1]) / 2.0 - ); - - } - - fg_rrcurveto(g, - (xcoord[k1 - 1] + 5.0 * xcoord[k1]) / 6.0, - (ycoord[k1 - 1] + 5.0 * ycoord[k1]) / 6.0, - (2.0 * xcoord[k1] + xcoord[ce]) / 3.0, - (2.0 * ycoord[k1] + ycoord[ce]) / 3.0, - xcoord[ce], - ycoord[ce] - ); - xlast = xcoord[ce]; - ylast = ycoord[ce]; - - break; - } - } - if (i >= contour_end) { - g_closepath(g); - first = 1; - i = contour_end + 1; - j++; - } else { - i++; - } - } - - if (matrix) { - /* guess whether do we need to reverse the results */ - - double x[3], y[3]; - int max = 0, from, to; - - /* transform a triangle going in proper direction */ - /* - * the origin of triangle is in (0,0) so we know it in - * advance - */ - - x[0] = y[0] = 0; - x[1] = matrix[0] * 0 + matrix[2] * 300; - y[1] = matrix[1] * 0 + matrix[3] * 300; - x[2] = matrix[0] * 300 + matrix[2] * 0; - y[2] = matrix[1] * 300 + matrix[3] * 0; - - /* then find the topmost point */ - for (i = 0; i < 3; i++) - if (y[i] > y[max]) - max = i; - from = (max + 3 - 1) % 3; - to = (max + 1) % 3; - - needreverse = 0; - - /* special cases for horizontal lines */ - if (y[max] == y[from]) { - if (x[max] < y[from]) - needreverse = 1; - } else if (y[to] == y[from]) { - if (x[to] < x[max]) - needreverse = 1; - } else { /* generic case */ - if ((x[to] - x[max]) * (y[max] - y[from]) - > (x[max] - x[from]) * (y[to] - y[max])) - needreverse = 1; - } - - if (needreverse) { - if (lge) { - assertpath(lge->next, __FILE__, __LINE__, g->name); - reversepathsfromto(lge->next, NULL); - } else { - assertpath(g->entries, __FILE__, __LINE__, g->name); - reversepaths(g); - } - } - } -} - -static double -f2dot14( - short x -) -{ - short y = ntohs(x); - return (y >> 14) + ((y & 0x3fff) / 16384.0); -} - - -/* check that the pointer points within the file */ -/* returns 0 if pointer is good, 1 if bad */ -static int -badpointer( - void *ptr -) -{ - return (ptr < (void *)filebuffer || ptr >= (void *)filebuffer_end); -} - -/* - * Externally accessible methods - */ - -/* - * Open font and prepare to return information to the main driver. - * May print error and warning messages. - * Exit on error. - */ - -static void -openfont( - char *fname, - char *arg /* unused now */ -) -{ - int i, j; - struct stat statbuf; - static struct { - void **tbpp; /* pointer to pointer to the table */ - char name[5]; /* table name */ - char optional; /* flag: table may be missing */ - } tables[] = { - { (void **)&name_table, "name", 0 }, - { (void **)&head_table, "head", 0 }, - { (void **)&hhea_table, "hhea", 0 }, - { (void **)&post_table, "post", 0 }, - { (void **)&glyf_start, "glyf", 0 }, - { (void **)&cmap_table, "cmap", 0 }, - { (void **)&kern_table, "kern", 1 }, - { (void **)&maxp_table, "maxp", 0 }, - { (void **)&hmtx_table, "hmtx", 0 }, - { (void **)&long_loca_table, "loca", 0 }, - { NULL, "", 0 } /* end of table */ - }; - - if (stat(fname, &statbuf) == -1) { - fprintf(stderr, "**** Cannot access %s ****\n", fname); - exit(1); - } - if ((filebuffer = malloc(statbuf.st_size)) == NULL) { - fprintf(stderr, "**** Cannot malloc space for file ****\n"); - exit(1); - } - - filebuffer_end = filebuffer + statbuf.st_size; - - if ((ttf_file = fopen(fname, "rb")) == NULL) { - fprintf(stderr, "**** Cannot open file '%s'\n", fname); - exit(1); - } else { - WARNING_2 fprintf(stderr, "Processing file %s\n", fname); - } - - if (fread(filebuffer, 1, statbuf.st_size, ttf_file) != statbuf.st_size) { - fprintf(stderr, "**** Could not read whole file \n"); - exit(1); - } - fclose(ttf_file); - - directory = (TTF_DIRECTORY *) filebuffer; - - if (ntohl(directory->sfntVersion) != 0x00010000) { - fprintf(stderr, - "**** Unknown File Version number [%x], or not a TrueType file\n", - directory->sfntVersion); - exit(1); - } - - /* clear the tables */ - for(j=0; tables[j].tbpp != NULL; j++) - *(tables[j].tbpp) = NULL; - - dir_entry = &(directory->list); - - for (i = 0; i < ntohs(directory->numTables); i++) { - - for(j=0; tables[j].tbpp != NULL; j++) - if (memcmp(dir_entry->tag, tables[j].name, 4) == 0) { - *(tables[j].tbpp) = (void *) (filebuffer + ntohl(dir_entry->offset)); - break; - } - - if (memcmp(dir_entry->tag, "EBDT", 4) == 0 || - memcmp(dir_entry->tag, "EBLC", 4) == 0 || - memcmp(dir_entry->tag, "EBSC", 4) == 0) { - WARNING_1 fprintf(stderr, "Font contains bitmaps\n"); - } - dir_entry++; - } - - for(j=0; tables[j].tbpp != NULL; j++) - if(!tables[j].optional && badpointer( *(tables[j].tbpp) )) { - fprintf(stderr, "**** File contains no required table '%s'\n", tables[j].name); - exit(1); - } - - handle_name(); - - handle_head(); - - ttf_nglyphs = ntohs(maxp_table->numGlyphs); - - enc_found_ms = enc_found_mac = 0; -} - -/* - * Close font. - * Exit on error. - */ - -static void -closefont( - void -) -{ - return; /* empty operation */ -} - -/* - * Get the number of glyphs in font. - */ - -static int -getnglyphs ( - void -) -{ - return ttf_nglyphs; -} - -/* - * Get the names of the glyphs. - * Returns 0 if the names were assigned, non-zero if the font - * provides no glyph names. - */ - -static int -glnames( - GLYPH *glyph_list -) -{ - int i, len, n, npost; - unsigned int format; - USHORT *name_index; - char *ptr, *p; - char **ps_name_ptr = (char **) malloc(ttf_nglyphs * sizeof(char *)); - int n_ps_names; - int ps_fmt_3 = 0; - - format = ntohl(post_table->formatType); - - if (format == 0x00010000) { - for (i = 0; i < 258 && i < ttf_nglyphs; i++) { - glyph_list[i].name = mac_glyph_names[i]; - } - } else if (format == 0x00020000) { - npost = ntohs(post_table->numGlyphs); - if (ttf_nglyphs != npost) { - /* This is an error in the font, but we can now cope */ - WARNING_1 fprintf(stderr, "**** Postscript table size mismatch %d/%d ****\n", - npost, ttf_nglyphs); - } - n_ps_names = 0; - name_index = &(post_table->glyphNameIndex); - - /* This checks the integrity of the post table */ - for (i=0; i<npost; i++) { - n = ntohs(name_index[i]); - if (n > n_ps_names + 257) { - n_ps_names = n - 257; - } - } - - ptr = (char *) post_table + 34 + (ttf_nglyphs << 1); - i = 0; - while (*ptr > 0 && i < n_ps_names) { - len = *ptr; - /* previously the program wrote nulls into the table. If the table - was corrupt, this could put zeroes anywhere, leading to obscure bugs, - so now I malloc space for the names. Yes it is much less efficient */ - - if ((p = malloc(len+1)) == NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - - ps_name_ptr[i] = p; - strncpy(p, ptr+1, len); - p[len] = '\0'; - i ++; - ptr += len + 1; - } - - if (i != n_ps_names) - { - WARNING_2 fprintf (stderr, "** Postscript Name mismatch %d != %d **\n", - i, n_ps_names); - n_ps_names = i; - } - - /* - * for (i=0; i<n_ps_names; i++) { fprintf(stderr, "i=%d, - * len=%d, name=%s\n", i, ps_name_len[i], ps_name_ptr[i]); } - */ - - for (i = 0; i < npost; i++) { - n = ntohs(name_index[i]); - if (n < 258) { - glyph_list[i].name = mac_glyph_names[n]; - } else if (n < 258 + n_ps_names) { - glyph_list[i].name = ps_name_ptr[n - 258]; - } else { - glyph_list[i].name = malloc(16); - sprintf(glyph_list[i].name, "_g_%d", i); - WARNING_2 fprintf(stderr, - "Glyph No. %d has no postscript name, becomes %s\n", - i, glyph_list[i].name); - } - } - /* Now fake postscript names for all those beyond the end of the table */ - if (npost < ttf_nglyphs) { - for (i=npost; i<ttf_nglyphs; i++) { - if ((glyph_list[i].name = malloc(16)) == NULL) - { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - sprintf(glyph_list[i].name, "_g_%d", i); - WARNING_2 fprintf(stderr, - "Glyph No. %d has no postscript name, becomes %s\n", - i, glyph_list[i].name); - } - } - } else if (format == 0x00030000) { - WARNING_3 fputs("No postscript table, using default\n", stderr); - ps_fmt_3 = 1; - } else if (format == 0x00028000) { - ptr = (char *) &(post_table->numGlyphs); - for (i = 0; i < ttf_nglyphs; i++) { - glyph_list[i].name = mac_glyph_names[i + ptr[i]]; - } - } else { - fprintf(stderr, - "**** Postscript table in wrong format %x ****\n", - format); - exit(1); - } - - return ps_fmt_3; -} - -/* - * Get the metrics of the glyphs. - */ - -static void -glmetrics( - GLYPH *glyph_list -) -{ - int i; - int n_hmetrics = ntohs(hhea_table->numberOfHMetrics); - GLYPH *g; - LONGHORMETRIC *hmtx_entry = hmtx_table; - FWORD *lsblist; - - for (i = 0; i < n_hmetrics; i++) { - g = &(glyph_list[i]); - g->width = ntohs(hmtx_entry->advanceWidth); - g->lsb = ntohs(hmtx_entry->lsb); - hmtx_entry++; - } - - lsblist = (FWORD *) hmtx_entry; - hmtx_entry--; - - for (i = n_hmetrics; i < ttf_nglyphs; i++) { - g = &(glyph_list[i]); - g->width = ntohs(hmtx_entry->advanceWidth); - g->lsb = ntohs(lsblist[i - n_hmetrics]); - } - - for (i = 0; i < ttf_nglyphs; i++) { - g = &(glyph_list[i]); - get_glyf_table(i, &glyf_table, &g->ttf_pathlen); - - g->xMin = (short)ntohs(glyf_table->xMin); - g->xMax = (short)ntohs(glyf_table->xMax); - g->yMin = (short)ntohs(glyf_table->yMin); - g->yMax = (short)ntohs(glyf_table->yMax); - } - -} - - -static void -handle_ms_encoding( - GLYPH *glyph_list, - int *encoding, - int *unimap -) -{ - int j, k, kk, set_ok; - USHORT start, end, ro; - short delta, n; - - for (j = 0; j < cmap_n_segs - 1; j++) { - start = ntohs(cmap_seg_start[j]); - end = ntohs(cmap_seg_end[j]); - delta = ntohs(cmap_idDelta[j]); - ro = ntohs(cmap_idRangeOffset[j]); - - for (k = start; k <= end; k++) { - if (ro == 0) { - n = k + delta; - } else { - n = ntohs(*((ro >> 1) + (k - start) + - &(cmap_idRangeOffset[j]))); - if (delta != 0) - { - /* Not exactly sure how to deal with this circumstance, - I suspect it never occurs */ - n += delta; - fprintf (stderr, - "rangeoffset and delta both non-zero - %d/%d", - ro, delta); - } - } - if(n<0 || n>=ttf_nglyphs) { - WARNING_1 fprintf(stderr, "Font contains a broken glyph code mapping, ignored\n"); - continue; - } - if (glyph_list[n].orig_code != -1) { -#if 0 - if (strcmp(glyph_list[n].name, ".notdef") != 0) { - WARNING_2 fprintf(stderr, - "Glyph %s has >= two encodings (A), %4.4x & %4.4x\n", - glyph_list[n].name, - glyph_list[n].orig_code, - k); - } -#endif - set_ok = 0; - } else { - set_ok = 1; - } - if (enc_type==1 || forcemap) { - kk = unicode_rev_lookup(k); - if(ISDBG(UNICODE)) - fprintf(stderr, "Unicode %s - 0x%04x\n",glyph_list[n].name,k); - if (set_ok) { - glyph_list[n].orig_code = k; - /* glyph_list[n].char_no = kk; */ - } - if (kk >= 0 && kk < ENCTABSZ && encoding[kk] == -1) - encoding[kk] = n; - } else { - if ((k & 0xff00) == 0xf000) { - if( encoding[k & 0x00ff] == -1 ) { - encoding[k & 0x00ff] = n; - if (set_ok) { - /* glyph_list[n].char_no = k & 0x00ff; */ - glyph_list[n].orig_code = k; - } - } - } else { - if (set_ok) { - /* glyph_list[n].char_no = k; */ - glyph_list[n].orig_code = k; - } - WARNING_2 fprintf(stderr, - "Glyph %s has non-symbol encoding %4.4x\n", - glyph_list[n].name, - k & 0xffff); - /* - * just use the code - * as it is - */ - if ((k & ~0xff) == 0 && encoding[k] == -1 ) - encoding[k] = n; - } - } - } - } -} - -static void -handle_mac_encoding( - GLYPH *glyph_list, - int *encoding, - int *unimap -) -{ - short n; - int j, size; - - size = ntohs(encoding0->length) - 6; - for (j = 0; j < size; j++) { - n = encoding0->glyphIdArray[j]; - if (glyph_list[n].char_no != -1) { - WARNING_2 fprintf(stderr, - "Glyph %s has >= two encodings (B), %4.4x & %4.4x\n", - glyph_list[n].name, - glyph_list[n].char_no, - j); - } else { - if (j < ENCTABSZ) { - if(encoding[j] == -1) { - glyph_list[n].char_no = j; - encoding[j] = n; - } - } - } - } -} - -/* - * Get the original encoding of the font. - * Returns 1 for if the original encoding is Unicode, 2 if the - * original encoding is other 16-bit, 0 if 8-bit. - */ - -static int -glenc( - GLYPH *glyph_list, - int *encoding, - int *unimap -) -{ - int num_tables = ntohs(cmap_table->numberOfEncodingTables); - BYTE *ptr; - int i, format, offset, seg_c2, found; - int platform, encoding_id; - TTF_CMAP_ENTRY *table_entry; - TTF_CMAP_FMT4 *encoding4; - - if(enc_found_ms) { - handle_ms_encoding(glyph_list, encoding, unimap); - return enc_type; - } else if(enc_found_mac) { - handle_mac_encoding(glyph_list, encoding, unimap); - return 0; - } - - if(force_pid != -1 && force_pid != 3) { - fputs("*** Only platform ID == 3 is supported\n", stderr); - exit(1); - } - - enc_type = 0; - found = 0; - - for (i = 0; i < num_tables && !found; i++) { - table_entry = &(cmap_table->encodingTable[i]); - offset = ntohl(table_entry->offset); - encoding4 = (TTF_CMAP_FMT4 *) ((BYTE *) cmap_table + offset); - format = ntohs(encoding4->format); - platform = ntohs(table_entry->platformID); - encoding_id = ntohs(table_entry->encodingID); - - if (platform == 3 && format == 4) { - if(force_pid == 3) { - if(encoding_id != force_eid) - continue; - WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n", - force_pid, force_eid); - enc_type = 1; - } else { - switch (encoding_id) { - case 0: - WARNING_1 fputs("Found Symbol Encoding\n", stderr); - break; - case 1: - WARNING_1 fputs("Found Unicode Encoding\n", stderr); - enc_type = 1; - break; - default: - WARNING_1 { - fprintf(stderr, - "****MS Encoding ID %d not supported****\n", - encoding_id); - fputs("Treating it like Symbol encoding\n", stderr); - } - break; - } - } - - found = 1; - seg_c2 = ntohs(encoding4->segCountX2); - cmap_n_segs = seg_c2 >> 1; - ptr = (BYTE *) encoding4 + 14; - cmap_seg_end = (USHORT *) ptr; - cmap_seg_start = (USHORT *) (ptr + seg_c2 + 2); - cmap_idDelta = (short *) (ptr + (seg_c2 * 2) + 2); - cmap_idRangeOffset = (short *) (ptr + (seg_c2 * 3) + 2); - enc_found_ms = 1; - - handle_ms_encoding(glyph_list, encoding, unimap); - } - } - - if (!found) { - if(force_pid != -1) { - fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n", - force_pid, force_eid); - exit(1); - } - - WARNING_1 fputs("No Microsoft encoding, looking for MAC encoding\n", stderr); - for (i = 0; i < num_tables && !found; i++) { - table_entry = &(cmap_table->encodingTable[i]); - offset = ntohl(table_entry->offset); - encoding0 = (TTF_CMAP_FMT0 *) ((BYTE *) cmap_table + offset); - format = ntohs(encoding0->format); - platform = ntohs(table_entry->platformID); - encoding_id = ntohs(table_entry->encodingID); - - if (format == 0) { - found = 1; - enc_found_mac = 1; - - handle_mac_encoding(glyph_list, encoding, unimap); - } - } - } - if (!found) { - fprintf(stderr, "**** No Recognised Encoding Table ****\n"); - exit(1); - } - - return enc_type; -} - -/* - * Get the font metrics - */ -static void -fnmetrics( - struct font_metrics *fm -) -{ - char *str; - static int fieldstocheck[]= {2,4,6}; - int i, j, len; - - fm->italic_angle = (short) (ntohs(post_table->italicAngle.upper)) + - ((short) ntohs(post_table->italicAngle.lower) / 65536.0); - fm->underline_position = (short) ntohs(post_table->underlinePosition); - fm->underline_thickness = (short) ntohs(post_table->underlineThickness); - fm->is_fixed_pitch = ntohl(post_table->isFixedPitch); - - fm->ascender = (short)ntohs(hhea_table->ascender); - fm->descender = (short)ntohs(hhea_table->descender); - - fm->units_per_em = ntohs(head_table->unitsPerEm); - - fm->bbox[0] = (short) ntohs(head_table->xMin); - fm->bbox[1] = (short) ntohs(head_table->yMin); - fm->bbox[2] = (short) ntohs(head_table->xMax); - fm->bbox[3] = (short) ntohs(head_table->yMax); - - fm->name_copyright = name_fields[0]; - fm->name_family = name_fields[1]; - fm->name_style = name_fields[2]; - fm->name_full = name_fields[4]; - fm->name_version = name_fields[5]; - fm->name_ps = name_fields[6]; - - /* guess the boldness from the font names */ - fm->force_bold=0; - - for(i=0; !fm->force_bold && i<sizeof fieldstocheck /sizeof(int); i++) { - str = name_fields[fieldstocheck[i]]; - len = strlen(str); - for(j=0; j<len; j++) { - if( (str[j]=='B' - || str[j]=='b' - && ( j==0 || !isalpha(str[j-1]) ) - ) - && !strncmp("old",&str[j+1],3) - && (j+4 >= len || !islower(str[j+4])) - ) { - fm->force_bold=1; - break; - } - } - } -} - -/* - * Get the path of contrours for a glyph. - */ - -static void -glpath( - int glyphno, - GLYPH *glyf_list -) -{ - double matrix[6]; - GLYPH *g; - - g = &glyph_list[glyphno]; - - matrix[0] = matrix[3] = 1.0; - matrix[1] = matrix[2] = matrix[4] = matrix[5] = 0.0; - draw_composite_glyf(g, glyf_list, glyphno, matrix, 0 /*level*/); -} - -/* - * Get the kerning data. - */ - -static void -kerning( - GLYPH *glyph_list -) -{ - TTF_KERN_SUB *subtable; - TTF_KERN_ENTRY *kern_entry; - int i, j; - int ntables; - int npairs; - char *ptr; - - if(kern_table == NULL) { - WARNING_1 fputs("No Kerning data\n", stderr); - return; - } - if(badpointer(kern_table)) { - fputs("**** Defective Kerning table, ignored\n", stderr); - return; - } - - ntables = ntohs(kern_table->nTables); - ptr = (char *) kern_table + 4; - - for (i = 0; i < ntables; i++) { - subtable = (TTF_KERN_SUB *) ptr; - if ((ntohs(subtable->coverage) & 0xff00) == 0) { - npairs = (short) ntohs(subtable->nPairs); - kern_entry = (TTF_KERN_ENTRY *) (ptr + sizeof(TTF_KERN_SUB)); - - kern_entry = (TTF_KERN_ENTRY *) (ptr + sizeof(TTF_KERN_SUB)); - for (j = 0; j < npairs; j++) { - if( kern_entry->value != 0) - addkernpair(ntohs(kern_entry->left), - ntohs(kern_entry->right), (short)ntohs(kern_entry->value)); - kern_entry++; - } - } - ptr += subtable->length; - } -} - diff --git a/nx-X11/extras/ttf2pt1/ttf.h b/nx-X11/extras/ttf2pt1/ttf.h deleted file mode 100644 index 297dcaf10..000000000 --- a/nx-X11/extras/ttf2pt1/ttf.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * see COPYRIGHT - */ - -/* these definitions are mostly taken from Microsoft's True Type - documentation. -*/ - -#ifdef XP_PSTEXT -typedef unsigned char BYTE; -typedef signed char CHAR; -typedef unsigned short USHORT; -typedef signed short SHORT; -typedef unsigned int ULONG; -typedef signed int LONG; -typedef SHORT FWORD; -typedef USHORT UFWORD; -#else -#define BYTE unsigned char -#define CHAR signed char -#define USHORT unsigned short -#define SHORT signed short -#define ULONG unsigned int -#define LONG signed int -#define FWORD SHORT -#define UFWORD USHORT -#endif /* XP_PSTEXT */ - -#define ONOROFF 0x01 -#define XSHORT 0x02 -#define YSHORT 0x04 -#define REPEAT 0x08 -#define XSAME 0x10 -#define YSAME 0x20 - -#define ARG_1_AND_2_ARE_WORDS 0x0001 -#define ARGS_ARE_XY_VALUES 0x0002 -#define XY_BOUND_TO_GRID 0x0004 -#define WE_HAVE_A_SCALE 0x0008 -#define MORE_COMPONENTS 0x0020 -#define WE_HAVE_AN_X_AND_Y_SCALE 0x0040 -#define WE_HAVE_A_TWO_BY_TWO 0x0080 -#define WE_HAVE_INSTRUCTIONS 0x0100 -#define USE_MY_METRICS 0x0200 - -typedef struct short_2 { - SHORT upper; - USHORT lower; -} FIXED ; - -typedef struct longhormetric { - UFWORD advanceWidth; - FWORD lsb; -} LONGHORMETRIC; - -typedef struct ttf_hhea { - BYTE version[4]; - SHORT ascender, descender, lineGap; - USHORT advnaceWidthMax; - SHORT minLSB, minRSB, xMaxExtent; - SHORT caretSlopeRise, caretSlopeRun; - SHORT reserved[5]; - SHORT metricDataFormat; - USHORT numberOfHMetrics; -} TTF_HHEA; - -typedef struct ttf_dir_entry { - char tag[4]; - ULONG checksum; - ULONG offset; - ULONG length; -} TTF_DIR_ENTRY ; - -typedef struct ttf_directory { - ULONG sfntVersion; - USHORT numTables; - USHORT searchRange; - USHORT entrySelector; - USHORT rangeShift; - TTF_DIR_ENTRY list; -} TTF_DIRECTORY ; - -typedef struct ttf_name_rec { - USHORT platformID; - USHORT encodingID; - USHORT languageID; - USHORT nameID; - USHORT stringLength; - USHORT stringOffset; -} TTF_NAME_REC; - -typedef struct ttf_name { - USHORT format; - USHORT numberOfNameRecords; - USHORT offset; - TTF_NAME_REC nameRecords; -} TTF_NAME ; - -typedef struct ttf_head { - ULONG version; - ULONG fontRevision; - ULONG checksumAdjust; - ULONG magicNo; - USHORT flags; - USHORT unitsPerEm; - BYTE created[8]; - BYTE modified[8]; - FWORD xMin, yMin, xMax, yMax; - USHORT macStyle, lowestRecPPEM; - SHORT fontDirection, indexToLocFormat, glyphDataFormat; -} TTF_HEAD ; - -typedef struct ttf_kern { - USHORT version, nTables; -} TTF_KERN ; - -typedef struct ttf_kern_sub { - USHORT version, length, coverage; - USHORT nPairs, searchRange, entrySelector, rangeShift; -} TTF_KERN_SUB; - -typedef struct ttf_kern_entry { - USHORT left, right; - FWORD value; -} TTF_KERN_ENTRY; - -typedef struct ttf_cmap_fmt0 { - USHORT format; - USHORT length; - USHORT version; - BYTE glyphIdArray[256]; -} TTF_CMAP_FMT0; - -typedef struct ttf_cmap_fmt4 { - USHORT format; - USHORT length; - USHORT version; - USHORT segCountX2; - USHORT searchRange; - USHORT entrySelector; - USHORT rangeShift; -} TTF_CMAP_FMT4; - -typedef struct ttf_cmap_entry { - USHORT platformID; - USHORT encodingID; - ULONG offset; -} TTF_CMAP_ENTRY; - -typedef struct ttf_cmap { - USHORT version; - USHORT numberOfEncodingTables; - TTF_CMAP_ENTRY encodingTable[1]; -} TTF_CMAP ; - -typedef struct ttf_glyf { - SHORT numberOfContours; - FWORD xMin, yMin, xMax, yMax; -} TTF_GLYF ; - -typedef struct ttf_maxp { - ULONG version; - USHORT numGlyphs, maxPoints, maxContours; - USHORT maxCompositePoints, maxCompositeContours; - USHORT maxZones, maxTwilightPoints, maxStorage; - USHORT maxFunctionDefs, maxInstructionsDefs; - USHORT maxSizeOfInstructions, maxComponentElements; - USHORT maxComponentDepth; -} TTF_MAXP ; - -typedef struct ttf_post_head { - ULONG formatType; - FIXED italicAngle; - FWORD underlinePosition; - FWORD underlineThickness; - ULONG isFixedPitch; - ULONG minMemType42; - ULONG maxMemType42; - ULONG minMemType1; - ULONG maxMemType1; - USHORT numGlyphs; - USHORT glyphNameIndex; -} TTF_POST_HEAD ; diff --git a/nx-X11/extras/ttf2pt1/ttf2pt1.1 b/nx-X11/extras/ttf2pt1/ttf2pt1.1 deleted file mode 100644 index 500a7d2ec..000000000 --- a/nx-X11/extras/ttf2pt1/ttf2pt1.1 +++ /dev/null @@ -1,832 +0,0 @@ -.rn '' }` -''' $RCSfile: ttf2pt1.1,v $$Revision: 1.2 $$Date: 2004/04/23 18:42:57 $ -''' -''' $Log: ttf2pt1.1,v $ -''' Revision 1.2 2004/04/23 18:42:57 eich -''' 2004-04-23 Egbert Eich <eich@freedesktop.org> -''' Merging XORG-CURRENT into trunk -''' -''' Revision 1.1.4.1 2004/04/21 10:03:13 gisburn -''' Fix for http://pdx.freedesktop.org/cgi-bin/bugzilla/show_bug.cgi?id=530 - Land XPRINT branch on XORG-CURRENT -''' -''' Revision 1.1 2003/06/04 00:33:54 roland -''' Fix for http://xprint.mozdev.org/bugs/show_bug.cgi?id=3846 - RFE: Upload Freetype --> PS Type1 font converter "ttf2pt1" ... -''' -''' -.de Sh -.br -.if t .Sp -.ne 5 -.PP -\fB\\$1\fR -.PP -.. -.de Sp -.if t .sp .5v -.if n .sp -.. -.de Ip -.br -.ie \\n(.$>=3 .ne \\$3 -.el .ne 3 -.IP "\\$1" \\$2 -.. -.de Vb -.ft CW -.nf -.ne \\$1 -.. -.de Ve -.ft R - -.fi -.. -''' -''' -''' Set up \*(-- to give an unbreakable dash; -''' string Tr holds user defined translation string. -''' Bell System Logo is used as a dummy character. -''' -.tr \(*W-|\(bv\*(Tr -.ie n \{\ -.ds -- \(*W- -.ds PI pi -.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -.ds L" "" -.ds R" "" -''' \*(M", \*(S", \*(N" and \*(T" are the equivalent of -''' \*(L" and \*(R", except that they are used on ".xx" lines, -''' such as .IP and .SH, which do another additional levels of -''' double-quote interpretation -.ds M" """ -.ds S" """ -.ds N" """"" -.ds T" """"" -.ds L' ' -.ds R' ' -.ds M' ' -.ds S' ' -.ds N' ' -.ds T' ' -'br\} -.el\{\ -.ds -- \(em\| -.tr \*(Tr -.ds L" `` -.ds R" '' -.ds M" `` -.ds S" '' -.ds N" `` -.ds T" '' -.ds L' ` -.ds R' ' -.ds M' ` -.ds S' ' -.ds N' ` -.ds T' ' -.ds PI \(*p -'br\} -.\" If the F register is turned on, we'll generate -.\" index entries out stderr for the following things: -.\" TH Title -.\" SH Header -.\" Sh Subsection -.\" Ip Item -.\" X<> Xref (embedded -.\" Of course, you have to process the output yourself -.\" in some meaninful fashion. -.if \nF \{ -.de IX -.tm Index:\\$1\t\\n%\t"\\$2" -.. -.nr % 0 -.rr F -.\} -.TH TTF2PT1 1 "version 3.4.4-SNAP-030526" "May 26, 2003" "TTF2PT1 Font Converter" -.UC -.if n .hy 0 -.if n .na -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.de CQ \" put $1 in typewriter font -.ft CW -'if n "\c -'if t \\&\\$1\c -'if n \\&\\$1\c -'if n \&" -\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7 -'.ft R -.. -.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2 -. \" AM - accent mark definitions -.bd B 3 -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds ? ? -. ds ! ! -. ds / -. ds q -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10' -. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#] -.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u' -.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u' -.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#] -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -.ds oe o\h'-(\w'o'u*4/10)'e -.ds Oe O\h'-(\w'O'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds v \h'-1'\o'\(aa\(ga' -. ds _ \h'-1'^ -. ds . \h'-1'. -. ds 3 3 -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -. ds oe oe -. ds Oe OE -.\} -.rm #[ #] #H #V #F C -.SH "NAME" -TTF2PT1 \- A True Type to PostScript Type 1 Font Converter -.SH "SYNOPSIS" -\f(CWttf2pt1 \fI[-options] ttffont.ttf [Fontname]\fR\fR -.PP -or -.PP -\f(CWttf2pt1 \fI[-options] ttffont.ttf -\fR\fR -.SH "DESCRIPTION" -Ttf2pt1 is a font converter from the True Type format (and some other formats -supported by the FreeType library as well) to the Adobe Type1 format. -.PP -The versions 3.0 and later got rather extensive post-processing algorithm that -brings the converted fonts to the requirements of the Type1 standard, tries to -correct the rounding errors introduced during conversions and some simple -kinds of bugs that are typical for the public domain TTF fonts. It -also generates the hints that enable much better rendering of fonts in -small sizes that are typical for the computer displays. But everything -has its price, and some of the optimizations may not work well for certain -fonts. That's why the options were added to the converter, to control -the performed optimizations. -.SH "OPTIONS" -The first variant creates the file \f(CWFontname.pfa\fR (or \f(CWFontname.pfb\fR if the -option \*(L'\fB\-b\fR\*(R' was used) with the converted font and \f(CWFontname.afm\fR with the -font metrics, the second one prints the font or another file (if the option -\&\*(R'\fB\-G\fR\*(R' was used) on the standard output from where it can be immediately -piped through some filter. If no \f(CWFontname\fR is specified for the first -variant, the name is generated from \f(CWttffont\fR by replacing the \f(CW.ttf\fR -filename suffix. -.PP -Most of the time no options are neccessary (with a possible exception -of \*(L'\fB\-e\fR'). But if there are some troubles with the resulting font, they -may be used to control the conversion. -The \fBoptions\fR are: -.Ip "\(bu" 2 -\f(CW\fB-a\fR\fR \- Include all the glyphs from the source file into the converted -file. If this option is not specified then only the glyphs that have -been assigned some encoding are included, because the rest of glyphs -would be inaccessible anyway and would only consume the disk space. -But some applications are clever enough to change the encoding on -the fly and thus use the other glyphs, in this case they could -benefit from using this option. But there is a catch: the X11 library -has rather low limit for the font size. Including more glyphs increases -the file size and thus increases the chance of hitting this limit. -See \f(CWapp/X11/README\fR for the description of a -patch to X11 which fixes this problem. -.Ip "\(bu" 2 -\f(CW\fB-b\fR\fR \- Encode the resulting font to produce a ready \f(CW.pfb\fR file. -.Ip "\(bu" 2 -\f(CW\fB-d \fIsuboptions\fR\fR\fR \- Debugging options. The suboptions are: -.Sp -\f(CW\fBa\fR\fR \- Print out the absolute coordinates of dots in outlines. Such -a font can not be used by any program (that's why this option is -incompatible with \*(L'\fB\-e\fR') but it has proven to be a valuable debuging -information. -.Sp -\f(CW\fBr\fR\fR \- Do not reverse the direction of outlines. The \s-1TTF\s0 fonts have -the standard direction of outlines opposite to the Type1 fonts. So -they should be reversed during proper conversion. This option -may be used for debugging or to handle a \s-1TTF\s0 font with wrong -direction of outlines (possibly, converted in a broken way from -a Type1 font). The first signs of the wrong direction are the -letters like \*(L"P\*(R" or \*(L"B\*(R" without the unpainted \*(L"holes\*(R" inside. -.Ip "\(bu" 2 -\f(CW\fB-e\fR\fR \- Assemble the resulting font to produce a ready \f(CW.pfa\fR file. -.Sp -[ S.B.: Personally I don't think that this option is particularly useful. -The same result may be achieved by piping the unassembled data -through t1asm, the Type 1 assembler. And, anyways, it's good to -have the t1utils package handy. But Mark and many users think that -this functionality is good and it took not much time to add this option. ] -.Ip "\(bu" 2 -\f(CW\fB-F\fR\fR \- Force the Unicode encoding: any type of \s-1MS\s0 encoding specified -in the font is ignored and the font is treated like it has Unicode -encoding. \fB\s-1WARNING\s0:\fR this option is intended for buggy fonts -which actually are in Unicode but are marked as something else. The -effect on the other fonts is unpredictable. -.Ip "\(bu" 2 -\f(CW\fB-G \fIsuboptions\fR\fR\fR \- File generation options. The suboptions may be lowercase -or uppercase, the lowercase ones disable the generation of particular -files, the corresponding uppercase suboptions enable the generation of the -same kind of files. If the result of ttf2pt1 is requested to be printed on -the standard output, the last enabling suboption of \fB\-G\fR determines -which file will be written to the standard output and the rest of files -will be discarded. For example, \fB\-G A\fR will request the \s-1AFM\s0 file. -The suboptions to disable/enable the generation of the files are: -.Sp -\f(CW\fBf/F\fR\fR \- The font file. Depending on the other options this file -will have one of the suffixes \f(CW.t1a\fR, \f(CW.pfa\fR or \f(CW.pfb\fR. If the conversion result -is requested on the standard output ('\f(CW-\fR\*(R' is used as the output file name) -then the font file will also be written there by default, if not overwritten -by another suboption of \fB\-G\fR. -\fBDefault: enabled\fR -.Sp -\f(CW\fBa/A\fR\fR \- The Adobe font metrics file (\f(CW.afm\fR). -\fBDefault: enabled\fR -.Sp -\f(CW\fBe/E\fR\fR \- The dvips encoding file (\f(CW.enc\fR). -\fBDefault: disabled\fR -.Ip "\(bu" 2 -\f(CW\fB-l \fIlanguage\fR[+\fIargument\fR]\fR\fR \- Extract the fonts for the specified language from a -multi-language Unicode font. If this option is not used the converter -tries to guess the language by the values of the shell variable \s-1LANG\s0. -If it is not able to guess the language by \s-1LANG\s0 it tries all the -languages in the order they are listed. -.Sp -After the plus sign an optional argument for the language extractor -may be specified. The format of the argument is absolutely up to -the particular language converter. The primary purpose of the -argument is to support selection of planes for the multi-plane -Eastern encodings but it can also be used in any other way. The -language extractor may decide to add the plane name in some form -to the name of the resulting font. None of the currently supported -languages make any use of the argument yet. -.Sp -As of now the following languages are supported: -.Sp -\ \ \f(CWlatin1\fR \- for all the languages using the Latin-1 encoding -.Sp -\ \ \f(CWlatin2\fR \- for the Central European languages -.Sp -\ \ \f(CWlatin4\fR \- for the Baltic languages -.Sp -\ \ \f(CWlatin5\fR \- for the Turkish language -.Sp -\ \ \f(CWcyrillic\fR \- for the languages with Cyrillic alphabet -.Sp -\ \ \f(CWrussian\fR \- historic synonym for cyrillic -.Sp -\ \ \f(CWbulgarian\fR \- historic synonym for cyrillic -.Sp -\ \ \f(CWadobestd\fR \- for the AdobeStandard encoding used by TeX -.Sp -\ \ \f(CWplane+\fIargument\fR\fR \- to select one plane from a multi-byte encoding -.Sp -The argument of the \*(L"\f(CWplane\fR\*(R" language may be in one of three forms: -.Sp -\ \ \f(CWplane+\fBpid=\fR\fI<pid>\fR\fB,eid=\fR\fI<eid>\fR\fR -.Sp -\ \ \f(CWplane+\fBpid=\fR\fI<pid>\fR\fB,eid=\fR\fI<eid>\fR\fB,\fR\fI<plane_number>\fR\fR -.Sp -\ \ \f(CWplane+\fI<plane_number>\fR\fR -.Sp -Pid (\s-1TTF\s0 platform id) and eid (\s-1TTF\s0 encoding id) select a particular -\s-1TTF\s0 encoding table in the original font. They are specified as decimal -numbers. If this particular encoding table is not present in the font -file then the conversion fails. The native ("ttf") front-end parser supports -only pid=3 (Windows platform), the FreeType-based ("ft") front-end supports -any platform. If pid/eid is not specified then the \s-1TTF\s0 encoding table is -determined as usual: Unicode encoding if it's first or an 8-bit encoding -if not (and for an 8-bit encoding the plane number is silently ignored). -To prevent the converter from falling back to an 8-bit encoding, specify -the Unicode pid/eid value explicitly. -.Sp -Plane_number is a hexadecimal (if starts with \*(L"\fB0x\fR") or decimal number. -It gives the values of upper bytes for which 256 characters will be -selected. If not specified, defaults to 0. It is also used as a font -name suffix (the leading \*(L"0x\*(R" is not included into the suffix). -.Sp -\fB\s-1NOTE\s0:\fR -You may notice that the language names are not uniform: some are the -names of particular languages and some are names of encodings. This -is because of the different approaches. The original idea was to -implement a conversion from Unicode to the appropriate Windows -encoding for a given language. And then use the translation tables -to generate the fonts in whatever final encodings are needed. This -would allow to pile together the Unicode fonts and the non-Unicode -Windows fonts for that language and let the program to sort them out -automatically. And then generate fonts in all the possible encodings -for that language. An example of this approach is the Russian language -support. But if there is no multiplicity of encodings used for some -languages and if the non-Unicode fonts are not considered important -by the users, another way would be simpler to implement: just provide -only one table for extraction of the target encoding from Unicode -and don't bother with the translation tables. The latin* \*(L"languages\*(R" -are examples of this approach. If somebody feels that he needs the -Type1 fonts both in Latin-* and Windows encodings he or she is absolutely -welcome to submit the code to implement it. -.Sp -\fB\s-1WARNING\s0:\fR -Some of the glyphs included into the AdobeStandard encoding are not -included into the Unicode standard. The most typical examples of such -glyphs are ligatures like \*(L'fi\*(R', \*(L'fl\*(R' etc. Because of this the font -designers may place them at various places. The converter tries to -do its best, if the glyphs have honest Adobe names and/or are -placed at the same codes as in the Microsoft fonts they will be -picked up. Otherwise a possible solution is to use the option \*(L'\fB\-L\fR\*(R' -with an external map. -.Ip "\(bu" 2 -\f(CW\fB-L \fIfile\fR[+[pid=\fI<pid>\fR,eid=\fI<eid>\fR,][\fIplane\fR]]\fR\fR \- Extract the fonts for the specified -language from a multi-language font using the map from this file. This is -rather like the option \*(L'\fB\-l\fR\*(R' but the encoding map is not -compiled into the program, it's taken from that file, so it's -easy to edit. Examples of such files are provided in -\f(CWmaps/adobe-standard-encoding.map\fR, \f(CWCP1250.map\fR. (\fB\s-1NOTE\s0:\fR -the \*(L'standard encoding\*(R' map does not include all the glyphs of the -AdobeStandard encoding, it's provided only as an example.) The -description of the supported map formats is in the file -\f(CWmaps/unicode-sample.map\fR. -.Sp -Likewise to \*(L'\fB\-l\fR\*(R', an argument may be specified after the map file -name. But in this case the argument has fixed meaning: it selects the -original \s-1TTF\s0 encoding table (the syntax is the same as in \*(L'\fB\-l plane\fR') -and/or a plane of the map file. The plane name also gets added after dash -to the font name. The plane is a concept used in the Eastern fonts with big -number of glyphs: one \s-1TTF\s0 font gets divided into multiple Type1 fonts, -each containing one plane of up to 256 glyphs. But with a little -creativity this concept may be used for other purposes of combining -multiple translation maps into one file. To extract multiple planes -from a \s-1TTF\s0 font \f(CWttf2pt1\fR must be run multiple times, each time with -a different plane name specified. -.Sp -The default original \s-1TTF\s0 encoding table used for the option \*(L'\fB\-L\fR\*(R' is -Unicode. The map files may include directives to specify different original -\s-1TTF\s0 encodings. However if the pid/eid pair is specified with -it overrides any original encoding specified in the map file. -.Ip "\(bu" 2 -\f(CW\fB-m \fItype\fR=\fIvalue\fR\fR\fR \- Set maximal or minimal limits of resources. -These limits control the the font generation by limiting the resources -that the font is permitted to require from the PostScript interpreter. -The currently supported types of limits are: -.Sp -\f(CW\fBh\fR\fR \- the maximal hint stack depth for the substituted hints. -The default value is 128, according to the limitation in X11. This seems to -be the lowest (and thus the safest) widespread value. To display the -hint stack depth required by each glyph in a \f(CW.t1a\fR file use the script -\f(CWscripts/cntstems.pl\fR. -.Ip "\(bu" 2 -\f(CW\fB-O \fIsuboptions\fR\fR\fR \- Outline processing options. The suboptions -may be lowercase or uppercase, the lowercase ones disable the features, -the corresponding uppercase suboptions enable the same features. -The suboptions to disable/enable features are: -.Sp -\f(CW\fBb/B\fR\fR \- Guessing of the ForceBold parameter. This parameter helps -the Type1 engine to rasterize the bold fonts properly at small sizes. -But the algorithm used to guess the proper value of this flag makes -that guess based solely on the font name. In rare cases that may cause -errors, in these cases you may want to disable this guessing. -\fBDefault: enabled\fR -.Sp -\f(CW\fBh/H\fR\fR \- Autogeneration of hints. The really complex outlines -may confuse the algorithm, so theoretically it may be useful -sometimes to disable them. Although up to now it seems that -even bad hints are better than no hints at all. -\fBDefault: enabled\fR -.Sp -\f(CW\fBu/U\fR\fR \- Hint substitution. Hint substitution is a technique -permitting generation of more detailed hints for the rasterizer. It allows -to use different sets of hints for different parts of a glyph and change -these sets as neccessary during rasterization (that's why \*(L"substituted"). -So it should improve the quality of the fonts rendered at small sizes. -But there are two catches: First, the X11 library has rather low limit for -the font size. More detailed hints increase the file size and thus increase -the chance of hitting this limit (that does not mean that you shall hit it -but you may if your fonts are particularly big). This is especially -probable for Unicode fonts converted with option \*(L'\fB\-a\fR\*(R', so you may want to -use \*(L'\fB\-a\fR\*(R' together with \*(L'\fB\-Ou\fR\*(R'. See \f(CWapp/X11/README\fR for the description of -a patch to X11 which fixes this problem. Second, some rasterizers (again, -X11 is the typical example) have a limitation for total number of hints -used when drawing a glyph (also known as the hint stack depth). If that -stack overflows the glyph is ignored. Starting from version 3.22 \f(CWttf2pt1\fR -uses algorithms to minimizing this depth, with the trade-off of slightly -bigger font files. The glyphs which still exceed the limit set by option -\&\*(R'\fB\-mh\fR\*(R' have all the substituted hints removed and only base hints left. -The algorithms seem to have been refined far enough to make the fonts with -substituted hints look better than the fonts without them or at least the -same. Still if the original fonts are not well-designed the detailed -hinting may emphasize the defects of the design, such as non-even thickness -of lines. So provided that you are not afraid of the X11 bug the best idea -would be to generate a font with this feature and without it, then compare -the results using the program \f(CWother/cmpf\fR (see the description -in \f(CWother/README\fR) and decide which one looks better. -\fBDefault: enabled\fR -.Sp -\f(CW\fBo/O\fR\fR \- Space optimization of the outlines\*(R' code. This kind of optimization -never hurts, and the only reason to disable this feature is for comparison -of the generated fonts with the fonts generated by the previous versions of -converter. Well, it _almost_ never hurts. As it turned out there exist -some brain-damaged printers which don't understand it. Actually this -feature does not change the outlines at all. The Type 1 font manual -provides a set of redundant operators that make font description shorter, -such as \*(L'10 hlineto\*(R' instead of \*(L'0 10 rlineto\*(R' to describe a horizontal -line. This feature enables use of these operators. -\fBDefault: enabled\fR -.Sp -\f(CW\fBs/S\fR\fR \- Smoothing of outlines. If the font is broken in some -way (even the ones that are not easily noticeable), such smoothing -may break it further. So disabling this feature is the first thing to be -tried if some font looks odd. But with smoothing off the hint generation -algorithms may not work properly too. -\fBDefault: enabled\fR -.Sp -\f(CW\fBt/T\fR\fR \- Auto-scaling to the 1000x1000 Type1 standard matrix. The -\s-1TTF\s0 fonts are described in terms of an arbitrary matrix up to -4000x4000. The converted fonts must be scaled to conform to -the Type1 standard. But the scaling introduces additional rounding -errors, so it may be curious sometimes to look at the font in its -original scale. -\fBDefault: enabled\fR -.Sp -\f(CW\fBv/V\fR\fR \- Do vectorization on the bitmap fonts. Functionally -\*(L"vectorization\*(R" is the same thing as \*(L"autotracing\*(R", a different word is -used purely to differentiate it from the Autotrace library. It tries to -produce nice smooth outlines from bitmaps. This feature is still a work -in progress though the results are already mostly decent. -\fBDefault: disabled\fR -.Sp -\f(CW\fBw/W\fR\fR \- Glyphs\*(R' width corection. This option is designed to be -used on broken fonts which specify too narrow widths for the -letters. You can tell that a font can benefit from this option -if you see that the characters are smashed together without -any whitespace between them. This option causes the converter -to set the character widths to the actual width of this character -plus the width of a typical vertical stem. But on the other hand -the well-designed fonts may have characters that look better if -their widths are set slightly narrower. Such well-designed fonts -will benefit from disabling this feature. You may want to convert -a font with and without this feature, compare the results and -select the better one. This feature may be used only on proportional -fonts, it has no effect on the fixed-width fonts. -\fBDefault: disabled\fR -.Sp -\f(CW\fBz/Z\fR\fR \- Use the Autotrace library on the bitmap fonts. The results -are horrible and \fBthe use of this option is not recommended\fR. This option is -present for experimental purposes. It may change or be removed in the -future. The working tracing can be achieved with option \f(CW\fB-OV\fR\fR. -\fBDefault: disabled\fR -.Ip "\(bu" 2 -\f(CW\fB-p \fIparser_name\fR\fR\fR \- Use the specified front-end parser to read the font file. -If this option is not used, ttf2pt1 selects the parser automatically based -on the suffix of the font file name, it uses the first parser in its -list that supports this font type. Now two parsers are supported: -.Sp -\ \ \f(CWttf\fR \- built-in parser for the ttf files (suffix \f(CW.ttf\fR) -.Sp -\ \ \f(CWbdf\fR \- built-in parser for the \s-1BDF\s0 files (suffix \f(CW.bdf\fR) -.Sp -\ \ \f(CWft\fR \- parser based on the FreeType-2 library (suffixes \f(CW.ttf\fR, -\&\f(CW.otf\fR, \f(CW.pfa\fR, \f(CW.pfb\fR) -.Sp -The parser \f(CWft\fR is \fB\s-1NOT\s0\fR linked in by default. See \f(CWMakefile\fR -for instructions how to enable it. We do no support this parser on -Windows: probably it will work but nobody tried and nobody knows how -to build it. -.Sp -The conversion of the bitmap fonts (such as \s-1BDF\s0) is simplistic yet, -producing jagged outlines. When converting such fonts, it might be -a good idea to turn off the hint substitution (using option \fB\-Ou\fR) -because the hints produced will be huge but not adding much to the -quality of the fonts. -.Ip "\(bu" 2 -\f(CW\fB-u \fInumber\fR\fR\fR \- Mark the font with this value as its -UniqueID. The UniqueID is used by the printers with the hard disks -to cache the rasterized characters and thus significantly -speed-up the printing. Some of those printers just can't -store the fonts without UniqueID on their disk.The problem -is that the \s-1ID\s0 is supposed to be unique, as it name says. And -there is no easy way to create a guaranteed unique \s-1ID\s0. Adobe specifies -the range 4000000-4999999 for private IDs but still it's difficult -to guarantee the uniqueness within it. So if you don't really need the -UniqueID don't use it, it's optional. Luckily there are a few millions of -possible IDs, so the chances of collision are rather low. -If instead of the number a special value \*(L'\f(CW\fBA\fR\fR\*(R' is given -then the converter generates the value of UniqueID automatically, -as a hash of the font name. (\fB\s-1NOTE\s0:\fR in the version 3.22 the -algorithm for autogeneration of UniqueID was changed to fit the values -into the Adobe-spacified range. This means that if UniqueIDs were used -then the printer's cache may need to be flushed before replacing the -fonts converted by an old version with fonts converted by a newer version). -A simple way to find if any of the fonts in a given directory have -duplicated UniqueIDs is to use the command: -.Sp -\f(CW\ \ cat *.pf[ab] | grep UniqueID | sort | uniq -c | grep -v ' 1 '\fR -.Sp -Or if you use \f(CWscripts/convert\fR it will do that for you automatically -plus it will also give the exact list of files with duplicate UIDs. -.Ip "\(bu" 2 -\f(CW\fB-v \fIsize\fR\fR\fR \- Re-scale the font to get the size of a typical uppercase -letter somewhere around the specified size. Actually, it re-scales -the whole font to get the size of one language-dependent letter to be -at least of the specified size. Now this letter is \*(L"A\*(R" in all the -supported languages. The size is specified in the points of the -Type 1 coordinate grids, the maximal value is 1000. This is an -experimental option and should be used with caution. It tries to -increase the visible font size for a given point size and thus make -the font more readable. But if overused it may cause the fonts to -look out of scale. As of now the interesting values of size for -this option seem to be located mostly between 600 and 850. This -re-scaling may be quite useful but needs more experience to -understand the balance of its effects. -.Ip "\(bu" 2 -\f(CW\fB-W \fIlevel\fR\fR\fR \- Select the verbosity level of the warnings. -Currently the levels from 0 to 4 are supported. Level 0 means no warnings -at all, level 4 means all the possible warnings. The default level is 3. -Other levels may be added in the future, so using the level number 99 is -recommended to get all the possible warnings. Going below level 2 is -not generally recommended because you may miss valuable information about -the problems with the fonts being converted. -.Ip "\(bu" 2 -\fBObsolete option:\fR -\f(CW\fB-A\fR\fR \- Print the font metrics (.afm file) instead of the font on \s-1STDOUT\s0. -Use \fB\-\s-1GA\s0\fR instead. -.Ip "\(bu" 2 -\fBVery obsolete option:\fR -.Sp -The algorithm that implemented the forced fixed width had major -flaws, so it was disabled. The code is still in the program and -some day it will be refined and returned back. Meanwhile the -option name \*(L'\fB\-f\fR\*(R' was reused for another option. The old version was: -.Sp -\f(CW\fB-f\fR\fR \- Don't try to force the fixed width of font. Normally the converter -considers the fonts in which the glyph width deviates by not more -than 5% as buggy fixed width fonts and forces them to have really -fixed width. If this is undesirable, it can be disabled by this option. -.PP -The \f(CW.pfa\fR font format supposes that the description of the characters -is binary encoded and encrypted. This converter does not encode or -encrypt the data by default, you have to specify the option \*(L'\fB\-e\fR\*(R' -or use the \f(CWt1asm\fR program to assemble (that means, encode and -encrypt) the font program. The \f(CWt1asm\fR program that is included with -the converter is actually a part of the \f(CWt1utils\fR package, rather old -version of which may be obtained from -.PP -http://ttf2pt1.sourceforge.net/t1utils.tar.gz -.PP -Note that \f(CWt1asm\fR from the old version of that package won't work properly -with the files generated by \f(CWttf2pt1\fR version 3.20 and later. Please use -\f(CWt1asm\fR packaged with \f(CWttf2pt1\fR or from the new version \f(CWt1utils\fR -instead. For a newer version of \f(CWt1utils\fR please look at -.PP -http://www.lcdf.org/~eddietwo/type/ -.SH "EXAMPLES" -So, the following command lines: -.PP -\f(CWttf2pt1 -e ttffont.ttf t1font\fR -.PP -\f(CWttf2pt1 ttffont.ttf - | t1asm >t1font.pfa\fR -.PP -represent two ways to get a working font. The benefit of the second form -is that other filters may be applied to the font between the converter -and assembler. -.SH "FILES" -.Ip "\(bu" 2 -\s-1TTF2PT1_LIBXDIR/\s0t1asm -.Ip "\(bu" 2 -\s-1TTF2PT1_SHAREDIR\s0/* -.Ip "\(bu" 2 -\s-1TTF2PT1_SHAREDIR/\s0scripts/* -.Ip "\(bu" 2 -\s-1TTF2PT1_SHAREDIR/\s0other/* -.Ip "\(bu" 2 -\s-1TTF2PT1_SHAREDIR/README\s0 -.Ip "\(bu" 2 -\s-1TTF2PT1_SHAREDIR/FONTS\s0 -.SH "SEE ALSO" -.Ip "\(bu" 4 -the \fIttf2pt1_convert(1)\fR manpage -.Ip "\(bu" 4 -the \fIttf2pt1_x2gs(1)\fR manpage -.Ip "\(bu" 4 -the \fIt1asm(1)\fR manpage -.Ip "\(bu" 4 -ttf2pt1-announce@lists.sourceforge.net -.Sp -The mailing list with announcements about ttf2pt1. It is a moderated mailing -with extremely low traffic. Everyone is encouraged to subscribe to keep in -touch with the current status of project. To subscribe use the Web interface -at http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-announce. -If you have only e-mail access to the Net then send a subscribe request to -the development mailing list ttf2pt1-devel@lists.sourceforge.net and somebody -will help you with subscription. -.Ip "\(bu" 4 -ttf2pt1-devel@lists.sourceforge.net -.Sp -ttf2pt1-users@lists.sourceforge.net -.Sp -The ttf2pt1 mailing lists for development and users issues. They have not -that much traffic either. To subscribe use the Web interface at -http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-devel -and http://lists.sourceforge.net/mailman/listinfo/ttf2pt1-users. -If you have only e-mail access to the Net then send a subscribe request to -the development mailing list ttf2pt1-devel@lists.sourceforge.net and somebody -will help you with subscription. -.Ip "\(bu" 4 -http://ttf2pt1.sourceforge.net -.Sp -The main page of the project. -.Sp -http://www.netspace.net.au/~mheath/ttf2pt1/ -.Sp -The old main page of the project. -.SH "BUGS" -It seems that many Eastern fonts use features of the TTF format that are -not supported by the ttf2pt1's built-in front-end parser. Because of -this for now we recommend using the FreeType-based parser (option -\&\*(R'\fB\-p ft\fR') with the \*(L"\f(CWplane\fR\*(R" language. -.Sh "Troubleshooting and bug reports" -Have problems with conversion of some font ? The converter dumps core ? Or your -printer refuses to understand the converted fonts ? Or some characters are -missing ? Or some characters look strange ? -.PP -Send the bug reports to the ttf2pt1 development mailing list at -ttf2pt1-devel@lists.sourceforge.net. -.PP -Try to collect more information about the problem and include it into -the bug report. (Of course, even better if you would provide a ready -fix, but just a detailed bug report is also good). Provide detailed -information about your problem, this will speed up the response greatly. -Don't just write \*(L"this font looks strange after conversion\*(R" but describe -what's exactly wrong with it: for example, what characters look wrong -and what exactly is wrong about their look. Providing a link to the -original font file would be also a good idea. Try to do a little -troublehooting and report its result. This not only would help with -the fix but may also give you a temporary work-around for the bug. -.PP -First, enable full warnings with option \*(L'\fB\-W99\fR\*(R', save them to -a file and read carefully. Sometimes the prolem is with a not implemented -feature which is reported in the warnings. Still, reporting about such -problems may be a good idea: some features were missed to cut corners, -in hope that no real font is using them. So a report about a font using -such a feature may motivate someone to implement it. Of course, you -may be the most motivated person: after all, you are the one wishing -to convert that font. ;\-) Seriously, the philosophy \*(L"scrath your own itch\*(R" -seems to be the strongest moving force behind the Open Source software. -.PP -The next step is playing with the options. This serves a dual purpose: -on one hand, it helps to localize the bug, on the other hand you may be -able to get a working version of the font for the meantime while the -bug is being fixed. The typical options to try out are: first \*(L'\fB\-Ou\fR\*(R', if -it does not help then \*(L'\fB\-Os\fR\*(R', then \*(L'\fB\-Oh\fR\*(R', then \*(L'\fB\-Oo\fR\*(R'. -They are described in a bit more detail above. Try them one by one -and in combinations. See if with them the resulting fonts look better. -.PP -On some fonts ttf2pt1 just crashes. Commonly that happens because the -font being converted is highly defective (although sometimes the bug -is in ttf2pt1 itself). In any case it should not crash, so the reports -about such cases will help to handle these defects properly in future. -.PP -We try to respond to the bug reports in a timely fashion but alas, this -may not always be possible, especially if the problem is complex. -This is a volunteer project and its resources are limited. Because -of this we would appreciate bug reports as detailed as possible, -and we would appreciate the ready fixes and contributions even more. -.SH "HISTORY" -Based on ttf2pfa by Andrew Weeks, and help from Frank Siegert. -.PP -Modification by Mark Heath. -.PP -Further modification by Sergey Babkin. -.PP -The Type1 assembler by I. Lee Hetherington with modifications by -Kai-Uwe Herbing. - -.rn }` '' -.IX Title "TTF2PT1 1" -.IX Name "TTF2PT1 - A True Type to PostScript Type 1 Font Converter" - -.IX Header "NAME" - -.IX Header "SYNOPSIS" - -.IX Header "DESCRIPTION" - -.IX Header "OPTIONS" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Header "EXAMPLES" - -.IX Header "FILES" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Header "SEE ALSO" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Header "BUGS" - -.IX Subsection "Troubleshooting and bug reports" - -.IX Header "HISTORY" - diff --git a/nx-X11/extras/ttf2pt1/ttf2pt1.c b/nx-X11/extras/ttf2pt1/ttf2pt1.c deleted file mode 100644 index a85a41658..000000000 --- a/nx-X11/extras/ttf2pt1/ttf2pt1.c +++ /dev/null @@ -1,2722 +0,0 @@ -/* - * True Type Font to Adobe Type 1 font converter - * By Mark Heath <mheath@netspace.net.au> - * Based on ttf2pfa by Andrew Weeks <ccsaw@bath.ac.uk> - * With help from Frank M. Siegert <fms@this.net> - * - * see COPYRIGHT for full copyright notice - * -*********************************************************************** - * - * Sergey Babkin <babkin@users.sourceforge.net>, <sab123@hotmail.com> - * - * Added post-processing of resulting outline to correct the errors - * both introduced during conversion and present in the original font, - * autogeneration of hints (has yet to be improved though) and BlueValues, - * scaling to 1000x1000 matrix, option to print the result on STDOUT, - * support of Unicode to CP1251 conversion, optimization of the - * resulting font code by space (that improves the speed too). Excluded - * the glyphs that are unaccessible through the encoding table from - * the output file. Added the built-in Type1 assembler (taken from - * the `t1utils' package). - * -*********************************************************************** - * - * Thomas Henlich <thenlich@rcs.urz.tu-dresden.de> - * - * Added generation of .afm file (font metrics) - * Read encoding information from encoding description file - * Fixed bug in error message about unknown language ('-l' option) - * Added `:' after %%!PS-AdobeFont-1.0 - * changed unused entries in ISOLatin1Encoding[] from .notdef to c127,c128... - * -*********************************************************************** - * - * Thomas Henlich <thenlich@rcs.urz.tu-dresden.de> - * - * Added generation of .afm file (font metrics) - * -*********************************************************************** - * - * Bug Fixes: -************************************************************************ - * - * Sun, 21 Jun 1998 Thomas Henlich <thenlich@Rcs1.urz.tu-dresden.de> - * 1. "width" should be "short int" because otherwise: - * characters with negative widths (e.g. -4) become *very* wide (65532) - * 2. the number of /CharStrings is numglyphs and not numglyphs+1 - * -*********************************************************************** - * - * - * - * The resultant font file produced by this program still needs to be ran - * through t1asm (from the t1utils archive) to produce a completely valid - * font. - * - */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <time.h> -#include <ctype.h> -#include <math.h> - -#ifdef _GNU_SOURCE -#include <getopt.h> -#endif - -#ifndef WINDOWS -# include <unistd.h> -# include <netinet/in.h> -# define BITBUCKET "/dev/null" -# include <sys/wait.h> -#else -# define WINDOWS_FUNCTIONS /* ask to define functions - in one file only */ -# include "windows.h" -# define BITBUCKET "NUL" -# define snprintf _snprintf -#endif - -#ifdef XP_PSTEXT -#include <ft2build.h> -#include FT_FREETYPE_H -#include FT_TRUETYPE_TABLES_H -#include FT_BBOX_H -#include FT_GLYPH_H - -#include FT_CONFIG_CONFIG_H -#include FT_CONFIG_OPTIONS_H -#include FT_ERRORS_H -#include FT_SYSTEM_H -#include FT_IMAGE_H -#include FT_TYPES_H -#include FT_OUTLINE_H -#include FT_MODULE_H -#include FT_RENDER_H -#include FT_TYPE1_TABLES_H -#include FT_TRUETYPE_IDS_H -#include FT_TRUETYPE_TAGS_H -#include FT_MULTIPLE_MASTERS_H -#include FT_SFNT_NAMES_H - -#include "os.h" -#include "Xproto.h" -#include "font.h" -#include "fontstruct.h" -#include "fntfilst.h" -#include "fontutil.h" -#include "fontenc.h" -#include "ft.h" -#define NOT_IN_FTFUNCS -#include "ftfuncs.h" -#endif /* XP_PSTEXT */ - -#include "pt1.h" -#include "global.h" -#include "version.h" - -/* globals */ - -/* table of front-ends */ - -#ifdef USE_TTF -extern struct frontsw ttf_sw; -#endif /* USE_TTF */ -#ifdef USE_BDF -extern struct frontsw bdf_sw; -#endif /* USE_BDF */ -#if defined(USE_FREETYPE) - extern struct frontsw freetype_sw; -#endif - -struct frontsw *frontswtab[] = { -#ifdef USE_BDF - &bdf_sw, -#endif /* USE_BDF */ -#if defined(USE_FREETYPE) && defined(PREFER_FREETYPE) - &freetype_sw, -#endif -#ifdef USE_TTF - &ttf_sw, -#endif /* USE_TTF */ -#if defined(USE_FREETYPE) && !defined(PREFER_FREETYPE) - &freetype_sw, -#endif - NULL /* end of table */ -}; - -struct frontsw *cursw=0; /* the active front end */ -char *front_arg=""; /* optional argument */ - -/* options */ -int encode = 0; /* encode the resulting file */ -int pfbflag = 0; /* produce compressed file */ -int wantafm=0; /* want to see .afm instead of .t1a on stdout */ -int correctvsize=0; /* try to correct the vertical size of characters */ -int wantuid = 0; /* user wants UniqueID entry in the font */ -int allglyphs = 0; /* convert all glyphs, not only 256 of them */ -int warnlevel = 3; /* the level of permitted warnings */ -int forcemap = 0; /* do mapping even on non-Unicode fonts */ -/* options - maximal limits */ -int max_stemdepth = 128; /* maximal depth of stem stack in interpreter (128 - limit from X11) */ -/* options - debugging */ -int absolute = 0; /* print out in absolute values */ -int reverse = 1; /* reverse font to Type1 path directions */ -/* options - suboptions of Outline Processing, defaults are set in table */ -int optimize; /* enables space optimization */ -int smooth; /* enable smoothing of outlines */ -int transform; /* enables transformation to 1000x1000 matrix */ -int hints; /* enables autogeneration of hints */ -int subhints; /* enables autogeneration of substituted hints */ -int trybold; /* try to guess whether the font is bold */ -int correctwidth; /* try to correct the character width */ -int vectorize; /* vectorize the bitmaps */ -int use_autotrace; /* use the autotrace library on bitmap */ -/* options - suboptions of File Generation, defaults are set in table */ -int gen_pfa; /* generate the font file */ -int gen_afm; /* generate the metrics file */ -int gen_dvienc; /* generate the dvips encoding file */ - -/* not quite options to select a particular source encoding */ -int force_pid = -1; /* specific platform id */ -int force_eid = -1; /* specific encoding id */ - -/* structure to define the sub-option lists controlled by the - * case: uppercase enables them, lowercase disables - */ -struct subo_case { - char disbl; /* character to disable - enforced lowercase */ - char enbl; /* character to enable - auto-set as toupper(disbl) */ - int *valp; /* pointer to the actual variable containing value */ - int dflt; /* default value */ - char *descr; /* description */ -}; - -#ifdef DEBUG -int debug = DEBUG; /* debugging flag */ -#else -int debug = 0; -#endif /* DEBUG */ - -FILE *null_file, *pfa_file, *afm_file, *dvienc_file; -int numglyphs; -struct font_metrics fontm; - -/* non-globals */ -static char *strUID = 0; /* user-supplied UniqueID */ -static unsigned long numUID; /* auto-generated UniqueID */ - -static int ps_fmt_3 = 0; -static double scale_factor, original_scale_factor; - -static char *glyph_rename[ENCTABSZ]; - -/* the names assigned if the original font - * does not specify any - */ - -static char *Fmt3Encoding[256] = { - "c0", "c1", "c2", "c3", - "c4", "c5", "c6", "c7", - "c8", "c9", "c10", "c11", - "c12", "CR", "c14", "c15", - "c16", "c17", "c18", "c19", - "c20", "c21", "c22", "c23", - "c24", "c25", "c26", "c27", - "c28", "c29", "c30", "c31", - "space", "exclam", "quotedbl", "numbersign", - "dollar", "percent", "ampersand", "quotesingle", - "parenleft", "parenright", "asterisk", "plus", - "comma", "hyphen", "period", "slash", - "zero", "one", "two", "three", - "four", "five", "six", "seven", - "eight", "nine", "colon", "semicolon", - "less", "equal", "greater", "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", - "backslash", "bracketright", "asciicircum", "underscore", - "grave", "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", "braceleft", - "bar", "braceright", "asciitilde", "c127", - "c128", "c129", "quotesinglbase", "florin", - "quotedblbase", "ellipsis", "dagger", "daggerdbl", - "circumflex", "perthousand", "Scaron", "guilsinglleft", - "OE", "c141", "c142", "c143", - "c144", "quoteleft", "quoteright", "quotedblleft", - "quotedblright", "bullet", "endash", "emdash", - "tilde", "trademark", "scaron", "guilsinglright", - "oe", "c157", "c158", "Ydieresis", - "nbspace", "exclamdown", "cent", "sterling", - "currency", "yen", "brokenbar", "section", - "dieresis", "copyright", "ordfeminine", "guillemotleft", - "logicalnot", "sfthyphen", "registered", "macron", - "degree", "plusminus", "twosuperior", "threesuperior", - "acute", "mu", "paragraph", "periodcentered", - "cedilla", "onesuperior", "ordmasculine", "guillemotright", - "onequarter", "onehalf", "threequarters", "questiondown", - "Agrave", "Aacute", "Acircumflex", "Atilde", - "Adieresis", "Aring", "AE", "Ccedilla", - "Egrave", "Eacute", "Ecircumflex", "Edieresis", - "Igrave", "Iacute", "Icircumflex", "Idieresis", - "Eth", "Ntilde", "Ograve", "Oacute", - "Ocircumflex", "Otilde", "Odieresis", "multiply", - "Oslash", "Ugrave", "Uacute", "Ucircumflex", - "Udieresis", "Yacute", "Thorn", "germandbls", - "agrave", "aacute", "acircumflex", "atilde", - "adieresis", "aring", "ae", "ccedilla", - "egrave", "eacute", "ecircumflex", "edieresis", - "igrave", "iacute", "icircumflex", "idieresis", - "eth", "ntilde", "ograve", "oacute", - "ocircumflex", "otilde", "odieresis", "divide", - "oslash", "ugrave", "uacute", "ucircumflex", - "udieresis", "yacute", "thorn", "ydieresis" -}; - -#ifdef notdef /* { */ -/* This table is not used anywhere in the code - * so it's ifdef-ed out by default but left in - * the source code for reference purposes (and - * possibly for future use) - */ - -static char *ISOLatin1Encoding[256] = { - ".null", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", "CR", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - "space", "exclam", "quotedbl", "numbersign", - "dollar", "percent", "ampersand", "quoteright", - "parenleft", "parenright", "asterisk", "plus", - "comma", "hyphen", "period", "slash", - "zero", "one", "two", "three", - "four", "five", "six", "seven", - "eight", "nine", "colon", "semicolon", - "less", "equal", "greater", "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", - "backslash", "bracketright", "asciicircum", "underscore", - "grave", "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", "braceleft", - "bar", "braceright", "asciitilde", "c127", - "c128", "c129", "quotesinglbase", "florin", - "quotedblbase", "ellipsis", "dagger", "daggerdbl", - "circumflex", "perthousand", "Scaron", "guilsinglleft", - "OE", "c141", "c142", "c143", - "c144", "quoteleft", "quoteright", "quotedblleft", - "quotedblright", "bullet", "endash", "emdash", - "tilde", "trademark", "scaron", "guilsinglright", - "oe", "c157", "c158", "Ydieresis", - "nbspace", "exclamdown", "cent", "sterling", - "currency", "yen", "brokenbar", "section", - "dieresis", "copyright", "ordfeminine", "guillemotleft", - "logicalnot", "sfthyphen", "registered", "macron", - "degree", "plusminus", "twosuperior", "threesuperior", - "acute", "mu", "paragraph", "periodcentered", - "cedilla", "onesuperior", "ordmasculine", "guillemotright", - "onequarter", "onehalf", "threequarters", "questiondown", - "Agrave", "Aacute", "Acircumflex", "Atilde", - "Adieresis", "Aring", "AE", "Ccedilla", - "Egrave", "Eacute", "Ecircumflex", "Edieresis", - "Igrave", "Iacute", "Icircumflex", "Idieresis", - "Eth", "Ntilde", "Ograve", "Oacute", - "Ocircumflex", "Otilde", "Odieresis", "multiply", - "Oslash", "Ugrave", "Uacute", "Ucircumflex", - "Udieresis", "Yacute", "Thorn", "germandbls", - "agrave", "aacute", "acircumflex", "atilde", - "adieresis", "aring", "ae", "ccedilla", - "egrave", "eacute", "ecircumflex", "edieresis", - "igrave", "iacute", "icircumflex", "idieresis", - "eth", "ntilde", "ograve", "oacute", - "ocircumflex", "otilde", "odieresis", "divide", - "oslash", "ugrave", "uacute", "ucircumflex", - "udieresis", "yacute", "thorn", "ydieresis" -}; - -#endif /* } notdef */ - -static char *adobe_StandardEncoding[256] = { - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - "space", "exclam", "quotedbl", "numbersign", - "dollar", "percent", "ampersand", "quoteright", - "parenleft", "parenright", "asterisk", "plus", - "comma", "hyphen", "period", "slash", - "zero", "one", "two", "three", - "four", "five", "six", "seven", - "eight", "nine", "colon", "semicolon", - "less", "equal", "greater", "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", - "backslash", "bracketright", "asciicircum", "underscore", - "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", "braceleft", - "bar", "braceright", "asciitilde", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", "exclamdown", "cent", "sterling", - "fraction", "yen", "florin", "section", - "currency", "quotesingle", "quotedblleft", "guillemotleft", - "guilsinglleft", "guilsinglright", "fi", "fl", - ".notdef", "endash", "dagger", "daggerdbl", - "periodcentered", ".notdef", "paragraph", "bullet", - "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", - "ellipsis", "perthousand", ".notdef", "questiondown", - ".notdef", "grave", "acute", "circumflex", - "tilde", "macron", "breve", "dotaccent", - "dieresis", ".notdef", "ring", "cedilla", - ".notdef", "hungarumlaut", "ogonek", "caron", - "emdash", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", "AE", ".notdef", "ordfeminine", - ".notdef", ".notdef", ".notdef", ".notdef", - "Lslash", "Oslash", "OE", "ordmasculine", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", "ae", ".notdef", ".notdef", - ".notdef", "dotlessi", ".notdef", ".notdef", - "lslash", "oslash", "oe", "germandbls", - ".notdef", ".notdef", ".notdef", ".notdef" -}; - -/* - * Decription of the supported conversions from Unicode - * - * SB - * Yes, I know that the compiled-in conversion is stupid but - * it is simple to implement and allows not to worry about the - * filesystem context. After all, the source is always available - * and adding another language to it is easy. - * - * The language name is expected to be the same as the subdirectory name - * in the `encodings' directory (for possible future extensions). - * The primary use of the aliases is for guessing based on the current - * locale. - */ - -#define MAXUNIALIAS 10 -#define MAXUNITABLES 3 - -/* the character used as the language argument separator */ -#define LANG_ARG_SEP '+' - - -/* - * Types of language-related routines. Arguments are: - * name is the glyph name - * arg is the user-specified language-dependent argument - * which can for example select the subfont plane for Eastern fonts. - * If none is supplied by user then an empty string ("") is passed. - * If no language is specified by user and auto-guessing happens - * then NULL is passed. - * when shows if the conversion by name was called before conversion by - * map or after (it's called twice) - */ - -/* type of the Unicode map initialization routine */ -typedef void uni_init_t(char *arg); - -/* type of Unicode converter-by-name function - * it's called for each glyph twice: one time for each glyph - * before doing conversion by map and one time after - */ -typedef int uni_conv_t(char *name, char *arg, int when); -#define UNICONV_BYNAME_BEFORE 0 -#define UNICONV_BYNAME_AFTER 1 - -struct uni_language { - uni_init_t *init[MAXUNITABLES]; /* map initialization routines */ - uni_conv_t *convbyname; /* the name-based conversion function */ - char *name; /* the language name */ - char *descr; /* description */ - char *alias[MAXUNIALIAS]; /* aliases of the language name */ - int sample_upper; /* code of some uppercase character for correctvsize() */ -}; - -/* the converter routines have an option of adding this suffix to the font name */ -static char *uni_font_name_suffix = ""; /* empty by default */ -/* this buffer may be used to store the suffix */ -#define UNI_MAX_SUFFIX_LEN 100 -static char uni_suffix_buf[UNI_MAX_SUFFIX_LEN+1]; - -/* - * Prototypes of the conversion routines - */ - -static uni_init_t unicode_latin1; -static uni_init_t unicode_latin2; -static uni_init_t unicode_latin4; -static uni_init_t unicode_latin5; -static uni_init_t unicode_cyrillic; -static uni_init_t unicode_adobestd; -static uni_init_t unicode_plane; -static uni_conv_t unicode_adobestd_byname; - -static uni_init_t unicode_init_user; - -/* - * The order of descriptions is important: if we can't guess the - * language we just call all the conversion routines in order until - * we find one that understands this glyph. - */ -static struct uni_language uni_lang[]= { - /* pseudo-language for all the languages using Latin1 */ - { - { unicode_latin1 }, - 0, /* no name-based mapping */ - "latin1", - "works for most of the Western languages", - { "en_", "de_", "fr_", "nl_", "no_", "da_", "it_" }, - 'A' - }, - { /* by Szalay Tamas <tomek@elender.hu> */ - { unicode_latin2 }, - 0, /* no name-based mapping */ - "latin2", - "works for Central European languages", - { "hu_","pl_","cz_","si_","sk_" }, - 'A' - }, - { /* by Rièardas Èepas <rch@WriteMe.Com> */ - { unicode_latin4 }, - 0, /* no name-based mapping */ - "latin4", - "works for Baltic languages", - { "lt_", "lv_" }, /* doubt about ee_ */ - 'A' - }, - { /* by Turgut Uyar <uyar@cs.itu.edu.tr> */ - { unicode_latin5 }, - 0, /* no name-based mapping */ - "latin5", - "for Turkish", - { "tr_" }, - 'A' - }, - { /* by Zvezdan Petkovic <z.petkovic@computer.org> */ - { unicode_cyrillic, unicode_latin1 }, - 0, /* no name-based mapping */ - "cyrillic", - "in Windows encoding", - { "bg_", "be_", "mk_", "ru_", "sr_", "su_", "uk_" }, - 'A' - }, - { - { unicode_cyrillic, unicode_latin1 }, - 0, /* no name-based mapping */ - "russian", - "obsolete, use cyrillic instead", - { 0 }, - 'A' - }, - { - { unicode_cyrillic, unicode_latin1 }, - 0, /* no name-based mapping */ - "bulgarian", - "obsolete, use cyrillic instead", - { 0 }, - 'A' - }, - { - { unicode_adobestd }, - unicode_adobestd_byname, - "adobestd", - "Adobe Standard, expected by TeX", - { NULL }, - 'A' - }, - { - { unicode_plane }, - 0, /* no name-based mapping */ - "plane", - "one plane of Unicode or other multi-byte encoding as is", - { NULL }, - 0 /* no easy way to predict the capital letters */ - }, -}; - -static struct uni_language uni_lang_user = { - { unicode_init_user }, - 0, /* no name-based mapping */ - 0, /* no name */ - 0, /* no description */ - { 0 }, - 0 /* no sample */ -}; - -static struct uni_language *uni_lang_selected=0; /* 0 means "unknown, try all" */ -static int uni_sample='A'; /* sample of an uppercase character */ -static char *uni_lang_arg=""; /* user-supplied language-dependent argument */ - -extern int runt1asm(int); - -/* - * user-defined loadable maps - */ - - -/* The idea begind buckets is to avoid comparing every code with all ENCTABSZ codes in table. - * All the 16-bit unicode space is divided between a number of equal-sized buckets. - * Initially all the buckets are marked with 0. Then if any code in the bucket is - * used it's marked with 1. Later during translation we check the code's bucket first - * and it it's 0 then return failure right away. This may be useful for - * Chinese fonts with many thousands of glyphs. - */ - -#define BUCKET_ID_BITS 11 -#define MARK_UNI_BUCKET(unicode) SET_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS)) -#define IS_UNI_BUCKET(unicode) IS_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS)) - -static DEF_BITMAP(uni_user_buckets, 1<<BUCKET_ID_BITS); - -static unsigned int unicode_map[ENCTABSZ]; /* font-encoding to unicode map */ -static int enctabsz = 256; /* actual number of codes used */ - -static void -unicode_init_user( - char *path -) -{ - FILE *unicode_map_file; -#define UNIBFSZ 256 - char buffer[UNIBFSZ]; - unsigned code, unicode, curpos, unicode2; - char *arg, *p; - int enabled, found, sawplane; - int lineno, cnt, n, nchars; - char next; - int pid, eid, overid=0; - - /* check if we have an argument (plane name) */ - arg = strrchr(path, LANG_ARG_SEP); - if(arg != 0) { - *arg++ = 0; - if( sscanf(arg, "pid=%d,eid=%d%n", &pid, &eid, &nchars) == 2 ) { - force_pid = pid; force_eid = eid; overid = 1; - WARNING_1 fprintf(stderr, "User override of the source encoding: pid=%d eid=%d\n", pid, eid); - forcemap = 1; - arg += nchars; - if(*arg == ',') - arg++; - } - if( *arg == 0 || strlen(arg) > UNI_MAX_SUFFIX_LEN-1) - arg = NULL; - else { - sprintf(uni_suffix_buf, "-%s", arg); - uni_font_name_suffix = uni_suffix_buf; - } - } - - /* now read in the encoding description file, if requested */ - if ((unicode_map_file = fopen(path, "r")) == NULL) { - fprintf(stderr, "**** Cannot access map file '%s' ****\n", path); - exit(1); - } - - sawplane = 0; - if(arg==NULL) - enabled = found = 1; - else - enabled = found = 0; - - lineno=0; curpos=0; - while (fgets (buffer, UNIBFSZ, unicode_map_file) != NULL) { - char name[UNIBFSZ]; - - lineno++; - - if(sscanf(buffer, "plane %s", name)==1) { - sawplane = 1; - if(arg == 0) { - fprintf(stderr, "**** map file '%s' requires plane name\n", path); - fprintf(stderr, "for example:\n"); - fprintf(stderr, " ttf2pt1 -L %s%c[pid=N,eid=N,]%s ...\n", - path, LANG_ARG_SEP, name); - fprintf(stderr, "to select plane '%s'\n", name); - exit(1); - } - if( !strcmp(arg, name) ) { - enabled = found = 1; - curpos = 0; - } else { - enabled = 0; - if(found) /* no need to read further */ - break; - } - continue; - } - - if(sscanf(buffer, "id %d %d", &pid, &eid)==2) { - if( !overid /* only if the user has not overriden */ - && (enabled || !sawplane) ) { - force_pid = pid; force_eid = eid; - forcemap = 1; - } - continue; - } - - if( !enabled ) - continue; /* skip to the next plane */ - - if( sscanf(buffer, "at %i", &curpos) == 1 ) { - if(curpos > 255) { - fprintf(stderr, "**** map file '%s' line %d: code over 255\n", path, lineno); - exit(1); - } - if(ISDBG(EXTMAP)) fprintf(stderr, "=== at 0x%x\n", curpos); - continue; - } - - /* try the format of Roman Czyborra's files */ - if ( sscanf (buffer, " =%x U+%4x", &code, &unicode) == 2 - /* try the format of Linux locale charmap file */ - || sscanf (buffer, " <%*s /x%x <U%4x>", &code, &unicode) == 2 ) { - if (code < ENCTABSZ) { - if(code >= enctabsz) enctabsz=code+1; - unicode_map[code] = unicode; - glyph_rename[code] = NULL; - } - } - /* try the format with glyph renaming */ - else if (sscanf (buffer, " !%x U+%4x %128s", &code, - &unicode, name) == 3) { - if (code < ENCTABSZ) { - if(code >= enctabsz) enctabsz=code+1; - unicode_map[code] = unicode; - glyph_rename[code] = strdup(name); - } - } - /* try the compact sequence format */ - else if( (n=sscanf(buffer, " %i%n", &unicode, &cnt)) == 1 ) { - p = buffer; - do { - if(curpos > 255) { - fprintf(stderr, "**** map file '%s' line %d: code over 255 for unicode 0x%x\n", - path, lineno, unicode); - exit(1); - } - if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%d -> 0x%x\n", curpos, unicode); - unicode_map[curpos++] = unicode; - p += cnt; - if( sscanf(p, " %[,-]%n", &next,&cnt) == 1 ) { - if(ISDBG(EXTMAP)) fprintf(stderr, "=== next: '%c'\n", next); - p += cnt; - if( next == '-' ) { /* range */ - if ( sscanf(p, " %i%n", &unicode2, &cnt) != 1 ) { - fprintf(stderr, "**** map file '%s' line %d: missing end of range\n", path, lineno); - exit(1); - } - p += cnt; - if(ISDBG(EXTMAP)) fprintf(stderr, "=== range 0x%x to 0x%x\n", unicode, unicode2); - for(unicode++; unicode <= unicode2; unicode++) { - if(curpos > 255) { - fprintf(stderr, "**** map file '%s' line %d: code over 255 in unicode range ...-0x%x\n", - path, lineno, unicode2); - exit(1); - } - if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%x -> 0x%x\n", curpos, unicode); - unicode_map[curpos++] = unicode; - } - } - } - } while ( sscanf(p, " %i%n", &unicode, &cnt) == 1 ); - } - - } - - fclose (unicode_map_file); - - if( !found ) { - fprintf(stderr, "**** map file '%s' has no plane '%s'\n", path, arg); - exit(1); - } - - if(unicode_map['A'] == 'A') - uni_sample = 'A'; /* seems to be compatible with Latin */ - else - uni_sample = 0; /* don't make any assumptions */ -} - -/* - * by Zvezdan Petkovic <z.petkovic@computer.org> - */ -static void -unicode_cyrillic( - char *arg -) -{ - int i; - static unsigned int cyrillic_unicode_map[] = { - 0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */ - 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f, /* 88 */ - 0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */ - 0x02dc, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f, /* 98 */ - 0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, /* A0 */ - 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407, /* A8 */ - 0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7, /* B0 */ - 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457, /* B8 */ - }; - - for(i=0; i<=0x7F; i++) - unicode_map[i] = i; - - for(i=0x80; i<=0xBF; i++) - unicode_map[i] = cyrillic_unicode_map[i-0x80]; - - for(i=0xC0; i<=0xFF; i++) - unicode_map[i] = i+0x350; - -} - -static void -unicode_latin1( - char *arg -) -{ - int i; - static unsigned int latin1_unicode_map[] = { - 0x20ac, -1, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */ - 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f, /* 88 */ - 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */ - 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178, /* 98 */ - }; - - for(i=0; i<=0x7F; i++) - unicode_map[i] = i; - - for(i=0x80; i<=0x9F; i++) - unicode_map[i] = latin1_unicode_map[i-0x80]; - - for(i=0xA0; i<=0xFF; i++) - unicode_map[i] = i; -} - -static void -unicode_adobestd( - char *arg -) -{ - int i; - static unsigned int adobestd_unicode_map[] = { - -1, 0x00a1, 0x00a2, 0x00a3, 0x2215, 0x00a5, 0x0192, 0x00a7, /* A0 */ - 0x00a4, 0x0027, 0x201c, 0x00ab, 0x2039, 0x203a, 0xfb01, 0xfb02, /* A8 */ - -1, 0x2013, 0x2020, 0x2021, 0x2219, -1, 0x00b6, 0x2022, /* B0 */ - 0x201a, 0x201e, 0x201d, 0x00bb, 0x2026, 0x2030, -1, 0x00bf, /* B8 */ - -1, 0x0060, 0x00b4, 0x02c6, 0x02dc, 0x02c9, 0x02d8, 0x02d9, /* C0 */ - 0x00a8, -1, 0x02da, 0x00b8, -1, 0x02dd, 0x02db, 0x02c7, /* C8 */ - 0x2014, -1, -1, -1, -1, -1, -1, -1, /* D0 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* D8 */ - -1, 0x00c6, -1, 0x00aa, -1, -1, -1, -1, /* E0 */ - 0x0141, 0x00d8, 0x0152, 0x00ba, -1, -1, -1, -1, /* E8 */ - -1, 0x00e6, -1, -1, -1, 0x0131, -1, -1, /* F0 */ - 0x0142, 0x00f8, 0x0153, 0x00df, -1, -1, -1, -1, /* F8 */ - }; - - for(i=0; i<=0x7F; i++) - unicode_map[i] = i; - - unicode_map[0x27] = 0x2019; - unicode_map[0x60] = -1; - - /* 0x80 to 0x9F is a hole */ - - for(i=0xA0; i<=0xFF; i++) - unicode_map[i] = adobestd_unicode_map[i-0xA0]; -} - -/* - * Not all of the Adobe glyphs are in the Unicode - * standard maps, so the font creators have - * different ideas about their codes. Because - * of this we try to map based on the glyph - * names instead of Unicode codes. If there are - * no glyph names (ps_fmt_3!=0) we fall back - * to the code-based scheme. - */ - -static int -unicode_adobestd_byname( - char *name, - char *arg, - int where -) -{ - int i; - - /* names always take precedence over codes */ - if(where == UNICONV_BYNAME_AFTER) - return -1; - - for(i=32; i<256; i++) { - if(!strcmp(name, adobe_StandardEncoding[i])) - return i; - } - return -1; - -} - -static void -unicode_latin2( - char *arg -) -{ - int i; - static unsigned int latin2_unicode_map[] = { - 0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7, /* A0 */ - 0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b, /* A8 */ - 0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7, /* B0 */ - 0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, /* B8 */ - 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, /* C0 */ - 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, /* C8 */ - 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, /* D0 */ - 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, /* D8 */ - 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, /* E0 */ - 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, /* E8 */ - 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, /* F0 */ - 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9, /* F8 */ - }; - - for(i=0; i<=0x7E; i++) - unicode_map[i] = i; - - /* 7F-9F are unused */ - - for(i=0xA0; i<=0xFF; i++) - unicode_map[i] = latin2_unicode_map[i-0xA0]; -} - -static void -unicode_latin4( - char *arg -) -{ - int i; - static unsigned int latin4_unicode_map[] = { - 0x0080, 0x0081, 0x201a, 0x0192, -1, 0x2026, 0x2020, 0x2021, /* 80 */ - 0x02c6, 0x2030, -1, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f, /* 88 */ - 0x201e, 0x201c, 0x2019, -1, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */ - 0x02dc, 0x2122, -1, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178, /* 98 */ - 0x00a0, 0x0104, 0x0138, 0x0156, 0x00a4, 0x0128, 0x013b, 0x00a7, /* A0 */ - 0x00a8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00ad, 0x017d, 0x00af, /* A8 */ - 0x00b0, 0x0105, 0x02db, 0x0157, 0x00b4, 0x0129, 0x013c, 0x02c7, /* B0 */ - 0x00b8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014a, 0x017e, 0x014b, /* B8 */ - 0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, /* C0 */ - 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x012a, /* C8 */ - 0x0110, 0x0145, 0x014c, 0x0136, 0x00d4, 0x00d5, 0x00d6, 0x00d7, /* D0 */ - 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x0168, 0x016a, 0x00df, /* D8 */ - 0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, /* E0 */ - 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x012b, /* E8 */ - 0x0111, 0x0146, 0x014d, 0x0137, 0x00f4, 0x00f5, 0x00f6, 0x00f7, /* F0 */ - 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x0169, 0x016b, 0x02d9, /* F8 */ - }; - - for(i=0; i<=0x7F; i++) - unicode_map[i] = i; - - for(i=0x80; i<=0xFF; i++) - unicode_map[i] = latin4_unicode_map[i-0x80]; - -#if 0 /* for documentation purposes only */ - case 0x201e: return 0x90; /* these two quotes are a hack only */ - case 0x201c: return 0x91; /* these two quotes are a hack only */ - case 0x00A0: return 0xA0; /* NO-BREAK SPACE */ - case 0x0104: return 0xA1; /* LATIN CAPITAL LETTER A WITH OGONEK */ - case 0x0138: return 0xA2; /* LATIN SMALL LETTER KRA */ - case 0x0156: return 0xA3; /* LATIN CAPITAL LETTER R WITH CEDILLA */ - case 0x00A4: return 0xA4; /* CURRENCY SIGN */ - case 0x0128: return 0xA5; /* LATIN CAPITAL LETTER I WITH TILDE */ - case 0x013B: return 0xA6; /* LATIN CAPITAL LETTER L WITH CEDILLA */ - case 0x00A7: return 0xA7; /* SECTION SIGN */ - case 0x00A8: return 0xA8; /* DIAERESIS */ - case 0x0160: return 0xA9; /* LATIN CAPITAL LETTER S WITH CARON */ - case 0x0112: return 0xAA; /* LATIN CAPITAL LETTER E WITH MACRON */ - case 0x0122: return 0xAB; /* LATIN CAPITAL LETTER G WITH CEDILLA */ - case 0x0166: return 0xAC; /* LATIN CAPITAL LETTER T WITH STROKE */ - case 0x00AD: return 0xAD; /* SOFT HYPHEN */ - case 0x017D: return 0xAE; /* LATIN CAPITAL LETTER Z WITH CARON */ - case 0x00AF: return 0xAF; /* MACRON */ - case 0x00B0: return 0xB0; /* DEGREE SIGN */ - case 0x0105: return 0xB1; /* LATIN SMALL LETTER A WITH OGONEK */ - case 0x02DB: return 0xB2; /* OGONEK */ - case 0x0157: return 0xB3; /* LATIN SMALL LETTER R WITH CEDILLA */ - case 0x00B4: return 0xB4; /* ACUTE ACCENT */ - case 0x0129: return 0xB5; /* LATIN SMALL LETTER I WITH TILDE */ - case 0x013C: return 0xB6; /* LATIN SMALL LETTER L WITH CEDILLA */ - case 0x02C7: return 0xB7; /* CARON */ - case 0x00B8: return 0xB8; /* CEDILLA */ - case 0x0161: return 0xB9; /* LATIN SMALL LETTER S WITH CARON */ - case 0x0113: return 0xBA; /* LATIN SMALL LETTER E WITH MACRON */ - case 0x0123: return 0xBB; /* LATIN SMALL LETTER G WITH CEDILLA */ - case 0x0167: return 0xBC; /* LATIN SMALL LETTER T WITH STROKE */ - case 0x014A: return 0xBD; /* LATIN CAPITAL LETTER ENG */ - case 0x017E: return 0xBE; /* LATIN SMALL LETTER Z WITH CARON */ - case 0x014B: return 0xBF; /* LATIN SMALL LETTER ENG */ - case 0x0100: return 0xC0; /* LATIN CAPITAL LETTER A WITH MACRON */ - case 0x00C1: return 0xC1; /* LATIN CAPITAL LETTER A WITH ACUTE */ - case 0x00C2: return 0xC2; /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */ - case 0x00C3: return 0xC3; /* LATIN CAPITAL LETTER A WITH TILDE */ - case 0x00C4: return 0xC4; /* LATIN CAPITAL LETTER A WITH DIAERESIS */ - case 0x00C5: return 0xC5; /* LATIN CAPITAL LETTER A WITH RING ABOVE */ - case 0x00C6: return 0xC6; /* LATIN CAPITAL LIGATURE AE */ - case 0x012E: return 0xC7; /* LATIN CAPITAL LETTER I WITH OGONEK */ - case 0x010C: return 0xC8; /* LATIN CAPITAL LETTER C WITH CARON */ - case 0x00C9: return 0xC9; /* LATIN CAPITAL LETTER E WITH ACUTE */ - case 0x0118: return 0xCA; /* LATIN CAPITAL LETTER E WITH OGONEK */ - case 0x00CB: return 0xCB; /* LATIN CAPITAL LETTER E WITH DIAERESIS */ - case 0x0116: return 0xCC; /* LATIN CAPITAL LETTER E WITH DOT ABOVE */ - case 0x00CD: return 0xCD; /* LATIN CAPITAL LETTER I WITH ACUTE */ - case 0x00CE: return 0xCE; /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */ - case 0x012A: return 0xCF; /* LATIN CAPITAL LETTER I WITH MACRON */ - case 0x0110: return 0xD0; /* LATIN CAPITAL LETTER D WITH STROKE */ - case 0x0145: return 0xD1; /* LATIN CAPITAL LETTER N WITH CEDILLA */ - case 0x014C: return 0xD2; /* LATIN CAPITAL LETTER O WITH MACRON */ - case 0x0136: return 0xD3; /* LATIN CAPITAL LETTER K WITH CEDILLA */ - case 0x00D4: return 0xD4; /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */ - case 0x00D5: return 0xD5; /* LATIN CAPITAL LETTER O WITH TILDE */ - case 0x00D6: return 0xD6; /* LATIN CAPITAL LETTER O WITH DIAERESIS */ - case 0x00D7: return 0xD7; /* MULTIPLICATION SIGN */ - case 0x00D8: return 0xD8; /* LATIN CAPITAL LETTER O WITH STROKE */ - case 0x0172: return 0xD9; /* LATIN CAPITAL LETTER U WITH OGONEK */ - case 0x00DA: return 0xDA; /* LATIN CAPITAL LETTER U WITH ACUTE */ - case 0x00DB: return 0xDB; /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */ - case 0x00DC: return 0xDC; /* LATIN CAPITAL LETTER U WITH DIAERESIS */ - case 0x0168: return 0xDD; /* LATIN CAPITAL LETTER U WITH TILDE */ - case 0x016A: return 0xDE; /* LATIN CAPITAL LETTER U WITH MACRON */ - case 0x00DF: return 0xDF; /* LATIN SMALL LETTER SHARP S */ - case 0x0101: return 0xE0; /* LATIN SMALL LETTER A WITH MACRON */ - case 0x00E1: return 0xE1; /* LATIN SMALL LETTER A WITH ACUTE */ - case 0x00E2: return 0xE2; /* LATIN SMALL LETTER A WITH CIRCUMFLEX */ - case 0x00E3: return 0xE3; /* LATIN SMALL LETTER A WITH TILDE */ - case 0x00E4: return 0xE4; /* LATIN SMALL LETTER A WITH DIAERESIS */ - case 0x00E5: return 0xE5; /* LATIN SMALL LETTER A WITH RING ABOVE */ - case 0x00E6: return 0xE6; /* LATIN SMALL LIGATURE AE */ - case 0x012F: return 0xE7; /* LATIN SMALL LETTER I WITH OGONEK */ - case 0x010D: return 0xE8; /* LATIN SMALL LETTER C WITH CARON */ - case 0x00E9: return 0xE9; /* LATIN SMALL LETTER E WITH ACUTE */ - case 0x0119: return 0xEA; /* LATIN SMALL LETTER E WITH OGONEK */ - case 0x00EB: return 0xEB; /* LATIN SMALL LETTER E WITH DIAERESIS */ - case 0x0117: return 0xEC; /* LATIN SMALL LETTER E WITH DOT ABOVE */ - case 0x00ED: return 0xED; /* LATIN SMALL LETTER I WITH ACUTE */ - case 0x00EE: return 0xEE; /* LATIN SMALL LETTER I WITH CIRCUMFLEX */ - case 0x012B: return 0xEF; /* LATIN SMALL LETTER I WITH MACRON */ - case 0x0111: return 0xF0; /* LATIN SMALL LETTER D WITH STROKE */ - case 0x0146: return 0xF1; /* LATIN SMALL LETTER N WITH CEDILLA */ - case 0x014D: return 0xF2; /* LATIN SMALL LETTER O WITH MACRON */ - case 0x0137: return 0xF3; /* LATIN SMALL LETTER K WITH CEDILLA */ - case 0x00F4: return 0xF4; /* LATIN SMALL LETTER O WITH CIRCUMFLEX */ - case 0x00F5: return 0xF5; /* LATIN SMALL LETTER O WITH TILDE */ - case 0x00F6: return 0xF6; /* LATIN SMALL LETTER O WITH DIAERESIS */ - case 0x00F7: return 0xF7; /* DIVISION SIGN */ - case 0x00F8: return 0xF8; /* LATIN SMALL LETTER O WITH STROKE */ - case 0x0173: return 0xF9; /* LATIN SMALL LETTER U WITH OGONEK */ - case 0x00FA: return 0xFA; /* LATIN SMALL LETTER U WITH ACUTE */ - case 0x00FB: return 0xFB; /* LATIN SMALL LETTER U WITH CIRCUMFLEX */ - case 0x00FC: return 0xFC; /* LATIN SMALL LETTER U WITH DIAERESIS */ - case 0x0169: return 0xFD; /* LATIN SMALL LETTER U WITH TILDE */ - case 0x016B: return 0xFE; /* LATIN SMALL LETTER U WITH MACRON */ - case 0x02D9: return 0xFF; /* DOT ABOVE */ -#endif -} - -static void -unicode_latin5( - char *arg -) -{ - int i; - static unsigned int latin5_unicode_map1[] = { - 0x0080, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */ - 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f, /* 88 */ - 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */ - 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178, /* 98 */ - }; - static unsigned int latin5_unicode_map2[] = { - 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, /* D0 */ - 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df, /* D8 */ - 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, /* E0 direct */ - 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, /* E8 direct */ - 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, /* F0 */ - 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff, /* F8 */ - }; - - for(i=0; i<=0x7F; i++) - unicode_map[i] = i; - - for(i=0x80; i<=0x9F; i++) - unicode_map[i] = latin5_unicode_map1[i-0x80]; - - for(i=0xA0; i<=0xCF; i++) - unicode_map[i] = i; - - for(i=0xD0; i<=0xFF; i++) - unicode_map[i] = latin5_unicode_map2[i-0xD0]; -} - -/* a way to select one 256-character plane from Unicode - * or other multi-byte encoding - */ - -static void -unicode_plane( - char *arg -) -{ - static unsigned plane; - int nchars; - int c1, c2, i; - - if(uni_lang_selected == 0) - return; /* don't participate in auto-guessing */ - - plane = 0; force_pid = force_eid = -1; - - c1 = sscanf(arg, "pid=%d,eid=%d%n", &force_pid, &force_eid, &nchars); - if(c1 == 2) { - arg += nchars; - if(*arg == ',') - arg++; - } - if(arg[0] == '0' && (arg[1]=='x' || arg[1]=='X') ) { - arg += 2; - c2 = sscanf(arg, "%x", &plane); - } else { - c2 = sscanf(arg, "%d", &plane); - } - - if( (c1!=2 && c1!=0) || (c1==0 && c2==0) ) { - fprintf(stderr, "**** option -l plane expects one of the following formats:\n"); - fprintf(stderr, " -l plane+0xNN - select hexadecimal number of plane of Unicode\n"); - fprintf(stderr, " -l plane+NN - select decimal number of plane of Unicode\n"); - fprintf(stderr, " -l plane+pid=N,eid=N - select plane 0 of specified encoding\n"); - fprintf(stderr, " -l plane+pid=N,eid=N,0xNN - select hex plane of TTF encoding with this PID/EID\n"); - fprintf(stderr, " -l plane+pid=N,eid=N,NN - select decimal plane of TTF encoding with this PID/EID\n"); - exit(1); - } - - if(c2!=0) { - if(strlen(arg) > sizeof(uni_suffix_buf)-2) { - fprintf(stderr, "**** plane number is too large\n"); - } - - sprintf(uni_suffix_buf, "-%s", arg); - uni_font_name_suffix = uni_suffix_buf; - } else { - uni_font_name_suffix = ""; - } - - plane <<= 8; - for(i=0; i<=0xFF; i++) - unicode_map[i] = plane | i; -} - -/* look up the 8-bit code by unicode */ - -int -unicode_rev_lookup( - int unival -) -{ - int res; - - if( ! IS_UNI_BUCKET(unival) ) - return -1; - - for (res = 0; res < enctabsz; res++) - if (unicode_map[res] == unival) - return res; - return -1; -} - -/* mark the buckets for quick lookup */ - -static void -unicode_prepare_buckets( - void -) -{ - int i; - - memset(uni_user_buckets, 0, sizeof uni_user_buckets); - for(i=0; i<enctabsz; i++) { - if(unicode_map[i] != (unsigned) -1) - MARK_UNI_BUCKET(unicode_map[i]); - } -} - -/* - * When we print errors about bad names we want to print these names in - * some decent-looking form - */ - -static char * -nametoprint( - unsigned char *s -) -{ - static char res[50]; - int c, i; - - for(i=0; ( c =* s )!=0 && i<sizeof(res)-8; s++) { - if(c < ' ' || c > 126) { - sprintf(res+i, "\\x%02X", c); - i+=4; - } else { - res[i++] = c; - } - } - if(*s != 0) { - res[i++] = '.'; - res[i++] = '.'; - res[i++] = '.'; - } - res[i++] = 0; - return res; -} - -/* - * Scale the values according to the scale_factor - */ - -double -fscale( - double val -) -{ - return scale_factor * val; -} - -int -iscale( - int val -) -{ - return (int) (val > 0 ? scale_factor * val + 0.5 - : scale_factor * val - 0.5); -} - -/* - * Try to force fixed width of characters - */ - -static void -alignwidths(void) -{ - int i; - int n = 0, avg, max = 0, min = 3000, sum = 0, x; - - for (i = 0; i < numglyphs; i++) { - if (glyph_list[i].flags & GF_USED) { - x = glyph_list[i].width; - - if (x != 0) { - if (x < min) - min = x; - if (x > max) - max = x; - - sum += x; - n++; - } - } - } - - if (n == 0) - return; - - avg = sum / n; - - WARNING_3 fprintf(stderr, "widths: max=%d avg=%d min=%d\n", max, avg, min); - - /* if less than 5% variation from average */ - /* force fixed width */ - if (20 * (avg - min) < avg && 20 * (max - avg) < avg) { - for (i = 0; i < numglyphs; i++) { - if (glyph_list[i].flags & GF_USED) - glyph_list[i].width = avg; - } - fontm.is_fixed_pitch = 1; - } -} - -static void -convert_glyf( - int glyphno -) -{ - GLYPH *g; - int ncurves; - - g = &glyph_list[glyphno]; - - - g->scaledwidth = iscale(g->width); - - g->entries = 0; - g->lastentry = 0; - g->path = 0; - if (g->ttf_pathlen != 0) { - cursw->glpath(glyphno, glyph_list); - g->lastentry = 0; - - if(ISDBG(BUILDG)) - dumppaths(g, NULL, NULL); - - assertpath(g->entries, __FILE__, __LINE__, g->name); - - fclosepaths(g); - assertpath(g->entries, __FILE__, __LINE__, g->name); - - /* float processing */ - if(smooth) { - ffixquadrants(g); - assertpath(g->entries, __FILE__, __LINE__, g->name); - - fsplitzigzags(g); - assertpath(g->entries, __FILE__, __LINE__, g->name); - - fforceconcise(g); - assertpath(g->entries, __FILE__, __LINE__, g->name); - - fstraighten(g); - assertpath(g->entries, __FILE__, __LINE__, g->name); - } - - pathtoint(g); - /* all processing past this point expects integer path */ - assertpath(g->entries, __FILE__, __LINE__, g->name); - -#if 0 - fixcontours(g); - testfixcvdir(g); -#endif - - /* int processing */ - if (smooth) { - smoothjoints(g); - assertpath(g->entries, __FILE__, __LINE__, g->name); - } - - ncurves = 0; - { - GENTRY *ge; - for(ge = g->entries; ge; ge = ge->next) - ncurves++; - } - if (ncurves > 200) { - WARNING_3 fprintf(stderr, - "** Glyph %s is too long, may display incorrectly\n", - g->name); - } - } else { - /* for buildstems */ - g->flags &= ~GF_FLOAT; - } -} - -static void -handle_gnames(void) -{ - int i, n, found, c, type; - - /* get the names from the font file */ - ps_fmt_3 = cursw->glnames(glyph_list); - -/* These checks are not required by Xprt's PS DDX... */ -#ifndef XP_PSTEXT - /* check for names with wrong characters */ - for (n = 0; n < numglyphs; n++) { - int c; - for (i = 0; (c = glyph_list[n].name[i]) != 0; i++) { - if (!(isalnum(c) || c == '.' || c == '_' || c == '-') - || i==0 && isdigit(c)) { /* must not start with a digit */ - WARNING_3 fprintf(stderr, "Glyph %d %s (%s), ", - n, isdigit(c) ? "name starts with a digit" : - "has bad characters in name", - nametoprint(glyph_list[n].name)); - glyph_list[n].name = malloc(16); - sprintf(glyph_list[n].name, "_b_%d", n); - WARNING_3 fprintf(stderr, "changing to %s\n", glyph_list[n].name); - break; - } - } - } - - if( !ps_fmt_3 ) { - /* check for duplicate names */ - for (n = 0; n < numglyphs; n++) { - found = 0; - for (i = 0; i < n && !found; i++) { - if (strcmp(glyph_list[i].name, glyph_list[n].name) == 0) { - if (( glyph_list[n].name = malloc(16) )==0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - sprintf(glyph_list[n].name, "_d_%d", n); - - /* if the font has no names in it (what the native parser - * recognises as ps_fmt_3), FreeType returns all the - * names as .notdef, so don't complain in this case - */ - if(strcmp(glyph_list[i].name, ".notdef")) { - WARNING_3 fprintf(stderr, - "Glyph %d has the same name as %d: (%s), changing to %s\n", - n, i, - glyph_list[i].name, - glyph_list[n].name); - } - found = 1; - } - } - } - - } -#endif /* !XP_PSTEXT */ - - /* start the encoding stuff */ - for (i = 0; i < ENCTABSZ; i++) { - encoding[i] = -1; - } - - /* do the 1st round of encoding by name */ - if(!ps_fmt_3 && uni_lang_selected && uni_lang_selected->convbyname) { - for (n = 0; n < numglyphs; n++) { - c = uni_lang_selected->convbyname(glyph_list[n].name, - uni_lang_arg, UNICONV_BYNAME_BEFORE); - if(c>=0 && c<ENCTABSZ && encoding[c] == -1) - encoding[c] = n; - } - } - - /* now do the encoding by table */ - if(uni_lang_selected) { - for(i=0; i < MAXUNITABLES && uni_lang_selected->init[i]; i++) { - for (n = 0; n < ENCTABSZ; n++) - unicode_map[n] = -1; - uni_lang_selected->init[i](uni_lang_arg); - unicode_prepare_buckets(); - type = cursw->glenc(glyph_list, encoding, unicode_map); - if( type == 0 ) - /* if we have an 8-bit encoding we don't need more tries */ - break; - } - } else { - /* language is unknown, try the first table of each */ - for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++) { - if(uni_lang[i].init[0] == NULL) - continue; - for (n = 0; n < ENCTABSZ; n++) - unicode_map[n] = -1; - uni_lang[i].init[0](uni_lang_arg); - unicode_prepare_buckets(); - type = cursw->glenc(glyph_list, encoding, unicode_map); - if( type == 0 ) - /* if we have an 8-bit encoding we don't need more tries */ - break; - } - } - - if (ps_fmt_3) { - /* get rid of the old names, they are all "UNKNOWN" anyawy */ - for (i = 0; i < numglyphs; i++) { - glyph_list[i].name = 0; - } - if(type == 0) { - /* 8-bit - give 8859/1 names to the first 256 glyphs */ - for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */ - if (encoding[i] > 0) { - glyph_list[encoding[i]].name = Fmt3Encoding[i]; - } - } - } else if(type == 1) { - /* Unicode - give 8859/1 names to the first 256 glyphs of Unicode */ - for (n = 0; n < 256; n++) { /* here 256, not ENCTABSZ */ - i = unicode_rev_lookup(n); - if (i>=0 && encoding[i] > 0) { - glyph_list[encoding[i]].name = Fmt3Encoding[i]; - } - } - } /* for other types of encodings just give generated names */ - /* assign unique names to the rest of the glyphs */ - for (i = 0; i < numglyphs; i++) { - if (glyph_list[i].name == 0) { - if (( glyph_list[i].name = malloc(16) )==0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - sprintf(glyph_list[i].name, "_d_%d", i); - } - } - } - - /* do the 2nd round of encoding by name */ - if(uni_lang_selected && uni_lang_selected->convbyname) { - for (n = 0; n < numglyphs; n++) { - c = uni_lang_selected->convbyname(glyph_list[n].name, - uni_lang_arg, UNICONV_BYNAME_AFTER); - if(c>=0 && c<ENCTABSZ && encoding[c] == -1) - encoding[c] = n; - } - } - /* all the encoding things are done */ - - for (i = 0; i < ENCTABSZ; i++) - if(encoding[i] == -1) { - /* check whether this character might be a duplicate - * (in which case it would be missed by unicode_rev_lookup()) - */ - c = unicode_map[i]; - if((type != 0 || forcemap) && c != -1) { - for(n = 0; n < i; n++) { - if(unicode_map[n] == c) { - encoding[i] = encoding[n]; - } - } - } - if(encoding[i] == -1) /* still not found, defaults to .notdef */ - encoding[i] = 0; - } - - for (i = 0; i < 256; i++) /* here 256, not ENCTABSZ */ - glyph_list[encoding[i]].char_no = i; - -#ifndef XP_PSTEXT - /* enforce two special cases defined in TTF manual */ - if(numglyphs > 0) - glyph_list[0].name = ".notdef"; - if(numglyphs > 1) - glyph_list[1].name = ".null"; -#endif /* !XP_PSTEXT */ - - for (i = 0; i < ENCTABSZ; i++) { - if ((encoding[i] != 0) && glyph_rename[i]) { - glyph_list[encoding[i]].name = glyph_rename[i]; - } - } -} - -static void -usage(void) -{ - -#ifdef XP_PSTEXT - fputs("ft2pt1: Internal startup error\n", stderr); -#else - -#ifdef _GNU_SOURCE -# define fplop(txt) fputs(txt, stderr); -#else -# define fplop(txt) -#endif - - fputs("Use:\n", stderr); - fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> [<fontname>]\n", stderr); - fputs(" or\n", stderr); - fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> -\n", stderr); - fputs(" or\n", stderr); - fputs("ttf2pt1 [-<opts>] [-l language | -L file] <ttf-file> - | t1asm > <pfa-file>\n", stderr); - - fplop("\n"); - fplop("This build supports both short and long option names,\n"); - fplop("the long options are listed before corresponding short ones\n"); - - fplop(" --all-glyphs\n"); - fputs(" -a - include all glyphs, even those not in the encoding table\n", stderr); - fplop(" --pfb\n"); - fputs(" -b - produce a compressed .pfb file\n", stderr); - fplop(" --debug dbg_suboptions\n"); - fputs(" -d dbg_suboptions - debugging options, run ttf2pt1 -d? for help\n", stderr); - fplop(" --encode\n"); - fputs(" -e - produce a fully encoded .pfa file\n", stderr); - fplop(" --force-unicode\n"); - fputs(" -F - force use of Unicode encoding even if other MS encoding detected\n", stderr); - fplop(" --generate suboptions\n"); - fputs(" -G suboptions - control the file generation, run ttf2pt1 -G? for help\n", stderr); - fplop(" --language language\n"); - fputs(" -l language - convert Unicode to specified language, run ttf2pt1 -l? for list\n", stderr); - fplop(" --language-map file\n"); - fputs(" -L file - convert Unicode according to encoding description file\n", stderr); - fplop(" --limit <type>=<value>\n"); - fputs(" -m <type>=<value> - set maximal limit of given type to value, types:\n", stderr); - fputs(" h - maximal hint stack depth in the PostScript interpreter\n", stderr); - fplop(" --processing suboptions\n"); - fputs(" -O suboptions - control outline processing, run ttf2pt1 -O? for help\n", stderr); - fplop(" --parser name\n"); - fputs(" -p name - use specific front-end parser, run ttf2pt1 -p? for list\n", stderr); - fplop(" --uid id\n"); - fputs(" -u id - use this UniqueID, -u A means autogeneration\n", stderr); - fplop(" --vertical-autoscale size\n"); - fputs(" -v size - scale the font to make uppercase letters >size/1000 high\n", stderr); - fplop(" --version\n"); - fputs(" -V - print ttf2pt1 version number\n", stderr); - fplop(" --warning number\n"); - fputs(" -W number - set the level of permitted warnings (0 - disable)\n", stderr); - fputs("Obsolete options (will be removed in future releases):\n", stderr); - fplop(" --afm\n"); - fputs(" -A - write the .afm file to STDOUT instead of the font, now -GA\n", stderr); - fputs(" -f - don't try to guess the value of the ForceBold hint, now -Ob\n", stderr); - fputs(" -h - disable autogeneration of hints, now -Oh\n", stderr); - fputs(" -H - disable hint substitution, now -Ou\n", stderr); - fputs(" -o - disable outline optimization, now -Oo\n", stderr); - fputs(" -s - disable outline smoothing, now -Os\n", stderr); - fputs(" -t - disable auto-scaling to 1000x1000 standard matrix, now -Ot\n", stderr); - fputs(" -w - correct the glyph widths (use only for buggy fonts), now -OW\n", stderr); - fputs("With no <fontname>, write to <ttf-file> with suffix replaced.\n", stderr); - fputs("The last '-' means 'use STDOUT'.\n", stderr); - -#undef fplop - -#endif /* XP_PSTEXT */ -} - -static void -printversion(void) -{ - fprintf(stderr, "ttf2pt1 %s\n", TTF2PT1_VERSION); -} - -/* initialize a table of suboptions */ -static void -init_subo_tbl( - struct subo_case *tbl -) -{ - int i; - - for(i=0; tbl[i].disbl != 0; i++) { - tbl[i].disbl = tolower(tbl[i].disbl); - tbl[i].enbl = toupper(tbl[i].disbl); - *(tbl[i].valp) = tbl[i].dflt; - } -} - -/* print the default value of the suboptions */ -static void -print_subo_dflt( - FILE *f, - struct subo_case *tbl -) -{ - int i; - - for(i=0; tbl[i].disbl != 0; i++) { - if(tbl[i].dflt) - putc(tbl[i].enbl, f); - else - putc(tbl[i].disbl, f); - } -} - -/* print the usage message for the suboptions */ -static void -print_subo_usage( - FILE *f, - struct subo_case *tbl -) -{ -#ifdef XP_PSTEXT - fputs("ft2pt1: Internal startup error\n", stderr); -#else - int i; - - fprintf(f,"The lowercase suboptions disable features, corresponding\n"); - fprintf(f,"uppercase suboptions enable them. The supported suboptions,\n"); - fprintf(f,"their default states and the features they control are:\n"); - for(i=0; tbl[i].disbl != 0; i++) { - fprintf(f," %c/%c - [%s] %s\n", tbl[i].disbl, tbl[i].enbl, - tbl[i].dflt ? "enabled" : "disabled", tbl[i].descr); - } -#endif /* XP_PSTEXT */ -} - -/* find and set the entry according to suboption, - * return the found entry (or if not found return NULL) - */ -struct subo_case * -set_subo( - struct subo_case *tbl, - int subopt -) -{ - int i; - - for(i=0; tbl[i].disbl != 0; i++) { - if(subopt == tbl[i].disbl) { - *(tbl[i].valp) = 0; - return &tbl[i]; - } else if(subopt == tbl[i].enbl) { - *(tbl[i].valp) = 1; - return &tbl[i]; - } - } - return NULL; -} - - -#ifdef XP_PSTEXT -FT_Face xp_pstext_ft_face = NULL; /* used by ft.c */ -FTFontPtr xp_xtf = NULL; -const char *xp_psfontname = NULL; -unsigned long xp_font_block_offset = 0UL; - -int -ft2pt1_main( - int argc, - char **argv, - FTFontPtr tf, - const char *download_psfontname, - unsigned long download_font_block_offset -) -#else -int -main( - int argc, - char **argv -) -#endif /* XP_PSTEXT */ -{ - long i, j; - time_t now; - char filename[4096]; - int c,nchars,nmetrics; - int ws; - int forcebold= -1; /* -1 means "don't know" */ - char *lang; - int oc; - int subid; - char *cmdline; -#ifdef _GNU_SOURCE -# define ttf2pt1_getopt(a, b, c, d, e) getopt_long(a, b, c, d, e) - static struct option longopts[] = { - { "afm", 0, NULL, 'A' }, - { "all-glyphs", 0, NULL, 'a' }, - { "pfb", 0, NULL, 'b' }, - { "debug", 1, NULL, 'd' }, - { "encode", 0, NULL, 'e' }, - { "force-unicode", 0, NULL, 'F' }, - { "generate", 1, NULL, 'G' }, - { "language", 1, NULL, 'l' }, - { "language-map", 1, NULL, 'L' }, - { "limit", 1, NULL, 'm' }, - { "processing", 1, NULL, 'O' }, - { "parser", 1, NULL, 'p' }, - { "uid", 1, NULL, 'u' }, - { "vertical-autoscale", 1, NULL, 'v' }, - { "version", 0, NULL, 'V' }, - { "warning", 1, NULL, 'W' }, - { NULL, 0, NULL, 0 } - }; -#else -# define ttf2pt1_getopt(a, b, c, d, e) getopt(a, b, c) -#endif - /* table of Outline Processing (may think also as Optimization) options */ - static struct subo_case opotbl[] = { - { 'b', 0/*auto-set*/, &trybold, 1, "guessing of the ForceBold hint" }, - { 'h', 0/*auto-set*/, &hints, 1, "autogeneration of hints" }, - { 'u', 0/*auto-set*/, &subhints, 1, "hint substitution technique" }, - { 'o', 0/*auto-set*/, &optimize, 1, "space optimization of font files" }, - { 's', 0/*auto-set*/, &smooth, 1, "smoothing and repair of outlines" }, - { 't', 0/*auto-set*/, &transform, 1, "auto-scaling to the standard matrix 1000x1000" }, - { 'w', 0/*auto-set*/, &correctwidth, 0, "correct the glyph widths (use only for buggy fonts)" }, - { 'v', 0/*auto-set*/, &vectorize, 0, "vectorize (trace) the bitmaps" }, -#ifdef USE_AUTOTRACE - { 'z', 0/*auto-set*/, &use_autotrace, 0, "use the autotrace library on bitmaps (works badly)" }, -#endif /*USE_AUTOTRACE*/ - { 0, 0, 0, 0, 0} /* terminator */ - }; - /* table of the File Generation options */ - static struct subo_case fgotbl[] = { - { 'f', 0/*auto-set*/, &gen_pfa, 1, "generate the font file (.t1a, .pfa or .pfb)" }, - { 'a', 0/*auto-set*/, &gen_afm, 1, "generate the Adobe metrics file (.afm)" }, - { 'e', 0/*auto-set*/, &gen_dvienc, 0, "generate the dvips encoding file (.enc)" }, - { 0, 0, 0, 0, 0} /* terminator */ - }; - int *genlast = NULL; - -#ifdef XP_PSTEXT - xp_pstext_ft_face = tf->instance->face->face; - xp_xtf = tf; - xp_psfontname = download_psfontname; - xp_font_block_offset = download_font_block_offset; -#endif /* XP_PSTEXT */ - - init_subo_tbl(opotbl); /* initialize sub-options of -O */ - init_subo_tbl(fgotbl); /* initialize sub-options of -G */ - - /* save the command line for the record - * (we don't bother about escaping the shell special characters) - */ - - j = 0; - for(i=1; i<argc; i++) { - j += strlen(argv[i])+1; - } - if ((cmdline = malloc(j+1)) == NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - cmdline[0] = 0; - for(i=1; i<argc; i++) { - strcat(cmdline, argv[i]); - strcat(cmdline, " "); - } - for(i=0; (j=cmdline[i])!=0; i++) - if(j == '\n') - cmdline[i] = ' '; - - - while(( oc=ttf2pt1_getopt(argc, argv, "FaoebAsthHfwVv:p:l:d:u:L:m:W:O:G:", - longopts, NULL) )!= -1) { - switch(oc) { - case 'W': - if(sscanf(optarg, "%d", &warnlevel) < 1 || warnlevel < 0) { - fprintf(stderr, "**** warning level must be a positive number\n"); - exit(1); - } - break; - case 'F': - forcemap = 1; - break; - case 'o': - fputs("Warning: option -o is obsolete, use -Oo instead\n", stderr); - optimize = 0; - break; - case 'e': - encode = 1; - break; - case 'b': - encode = pfbflag = 1; - break; - case 'A': - fputs("Warning: option -A is obsolete, use -GA instead\n", stderr); - wantafm = 1; - break; - case 'a': - allglyphs = 1; - break; - case 's': - fputs("Warning: option -s is obsolete, use -Os instead\n", stderr); - smooth = 0; - break; - case 't': - fputs("Warning: option -t is obsolete, use -Ot instead\n", stderr); - transform = 0; - break; - case 'd': - for(i=0; optarg[i]!=0; i++) - switch(optarg[i]) { - case 'a': - absolute = 1; - break; - case 'r': - reverse = 0; - break; - default: - if (optarg[i] != '?') - fprintf(stderr, "**** Unknown debugging option '%c' ****\n", optarg[i]); - fputs("The recognized debugging options are:\n", stderr); - fputs(" a - enable absolute coordinates\n", stderr); - fputs(" r - do not reverse font outlines directions\n", stderr); - exit(1); - break; - }; - break; - case 'm': - { - char subopt; - int val; - - if(sscanf(optarg, "%c=%d", &subopt, &val) !=2) { - fprintf(stderr, "**** Misformatted maximal limit ****\n"); - fprintf(stderr, "spaces around the equal sign are not allowed\n"); - fprintf(stderr, "good examples: -mh=100 -m h=100\n"); - fprintf(stderr, "bad examples: -mh = 100 -mh= 100\n"); - exit(1); - break; - } - switch(subopt) { - case 'h': - max_stemdepth = val; - break; - default: - if (subopt != '?') - fprintf(stderr, "**** Unknown limit type '%c' ****\n", subopt); - fputs("The recognized limit types are:\n", stderr); - fputs(" h - maximal hint stack depth in the PostScript interpreter\n", stderr); - exit(1); - break; - } - break; - } - case 'O': - { - char *p; - for(p=optarg; *p != 0; p++) { - if(set_subo(opotbl, *p) == NULL) { /* found no match */ - if (*p != '?') - fprintf(stderr, "**** Unknown outline processing suboption '%c' ****\n", *p); - fprintf(stderr,"The general form of the outline processing option is:\n"); - fprintf(stderr," -O suboptions\n"); - fprintf(stderr,"(To remember easily -O may be also thought of as \"optimization\").\n"); - print_subo_usage(stderr, opotbl); - fprintf(stderr, "The default state corresponds to the option -O "); - print_subo_dflt(stderr, opotbl); - fprintf(stderr, "\n"); - exit(1); - } - } - break; - } - case 'G': - { - char *p; - struct subo_case *s; - - for(p=optarg; *p != 0; p++) { - if(( s = set_subo(fgotbl, *p) )==NULL) { /* found no match */ - if (*p != '?') - fprintf(stderr, "**** Unknown outline processing suboption '%c' ****\n", *p); - fprintf(stderr,"The general form of the file generation option is:\n"); - fprintf(stderr," -G suboptions\n"); - print_subo_usage(stderr, fgotbl); - fprintf(stderr, "The default state corresponds to the option -G "); - print_subo_dflt(stderr, fgotbl); - fprintf(stderr, "\n"); - fprintf(stderr, "If the result is written to STDOUT, the last specified enabling suboption of -G\n"); - fprintf(stderr, "selects the file to be written to STDOUT (the font file by default).\n"); - exit(1); - } - if( *(s->valp) ) - genlast = s->valp; - } - break; - } - case 'h': - fputs("Warning: option -h is obsolete, use -Oh instead\n", stderr); - hints = 0; - break; - case 'H': - fputs("Warning: meaning of option -H has been changed to its opposite\n", stderr); - fputs("Warning: option -H is obsolete, use -Ou instead\n", stderr); - subhints = 0; - break; - case 'f': - fputs("Warning: option -f is obsolete, use -Ob instead\n", stderr); - trybold = 0; - break; - case 'w': - fputs("Warning: option -w is obsolete, use -OW instead\n", stderr); - correctwidth = 1; - break; - case 'u': - if(wantuid) { - fprintf(stderr, "**** UniqueID may be specified only once ****\n"); - exit(1); - } - wantuid = 1; - if(optarg[0]=='A' && optarg[1]==0) - strUID=0; /* will be generated automatically */ - else { - strUID=optarg; - for(i=0; optarg[i]!=0; i++) - if( !isdigit(optarg[i]) ) { - fprintf(stderr, "**** UniqueID must be numeric or A for automatic ****\n"); - exit(1); - } - } - break; - case 'v': - correctvsize = atoi(optarg); - if(correctvsize <= 0 && correctvsize > 1000) { - fprintf(stderr, "**** wrong vsize '%d', ignored ****\n", correctvsize); - correctvsize=0; - } - break; - case 'p': - if(cursw!=0) { - fprintf(stderr, "**** only one front-end parser be used ****\n"); - exit(1); - } - - { /* separate parser from parser-specific argument */ - char *p = strchr(optarg, LANG_ARG_SEP); - if(p != 0) { - *p = 0; - front_arg = p+1; - } else - front_arg = ""; - } - for(i=0; frontswtab[i] != NULL; i++) - if( !strcmp(frontswtab[i]->name, optarg) ) { - cursw = frontswtab[i]; - break; - } - - if(cursw==0) { - if (strcmp(optarg, "?")) - fprintf(stderr, "**** unknown front-end parser '%s' ****\n", optarg); - fputs("the following front-ends are supported now:\n", stderr); - for(i=0; frontswtab[i] != NULL; i++) { - fprintf(stderr," %s (%s)\n file suffixes: ", - frontswtab[i]->name, - frontswtab[i]->descr ? frontswtab[i]->descr : "no description" - ); - for(j=0; j<MAXSUFFIX; j++) - if(frontswtab[i]->suffix[j]) - fprintf(stderr, "%s ", frontswtab[i]->suffix[j]); - fprintf(stderr, "\n"); - } - exit(1); - } - break; - case 'l': - if(uni_lang_selected!=0) { - fprintf(stderr, "**** only one language option may be used ****\n"); - exit(1); - } - - { /* separate language from language-specific argument */ - char *p = strchr(optarg, LANG_ARG_SEP); - if(p != 0) { - *p = 0; - uni_lang_arg = p+1; - } else - uni_lang_arg = ""; - } - for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++) - if( !strcmp(uni_lang[i].name, optarg) ) { - uni_lang_selected = &uni_lang[i]; - uni_sample = uni_lang[i].sample_upper; - break; - } - - if(uni_lang_selected==0) { - if (strcmp(optarg, "?")) - fprintf(stderr, "**** unknown language '%s' ****\n", optarg); - fputs(" the following languages are supported now:\n", stderr); - for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++) - fprintf(stderr," %s (%s)\n", - uni_lang[i].name, - uni_lang[i].descr ? uni_lang[i].descr : "no description" - ); - exit(1); - } - break; - case 'L': - if(uni_lang_selected!=0) { - fprintf(stderr, "**** only one language option may be used ****\n"); - exit(1); - } - uni_lang_selected = &uni_lang_user; - uni_lang_arg = optarg; - break; - case 'V': - printversion(); - exit(0); - break; - default: - usage(); - exit(1); - break; - } - } - argc-=optind-1; /* the rest of code counts from argv[0] */ - argv+=optind-1; - - if (absolute && encode) { - fprintf(stderr, "**** options -a and -e are incompatible ****\n"); - exit(1); - } - if ((argc != 2) && (argc != 3)) { - usage(); - exit(1); - } - - /* try to guess the language by the locale used */ - if(uni_lang_selected==0 && (lang=getenv("LANG"))!=0 ) { - for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) { - if( !strncmp(uni_lang[i].name, lang, strlen(uni_lang[i].name)) ) { - uni_lang_selected = &uni_lang[i]; - goto got_a_language; - } - } - /* no full name ? try aliases */ - for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) { - for(c=0; c<MAXUNIALIAS; c++) - if( uni_lang[i].alias[c]!=0 - && !strncmp(uni_lang[i].alias[c], lang, strlen(uni_lang[i].alias[c])) ) { - uni_lang_selected = &uni_lang[i]; - goto got_a_language; - } - } - got_a_language: - if(uni_lang_selected!=0) { - WARNING_1 fprintf(stderr, "Using language '%s' for Unicode fonts\n", uni_lang[i].name); - uni_sample = uni_lang[i].sample_upper; - } - } - - /* try to guess the front-end parser by the file name suffix */ - if(cursw==0) { - char *p = strrchr(argv[1], '.'); - char *s; - - if(p!=0 && (s = strdup(p+1))!=0) { - for(p=s; *p; p++) - *p = tolower(*p); - p = s; - - for(i=0; frontswtab[i] != 0 && cursw == 0; i++) { - for(j=0; j<MAXSUFFIX; j++) - if(frontswtab[i]->suffix[j] - && !strcmp(p, frontswtab[i]->suffix[j]) ) { - cursw = frontswtab[i]; - WARNING_1 fprintf(stderr, "Auto-detected front-end parser '%s'\n", - cursw->name); - WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n"); - break; - } - } - free(s); - } - - if(cursw==0) { - cursw = frontswtab[0]; - WARNING_1 fprintf(stderr, "Can't detect front-end parser, using '%s' by default\n", - cursw->name); - WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n"); - } - } - - /* open the input file */ - cursw->open(argv[1], front_arg); - - /* Get base name of output file (if not specified) - * by removing (known) suffixes - */ - if (argc == 2) { - char *p; - argv[2] = strdup (argv[1]); - p = strrchr(argv[2], '.'); - if (p != NULL) - for (j = 0; (j < MAXSUFFIX) && (cursw->suffix[j]); j++) - if (!strcmp(p+1, cursw->suffix[j])) { - *p = '\0'; - break; - } - } - - if ((null_file = fopen(BITBUCKET, "w")) == NULL) { - fprintf(stderr, "**** Cannot open %s ****\n", - BITBUCKET); - exit(1); - } - - if (argv[2][0] == '-' && argv[2][1] == 0) { -#ifdef WINDOWS - if(encode) { - fprintf(stderr, "**** can't write encoded file to stdout ***\n"); - exit(1); - } -#endif /* WINDOWS */ - pfa_file = afm_file = dvienc_file = null_file; - - if(wantafm || genlast == &gen_afm) { /* print .afm instead of .pfa */ - afm_file=stdout; - } else if(genlast == &gen_dvienc) { /* print .enc instead of .pfa */ - dvienc_file=stdout; - } else { - pfa_file=stdout; - } - } else { -#ifndef WINDOWS - snprintf(filename, sizeof filename, "%s.%s", argv[2], encode ? (pfbflag ? "pfb" : "pfa") : "t1a" ); -#else /* WINDOWS */ - snprintf(filename, sizeof filename, "%s.t1a", argv[2]); -#endif /* WINDOWS */ - if(gen_pfa) { - if ((pfa_file = fopen(filename, "w+b")) == NULL) { - fprintf(stderr, "**** Cannot create %s ****\n", filename); - exit(1); - } else { - WARNING_2 fprintf(stderr, "Creating file %s\n", filename); - } - } else - pfa_file = null_file; - - if(gen_afm) { - snprintf(filename, sizeof filename, "%s.afm", argv[2]) ; - if ((afm_file = fopen(filename, "w+")) == NULL) { - fprintf(stderr, "**** Cannot create %s ****\n", filename); - exit(1); - } - } else - afm_file = null_file; - - if(gen_dvienc) { - snprintf(filename, sizeof filename, "%s.enc", argv[2]) ; - if ((dvienc_file = fopen(filename, "w+")) == NULL) { - fprintf(stderr, "**** Cannot create %s ****\n", filename); - exit(1); - } - } else - dvienc_file = null_file; - } - - /* - * Now check whether we want a fully encoded .pfa file - */ -#ifndef WINDOWS - if (encode && pfa_file != null_file) { - int p[2]; - extern FILE *ifp, *ofp; /* from t1asm.c */ - - ifp=stdin; - ofp=stdout; - - if (pipe(p) < 0) { - perror("**** Cannot create pipe ****\n"); - exit(1); - } - ofp = pfa_file; - ifp = fdopen(p[0], "r"); - if (ifp == NULL) { - perror("**** Cannot use pipe for reading ****\n"); - exit(1); - } - pfa_file = fdopen(p[1], "w"); - if (pfa_file == NULL) { - perror("**** Cannot use pipe for writing ****\n"); - exit(1); - } - switch (fork()) { - case -1: - perror("**** Cannot fork the assembler process ****\n"); - exit(1); - case 0: /* child */ - fclose(pfa_file); - exit(runt1asm(pfbflag)); - default: /* parent */ - fclose(ifp); fclose(ofp); - } - } -#endif /* WINDOWS */ - - numglyphs = cursw->nglyphs(); - - WARNING_3 fprintf(stderr, "numglyphs = %d\n", numglyphs); - - glyph_list = (GLYPH *) calloc(numglyphs, sizeof(GLYPH)); - - /* initialize non-0 fields */ - for (i = 0; i < numglyphs; i++) { - GLYPH *g; - - g = &glyph_list[i]; - g->char_no = -1; - g->orig_code = -1; - g->name = "UNKNOWN"; - g->flags = GF_FLOAT; /* we start with float representation */ - } - - handle_gnames(); - - cursw->glmetrics(glyph_list); - cursw->fnmetrics(&fontm); - - original_scale_factor = 1000.0 / (double) fontm.units_per_em; - - if(transform == 0) - scale_factor = 1.0; /* don't transform */ - else - scale_factor = original_scale_factor; - - if(correctvsize && uni_sample!=0) { /* only for known languages */ - /* try to adjust the scale factor to make a typical - * uppercase character of hight at least (correctvsize), this - * may improve the appearance of the font but also - * make it weird, use with caution - */ - int ysz; - - ysz = iscale(glyph_list[encoding[uni_sample]].yMax); - if( ysz<correctvsize ) { - scale_factor *= (double)correctvsize / ysz; - } - } - -#ifdef XP_ONLY_BLOCKS - /* All glyphs from |xp_font_block_offset| to |xp_font_block_offset+255|*/ - for( i = xp_font_block_offset ; i < (xp_font_block_offset+256) ; i++ ) { - unsigned long ftindex; - - /* Remap X11 font index to FreeType font index */ - ftindex = FTRemap(xp_pstext_ft_face, &xp_xtf->mapping, i); - - if( ftindex < numglyphs ) { - glyph_list[ftindex].flags |= GF_USED; - } - } - - /* also always include .notdef */ - { - int notdef_found = FALSE; - - for (i = 0; i < numglyphs; i++) { - if(!strcmp(glyph_list[i].name, ".notdef")) { - glyph_list[i].flags |= GF_USED; - notdef_found = TRUE; - break; - } - } - - if( !notdef_found ) - { - /* No ".notdef" found ? - * Then copy outlines of char 0 to the first "free" slot and make - * it our ".notdef" char. - */ - for (i = 0; i < numglyphs; i++) { - if((glyph_list[i].flags & GF_USED) == 0) { - glyph_list[i] = glyph_list[0]; - glyph_list[i].flags |= GF_USED; - glyph_list[i].name = ".notdef"; - notdef_found = TRUE; - break; - } - } - } - - if( !notdef_found ) - { - /* This shoudl never happen... */ - fprintf(stderr, "ft2pt1: '.notdef' missing in generated font.\n"); - } - } -#else - if(allglyphs) { - for (i = 0; i < numglyphs; i++) { - glyph_list[i].flags |= GF_USED; - } - } else { - for (i = 0; i < ENCTABSZ; i++) { - glyph_list[encoding[i]].flags |= GF_USED; - } - - /* also always include .notdef */ - for (i = 0; i < numglyphs; i++) - if(!strcmp(glyph_list[i].name, ".notdef")) { - glyph_list[i].flags |= GF_USED; - break; - } - } -#endif /* XP_ONLY_BLOCKS */ - - for (i = 0; i < numglyphs; i++) { - if (glyph_list[i].flags & GF_USED) { - DBG_TO_GLYPH(&glyph_list[i]); - convert_glyf(i); - DBG_FROM_GLYPH(&glyph_list[i]); - } - } - - italic_angle = fontm.italic_angle; - - if (italic_angle > 45.0 || italic_angle < -45.0) - italic_angle = 0.0; /* consider buggy */ - - if (hints) { - findblues(); - for (i = 0; i < numglyphs; i++) { - if (glyph_list[i].flags & GF_USED) { - DBG_TO_GLYPH(&glyph_list[i]); - buildstems(&glyph_list[i]); - assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name); - DBG_FROM_GLYPH(&glyph_list[i]); - } - } - stemstatistics(); - } else { - for(i=0; i<4; i++) - bbox[i] = iscale(fontm.bbox[i]); - } - /* don't touch the width of fixed width fonts */ - if( fontm.is_fixed_pitch ) - correctwidth=0; - docorrectwidth(); /* checks correctwidth inside */ - if (reverse) - for (i = 0; i < numglyphs; i++) { - if (glyph_list[i].flags & GF_USED) { - DBG_TO_GLYPH(&glyph_list[i]); - reversepaths(&glyph_list[i]); - assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name); - DBG_FROM_GLYPH(&glyph_list[i]); - } - } - - -#if 0 - /* - ** It seems to bring troubles. The problem is that some - ** styles of the font may be recognized as fixed-width - ** while other styles of the same font as proportional. - ** So it's better to be commented out yet. - */ - if (tryfixed) - alignwidths(); -#endif - - if(trybold) { - forcebold = fontm.force_bold; - } - -#ifdef XP_PSTEXT - fprintf(pfa_file, "%%!PS-AdobeFont-1.0: %s\n", fontm.name_ps); -#else - fprintf(pfa_file, "%%!PS-AdobeFont-1.0: %s %s\n", fontm.name_ps, fontm.name_copyright); - time(&now); - fprintf(pfa_file, "%%%%CreationDate: %s", ctime(&now)); - fprintf(pfa_file, "%% Converted by ttf2pt1 %s/%s\n", TTF2PT1_VERSION, cursw->name); - fprintf(pfa_file, "%% Args: %s\n", cmdline); - fprintf(pfa_file, "%%%%EndComments\n"); -#endif /* XP_PSTEXT */ - fprintf(pfa_file, "12 dict begin\n/FontInfo 9 dict dup begin\n"); - - WARNING_3 fprintf(stderr, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix); - - - fprintf(pfa_file, " /version (%s) readonly def\n", fontm.name_version); - - fprintf(pfa_file, " /Notice (%s) readonly def\n", fontm.name_copyright); - - fprintf(pfa_file, " /FullName (%s) readonly def\n", fontm.name_full); - fprintf(pfa_file, " /FamilyName (%s) readonly def\n", fontm.name_family); - - if(wantuid) { - if(strUID) - fprintf(pfa_file, " /UniqueID %s def\n", strUID); - else { - numUID=0; - for(i=0; fontm.name_full[i]!=0; i++) { - numUID *= 37; /* magic number, good for hash */ - numUID += fontm.name_full[i]-' '; - /* if the name is long the first chars - * may be lost forever, so re-insert - * them thus making kind of CRC - */ - numUID += (numUID>>24) & 0xFF; - } - /* the range for private UIDs is 4 000 000 - 4 999 999 */ - fprintf(pfa_file, " /UniqueID %lu def\n", numUID%1000000+4000000); - } - } - - fprintf(pfa_file, " /Weight (%s) readonly def\n", fontm.name_style); - - fprintf(pfa_file, " /ItalicAngle %f def\n", italic_angle); - fprintf(pfa_file, " /isFixedPitch %s def\n", - fontm.is_fixed_pitch ? "true" : "false"); - - /* we don't print out the unused glyphs */ - nchars = 0; - for (i = 0; i < numglyphs; i++) { - if (glyph_list[i].flags & GF_USED) { - nchars++; - } - } - - fprintf(afm_file, "StartFontMetrics 4.1\n"); - fprintf(afm_file, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix); - fprintf(afm_file, "FullName %s\n", fontm.name_full); - fprintf(afm_file, "Notice %s\n", fontm.name_copyright); - fprintf(afm_file, "EncodingScheme FontSpecific\n"); - fprintf(afm_file, "FamilyName %s\n", fontm.name_family); - fprintf(afm_file, "Weight %s\n", fontm.name_style); - fprintf(afm_file, "Version %s\n", fontm.name_version); - fprintf(afm_file, "Characters %d\n", nchars); - fprintf(afm_file, "ItalicAngle %.1f\n", italic_angle); - - fprintf(afm_file, "Ascender %d\n", iscale(fontm.ascender)); - fprintf(afm_file, "Descender %d\n", iscale(fontm.descender)); - - fprintf(pfa_file, " /UnderlinePosition %d def\n", - iscale(fontm.underline_position)); - - fprintf(pfa_file, " /UnderlineThickness %hd def\n", - iscale(fontm.underline_thickness)); - - fprintf(pfa_file, "end readonly def\n"); - - fprintf(afm_file, "UnderlineThickness %d\n", - iscale(fontm.underline_thickness)); - - fprintf(afm_file, "UnderlinePosition %d\n", - iscale(fontm.underline_position)); - - fprintf(afm_file, "IsFixedPitch %s\n", - fontm.is_fixed_pitch ? "true" : "false"); - fprintf(afm_file, "FontBBox %d %d %d %d\n", - bbox[0], bbox[1], bbox[2], bbox[3]); - - fprintf(pfa_file, "/FontName /%s%s def\n", fontm.name_ps, uni_font_name_suffix); - fprintf(pfa_file, "/PaintType 0 def\n/StrokeWidth 0 def\n"); - /* I'm not sure if these are fixed */ - fprintf(pfa_file, "/FontType 1 def\n"); - - if (transform) { - fprintf(pfa_file, "/FontMatrix [0.001 0 0 0.001 0 0] def\n"); - } else { - fprintf(pfa_file, "/FontMatrix [%9.7f 0 0 %9.7f 0 0] def\n", - original_scale_factor / 1000.0, original_scale_factor / 1000.0); - } - - fprintf(pfa_file, "/FontBBox {%d %d %d %d} readonly def\n", - bbox[0], bbox[1], bbox[2], bbox[3]); - - fprintf(pfa_file, "/Encoding 256 array\n"); - /* determine number of elements for metrics table */ - nmetrics = 256; - for (i = 0; i < numglyphs; i++) { - if( glyph_list[i].flags & GF_USED - && glyph_list[i].char_no == -1 ) { - nmetrics++; - } - } - fprintf(afm_file, "StartCharMetrics %d\n", nmetrics); - - fprintf(dvienc_file, "/%s%sEncoding [\n", - fontm.name_ps, uni_font_name_suffix); - -#ifdef XP_PSTEXT - { - int linewidth = 0; - for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */ - linewidth += strlen(glyph_list[encoding[i]].name) + 14 + 8; - fprintf(pfa_file, "dup %d /%s put%s", - i, - glyph_list[encoding[i]].name, - (linewidth > 70 || i == 255)?(linewidth = 0, "\n"):("\t")); - if( glyph_list[encoding[i]].flags & GF_USED ) { - print_glyph_metrics(i, encoding[i]); - } - if (encoding[i]) - fprintf (dvienc_file, "/index0x%04X\n", encoding[i]); - else - fprintf (dvienc_file, "/.notdef\n"); - } - } -#else - for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */ - fprintf(pfa_file, - "dup %d /%s put\n", i, glyph_list[encoding[i]].name); - if( glyph_list[encoding[i]].flags & GF_USED ) { - print_glyph_metrics(i, encoding[i]); - } - if (encoding[i]) - fprintf (dvienc_file, "/index0x%04X\n", encoding[i]); - else - fprintf (dvienc_file, "/.notdef\n"); - } -#endif /* XP_PSTEXT */ - /* print the metrics for glyphs not in encoding table */ - for(i=0; i<numglyphs; i++) { - if( (glyph_list[i].flags & GF_USED) - && glyph_list[i].char_no == -1 ) { - print_glyph_metrics(-1, i); - } - } - - fprintf(pfa_file, "readonly def\ncurrentdict end\ncurrentfile eexec\n"); - fprintf(pfa_file, "dup /Private 16 dict dup begin\n"); - - fprintf(pfa_file, "/RD{string currentfile exch readstring pop}executeonly def\n"); - fprintf(pfa_file, "/ND{noaccess def}executeonly def\n"); - fprintf(pfa_file, "/NP{noaccess put}executeonly def\n"); - - /* UniqueID must be shown twice, in both font and Private dictionary */ - if(wantuid) { - if(strUID) - fprintf(pfa_file, "/UniqueID %s def\n", strUID); - else - /* the range for private UIDs is 4 000 000 - 4 999 999 */ - fprintf(pfa_file, "/UniqueID %lu def\n", numUID%1000000+4000000); - } - - if(forcebold==0) - fprintf(pfa_file, "/ForceBold false def\n"); - else if(forcebold==1) - fprintf(pfa_file, "/ForceBold true def\n"); - - fprintf(pfa_file, "/BlueValues [ "); - for (i = 0; i < nblues; i++) - fprintf(pfa_file, "%d ", bluevalues[i]); - fprintf(pfa_file, "] def\n"); - - fprintf(pfa_file, "/OtherBlues [ "); - for (i = 0; i < notherb; i++) - fprintf(pfa_file, "%d ", otherblues[i]); - fprintf(pfa_file, "] def\n"); - - if (stdhw != 0) - fprintf(pfa_file, "/StdHW [ %d ] def\n", stdhw); - if (stdvw != 0) - fprintf(pfa_file, "/StdVW [ %d ] def\n", stdvw); - fprintf(pfa_file, "/StemSnapH [ "); - for (i = 0; i < 12 && stemsnaph[i] != 0; i++) - fprintf(pfa_file, "%d ", stemsnaph[i]); - fprintf(pfa_file, "] def\n"); - fprintf(pfa_file, "/StemSnapV [ "); - for (i = 0; i < 12 && stemsnapv[i] != 0; i++) - fprintf(pfa_file, "%d ", stemsnapv[i]); - fprintf(pfa_file, "] def\n"); - - fprintf(pfa_file, "/MinFeature {16 16} def\n"); - /* Are these fixed also ? */ - fprintf(pfa_file, "/password 5839 def\n"); - - /* calculate the number of subroutines */ - - subid=5; - for (i = 0; i < numglyphs; i++) { - if (glyph_list[i].flags & GF_USED) { - subid+=glyph_list[i].nsg; - } - } - - fprintf(pfa_file, "/Subrs %d array\n", subid); - /* standard subroutines */ - fprintf(pfa_file, "dup 0 {\n\t3 0 callothersubr pop pop setcurrentpoint return\n\t} NP\n"); - fprintf(pfa_file, "dup 1 {\n\t0 1 callothersubr return\n\t} NP\n"); - fprintf(pfa_file, "dup 2 {\n\t0 2 callothersubr return\n\t} NP\n"); - fprintf(pfa_file, "dup 3 {\n\treturn\n\t} NP\n"); - /* our sub to make the hint substitution code shorter */ - fprintf(pfa_file, "dup 4 {\n\t1 3 callothersubr pop callsubr return\n\t} NP\n"); - - if(pfa_file != null_file) { /* save time if the output would be wasted */ - /* print the hinting subroutines */ - subid=5; - for (i = 0; i < numglyphs; i++) { - if (glyph_list[i].flags & GF_USED) { - subid+=print_glyph_subs(i, subid); - } - } - - fprintf(pfa_file, "ND\n"); - - fprintf(pfa_file, "2 index /CharStrings %d dict dup begin\n", nchars); - - for (i = 0; i < numglyphs; i++) { - if (glyph_list[i].flags & GF_USED) { - print_glyph(i); - } - } - } - - - fprintf(pfa_file, "end\nend\nreadonly put\n"); - fprintf(pfa_file, "noaccess put\n"); - fprintf(pfa_file, "dup/FontName get exch definefont pop\n"); - fprintf(pfa_file, "mark currentfile closefile\n"); - fprintf(pfa_file, "cleartomark\n"); - if(pfa_file != null_file) - fclose(pfa_file); - - fprintf(afm_file, "EndCharMetrics\n"); - - if(afm_file != null_file) { /* save time if the output would be wasted */ - /* print the kerning data if present */ - cursw->kerning(glyph_list); - print_kerning(afm_file); - } - - fprintf(afm_file, "EndFontMetrics\n"); - if(afm_file != null_file) - fclose(afm_file); - - fprintf(dvienc_file, "] def\n"); - if(dvienc_file != null_file) - fclose(dvienc_file); - - WARNING_1 fprintf(stderr, "Finished - font files created\n"); - - cursw->close(); - -#ifndef WINDOWS - while (wait(&ws) > 0) { - } -#else - if (encode && pfa_file != null_file) { - extern FILE *ifp, *ofp; /* from t1asm.c */ - - snprintf(filename, sizeof filename, "%s.%s", argv[2], pfbflag ? "pfb" : "pfa" ); - - if ((ofp = fopen(filename, "w+b")) == NULL) { - fprintf(stderr, "**** Cannot create %s ****\n", filename); - exit(1); - } else { - WARNING_2 fprintf(stderr, "Creating file %s\n", filename); - } - - snprintf(filename, sizeof filename, "%s.t1a", argv[2]); - - if ((ifp = fopen(filename, "rb")) == NULL) { - fprintf(stderr, "**** Cannot read %s ****\n", filename); - exit(1); - } else { - WARNING_2 fprintf(stderr, "Converting file %s\n", filename); - } - - runt1asm(pfbflag); - - WARNING_2 fprintf(stderr, "Removing file %s\n", filename); - if(unlink(filename) < 0) - WARNING_1 fprintf(stderr, "Unable to remove file %s\n", filename); - } -#endif /* WINDOWS */ - - fclose(null_file); - return 0; -} diff --git a/nx-X11/extras/ttf2pt1/ttf2pt1_convert.1 b/nx-X11/extras/ttf2pt1/ttf2pt1_convert.1 deleted file mode 100644 index 8e07150aa..000000000 --- a/nx-X11/extras/ttf2pt1/ttf2pt1_convert.1 +++ /dev/null @@ -1,516 +0,0 @@ -.rn '' }` -''' $RCSfile: ttf2pt1_convert.1,v $$Revision: 1.2 $$Date: 2004/04/23 18:42:57 $ -''' -''' $Log: ttf2pt1_convert.1,v $ -''' Revision 1.2 2004/04/23 18:42:57 eich -''' 2004-04-23 Egbert Eich <eich@freedesktop.org> -''' Merging XORG-CURRENT into trunk -''' -''' Revision 1.1.4.1 2004/04/21 10:03:13 gisburn -''' Fix for http://pdx.freedesktop.org/cgi-bin/bugzilla/show_bug.cgi?id=530 - Land XPRINT branch on XORG-CURRENT -''' -''' Revision 1.1 2003/06/04 00:33:54 roland -''' Fix for http://xprint.mozdev.org/bugs/show_bug.cgi?id=3846 - RFE: Upload Freetype --> PS Type1 font converter "ttf2pt1" ... -''' -''' -.de Sh -.br -.if t .Sp -.ne 5 -.PP -\fB\\$1\fR -.PP -.. -.de Sp -.if t .sp .5v -.if n .sp -.. -.de Ip -.br -.ie \\n(.$>=3 .ne \\$3 -.el .ne 3 -.IP "\\$1" \\$2 -.. -.de Vb -.ft CW -.nf -.ne \\$1 -.. -.de Ve -.ft R - -.fi -.. -''' -''' -''' Set up \*(-- to give an unbreakable dash; -''' string Tr holds user defined translation string. -''' Bell System Logo is used as a dummy character. -''' -.tr \(*W-|\(bv\*(Tr -.ie n \{\ -.ds -- \(*W- -.ds PI pi -.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -.ds L" "" -.ds R" "" -''' \*(M", \*(S", \*(N" and \*(T" are the equivalent of -''' \*(L" and \*(R", except that they are used on ".xx" lines, -''' such as .IP and .SH, which do another additional levels of -''' double-quote interpretation -.ds M" """ -.ds S" """ -.ds N" """"" -.ds T" """"" -.ds L' ' -.ds R' ' -.ds M' ' -.ds S' ' -.ds N' ' -.ds T' ' -'br\} -.el\{\ -.ds -- \(em\| -.tr \*(Tr -.ds L" `` -.ds R" '' -.ds M" `` -.ds S" '' -.ds N" `` -.ds T" '' -.ds L' ` -.ds R' ' -.ds M' ` -.ds S' ' -.ds N' ` -.ds T' ' -.ds PI \(*p -'br\} -.\" If the F register is turned on, we'll generate -.\" index entries out stderr for the following things: -.\" TH Title -.\" SH Header -.\" Sh Subsection -.\" Ip Item -.\" X<> Xref (embedded -.\" Of course, you have to process the output yourself -.\" in some meaninful fashion. -.if \nF \{ -.de IX -.tm Index:\\$1\t\\n%\t"\\$2" -.. -.nr % 0 -.rr F -.\} -.TH TTF2PT1_CONVERT 1 "version 3.4.4-SNAP-030526" "May 26, 2003" "TTF2PT1 Font Converter" -.UC -.if n .hy 0 -.if n .na -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.de CQ \" put $1 in typewriter font -.ft CW -'if n "\c -'if t \\&\\$1\c -'if n \\&\\$1\c -'if n \&" -\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7 -'.ft R -.. -.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2 -. \" AM - accent mark definitions -.bd B 3 -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds ? ? -. ds ! ! -. ds / -. ds q -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10' -. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#] -.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u' -.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u' -.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#] -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -.ds oe o\h'-(\w'o'u*4/10)'e -.ds Oe O\h'-(\w'O'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds v \h'-1'\o'\(aa\(ga' -. ds _ \h'-1'^ -. ds . \h'-1'. -. ds 3 3 -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -. ds oe oe -. ds Oe OE -.\} -.rm #[ #] #H #V #F C -.SH "NAME" -\fBttf2pt1_convert\fR \- convenience font conversion script -.SH "SYNOPSIS" -ttf2pt1_convert \fB[config-file]\fR -.SH "DESCRIPTION" -`\fBConvert\fR\*(R' is the master conversion script provided with ttf2pt1. -When installed into a public directory it's named `\fBttf2pt1_convert\fR\*(R' -to avoid name collisions with the other programs. -.PP -If the configuration file is not specified as an argument then the file -`\f(CWconvert.cfg\fR\*(R' in the current directory is used. This file contains -a set of configuration variables. The distribution contains a sample file -file `\f(CWconvert.cfg.sample\fR\*(R'. Please copy it to `\f(CWconvert.cfg\fR\*(R', -look inside it and change the configuration variables. The more stable -configuration variables, such as the path names of the scripts and -encoding files are located in `\f(CWconvert\fR\*(R' itself, they are -automatically updated when installing \fBttf2pt1\fR. -.PP -Put all the TTF fonts you want to convert into some directory (this -may be just the directory that already contains all the Windows -fonts on a mounted FAT filesystem). If you have fonts in different -source encoding then put the fonts in each of the encodings -into a separate directory. Up to 10 source directories are -supported. If you (in a rather unlikely case) have more source -directories then you can make two separate runs of the converter, -converting up to 10 directories at a time. -.PP -The variables in the configuration file are: -.Ip "\(bu" 2 -\fB\f(CWSRCDIRS\fR\fR \- the list of directories (with absolute paths) with -\s-1TTF\s0 fonts. Each line contains at least 3 fields: the name of the directory, -the language of the fonts in it (if you have fonts for different -languages you have to put them into the separate directories) and the -encoding of the fonts. Again, if you have some of the \s-1TTF\s0 typefaces in -one encoding, and some in another (say, \s-1CP\s0\-1251 and \s-1KOI\s0\-8), you have -to put them into the separate source directories. Some lines may contain -4 fields. Then the fourth field is the name of the external map to -convert the Unicode fonts into the desirable encoding. This map is -used instead of the built-in map for the specified language. -.Sp -*8* -An interesting thing is that some languages have more than one -widely used character encodings. For example, the widely used -encodings for Russian are \s-1IBM\s0 \s-1CP\s0\-866 (\s-1MS\s0\-\s-1DOS\s0 and Unix), \s-1KOI\s0\-8 -(Unix and \s-1VAX\s0, also the standard Internet encoding), \s-1IBM\s0 \s-1CP\s0\-1251 (\s-1MS\s0 Windows). -That's why I have provided the means to generate the converted fonts -in more than one encoding. See the file encodings/\s-1README\s0 for -details about the encoding tables. Actually, if you plan to use -these fonts with Netscape Navigator better use the aliases -cp-866 instead of ibm-866 and windows-1251 instead of ibm-1251 -because that's what Netscape wants. -.Ip "\(bu" 2 -\fB\f(CWDSTDIR\fR\fR \- directory for the resulting Type1 fonts. Be careful! -This directory gets completely wiped out before conversion, -so don't use any already existing directory for this purpose. -.Ip "\(bu" 2 -\fB\f(CWDSTENC\fI{language}\fR\fR\fR \- the list of encodings in which the destination -fonts will be generated for each language. Each font of that -language will be generated in each of the specified -encodings. If you don't want any translation, just specify both -\f(CWSRCENC\fR and \f(CWDSTENC\fR as iso8859-1 (or if you want any other encoding -specified in the fonts.dir, copy the description of 8859-1 with -new name and use this new name for \f(CWSRCENC\fR and \f(CWDSTENC\fR). -.Ip "\(bu" 2 -\fB\f(CWFOUNDRY\fR\fR \- the foundry name to be used in the fonts.dir file. I have -set it to `fromttf\*(R' to avoid name conflicts with any existing font for -sure. But this foundry name is not registered in X11 standards and -if you want to get the full standard compliance or have a font server -that enforces such a compliance, use `misc\*(R'. -.PP -The next few parameters control the general behavior of the converter. -They default values are set to something reasonable. -.Ip "\(bu" 2 -\fB\f(CWCORRECTWIDTH\fR\fR \- if the value is set to \fB\f(CWYES\fR\fR then use the -converter option \f(CW\fB-w\fR\fR, otherwise don't use it. See the description of -this option in the \s-1README\s0 file. -.Ip "\(bu" 2 -\fB\f(CWREMOVET1A\fR\fR \- if the value is set to \fB\f(CWYES\fR\fR then after -conversion remove the un-encoded \f(CW.t1a\fR font files and the -intermediate \f(CW.xpfa\fR font metric files. -.Ip "\(bu" 2 -\fB\f(CWINSTALLFONTMAP\fR\fR \- a Ghostscript parameter, if the value is set to -\fB\f(CWYES\fR\fR then install the entries for the new fonts -right into the main \f(CWFontmap\fR file. Otherwise just leave -the file \f(CWFontmap.ttf\fR in the Ghostscript configuration -directory. -.Ip "\(bu" 2 -\fB\f(CWHINTSUBST\fR\fR \- if the value is set to \fB\f(CWYES\fR\fR use the option -\f(CW\fB-H\fR\fR, otherwise don't use it. This option enables the -hint substitution technique. If you have not installed the X11 patch -described above, use this option with great caution. See further -description of this option in the \s-1README\s0 file. -.Ip "\(bu" 2 -\fB\f(CWENFORCEISO\fR\fR \- if the value is set to \fB\f(CWYES\fR\fR then -disguise the resulting fonts as the fonts in ISOLatin1 encoding. Historically -this was neccessary due to the way the installer scripts created the -X11 font configuration files. It is not neccessary any more for this -purpose. But if you plan to use these fonts with some other application -that expects ISOLatin1 encoding then better enable this option. -.Ip "\(bu" 2 -\fB\f(CWALLGLYPHS\fR\fR \- if the value is set to \fB\f(CWYES\fR\fR then -include all the glyphs from the source fonts into the resulting fonts, even -if these glyphs are inaccessible. If it's set to \fB\f(CWNO\fR\fR then -include only the glyphs which have codes assigned to them. The glyphs -without codes can not be used directly. But some clever programs, -such as the Type 1 library from XFree86 3.9 and higher can change -the encoding on the fly and use another set of glyphs. If you have not -installed the X11 patch described above, use this option with great -caution. See further description of the option option \f(CW\fB-a\fR\fR in the -\s-1README\s0 file. -.Ip "\(bu" 2 -\fB\f(CWGENUID\fR\fR \- if the value is set to \fB\f(CWYES\fR\fR then use -the option \f(CW\fB-uA\fR\fR of the converter to generate UniqueIDs for -the converted fonts. The standard X11 Type 1 library does not use -this \s-1ID\s0, so it may only be neccessary for the other applications. -The script is clever enough to generate different UniqueID for the -same font converted to multiple encodings. Also after conversion it -checks all the fonts generacted during the session for duplicated -UniqueID and shows those. Still, this does not quarantee that these -UniqueIDs won't overlap with some other fonts. The UniqueIDs are -generated as hash values from the font names, so it's guaranteed -that if the `\f(CWconvert\fR\*(R' script runs multiple times it will -generate the same UniqueIDs during each run. See further description -of this option in the \s-1README\s0 file. -.Ip "\(bu" 2 -\fB\f(CWGENUID\fR\fR \- if the value is set to \fB\f(CWYES\fR\fR then create -the \f(CW.pfb\fR files, otherwise the \f(CW.pfa\fR files. The \f(CW.pfb\fR -files are more compact but contain binary data, so you may experience some -troubles when transferring them through the network. -.PP -The following parameters are used to locate the other scripts and -configuration files. By default the scripts do a bit of guessing for them: -they search in the \fBttf2pt1\fR installation directory if \fBttf2pt1\fR -was installed or otherwise suppose that you are running `\f(CWconvert\fR\*(R' with -`\f(CWscripts\fR\*(R' subdirectory being the current directory. -.Ip "\(bu" 2 -\fB\f(CWENCDIR\fR\fR \- directory containing the descriptions of encodings -.Ip "\(bu" 2 -\fB\f(CWMAPDIR\fR\fR \- directory containing the external map files -.PP -Besides that a few parameters are built into the `\f(CWconvert\fR\*(R' script itself. -You probably won't need to change them: -.Ip "\(bu" 2 -\f(CW\fBT1ASM\fR\fR, \f(CW\fBTTF2PT1\fR\fR, \f(CW\fBTRANS\fR\fR, \f(CW\fBT1FDIR\fR\fR, \f(CW\fBFORCEISO\fR\fR \- paths to the other script -.PP -Also there are a few parameters controlling the installation of -fonts for Ghostscript. Please look at their description in the -Ghostscript section of documentation or in the \fBttf2pt1_x2gs(1)\fR -manual page before running `\f(CWconvert\fR\*(R'. If these parameters are -set, `\f(CWconvert\fR\*(R' will call the `\f(CWx2gs\fR\*(R' script automatically -to install the newly converted fonts in Ghostscript. -.PP -After creating the configuration file run the `\f(CWconvert\fR\*(R' script. Look at -the result and the log file in \f(CWDSTDIR\fR. -.PP -Add the directory with newly converted fonts to the configuration -of X server or font server. For most of the systems this step is -very straightforward. For \s-1HP\s0\-\s-1UX\s0 it's rather tricky and poorly -documented, so the file \s-1FONTS\s0.hpux gives a short description. -.PP -If you don't have the privileges of the root user, you still can -configure your private font server. Just use some non-standard -port number (see \s-1FONTS\s0.hpux for an example, exept that you won't -need all the \s-1HP\s0\-related stuff on any other system). -.SH "FILES" -.Ip "\(bu" 2 -\s-1TTF2PT1_SHAREDIR/\s0scripts/convert.cfg.sample -.Ip "\(bu" 2 -\s-1TTF2PT1_SHAREDIR/\s0scripts/* -.Ip "\(bu" 2 -\s-1TTF2PT1_SHAREDIR/README\s0 -.Ip "\(bu" 2 -\s-1TTF2PT1_SHAREDIR/FONTS\s0 -.Ip "\(bu" 2 -\s-1TTF2PT1_SHAREDIR\s0/* -.Ip "\(bu" 2 -\s-1TTF2PT1_BINDIR/\s0ttf2pt1 -.SH "SEE ALSO" -.Ip "\(bu" 4 -the \fIttf2pt1(1)\fR manpage -.Ip "\(bu" 4 -the \fIttf2pt1_x2gs(1)\fR manpage -.Ip "\(bu" 4 -the \fIt1asm(1)\fR manpage -.SH "BUGS" -.Sh "Known problems" -.Ip "\(bu" 4 -One catch is that the X11 Type 1 font library has a rather low limit -on the font size. Because of this the fonts with more complicated -outlines and the enabled hint substitution may not fit into -this limit. The same applies to the fonts with very complicated -outlines or with very many glyphs (especially the fonts with -over 256 glyphs). So you will need to excercise caution with -these options if you plan using these fonts with X11. Some vendors -such as \s-1HP\s0 provide the Type 1 implementation licensed from Adobe -which should have no such problem. -.Sp -But there is a solution even for the generic X11. A patch located -in the subdirectory `\f(CWapp/X11\fR\*(R' fixes this problem as well -as some other minor problems. Its description is provided in -app/X11/\s-1README\s0. -.Sp -To fix the X11 font library, you have to get the X11 sources. I -can recommend the ftp sites of the XFree86 project ftp://ftp.xfree86.org -or of the Open Group ftp://ftp.x.org. This patch was made on the sources -of XFree86 so you may have better success with applying it to the -XFree86 distribution. After you have got the sources, make sure -that you can compile them. Then apply the patch as described. -Make sure that it was applied properly. Compile the sources again -(actually, you need only the fonts library, the fonts server, and -possibly the X server). It would be prudent now to save your old -font library, font server and, possibly, X server. Then install -the new recently compiled versions of these files. Of course, -if you know someone who already has compiled these files for the -same \s-1OS\s0 as yours, you can just copy the binary fles from him. -.Sp -Alas, building the X11 system from the source code is not the -easiest thing in the world and if you have no experience it -can be quite difficult. In this case just avoid the aforementioned -features or check each converted font to make sure that it -works properly. -.Ip "\(bu" 4 -The Type1 font library from the standard X11 distribution -does not work on \s-1HP\s0\-\s-1UX\s0 (at least, up to 10.01). The font server -supplied with \s-1HP\s0\-\s-1UX\s0 up to 10.01 is also broken. Starting from -\s-1HP\s0\-\s-1UX\s0 10.20 (I don't know about 10.10) they supply a proprietary font -library and the converted fonts work fine with it, provided that -they are configured properly (see the file \s-1FONTS\s0.hpux). -.Ip "\(bu" 4 -The \f(CWfonts.scale\fR files created by the older versions of the -\f(CWttf2pt1\fR installation program (up to release 3.1) have conflicted -with the language definitions of the \f(CWXfsft\fR font server and -parts of it included into XFree86. To overcome this incompatibility -the never versions creats the \f(CWfonts.scale\fR file describing all the -fonts as belonging to the \f(CWadobe-fontspecific\fR encoding and -the \f(CWfonts.alias\fR file with the proper names. The drawback of -this solution is that \f(CWxlsfonts\fR gives the list of twice more -fonts. But as a side effect the option \f(CW\fBENFORCEISO\fR\fR in -`\f(CWconvert.cfg\fR\*(R' is not required for X11 any more. -.Ip "\(bu" 4 -The conversion script has no support for Eastern multi-plane fonts. -Contribution of such a support would be welcome. - -.rn }` '' -.IX Title "TTF2PT1_CONVERT 1" -.IX Name "B<ttf2pt1_convert> - convenience font conversion script" - -.IX Header "NAME" - -.IX Header "SYNOPSIS" - -.IX Header "DESCRIPTION" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Header "FILES" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Header "SEE ALSO" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Header "BUGS" - -.IX Subsection "Known problems" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - diff --git a/nx-X11/extras/ttf2pt1/ttf2pt1_x2gs.1 b/nx-X11/extras/ttf2pt1/ttf2pt1_x2gs.1 deleted file mode 100644 index 9ac5caad7..000000000 --- a/nx-X11/extras/ttf2pt1/ttf2pt1_x2gs.1 +++ /dev/null @@ -1,323 +0,0 @@ -.rn '' }` -''' $RCSfile: ttf2pt1_x2gs.1,v $$Revision: 1.2 $$Date: 2004/04/23 18:42:57 $ -''' -''' $Log: ttf2pt1_x2gs.1,v $ -''' Revision 1.2 2004/04/23 18:42:57 eich -''' 2004-04-23 Egbert Eich <eich@freedesktop.org> -''' Merging XORG-CURRENT into trunk -''' -''' Revision 1.1.4.1 2004/04/21 10:03:13 gisburn -''' Fix for http://pdx.freedesktop.org/cgi-bin/bugzilla/show_bug.cgi?id=530 - Land XPRINT branch on XORG-CURRENT -''' -''' Revision 1.1 2003/06/04 00:33:54 roland -''' Fix for http://xprint.mozdev.org/bugs/show_bug.cgi?id=3846 - RFE: Upload Freetype --> PS Type1 font converter "ttf2pt1" ... -''' -''' -.de Sh -.br -.if t .Sp -.ne 5 -.PP -\fB\\$1\fR -.PP -.. -.de Sp -.if t .sp .5v -.if n .sp -.. -.de Ip -.br -.ie \\n(.$>=3 .ne \\$3 -.el .ne 3 -.IP "\\$1" \\$2 -.. -.de Vb -.ft CW -.nf -.ne \\$1 -.. -.de Ve -.ft R - -.fi -.. -''' -''' -''' Set up \*(-- to give an unbreakable dash; -''' string Tr holds user defined translation string. -''' Bell System Logo is used as a dummy character. -''' -.tr \(*W-|\(bv\*(Tr -.ie n \{\ -.ds -- \(*W- -.ds PI pi -.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -.ds L" "" -.ds R" "" -''' \*(M", \*(S", \*(N" and \*(T" are the equivalent of -''' \*(L" and \*(R", except that they are used on ".xx" lines, -''' such as .IP and .SH, which do another additional levels of -''' double-quote interpretation -.ds M" """ -.ds S" """ -.ds N" """"" -.ds T" """"" -.ds L' ' -.ds R' ' -.ds M' ' -.ds S' ' -.ds N' ' -.ds T' ' -'br\} -.el\{\ -.ds -- \(em\| -.tr \*(Tr -.ds L" `` -.ds R" '' -.ds M" `` -.ds S" '' -.ds N" `` -.ds T" '' -.ds L' ` -.ds R' ' -.ds M' ` -.ds S' ' -.ds N' ` -.ds T' ' -.ds PI \(*p -'br\} -.\" If the F register is turned on, we'll generate -.\" index entries out stderr for the following things: -.\" TH Title -.\" SH Header -.\" Sh Subsection -.\" Ip Item -.\" X<> Xref (embedded -.\" Of course, you have to process the output yourself -.\" in some meaninful fashion. -.if \nF \{ -.de IX -.tm Index:\\$1\t\\n%\t"\\$2" -.. -.nr % 0 -.rr F -.\} -.TH TTF2PT1_X2GS 1 "version 3.4.4-SNAP-030526" "May 26, 2003" "TTF2PT1 Font Converter" -.UC -.if n .hy 0 -.if n .na -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.de CQ \" put $1 in typewriter font -.ft CW -'if n "\c -'if t \\&\\$1\c -'if n \\&\\$1\c -'if n \&" -\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7 -'.ft R -.. -.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2 -. \" AM - accent mark definitions -.bd B 3 -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds ? ? -. ds ! ! -. ds / -. ds q -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10' -. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#] -.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u' -.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u' -.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#] -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -.ds oe o\h'-(\w'o'u*4/10)'e -.ds Oe O\h'-(\w'O'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds v \h'-1'\o'\(aa\(ga' -. ds _ \h'-1'^ -. ds . \h'-1'. -. ds 3 3 -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -. ds oe oe -. ds Oe OE -.\} -.rm #[ #] #H #V #F C -.SH "NAME" -\fBttf2pt1_x2gs\fR \- font installer for Ghostscript -.SH "SYNOPSIS" -ttf2pt1_x2gs \fB[config-file]\fR -.SH "DESCRIPTION" -The fonts generated with \fBttf2pt1\fR work fine with Ghostscript by -themselves. The script `\fBx2gs\fR\*(R' (or `\fBttf2pt1_x2gs\fR\*(R' when installed -into a public directory, to avoid name conflicts with other -programs) links the font files from the X11 direcotry into the Ghostscript -directory and automatically creates the description file (\f(CWFontmap\fR) -in Ghostscript format. -.PP -If the configuration file is not specified as an argument then the file -`\f(CWconvert.cfg\fR\*(R' in the current directory is used, just like the -`\f(CWconvert\fR\*(R' script does. Indeed, this configuration file is used for -both scripts. -.PP -The Ghostscript-related parameters in the configuration file are: -.PP -\fB\f(CWDSTDIR\fR\fR \- the X11 font directory used by `\f(CWx2gs\fR\*(R' as the -source of the fonts. This parameter is common with the X11 -configuration. -.PP -\fB\f(CWGSDIR\fR\fR \- the base directory of Ghostsript. If this -parameter is set to an empty string then `\f(CWconvert\fR\*(R' won't -call `\f(CWx2gs\fR\*(R'. So if you want to get only the X11 fonts -installed then set this parameter to an empty string. This -directory may vary on various system, so please check your -system and set this value accordingly before running the script. -.PP -\fB\f(CWGSFONTDIR\fR\fR \- the font directory of Ghostscript. In the standard -Ghostscript installation it's a subdirectory of \f(CWGSDIR\fR -but some systems may use completely different directories. -.PP -\fB\f(CWGSCONFDIR\fR\fR \- the configuration subdirectory of Ghostscript -that contains the \f(CWFontmap\fR file. -.PP -\fB\f(CWINSTALLFONTMAP\fR\fR \- if the value is set to \fB\f(CWYES\fR\fR then -install the entries for the new fonts right into the main -\f(CWFontmap\fR file. Otherwise just leave the file \f(CWFontmap.ttf\fR -in the Ghostscript configuration directory. -.PP -After preparing the configuration file run the script. It symbolicaly links -all the font files and creates the description file \f(CWFontmap.ttf\fR in -\f(CWGSCONDFIR\fR. After that there are two choices. -.PP -If the option \f(CWINSTALLFONTMAP\fR was set to \f(CWYES\fR then -the font descriptions are also automatically installed into the -master \f(CWFontmap\fR file. The script is clever enough to -detect if it was run multiple times with the same directories -and if so it replaces the old \f(CWFontmap\fR entries with -the new ones instead of just accumulating all of them. You -may also run it multiple times for multiple X11 directories -and all the results will be properly collected in the \f(CWFontmap\fR. -But it's your responsibility to watch that the names of the -font files don't overlap. If the X11 font directory gets -renamed then you have to remove its font entries from the -\f(CWFontmap\fR and only after that re-run `\f(CWx2gs\fR\*(R' -for the new directory. -.PP -On the other hand if the option \f(CWINSTALLFONTMAP\fR was set to -\f(CWNO\fR then go to the \f(CWGSCONFDIR\fR directory and insert the -contents of \f(CWFontmap.ttf\fR into the \f(CWFontmap\fR file -manually. This step may be left manual to make the installation -a little bit more safe. -.PP -After that you may also want to redefine some of the aliases in -\f(CWFontmap\fR to refer to the newly installed fonts. -But the redefinition of the aliases may be dangerous if the width of -characters in the new font will be different from the old font. -Alas, there is no visible solution of this problem yet. -.SH "FILES" -.Ip "\(bu" 2 -\s-1TTF2PT1_SHAREDIR/\s0scripts/convert.cfg.sample -.Ip "\(bu" 2 -\s-1TTF2PT1_SHAREDIR/\s0scripts/* -.Ip "\(bu" 2 -\s-1TTF2PT1_SHAREDIR/README\s0 -.Ip "\(bu" 2 -\s-1TTF2PT1_SHAREDIR/FONTS\s0 -.Ip "\(bu" 2 -\s-1TTF2PT1_SHAREDIR\s0/* -.Ip "\(bu" 2 -\s-1TTF2PT1_BINDIR/\s0ttf2pt1 -.SH "SEE ALSO" -.Ip "\(bu" 4 -the \fIttf2pt1(1)\fR manpage -.Ip "\(bu" 4 -the \fIttf2pt1_convert(1)\fR manpage -.Ip "\(bu" 4 -the \fIt1asm(1)\fR manpage - -.rn }` '' -.IX Title "TTF2PT1_X2GS 1" -.IX Name "B<ttf2pt1_x2gs> - font installer for Ghostscript" - -.IX Header "NAME" - -.IX Header "SYNOPSIS" - -.IX Header "DESCRIPTION" - -.IX Header "FILES" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Header "SEE ALSO" - -.IX Item "\(bu" - -.IX Item "\(bu" - -.IX Item "\(bu" - diff --git a/nx-X11/extras/ttf2pt1/version.h b/nx-X11/extras/ttf2pt1/version.h deleted file mode 100644 index d1b3525ba..000000000 --- a/nx-X11/extras/ttf2pt1/version.h +++ /dev/null @@ -1,7 +0,0 @@ -/* - * see COPYRIGHT - */ - - -/* version number */ -#define TTF2PT1_VERSION "3.4.4-SNAP-030526" diff --git a/nx-X11/extras/ttf2pt1/winbuild.bat b/nx-X11/extras/ttf2pt1/winbuild.bat deleted file mode 100644 index 0e8c09341..000000000 --- a/nx-X11/extras/ttf2pt1/winbuild.bat +++ /dev/null @@ -1,11 +0,0 @@ -rem file to build ttf2pt1 with Visual C++
-
-cl -DWINDOWS -c bdf.c
-cl -DWINDOWS -c ttf2pt1.c
-cl -DWINDOWS -c pt1.c
-cl -DWINDOWS -c ttf.c
-cl -DWINDOWS -c t1asm.c
-cl -DWINDOWS -c bitmap.c
-cl -o ttf2pt1 ttf2pt1.obj pt1.obj t1asm.obj ttf.obj bdf.obj bitmap.obj
-cl -o t1asm -DWINDOWS -DSTANDALONE t1asm.c
-
diff --git a/nx-X11/extras/ttf2pt1/windows.h b/nx-X11/extras/ttf2pt1/windows.h deleted file mode 100644 index a90ecf7e5..000000000 --- a/nx-X11/extras/ttf2pt1/windows.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Implementation of things missing in Windows - */ - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -#undef ntohs -#undef ntohl -#undef htonl - -#ifdef WINDOWS_FUNCTIONS -/* byte order */ - -static unsigned short StoM(unsigned short inv) { - union iconv { - unsigned short ui; - unsigned char uc[2]; - } *inp, outv; - - inp = (union iconv *)&inv; - - outv.uc[0] = inp->uc[1]; - outv.uc[1] = inp->uc[0]; - - return (outv.ui); -} - -static unsigned int ItoM(unsigned int inv) { - union iconv { - unsigned int ui; - unsigned char uc[4]; - } *inp, outv; - - inp = (union iconv *)&inv; - - outv.uc[0] = inp->uc[3]; - outv.uc[1] = inp->uc[2]; - outv.uc[2] = inp->uc[1]; - outv.uc[3] = inp->uc[0]; - - return (outv.ui); -} - -unsigned short ntohs(unsigned short inv) { return StoM(inv); } -unsigned long ntohl(unsigned long inv) { return ItoM(inv); } -unsigned long htonl(unsigned long inv) { return ItoM(inv); } - -char *optarg; -int optind=1; - -char getopt(int argc, char **argv, char *args) { - int n,nlen=strlen(args),nLen=0; - char nCmd; - - if (argv[optind] && *argv[optind]=='-') { - nCmd=*((argv[optind]+1)); - - for (n=0;n<nlen;n++) { - if (args[n] == ':') continue; - if (args[n] == nCmd) { - if (args[n+1]==':') { - char retVal; - retVal=*(argv[optind]+1); - optarg=argv[optind+1]; - if (!optarg) optarg=""; - optind+=2; - return retVal; - } else { - char retVal; - retVal=*(argv[optind]+1); - optarg=NULL; - optind+=1; - return retVal; - } - } - } - } - return -1; -} - -#else - -unsigned short ntohs(unsigned short inv); -unsigned long ntohl(unsigned long inv); -unsigned long htonl(unsigned long inv); - -extern char *optarg; -extern int optind; - -char getopt(int argc, char **argv, char *args); -#endif |